NFSv4: Allow entries in the idmap cache to expire
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Jan 2006 08:55:57 +0000 (09:55 +0100)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 6 Jan 2006 19:58:58 +0000 (14:58 -0500)
 If someone changes the uid/gid mapping in userland, then we do eventually
 want those changes to be propagated to the kernel. Currently the kernel
 assumes that it may cache entries forever.

 Add an expiration time + garbage collector for idmap entries.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Documentation/kernel-parameters.txt
fs/nfs/idmap.c
fs/nfs/inode.c
fs/nfs/sysctl.c
include/linux/nfs_idmap.h

index 309c9cec6e7c576a26e7efda557b84e44eb92844..a482fde09bbbe01756627bffb4ce3cd98ebbeed5 100644 (file)
@@ -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
index ffb8df91dc34198034264ae7d06de277094aef00..821edd30333b8aff740fc1e66a013527f967fcfc 100644 (file)
 
 #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;
 }
 
 /*
index 4625479a6b62855d224ccee5d0dbae3208c97881..e7bd0d92600f6e34e65574bb464f03c45a17a033 100644 (file)
@@ -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); \
index fdc64b59a4eef6156a5d2c84910c3c02c2a8f254..4c486eb867ca0655d2c671d1b8c5eebf050e01ac 100644 (file)
@@ -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 }
 };
index a0f1f25e0ead2fa7f2dc2184478d310943a353c6..102e560942960d6d27cc6b9e1bb5778d035a852a 100644 (file)
@@ -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 */