aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs_dev.c
diff options
context:
space:
mode:
authorJiri Kosina <jkosina@suse.cz>2011-07-11 08:15:48 -0400
committerJiri Kosina <jkosina@suse.cz>2011-07-11 08:15:55 -0400
commitb7e9c223be8ce335e30f2cf6ba588e6a4092275c (patch)
tree2d1e3b75606abc18df7ad65e51ac3f90cd68b38d /fs/nfs/pnfs_dev.c
parentc172d82500a6cf3c32d1e650722a1055d72ce858 (diff)
parente3bbfa78bab125f58b831b5f7f45b5a305091d72 (diff)
Merge branch 'master' into for-next
Sync with Linus' tree to be able to apply pending patches that are based on newer code already present upstream.
Diffstat (limited to 'fs/nfs/pnfs_dev.c')
-rw-r--r--fs/nfs/pnfs_dev.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index c65e133ce9c0..f0f8e1e22f6c 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -174,6 +174,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,
174 const struct nfs4_deviceid *id) 174 const struct nfs4_deviceid *id)
175{ 175{
176 INIT_HLIST_NODE(&d->node); 176 INIT_HLIST_NODE(&d->node);
177 INIT_HLIST_NODE(&d->tmpnode);
177 d->ld = ld; 178 d->ld = ld;
178 d->nfs_client = nfs_client; 179 d->nfs_client = nfs_client;
179 d->deviceid = *id; 180 d->deviceid = *id;
@@ -208,6 +209,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new)
208 209
209 hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); 210 hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]);
210 spin_unlock(&nfs4_deviceid_lock); 211 spin_unlock(&nfs4_deviceid_lock);
212 atomic_inc(&new->ref);
211 213
212 return new; 214 return new;
213} 215}
@@ -238,24 +240,29 @@ static void
238_deviceid_purge_client(const struct nfs_client *clp, long hash) 240_deviceid_purge_client(const struct nfs_client *clp, long hash)
239{ 241{
240 struct nfs4_deviceid_node *d; 242 struct nfs4_deviceid_node *d;
241 struct hlist_node *n, *next; 243 struct hlist_node *n;
242 HLIST_HEAD(tmp); 244 HLIST_HEAD(tmp);
243 245
246 spin_lock(&nfs4_deviceid_lock);
244 rcu_read_lock(); 247 rcu_read_lock();
245 hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) 248 hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node)
246 if (d->nfs_client == clp && atomic_read(&d->ref)) { 249 if (d->nfs_client == clp && atomic_read(&d->ref)) {
247 hlist_del_init_rcu(&d->node); 250 hlist_del_init_rcu(&d->node);
248 hlist_add_head(&d->node, &tmp); 251 hlist_add_head(&d->tmpnode, &tmp);
249 } 252 }
250 rcu_read_unlock(); 253 rcu_read_unlock();
254 spin_unlock(&nfs4_deviceid_lock);
251 255
252 if (hlist_empty(&tmp)) 256 if (hlist_empty(&tmp))
253 return; 257 return;
254 258
255 synchronize_rcu(); 259 synchronize_rcu();
256 hlist_for_each_entry_safe(d, n, next, &tmp, node) 260 while (!hlist_empty(&tmp)) {
261 d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode);
262 hlist_del(&d->tmpnode);
257 if (atomic_dec_and_test(&d->ref)) 263 if (atomic_dec_and_test(&d->ref))
258 d->ld->free_deviceid_node(d); 264 d->ld->free_deviceid_node(d);
265 }
259} 266}
260 267
261void 268void
@@ -263,8 +270,8 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp)
263{ 270{
264 long h; 271 long h;
265 272
266 spin_lock(&nfs4_deviceid_lock); 273 if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_MDS))
274 return;
267 for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) 275 for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)
268 _deviceid_purge_client(clp, h); 276 _deviceid_purge_client(clp, h);
269 spin_unlock(&nfs4_deviceid_lock);
270} 277}