aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/delegation.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 15:21:46 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-12-23 15:21:46 -0500
commit515d86117724abe39d7d57d7ccc7cc5c44480529 (patch)
treedce297acebc94355217219893a5c6a81ca281ff7 /fs/nfs/delegation.c
parent9e33bed55239bdcee1746c31a11177d239bac1b5 (diff)
NFSv4: Clean up the support for returning multiple delegations
Add a flag to mark delegations as requiring return, then run a garbage collector. In the future, this will allow for more flexible delegation management, where delegations may be marked for return if it turns out that they are not being referenced. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/delegation.c')
-rw-r--r--fs/nfs/delegation.c97
1 files changed, 45 insertions, 52 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 {