Commit d3978bb325510f0a26ebd92f211b36c5f98b2306

Authored by Chuck Lever
Committed by Trond Myklebust
1 parent dda4b22562

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>

Showing 5 changed files with 251 additions and 93 deletions Side-by-side Diff

... ... @@ -172,7 +172,6 @@
172 172 if (err)
173 173 goto error_cleanup;
174 174  
175   - INIT_LIST_HEAD(&clp->cl_delegations);
176 175 spin_lock_init(&clp->cl_lock);
177 176 INIT_DELAYED_WORK(&clp->cl_renewd, nfs4_renew_state);
178 177 rpc_init_wait_queue(&clp->cl_rpcwaitq, "NFS client");
... ... @@ -1040,6 +1039,7 @@
1040 1039 /* Zero out the NFS state stuff */
1041 1040 INIT_LIST_HEAD(&server->client_link);
1042 1041 INIT_LIST_HEAD(&server->master_link);
  1042 + INIT_LIST_HEAD(&server->delegations);
1043 1043  
1044 1044 atomic_set(&server->active, 0);
1045 1045  
... ... @@ -40,11 +40,23 @@
40 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 + */
43 48 void nfs_mark_delegation_referenced(struct nfs_delegation *delegation)
44 49 {
45 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 + */
48 60 int nfs_have_delegation(struct inode *inode, fmode_t flags)
49 61 {
50 62 struct nfs_delegation *delegation;
51 63  
... ... @@ -119,10 +131,15 @@
119 131 return 0;
120 132 }
121 133  
122   -/*
123   - * Set up a delegation on an inode
  134 +/**
  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 */
125   -void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res)
  141 +void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred,
  142 + struct nfs_openres *res)
126 143 {
127 144 struct nfs_delegation *delegation;
128 145 struct rpc_cred *oldcred = NULL;
129 146  
... ... @@ -177,11 +194,11 @@
177 194  
178 195 static struct nfs_delegation *
179 196 nfs_detach_delegation_locked(struct nfs_inode *nfsi,
180   - struct nfs_client *clp)
  197 + struct nfs_server *server)
181 198 {
182 199 struct nfs_delegation *delegation =
183 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 203 if (delegation == NULL)
187 204 goto nomatch;
188 205  
189 206  
190 207  
191 208  
... ... @@ -198,22 +215,29 @@
198 215 }
199 216  
200 217 static 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 221 struct nfs_delegation *delegation;
204 222  
205 223 spin_lock(&clp->cl_lock);
206   - delegation = nfs_detach_delegation_locked(nfsi, clp);
  224 + delegation = nfs_detach_delegation_locked(nfsi, server);
207 225 spin_unlock(&clp->cl_lock);
208 226 return delegation;
209 227 }
210 228  
211   -/*
212   - * Set up a delegation on an inode
  229 +/**
  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 */
214 237 int 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 241 struct nfs_inode *nfsi = NFS_I(inode);
218 242 struct nfs_delegation *delegation, *old_delegation;
219 243 struct nfs_delegation *freeme = NULL;
... ... @@ -234,7 +258,7 @@
234 258  
235 259 spin_lock(&clp->cl_lock);
236 260 old_delegation = rcu_dereference_protected(nfsi->delegation,
237   - lockdep_is_held(&clp->cl_lock));
  261 + lockdep_is_held(&clp->cl_lock));
238 262 if (old_delegation != NULL) {
239 263 if (memcmp(&delegation->stateid, &old_delegation->stateid,
240 264 sizeof(old_delegation->stateid)) == 0 &&
241 265  
... ... @@ -253,9 +277,9 @@
253 277 delegation = NULL;
254 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 283 nfsi->delegation_state = delegation->type;
260 284 rcu_assign_pointer(nfsi->delegation, delegation);
261 285 delegation = NULL;
262 286  
263 287  
264 288  
265 289  
266 290  
267 291  
268 292  
269 293  
270 294  
... ... @@ -297,67 +321,85 @@
297 321 return err;
298 322 }
299 323  
300   -/*
301   - * Return all delegations that have been marked for return
  324 +/**
  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 */
303 330 int nfs_client_return_marked_delegations(struct nfs_client *clp)
304 331 {
305 332 struct nfs_delegation *delegation;
  333 + struct nfs_server *server;
306 334 struct inode *inode;
307 335 int err = 0;
308 336  
309 337 restart:
310 338 rcu_read_lock();
311   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
312   - if (!test_and_clear_bit(NFS_DELEGATION_RETURN, &delegation->flags))
313   - continue;
314   - inode = nfs_delegation_grab_inode(delegation);
315   - if (inode == NULL)
316   - continue;
317   - delegation = nfs_detach_delegation(NFS_I(inode), clp);
318   - rcu_read_unlock();
319   - if (delegation != NULL) {
320   - filemap_flush(inode->i_mapping);
321   - err = __nfs_inode_return_delegation(inode, delegation, 0);
  339 + list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
  340 + list_for_each_entry_rcu(delegation, &server->delegations,
  341 + super_list) {
  342 + if (!test_and_clear_bit(NFS_DELEGATION_RETURN,
  343 + &delegation->flags))
  344 + continue;
  345 + inode = nfs_delegation_grab_inode(delegation);
  346 + if (inode == NULL)
  347 + continue;
  348 + delegation = nfs_detach_delegation(NFS_I(inode),
  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 364 rcu_read_unlock();
330 365 return 0;
331 366 }
332 367  
333   -/*
334   - * This function returns the delegation without reclaiming opens
335   - * or protecting against delegation reclaims.
336   - * It is therefore really only safe to be called from
337   - * nfs4_clear_inode()
  368 +/**
  369 + * nfs_inode_return_delegation_noreclaim - return delegation, don't reclaim opens
  370 + * @inode: inode to process
  371 + *
  372 + * Does not protect against delegation reclaims, therefore really only safe
  373 + * to be called from nfs4_clear_inode().
338 374 */
339 375 void 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 378 struct nfs_inode *nfsi = NFS_I(inode);
343 379 struct nfs_delegation *delegation;
344 380  
345 381 if (rcu_access_pointer(nfsi->delegation) != NULL) {
346   - delegation = nfs_detach_delegation(nfsi, clp);
  382 + delegation = nfs_detach_delegation(nfsi, server);
347 383 if (delegation != NULL)
348 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 + */
352 394 int 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 397 struct nfs_inode *nfsi = NFS_I(inode);
356 398 struct nfs_delegation *delegation;
357 399 int err = 0;
358 400  
359 401 if (rcu_access_pointer(nfsi->delegation) != NULL) {
360   - delegation = nfs_detach_delegation(nfsi, clp);
  402 + delegation = nfs_detach_delegation(nfsi, server);
361 403 if (delegation != NULL) {
362 404 nfs_wb_all(inode);
363 405 err = __nfs_inode_return_delegation(inode, delegation, 1);
364 406  
365 407  
366 408  
367 409  
368 410  
369 411  
370 412  
371 413  
372 414  
373 415  
374 416  
... ... @@ -366,46 +408,61 @@
366 408 return err;
367 409 }
368 410  
369   -static void nfs_mark_return_delegation(struct nfs_client *clp, struct nfs_delegation *delegation)
  411 +static void nfs_mark_return_delegation(struct nfs_delegation *delegation)
370 412 {
  413 + struct nfs_client *clp = NFS_SERVER(delegation->inode)->nfs_client;
  414 +
371 415 set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
372 416 set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
373 417 }
374 418  
375   -/*
376   - * Return all delegations associated to a super block
  419 +/**
  420 + * nfs_super_return_all_delegations - return delegations for one superblock
  421 + * @sb: sb to process
  422 + *
377 423 */
378 424 void 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 428 struct nfs_delegation *delegation;
382 429  
383 430 if (clp == NULL)
384 431 return;
  432 +
385 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 435 spin_lock(&delegation->lock);
388   - if (delegation->inode != NULL && delegation->inode->i_sb == sb)
389   - set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
  436 + set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
390 437 spin_unlock(&delegation->lock);
391 438 }
392 439 rcu_read_unlock();
  440 +
393 441 if (nfs_client_return_marked_delegations(clp) != 0)
394 442 nfs4_schedule_state_manager(clp);
395 443 }
396 444  
397   -static
398   -void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp, fmode_t flags)
  445 +static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
  446 + fmode_t flags)
399 447 {
400 448 struct nfs_delegation *delegation;
401 449  
402   - rcu_read_lock();
403   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
  450 + list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
404 451 if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
405 452 continue;
406 453 if (delegation->type & flags)
407   - nfs_mark_return_delegation(clp, delegation);
  454 + nfs_mark_return_delegation(delegation);
408 455 }
  456 +}
  457 +
  458 +static 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 466 rcu_read_unlock();
410 467 }
411 468  
412 469  
413 470  
... ... @@ -420,19 +477,32 @@
420 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 + */
423 486 void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
424 487 {
425 488 nfs_client_mark_return_all_delegation_types(clp, flags);
426 489 nfs_delegation_run_state_manager(clp);
427 490 }
428 491  
  492 +/**
  493 + * nfs_expire_all_delegations
  494 + * @clp: client to process
  495 + *
  496 + */
429 497 void nfs_expire_all_delegations(struct nfs_client *clp)
430 498 {
431 499 nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
432 500 }
433 501  
434   -/*
435   - * Return all delegations following an NFS4ERR_CB_PATH_DOWN error.
  502 +/**
  503 + * nfs_handle_cb_pathdown - return all delegations after NFS4ERR_CB_PATH_DOWN
  504 + * @clp: client to process
  505 + *
436 506 */
437 507 void nfs_handle_cb_pathdown(struct nfs_client *clp)
438 508 {
439 509  
440 510  
441 511  
442 512  
443 513  
444 514  
445 515  
... ... @@ -441,29 +511,43 @@
441 511 nfs_client_mark_return_all_delegations(clp);
442 512 }
443 513  
444   -static void nfs_client_mark_return_unreferenced_delegations(struct nfs_client *clp)
  514 +static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
445 515 {
446 516 struct nfs_delegation *delegation;
447 517  
448   - rcu_read_lock();
449   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
  518 + list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
450 519 if (test_and_clear_bit(NFS_DELEGATION_REFERENCED, &delegation->flags))
451 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 + */
457 530 void 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 539 nfs_delegation_run_state_manager(clp);
461 540 }
462 541  
463   -/*
464   - * Asynchronous delegation recall!
  542 +/**
  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 */
466   -int nfs_async_inode_return_delegation(struct inode *inode, const nfs4_stateid *stateid)
  549 +int nfs_async_inode_return_delegation(struct inode *inode,
  550 + const nfs4_stateid *stateid)
467 551 {
468 552 struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
469 553 struct nfs_delegation *delegation;
470 554  
471 555  
472 556  
... ... @@ -475,22 +559,21 @@
475 559 rcu_read_unlock();
476 560 return -ENOENT;
477 561 }
478   -
479   - nfs_mark_return_delegation(clp, delegation);
  562 + nfs_mark_return_delegation(delegation);
480 563 rcu_read_unlock();
  564 +
481 565 nfs_delegation_run_state_manager(clp);
482 566 return 0;
483 567 }
484 568  
485   -/*
486   - * Retrieve the inode associated with a delegation
487   - */
488   -struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs_fh *fhandle)
  569 +static struct inode *
  570 +nfs_delegation_find_inode_server(struct nfs_server *server,
  571 + const struct nfs_fh *fhandle)
489 572 {
490 573 struct nfs_delegation *delegation;
491 574 struct inode *res = NULL;
492   - rcu_read_lock();
493   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
  575 +
  576 + list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
494 577 spin_lock(&delegation->lock);
495 578 if (delegation->inode != NULL &&
496 579 nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
497 580  
498 581  
499 582  
500 583  
501 584  
502 585  
503 586  
504 587  
... ... @@ -500,47 +583,121 @@
500 583 if (res != NULL)
501 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 + */
  597 +struct 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 609 rcu_read_unlock();
504 610 return res;
505 611 }
506 612  
507   -/*
508   - * Mark all delegations as needing to be reclaimed
  613 +static void nfs_delegation_mark_reclaim_server(struct nfs_server *server)
  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 */
510 626 void nfs_delegation_mark_reclaim(struct nfs_client *clp)
511 627 {
512   - struct nfs_delegation *delegation;
  628 + struct nfs_server *server;
  629 +
513 630 rcu_read_lock();
514   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
515   - set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
  631 + list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
  632 + nfs_delegation_mark_reclaim_server(server);
516 633 rcu_read_unlock();
517 634 }
518 635  
519   -/*
520   - * Reap all unclaimed delegations after reboot recovery is done
  636 +/**
  637 + * nfs_delegation_reap_unclaimed - reap unclaimed delegations after reboot recovery is done
  638 + * @clp: nfs_client to process
  639 + *
521 640 */
522 641 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
523 642 {
524 643 struct nfs_delegation *delegation;
  644 + struct nfs_server *server;
525 645 struct inode *inode;
  646 +
526 647 restart:
527 648 rcu_read_lock();
528   - list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
529   - if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0)
530   - continue;
531   - inode = nfs_delegation_grab_inode(delegation);
532   - if (inode == NULL)
533   - continue;
534   - delegation = nfs_detach_delegation(NFS_I(inode), clp);
535   - rcu_read_unlock();
536   - if (delegation != NULL)
537   - nfs_free_delegation(delegation);
538   - iput(inode);
539   - goto restart;
  649 + list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
  650 + list_for_each_entry_rcu(delegation, &server->delegations,
  651 + super_list) {
  652 + if (test_bit(NFS_DELEGATION_NEED_RECLAIM,
  653 + &delegation->flags) == 0)
  654 + continue;
  655 + inode = nfs_delegation_grab_inode(delegation);
  656 + if (inode == NULL)
  657 + continue;
  658 + delegation = nfs_detach_delegation(NFS_I(inode),
  659 + server);
  660 + rcu_read_unlock();
  661 +
  662 + if (delegation != NULL)
  663 + nfs_free_delegation(delegation);
  664 + iput(inode);
  665 + goto restart;
  666 + }
540 667 }
541 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 + */
  678 +int 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 + */
544 701 int nfs4_copy_delegation_stateid(nfs4_stateid *dst, struct inode *inode)
545 702 {
546 703 struct nfs_inode *nfsi = NFS_I(inode);
... ... @@ -44,6 +44,7 @@
44 44 void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
45 45 void nfs_handle_cb_pathdown(struct nfs_client *clp);
46 46 int nfs_client_return_marked_delegations(struct nfs_client *clp);
  47 +int nfs_delegations_present(struct nfs_client *clp);
47 48  
48 49 void nfs_delegation_mark_reclaim(struct nfs_client *clp);
49 50 void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
... ... @@ -80,7 +80,7 @@
80 80 cred = ops->get_state_renewal_cred_locked(clp);
81 81 spin_unlock(&clp->cl_lock);
82 82 if (cred == NULL) {
83   - if (list_empty(&clp->cl_delegations)) {
  83 + if (!nfs_delegations_present(clp)) {
84 84 set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
85 85 goto out;
86 86 }
include/linux/nfs_fs_sb.h
... ... @@ -47,7 +47,6 @@
47 47 u64 cl_clientid; /* constant */
48 48 unsigned long cl_state;
49 49  
50   - struct list_head cl_delegations;
51 50 spinlock_t cl_lock;
52 51  
53 52 unsigned long cl_lease_time;
... ... @@ -152,6 +151,7 @@
152 151 struct rb_root openowner_id;
153 152 struct rb_root lockowner_id;
154 153 #endif
  154 + struct list_head delegations;
155 155 void (*destroy)(struct nfs_server *);
156 156  
157 157 atomic_t active; /* Keep trace of any activity to this server */