aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/delegation.c97
-rw-r--r--fs/nfs/delegation.h8
-rw-r--r--fs/nfs/super.c2
3 files changed, 52 insertions, 55 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index ebc06f2da31a..bc9d4f9a788d 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -256,6 +256,34 @@ static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegat
256} 256}
257 257
258/* 258/*
259 * Return all delegations that have been marked for return
260 */
261static void nfs_client_return_marked_delegations(struct nfs_client *clp)
262{
263 struct nfs_delegation *delegation;
264 struct inode *inode;
265
266restart:
267 rcu_read_lock();
268 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
269 if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
270 continue;
271 inode = nfs_delegation_grab_inode(delegation);
272 if (inode == NULL)
273 continue;
274 spin_lock(&clp->cl_lock);
275 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
276 spin_unlock(&clp->cl_lock);
277 rcu_read_unlock();
278 if (delegation != NULL)
279 __nfs_inode_return_delegation(inode, delegation);
280 iput(inode);
281 goto restart;
282 }
283 rcu_read_unlock();
284}
285
286/*
259 * This function returns the delegation without reclaiming opens 287 * This function returns the delegation without reclaiming opens
260 * or protecting against delegation reclaims. 288 * or protecting against delegation reclaims.
261 * It is therefore really only safe to be called from 289 * It is therefore really only safe to be called from
@@ -296,63 +324,46 @@ int nfs_inode_return_delegation(struct inode *inode)
296/* 324/*
297 * Return all delegations associated to a super block 325 * Return all delegations associated to a super block
298 */ 326 */
299void nfs_return_all_delegations(struct super_block *sb) 327void nfs_super_return_all_delegations(struct super_block *sb)
300{ 328{
301 struct nfs_client *clp = NFS_SB(sb)->nfs_client; 329 struct nfs_client *clp = NFS_SB(sb)->nfs_client;
302 struct nfs_delegation *delegation; 330 struct nfs_delegation *delegation;
303 struct inode *inode;
304 331
305 if (clp == NULL) 332 if (clp == NULL)
306 return; 333 return;
307restart:
308 rcu_read_lock(); 334 rcu_read_lock();
309 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 335 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
310 inode = NULL;
311 spin_lock(&delegation->lock); 336 spin_lock(&delegation->lock);
312 if (delegation->inode != NULL && delegation->inode->i_sb == sb) 337 if (delegation->inode != NULL && delegation->inode->i_sb == sb)
313 inode = igrab(delegation->inode); 338 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
314 spin_unlock(&delegation->lock); 339 spin_unlock(&delegation->lock);
315 if (inode == NULL)
316 continue;
317 spin_lock(&clp->cl_lock);
318 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
319 spin_unlock(&clp->cl_lock);
320 rcu_read_unlock();
321 if (delegation != NULL)
322 __nfs_inode_return_delegation(inode, delegation);
323 iput(inode);
324 goto restart;
325 } 340 }
326 rcu_read_unlock(); 341 rcu_read_unlock();
342 nfs_client_return_marked_delegations(clp);
343}
344
345static void nfs_client_return_all_delegations(struct nfs_client *clp)
346{
347 struct nfs_delegation *delegation;
348
349 rcu_read_lock();
350 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
351 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
352 rcu_read_unlock();
353 nfs_client_return_marked_delegations(clp);
327} 354}
328 355
329static int nfs_do_expire_all_delegations(void *ptr) 356static int nfs_do_expire_all_delegations(void *ptr)
330{ 357{
331 struct nfs_client *clp = ptr; 358 struct nfs_client *clp = ptr;
332 struct nfs_delegation *delegation;
333 struct inode *inode;
334 359
335 allow_signal(SIGKILL); 360 allow_signal(SIGKILL);
336restart: 361
337 if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0) 362 if (test_bit(NFS4CLNT_STATE_RECOVER, &clp->cl_state) != 0)
338 goto out; 363 goto out;
339 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0) 364 if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) == 0)
340 goto out; 365 goto out;
341 rcu_read_lock(); 366 nfs_client_return_all_delegations(clp);
342 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
343 inode = nfs_delegation_grab_inode(delegation);
344 if (inode == NULL)
345 continue;
346 spin_lock(&clp->cl_lock);
347 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
348 spin_unlock(&clp->cl_lock);
349 rcu_read_unlock();
350 if (delegation)
351 __nfs_inode_return_delegation(inode, delegation);
352 iput(inode);
353 goto restart;
354 }
355 rcu_read_unlock();
356out: 367out:
357 nfs_put_client(clp); 368 nfs_put_client(clp);
358 module_put_and_exit(0); 369 module_put_and_exit(0);
@@ -379,27 +390,9 @@ void nfs_expire_all_delegations(struct nfs_client *clp)
379 */ 390 */
380void nfs_handle_cb_pathdown(struct nfs_client *clp) 391void nfs_handle_cb_pathdown(struct nfs_client *clp)
381{ 392{
382 struct nfs_delegation *delegation;
383 struct inode *inode;
384
385 if (clp == NULL) 393 if (clp == NULL)
386 return; 394 return;
387restart: 395 nfs_client_return_all_delegations(clp);
388 rcu_read_lock();
389 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
390 inode = nfs_delegation_grab_inode(delegation);
391 if (inode == NULL)
392 continue;
393 spin_lock(&clp->cl_lock);
394 delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
395 spin_unlock(&clp->cl_lock);
396 rcu_read_unlock();
397 if (delegation != NULL)
398 __nfs_inode_return_delegation(inode, delegation);
399 iput(inode);
400 goto restart;
401 }
402 rcu_read_unlock();
403} 396}
404 397
405struct recall_threadargs { 398struct recall_threadargs {
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 5e9f40e0a7d8..c772bab12eea 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -20,12 +20,16 @@ struct nfs_delegation {
20 int type; 20 int type;
21 loff_t maxsize; 21 loff_t maxsize;
22 __u64 change_attr; 22 __u64 change_attr;
23#define NFS_DELEGATION_NEED_RECLAIM 0
24 unsigned long flags; 23 unsigned long flags;
25 spinlock_t lock; 24 spinlock_t lock;
26 struct rcu_head rcu; 25 struct rcu_head rcu;
27}; 26};
28 27
28enum {
29 NFS_DELEGATION_NEED_RECLAIM = 0,
30 NFS_DELEGATION_RETURN,
31};
32
29int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); 33int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
30void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res); 34void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);
31int nfs_inode_return_delegation(struct inode *inode); 35int nfs_inode_return_delegation(struct inode *inode);
@@ -33,7 +37,7 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
33void nfs_inode_return_delegation_noreclaim(struct inode *inode); 37void nfs_inode_return_delegation_noreclaim(struct inode *inode);
34 38
35struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle); 39struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle);
36void nfs_return_all_delegations(struct super_block *sb); 40void nfs_super_return_all_delegations(struct super_block *sb);
37void nfs_expire_all_delegations(struct nfs_client *clp); 41void nfs_expire_all_delegations(struct nfs_client *clp);
38void nfs_handle_cb_pathdown(struct nfs_client *clp); 42void nfs_handle_cb_pathdown(struct nfs_client *clp);
39 43
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index d8e062fe76b1..bd4c3dd550df 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2433,7 +2433,7 @@ static void nfs4_kill_super(struct super_block *sb)
2433{ 2433{
2434 struct nfs_server *server = NFS_SB(sb); 2434 struct nfs_server *server = NFS_SB(sb);
2435 2435
2436 nfs_return_all_delegations(sb); 2436 nfs_super_return_all_delegations(sb);
2437 kill_anon_super(sb); 2437 kill_anon_super(sb);
2438 2438
2439 nfs4_renewd_prepare_shutdown(server); 2439 nfs4_renewd_prepare_shutdown(server);