diff options
Diffstat (limited to 'fs/nfs/pnfs_dev.c')
-rw-r--r-- | fs/nfs/pnfs_dev.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index aa2ec0015183..2961fcd7a2df 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
@@ -149,6 +149,8 @@ nfs4_get_device_info(struct nfs_server *server, | |||
149 | */ | 149 | */ |
150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, | 150 | d = server->pnfs_curr_ld->alloc_deviceid_node(server, pdev, |
151 | gfp_flags); | 151 | gfp_flags); |
152 | if (d && pdev->nocache) | ||
153 | set_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
152 | 154 | ||
153 | out_free_pages: | 155 | out_free_pages: |
154 | for (i = 0; i < max_pages; i++) | 156 | for (i = 0; i < max_pages; i++) |
@@ -175,8 +177,8 @@ __nfs4_find_get_deviceid(struct nfs_server *server, | |||
175 | rcu_read_lock(); | 177 | rcu_read_lock(); |
176 | d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, | 178 | d = _lookup_deviceid(server->pnfs_curr_ld, server->nfs_client, id, |
177 | hash); | 179 | hash); |
178 | if (d != NULL) | 180 | if (d != NULL && !atomic_inc_not_zero(&d->ref)) |
179 | atomic_inc(&d->ref); | 181 | d = NULL; |
180 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
181 | return d; | 183 | return d; |
182 | } | 184 | } |
@@ -235,12 +237,11 @@ nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld, | |||
235 | return; | 237 | return; |
236 | } | 238 | } |
237 | hlist_del_init_rcu(&d->node); | 239 | hlist_del_init_rcu(&d->node); |
240 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
238 | spin_unlock(&nfs4_deviceid_lock); | 241 | spin_unlock(&nfs4_deviceid_lock); |
239 | synchronize_rcu(); | ||
240 | 242 | ||
241 | /* balance the initial ref set in pnfs_insert_deviceid */ | 243 | /* balance the initial ref set in pnfs_insert_deviceid */ |
242 | if (atomic_dec_and_test(&d->ref)) | 244 | nfs4_put_deviceid_node(d); |
243 | d->ld->free_deviceid_node(d); | ||
244 | } | 245 | } |
245 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); | 246 | EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); |
246 | 247 | ||
@@ -271,6 +272,11 @@ EXPORT_SYMBOL_GPL(nfs4_init_deviceid_node); | |||
271 | bool | 272 | bool |
272 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) | 273 | nfs4_put_deviceid_node(struct nfs4_deviceid_node *d) |
273 | { | 274 | { |
275 | if (test_bit(NFS_DEVICEID_NOCACHE, &d->flags)) { | ||
276 | if (atomic_add_unless(&d->ref, -1, 2)) | ||
277 | return false; | ||
278 | nfs4_delete_deviceid(d->ld, d->nfs_client, &d->deviceid); | ||
279 | } | ||
274 | if (!atomic_dec_and_test(&d->ref)) | 280 | if (!atomic_dec_and_test(&d->ref)) |
275 | return false; | 281 | return false; |
276 | d->ld->free_deviceid_node(d); | 282 | d->ld->free_deviceid_node(d); |
@@ -314,6 +320,7 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash) | |||
314 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | 320 | if (d->nfs_client == clp && atomic_read(&d->ref)) { |
315 | hlist_del_init_rcu(&d->node); | 321 | hlist_del_init_rcu(&d->node); |
316 | hlist_add_head(&d->tmpnode, &tmp); | 322 | hlist_add_head(&d->tmpnode, &tmp); |
323 | clear_bit(NFS_DEVICEID_NOCACHE, &d->flags); | ||
317 | } | 324 | } |
318 | rcu_read_unlock(); | 325 | rcu_read_unlock(); |
319 | spin_unlock(&nfs4_deviceid_lock); | 326 | spin_unlock(&nfs4_deviceid_lock); |
@@ -321,12 +328,10 @@ _deviceid_purge_client(const struct nfs_client *clp, long hash) | |||
321 | if (hlist_empty(&tmp)) | 328 | if (hlist_empty(&tmp)) |
322 | return; | 329 | return; |
323 | 330 | ||
324 | synchronize_rcu(); | ||
325 | while (!hlist_empty(&tmp)) { | 331 | while (!hlist_empty(&tmp)) { |
326 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); | 332 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); |
327 | hlist_del(&d->tmpnode); | 333 | hlist_del(&d->tmpnode); |
328 | if (atomic_dec_and_test(&d->ref)) | 334 | nfs4_put_deviceid_node(d); |
329 | d->ld->free_deviceid_node(d); | ||
330 | } | 335 | } |
331 | } | 336 | } |
332 | 337 | ||