aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/fscache.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/fscache.c')
-rw-r--r--fs/nfs/fscache.c116
1 files changed, 116 insertions, 0 deletions
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index c3f056f89477..ab2de2c92b21 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -23,6 +23,9 @@
23 23
24#define NFSDBG_FACILITY NFSDBG_FSCACHE 24#define NFSDBG_FACILITY NFSDBG_FSCACHE
25 25
26static struct rb_root nfs_fscache_keys = RB_ROOT;
27static DEFINE_SPINLOCK(nfs_fscache_keys_lock);
28
26/* 29/*
27 * Get the per-client index cookie for an NFS client if the appropriate mount 30 * Get the per-client index cookie for an NFS client if the appropriate mount
28 * flag was set 31 * flag was set
@@ -50,3 +53,116 @@ void nfs_fscache_release_client_cookie(struct nfs_client *clp)
50 fscache_relinquish_cookie(clp->fscache, 0); 53 fscache_relinquish_cookie(clp->fscache, 0);
51 clp->fscache = NULL; 54 clp->fscache = NULL;
52} 55}
56
57/*
58 * Get the cache cookie for an NFS superblock. We have to handle
59 * uniquification here because the cache doesn't do it for us.
60 */
61void nfs_fscache_get_super_cookie(struct super_block *sb,
62 struct nfs_parsed_mount_data *data)
63{
64 struct nfs_fscache_key *key, *xkey;
65 struct nfs_server *nfss = NFS_SB(sb);
66 struct rb_node **p, *parent;
67 const char *uniq = data->fscache_uniq ?: "";
68 int diff, ulen;
69
70 ulen = strlen(uniq);
71 key = kzalloc(sizeof(*key) + ulen, GFP_KERNEL);
72 if (!key)
73 return;
74
75 key->nfs_client = nfss->nfs_client;
76 key->key.super.s_flags = sb->s_flags & NFS_MS_MASK;
77 key->key.nfs_server.flags = nfss->flags;
78 key->key.nfs_server.rsize = nfss->rsize;
79 key->key.nfs_server.wsize = nfss->wsize;
80 key->key.nfs_server.acregmin = nfss->acregmin;
81 key->key.nfs_server.acregmax = nfss->acregmax;
82 key->key.nfs_server.acdirmin = nfss->acdirmin;
83 key->key.nfs_server.acdirmax = nfss->acdirmax;
84 key->key.nfs_server.fsid = nfss->fsid;
85 key->key.rpc_auth.au_flavor = nfss->client->cl_auth->au_flavor;
86
87 key->key.uniq_len = ulen;
88 memcpy(key->key.uniquifier, uniq, ulen);
89
90 spin_lock(&nfs_fscache_keys_lock);
91 p = &nfs_fscache_keys.rb_node;
92 parent = NULL;
93 while (*p) {
94 parent = *p;
95 xkey = rb_entry(parent, struct nfs_fscache_key, node);
96
97 if (key->nfs_client < xkey->nfs_client)
98 goto go_left;
99 if (key->nfs_client > xkey->nfs_client)
100 goto go_right;
101
102 diff = memcmp(&key->key, &xkey->key, sizeof(key->key));
103 if (diff < 0)
104 goto go_left;
105 if (diff > 0)
106 goto go_right;
107
108 if (key->key.uniq_len == 0)
109 goto non_unique;
110 diff = memcmp(key->key.uniquifier,
111 xkey->key.uniquifier,
112 key->key.uniq_len);
113 if (diff < 0)
114 goto go_left;
115 if (diff > 0)
116 goto go_right;
117 goto non_unique;
118
119 go_left:
120 p = &(*p)->rb_left;
121 continue;
122 go_right:
123 p = &(*p)->rb_right;
124 }
125
126 rb_link_node(&key->node, parent, p);
127 rb_insert_color(&key->node, &nfs_fscache_keys);
128 spin_unlock(&nfs_fscache_keys_lock);
129 nfss->fscache_key = key;
130
131 /* create a cache index for looking up filehandles */
132 nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
133 &nfs_fscache_super_index_def,
134 nfss);
135 dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
136 nfss, nfss->fscache);
137 return;
138
139non_unique:
140 spin_unlock(&nfs_fscache_keys_lock);
141 kfree(key);
142 nfss->fscache_key = NULL;
143 nfss->fscache = NULL;
144 printk(KERN_WARNING "NFS:"
145 " Cache request denied due to non-unique superblock keys\n");
146}
147
148/*
149 * release a per-superblock cookie
150 */
151void nfs_fscache_release_super_cookie(struct super_block *sb)
152{
153 struct nfs_server *nfss = NFS_SB(sb);
154
155 dfprintk(FSCACHE, "NFS: releasing superblock cookie (0x%p/0x%p)\n",
156 nfss, nfss->fscache);
157
158 fscache_relinquish_cookie(nfss->fscache, 0);
159 nfss->fscache = NULL;
160
161 if (nfss->fscache_key) {
162 spin_lock(&nfs_fscache_keys_lock);
163 rb_erase(&nfss->fscache_key->node, &nfs_fscache_keys);
164 spin_unlock(&nfs_fscache_keys_lock);
165 kfree(nfss->fscache_key);
166 nfss->fscache_key = NULL;
167 }
168}