diff options
-rw-r--r-- | Documentation/kernel-parameters.txt | 4 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 9 | ||||
-rw-r--r-- | fs/nfs/inode.c | 14 | ||||
-rw-r--r-- | fs/nfs/sysctl.c | 10 | ||||
-rw-r--r-- | include/linux/nfs_idmap.h | 2 |
5 files changed, 39 insertions, 0 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 309c9cec6e7c..a482fde09bbb 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -914,6 +914,10 @@ running once the system is up. [NFS] set the TCP port on which the NFSv4 callback channel should listen. + nfs.idmap_cache_timeout= + [NFS] set the maximum lifetime for idmapper cache + entries. + nmi_watchdog= [KNL,BUGS=IA-32] Debugging features for SMP kernels no387 [BUGS=IA-32] Tells the kernel to use the 387 maths diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index ffb8df91dc34..821edd30333b 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c @@ -54,7 +54,11 @@ #define IDMAP_HASH_SZ 128 +/* Default cache timeout is 10 minutes */ +unsigned int nfs_idmap_cache_timeout = 600 * HZ; + struct idmap_hashent { + unsigned long ih_expires; __u32 ih_id; int ih_namelen; char ih_name[IDMAP_NAMESZ]; @@ -149,6 +153,8 @@ idmap_lookup_name(struct idmap_hashtable *h, const char *name, size_t len) if (he->ih_namelen != len || memcmp(he->ih_name, name, len) != 0) return NULL; + if (time_after(jiffies, he->ih_expires)) + return NULL; return he; } @@ -164,6 +170,8 @@ idmap_lookup_id(struct idmap_hashtable *h, __u32 id) struct idmap_hashent *he = idmap_id_hash(h, id); if (he->ih_id != id || he->ih_namelen == 0) return NULL; + if (time_after(jiffies, he->ih_expires)) + return NULL; return he; } @@ -192,6 +200,7 @@ idmap_update_entry(struct idmap_hashent *he, const char *name, memcpy(he->ih_name, name, namelen); he->ih_name[namelen] = '\0'; he->ih_namelen = namelen; + he->ih_expires = jiffies + nfs_idmap_cache_timeout; } /* diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 4625479a6b62..e7bd0d92600f 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -2050,6 +2050,20 @@ static int param_set_port(const char *val, struct kernel_param *kp) module_param_call(callback_tcpport, param_set_port, param_get_int, &nfs_callback_set_tcpport, 0644); +static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) +{ + char *endp; + int num = simple_strtol(val, &endp, 0); + int jif = num * HZ; + if (endp == val || *endp || num < 0 || jif < num) + return -EINVAL; + *((int *)kp->arg) = jif; + return 0; +} + +module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, + &nfs_idmap_cache_timeout, 0644); + #define nfs4_init_once(nfsi) \ do { \ INIT_LIST_HEAD(&(nfsi)->open_states); \ diff --git a/fs/nfs/sysctl.c b/fs/nfs/sysctl.c index fdc64b59a4ee..4c486eb867ca 100644 --- a/fs/nfs/sysctl.c +++ b/fs/nfs/sysctl.c @@ -11,6 +11,7 @@ #include <linux/sysctl.h> #include <linux/module.h> #include <linux/nfs4.h> +#include <linux/nfs_idmap.h> #include "callback.h" @@ -35,6 +36,15 @@ static ctl_table nfs_cb_sysctls[] = { .extra1 = (int *)&nfs_set_port_min, .extra2 = (int *)&nfs_set_port_max, }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "idmap_cache_timeout", + .data = &nfs_idmap_cache_timeout, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec_jiffies, + .strategy = &sysctl_jiffies, + }, #endif { .ctl_name = 0 } }; diff --git a/include/linux/nfs_idmap.h b/include/linux/nfs_idmap.h index a0f1f25e0ead..102e56094296 100644 --- a/include/linux/nfs_idmap.h +++ b/include/linux/nfs_idmap.h @@ -71,6 +71,8 @@ int nfs_map_name_to_uid(struct nfs4_client *, const char *, size_t, __u32 *); int nfs_map_group_to_gid(struct nfs4_client *, const char *, size_t, __u32 *); int nfs_map_uid_to_name(struct nfs4_client *, __u32, char *); int nfs_map_gid_to_group(struct nfs4_client *, __u32, char *); + +extern unsigned int nfs_idmap_cache_timeout; #endif /* __KERNEL__ */ #endif /* NFS_IDMAP_H */ |