aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-12-23 20:33:04 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-01-06 14:57:46 -0500
commitd3978bb325510f0a26ebd92f211b36c5f98b2306 (patch)
tree5d376fef966d242cb61df1bcfaefeec1e71663d4 /fs
parentdda4b225623f316335052828c24a16e2da313f8f (diff)
NFS: Move cl_delegations to the nfs_server struct
Delegations are per-inode, not per-nfs_client. When a server file system is migrated, delegations on the client must be moved from the source to the destination nfs_server. Make it easier to manage a mount point's delegation list across a migration event by moving the list to the nfs_server struct. Clean up: I added documenting comments to public functions I changed in this patch. For consistency I added comments to all the other public functions in fs/nfs/delegation.c. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/client.c2
-rw-r--r--fs/nfs/delegation.c337
-rw-r--r--fs/nfs/delegation.h1
-rw-r--r--fs/nfs/nfs4renewd.c2
4 files changed, 250 insertions, 92 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 32b5fbfab35..192f2f86026 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -172,7 +172,6 @@ static struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_
172 if (err) 172 if (err)
173 goto error_cleanup; 173 goto error_cleanup;
174 174
175 INIT_LIST_HEAD(&clp->cl_delegations);
176 spin_lock_init(&clp->cl_lock); 175 spin_lock_init(&clp->cl_lock);
177 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state); 176 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
178 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client"); 177 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
@@ -1040,6 +1039,7 @@ static struct nfs_server *nfs_alloc_server(void)
1040 /* Zero out the NFS state stuff */ 1039 /* Zero out the NFS state stuff */
1041 INIT_LIST_HEAD(&server->client_link); 1040 INIT_LIST_HEAD(&server->client_link);
1042 INIT_LIST_HEAD(&server->master_link); 1041 INIT_LIST_HEAD(&server->master_link);
1042 INIT_LIST_HEAD(&server->delegations);
1043 1043
1044 atomic_set(&server->active, 0); 1044 atomic_set(&server->active, 0);
1045 1045
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index 521d71b8182..364e4328f39 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -40,11 +40,23 @@ static void nfs_free_delegation(struct nfs_delegation *delegation)
40 call_rcu(&delegation->rcu, nfs_free_delegation_callback); 40 call_rcu(&delegation->rcu, nfs_free_delegation_callback);
41} 41}
42 42
43/**
44 * nfs_mark_delegation_referenced - set delegation's REFERENCED flag
45 * @delegation: delegation to process
46 *
47 */
43void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) 48void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
44{ 49{
45 set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags); 50 set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags);
46} 51}
47 52
53/**
54 * nfs_have_delegation - check if inode has a delegation
55 * @inode: inode to check
56 * @flags: delegation types to check for
57 *
58 * Returns one if inode has the indicated delegation, otherwise zero.
59 */
48int nfs_have_delegation(struct inode *inode, fmode_t flags) 60int nfs_have_delegation(struct inode *inode, fmode_t flags)
49{ 61{
50 struct nfs_delegation *delegation; 62 struct nfs_delegation *delegation;
@@ -119,10 +131,15 @@ again:
119 return 0; 131 return 0;
120} 132}
121 133
122/* 134/**
123 * Set up a delegation on an inode 135 * nfs_inode_reclaim_delegation - process a delegation reclaim request
136 * @inode: inode to process
137 * @cred: credential to use for request
138 * @res: new delegation state from server
139 *
124 */ 140 */
125void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 141void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
142 struct nfs_openres *res)
126{ 143{
127 struct nfs_delegation *delegation; 144 struct nfs_delegation *delegation;
128 struct rpc_cred *oldcred = NULL; 145 struct rpc_cred *oldcred = NULL;
@@ -177,11 +194,11 @@ static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation
177 194
178static struct nfs_delegation * 195static struct nfs_delegation *
179nfs_detach_delegation_locked(struct nfs_inode *nfsi, 196nfs_detach_delegation_locked(struct nfs_inode *nfsi,
180 struct nfs_client *clp) 197 struct nfs_server *server)
181{ 198{
182 struct nfs_delegation *delegation = 199 struct nfs_delegation *delegation =
183 rcu_dereference_protected(nfsi->delegation, 200 rcu_dereference_protected(nfsi->delegation,
184 lockdep_is_held(&clp->cl_lock)); 201 lockdep_is_held(&server->nfs_client->cl_lock));
185 202
186 if (delegation == NULL) 203 if (delegation == NULL)
187 goto nomatch; 204 goto nomatch;
@@ -198,22 +215,29 @@ nomatch:
198} 215}
199 216
200static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi, 217static struct nfs_delegation *nfs_detach_delegation(struct nfs_inode *nfsi,
201 struct nfs_client *clp) 218 struct nfs_server *server)
202{ 219{
220 struct nfs_client *clp = server->nfs_client;
203 struct nfs_delegation *delegation; 221 struct nfs_delegation *delegation;
204 222
205 spin_lock(&clp->cl_lock); 223 spin_lock(&clp->cl_lock);
206 delegation = nfs_detach_delegation_locked(nfsi, clp); 224 delegation = nfs_detach_delegation_locked(nfsi, server);
207 spin_unlock(&clp->cl_lock); 225 spin_unlock(&clp->cl_lock);
208 return delegation; 226 return delegation;
209} 227}
210 228
211/* 229/**
212 * Set up a delegation on an inode 230 * nfs_inode_set_delegation - set up a delegation on an inode
231 * @inode: inode to which delegation applies
232 * @cred: cred to use for subsequent delegation processing
233 * @res: new delegation state from server
234 *
235 * Returns zero on success, or a negative errno value.
213 */ 236 */
214int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res) 237int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
215{ 238{
216 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 239 struct nfs_server *server = NFS_SERVER(inode);
240 struct nfs_client *clp = server->nfs_client;
217 struct nfs_inode *nfsi = NFS_I(inode); 241 struct nfs_inode *nfsi = NFS_I(inode);
218 struct nfs_delegation *delegation, *old_delegation; 242 struct nfs_delegation *delegation, *old_delegation;
219 struct nfs_delegation *freeme = NULL; 243 struct nfs_delegation *freeme = NULL;
@@ -234,7 +258,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
234 258
235 spin_lock(&clp->cl_lock); 259 spin_lock(&clp->cl_lock);
236 old_delegation = rcu_dereference_protected(nfsi->delegation, 260 old_delegation = rcu_dereference_protected(nfsi->delegation,
237 lockdep_is_held(&clp->cl_lock)); 261 lockdep_is_held(&clp->cl_lock));
238 if (old_delegation != NULL) { 262 if (old_delegation != NULL) {
239 if (memcmp(&delegation->stateid, &old_delegation->stateid, 263 if (memcmp(&delegation->stateid, &old_delegation->stateid,
240 sizeof(old_delegation->stateid)) == 0 && 264 sizeof(old_delegation->stateid)) == 0 &&
@@ -253,9 +277,9 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
253 delegation = NULL; 277 delegation = NULL;
254 goto out; 278 goto out;
255 } 279 }
256 freeme = nfs_detach_delegation_locked(nfsi, clp); 280 freeme = nfs_detach_delegation_locked(nfsi, server);
257 } 281 }
258 list_add_rcu(&delegation->super_list, &clp->cl_delegations); 282 list_add_rcu(&delegation->super_list, &server->delegations);
259 nfsi->delegation_state = delegation->type; 283 nfsi->delegation_state = delegation->type;
260 rcu_assign_pointer(nfsi->delegation, delegation); 284 rcu_assign_pointer(nfsi->delegation, delegation);
261 delegation = NULL; 285 delegation = NULL;
@@ -297,67 +321,85 @@ out:
297 return err; 321 return err;
298} 322}
299 323
300/* 324/**
301 * Return all delegations that have been marked for return 325 * nfs_client_return_marked_delegations - return previously marked delegations
326 * @clp: nfs_client to process
327 *
328 * Returns zero on success, or a negative errno value.
302 */ 329 */
303int nfs_client_return_marked_delegations(struct nfs_client *clp) 330int nfs_client_return_marked_delegations(struct nfs_client *clp)
304{ 331{
305 struct nfs_delegation *delegation; 332 struct nfs_delegation *delegation;
333 struct nfs_server *server;
306 struct inode *inode; 334 struct inode *inode;
307 int err = 0; 335 int err = 0;
308 336
309restart: 337restart:
310 rcu_read_lock(); 338 rcu_read_lock();
311 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 339 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
312 if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags)) 340 list_for_each_entry_rcu(delegation, &server->delegations,
313 continue; 341 super_list) {
314 inode = nfs_delegation_grab_inode(delegation); 342 if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
315 if (inode == NULL) 343 &delegation->flags))
316 continue; 344 continue;
317 delegation = nfs_detach_delegation(NFS_I(inode), clp); 345 inode = nfs_delegation_grab_inode(delegation);
318 rcu_read_unlock(); 346 if (inode == NULL)
319 if (delegation != NULL) { 347 continue;
320 filemap_flush(inode->i_mapping); 348 delegation = nfs_detach_delegation(NFS_I(inode),
321 err = __nfs_inode_return_delegation(inode, delegation, 0); 349 server);
350 rcu_read_unlock();
351
352 if (delegation != NULL) {
353 filemap_flush(inode->i_mapping);
354 err = __nfs_inode_return_delegation(inode,
355 delegation, 0);
356 }
357 iput(inode);
358 if (!err)
359 goto restart;
360 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
361 return err;
322 } 362 }
323 iput(inode);
324 if (!err)
325 goto restart;
326 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
327 return err;
328 } 363 }
329 rcu_read_unlock(); 364 rcu_read_unlock();
330 return 0; 365 return 0;
331} 366}
332 367
333/* 368/**
334 * This function returns the delegation without reclaiming opens 369 * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
335 * or protecting against delegation reclaims. 370 * @inode: inode to process
336 * It is therefore really only safe to be called from 371 *
337 * nfs4_clear_inode() 372 * Does not protect against delegation reclaims, therefore really only safe
373 * to be called from nfs4_clear_inode().
338 */ 374 */
339void nfs_inode_return_delegation_noreclaim(struct inode *inode) 375void nfs_inode_return_delegation_noreclaim(struct inode *inode)
340{ 376{
341 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 377 struct nfs_server *server = NFS_SERVER(inode);
342 struct nfs_inode *nfsi = NFS_I(inode); 378 struct nfs_inode *nfsi = NFS_I(inode);
343 struct nfs_delegation *delegation; 379 struct nfs_delegation *delegation;
344 380
345 if (rcu_access_pointer(nfsi->delegation) != NULL) { 381 if (rcu_access_pointer(nfsi->delegation) != NULL) {
346 delegation = nfs_detach_delegation(nfsi, clp); 382 delegation = nfs_detach_delegation(nfsi, server);
347 if (delegation != NULL) 383 if (delegation != NULL)
348 nfs_do_return_delegation(inode, delegation, 0); 384 nfs_do_return_delegation(inode, delegation, 0);
349 } 385 }
350} 386}
351 387
388/**
389 * nfs_inode_return_delegation - synchronously return a delegation
390 * @inode: inode to process
391 *
392 * Returns zero on success, or a negative errno value.
393 */
352int nfs_inode_return_delegation(struct inode *inode) 394int nfs_inode_return_delegation(struct inode *inode)
353{ 395{
354 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 396 struct nfs_server *server = NFS_SERVER(inode);
355 struct nfs_inode *nfsi = NFS_I(inode); 397 struct nfs_inode *nfsi = NFS_I(inode);
356 struct nfs_delegation *delegation; 398 struct nfs_delegation *delegation;
357 int err = 0; 399 int err = 0;
358 400
359 if (rcu_access_pointer(nfsi->delegation) != NULL) { 401 if (rcu_access_pointer(nfsi->delegation) != NULL) {
360 delegation = nfs_detach_delegation(nfsi, clp); 402 delegation = nfs_detach_delegation(nfsi, server);
361 if (delegation != NULL) { 403 if (delegation != NULL) {
362 nfs_wb_all(inode); 404 nfs_wb_all(inode);
363 err = __nfs_inode_return_delegation(inode, delegation, 1); 405 err = __nfs_inode_return_delegation(inode, delegation, 1);
@@ -366,46 +408,61 @@ int nfs_inode_return_delegation(struct inode *inode)
366 return err; 408 return err;
367} 409}
368 410
369static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation) 411static void nfs_mark_return_delegation(struct nfs_delegation *delegation)
370{ 412{
413 struct nfs_client *clp = NFS_SERVER(delegation->inode)->nfs_client;
414
371 set_bit(NFS_DELEGATION_RETURN, &delegation->flags); 415 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
372 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); 416 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
373} 417}
374 418
375/* 419/**
376 * Return all delegations associated to a super block 420 * nfs_super_return_all_delegations - return delegations for one superblock
421 * @sb: sb to process
422 *
377 */ 423 */
378void nfs_super_return_all_delegations(struct super_block *sb) 424void nfs_super_return_all_delegations(struct super_block *sb)
379{ 425{
380 struct nfs_client *clp = NFS_SB(sb)->nfs_client; 426 struct nfs_server *server = NFS_SB(sb);
427 struct nfs_client *clp = server->nfs_client;
381 struct nfs_delegation *delegation; 428 struct nfs_delegation *delegation;
382 429
383 if (clp == NULL) 430 if (clp == NULL)
384 return; 431 return;
432
385 rcu_read_lock(); 433 rcu_read_lock();
386 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 434 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
387 spin_lock(&delegation->lock); 435 spin_lock(&delegation->lock);
388 if (delegation->inode != NULL && delegation->inode->i_sb == sb) 436 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
389 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
390 spin_unlock(&delegation->lock); 437 spin_unlock(&delegation->lock);
391 } 438 }
392 rcu_read_unlock(); 439 rcu_read_unlock();
440
393 if (nfs_client_return_marked_delegations(clp) != 0) 441 if (nfs_client_return_marked_delegations(clp) != 0)
394 nfs4_schedule_state_manager(clp); 442 nfs4_schedule_state_manager(clp);
395} 443}
396 444
397static 445static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
398void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags) 446 fmode_t flags)
399{ 447{
400 struct nfs_delegation *delegation; 448 struct nfs_delegation *delegation;
401 449
402 rcu_read_lock(); 450 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
403 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
404 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE)) 451 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
405 continue; 452 continue;
406 if (delegation->type & flags) 453 if (delegation->type & flags)
407 nfs_mark_return_delegation(clp, delegation); 454 nfs_mark_return_delegation(delegation);
408 } 455 }
456}
457
458static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp,
459 fmode_t flags)
460{
461 struct nfs_server *server;
462
463 rcu_read_lock();
464 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
465 nfs_mark_return_all_delegation_types(server, flags);
409 rcu_read_unlock(); 466 rcu_read_unlock();
410} 467}
411 468
@@ -420,19 +477,32 @@ static void nfs_delegation_run_state_manager(struct nfs_client *clp)
420 nfs4_schedule_state_manager(clp); 477 nfs4_schedule_state_manager(clp);
421} 478}
422 479
480/**
481 * nfs_expire_all_delegation_types
482 * @clp: client to process
483 * @flags: delegation types to expire
484 *
485 */
423void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags) 486void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
424{ 487{
425 nfs_client_mark_return_all_delegation_types(clp, flags); 488 nfs_client_mark_return_all_delegation_types(clp, flags);
426 nfs_delegation_run_state_manager(clp); 489 nfs_delegation_run_state_manager(clp);
427} 490}
428 491
492/**
493 * nfs_expire_all_delegations
494 * @clp: client to process
495 *
496 */
429void nfs_expire_all_delegations(struct nfs_client *clp) 497void nfs_expire_all_delegations(struct nfs_client *clp)
430{ 498{
431 nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE); 499 nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
432} 500}
433 501
434/* 502/**
435 * Return all delegations following an NFS4ERR_CB_PATH_DOWN error. 503 * nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
504 * @clp: client to process
505 *
436 */ 506 */
437void nfs_handle_cb_pathdown(struct nfs_client *clp) 507void nfs_handle_cb_pathdown(struct nfs_client *clp)
438{ 508{
@@ -441,29 +511,43 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
441 nfs_client_mark_return_all_delegations(clp); 511 nfs_client_mark_return_all_delegations(clp);
442} 512}
443 513
444static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp) 514static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
445{ 515{
446 struct nfs_delegation *delegation; 516 struct nfs_delegation *delegation;
447 517
448 rcu_read_lock(); 518 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
449 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
450 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags)) 519 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
451 continue; 520 continue;
452 nfs_mark_return_delegation(clp, delegation); 521 nfs_mark_return_delegation(delegation);
453 } 522 }
454 rcu_read_unlock();
455} 523}
456 524
525/**
526 * nfs_expire_unreferenced_delegations - Eliminate unused delegations
527 * @clp: nfs_client to process
528 *
529 */
457void nfs_expire_unreferenced_delegations(struct nfs_client *clp) 530void nfs_expire_unreferenced_delegations(struct nfs_client *clp)
458{ 531{
459 nfs_client_mark_return_unreferenced_delegations(clp); 532 struct nfs_server *server;
533
534 rcu_read_lock();
535 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
536 nfs_mark_return_unreferenced_delegations(server);
537 rcu_read_unlock();
538
460 nfs_delegation_run_state_manager(clp); 539 nfs_delegation_run_state_manager(clp);
461} 540}
462 541
463/* 542/**
464 * Asynchronous delegation recall! 543 * nfs_async_inode_return_delegation - asynchronously return a delegation
544 * @inode: inode to process
545 * @stateid: state ID information from CB_RECALL arguments
546 *
547 * Returns zero on success, or a negative errno value.
465 */ 548 */
466int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid) 549int nfs_async_inode_return_delegation(struct inode *inode,
550 const nfs4_stateid *stateid)
467{ 551{
468 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client; 552 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
469 struct nfs_delegation *delegation; 553 struct nfs_delegation *delegation;
@@ -475,22 +559,21 @@ int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *s
475 rcu_read_unlock(); 559 rcu_read_unlock();
476 return -ENOENT; 560 return -ENOENT;
477 } 561 }
478 562 nfs_mark_return_delegation(delegation);
479 nfs_mark_return_delegation(clp, delegation);
480 rcu_read_unlock(); 563 rcu_read_unlock();
564
481 nfs_delegation_run_state_manager(clp); 565 nfs_delegation_run_state_manager(clp);
482 return 0; 566 return 0;
483} 567}
484 568
485/* 569static struct inode *
486 * Retrieve the inode associated with a delegation 570nfs_delegation_find_inode_server(struct nfs_server *server,
487 */ 571 const struct nfs_fh *fhandle)
488struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
489{ 572{
490 struct nfs_delegation *delegation; 573 struct nfs_delegation *delegation;
491 struct inode *res = NULL; 574 struct inode *res = NULL;
492 rcu_read_lock(); 575
493 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 576 list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
494 spin_lock(&delegation->lock); 577 spin_lock(&delegation->lock);
495 if (delegation->inode != NULL && 578 if (delegation->inode != NULL &&
496 nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) { 579 nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
@@ -500,47 +583,121 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
500 if (res != NULL) 583 if (res != NULL)
501 break; 584 break;
502 } 585 }
586 return res;
587}
588
589/**
590 * nfs_delegation_find_inode - retrieve the inode associated with a delegation
591 * @clp: client state handle
592 * @fhandle: filehandle from a delegation recall
593 *
594 * Returns pointer to inode matching "fhandle," or NULL if a matching inode
595 * cannot be found.
596 */
597struct inode *nfs_delegation_find_inode(struct nfs_client *clp,
598 const struct nfs_fh *fhandle)
599{
600 struct nfs_server *server;
601 struct inode *res = NULL;
602
603 rcu_read_lock();
604 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
605 res = nfs_delegation_find_inode_server(server, fhandle);
606 if (res != NULL)
607 break;
608 }
503 rcu_read_unlock(); 609 rcu_read_unlock();
504 return res; 610 return res;
505} 611}
506 612
507/* 613static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
508 * Mark all delegations as needing to be reclaimed 614{
615 struct nfs_delegation *delegation;
616
617 list_for_each_entry_rcu(delegation, &server->delegations, super_list)
618 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
619}
620
621/**
622 * nfs_delegation_mark_reclaim - mark all delegations as needing to be reclaimed
623 * @clp: nfs_client to process
624 *
509 */ 625 */
510void nfs_delegation_mark_reclaim(struct nfs_client *clp) 626void nfs_delegation_mark_reclaim(struct nfs_client *clp)
511{ 627{
512 struct nfs_delegation *delegation; 628 struct nfs_server *server;
629
513 rcu_read_lock(); 630 rcu_read_lock();
514 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) 631 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
515 set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags); 632 nfs_delegation_mark_reclaim_server(server);
516 rcu_read_unlock(); 633 rcu_read_unlock();
517} 634}
518 635
519/* 636/**
520 * Reap all unclaimed delegations after reboot recovery is done 637 * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
638 * @clp: nfs_client to process
639 *
521 */ 640 */
522void nfs_delegation_reap_unclaimed(struct nfs_client *clp) 641void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
523{ 642{
524 struct nfs_delegation *delegation; 643 struct nfs_delegation *delegation;
644 struct nfs_server *server;
525 struct inode *inode; 645 struct inode *inode;
646
526restart: 647restart:
527 rcu_read_lock(); 648 rcu_read_lock();
528 list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) { 649 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
529 if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0) 650 list_for_each_entry_rcu(delegation, &server->delegations,
530 continue; 651 super_list) {
531 inode = nfs_delegation_grab_inode(delegation); 652 if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
532 if (inode == NULL) 653 &delegation->flags) == 0)
533 continue; 654 continue;
534 delegation = nfs_detach_delegation(NFS_I(inode), clp); 655 inode = nfs_delegation_grab_inode(delegation);
535 rcu_read_unlock(); 656 if (inode == NULL)
536 if (delegation != NULL) 657 continue;
537 nfs_free_delegation(delegation); 658 delegation = nfs_detach_delegation(NFS_I(inode),
538 iput(inode); 659 server);
539 goto restart; 660 rcu_read_unlock();
661
662 if (delegation != NULL)
663 nfs_free_delegation(delegation);
664 iput(inode);
665 goto restart;
666 }
540 } 667 }
541 rcu_read_unlock(); 668 rcu_read_unlock();
542} 669}
543 670
671/**
672 * nfs_delegations_present - check for existence of delegations
673 * @clp: client state handle
674 *
675 * Returns one if there are any nfs_delegation structures attached
676 * to this nfs_client.
677 */
678int nfs_delegations_present(struct nfs_client *clp)
679{
680 struct nfs_server *server;
681 int ret = 0;
682
683 rcu_read_lock();
684 list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
685 if (!list_empty(&server->delegations)) {
686 ret = 1;
687 break;
688 }
689 rcu_read_unlock();
690 return ret;
691}
692
693/**
694 * nfs4_copy_delegation_stateid - Copy inode's state ID information
695 * @dst: stateid data structure to fill in
696 * @inode: inode to check
697 *
698 * Returns one and fills in "dst->data" * if inode had a delegation,
699 * otherwise zero is returned.
700 */
544int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode) 701int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
545{ 702{
546 struct nfs_inode *nfsi = NFS_I(inode); 703 struct nfs_inode *nfsi = NFS_I(inode);
diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h
index 2026304bda1..d9322e490c5 100644
--- a/fs/nfs/delegation.h
+++ b/fs/nfs/delegation.h
@@ -44,6 +44,7 @@ void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags);
44void nfs_expire_unreferenced_delegations(struct nfs_client *clp); 44void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
45void nfs_handle_cb_pathdown(struct nfs_client *clp); 45void nfs_handle_cb_pathdown(struct nfs_client *clp);
46int nfs_client_return_marked_delegations(struct nfs_client *clp); 46int nfs_client_return_marked_delegations(struct nfs_client *clp);
47int nfs_delegations_present(struct nfs_client *clp);
47 48
48void nfs_delegation_mark_reclaim(struct nfs_client *clp); 49void nfs_delegation_mark_reclaim(struct nfs_client *clp);
49void nfs_delegation_reap_unclaimed(struct nfs_client *clp); 50void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c
index cde5650ee5a..402143d75fc 100644
--- a/fs/nfs/nfs4renewd.c
+++ b/fs/nfs/nfs4renewd.c
@@ -80,7 +80,7 @@ nfs4_renew_state(struct work_struct *work)
80 cred = ops->get_state_renewal_cred_locked(clp); 80 cred = ops->get_state_renewal_cred_locked(clp);
81 spin_unlock(&clp->cl_lock); 81 spin_unlock(&clp->cl_lock);
82 if (cred == NULL) { 82 if (cred == NULL) {
83 if (list_empty(&clp->cl_delegations)) { 83 if (!nfs_delegations_present(clp)) {
84 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); 84 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
85 goto out; 85 goto out;
86 } 86 }