diff options
author | Jeff Layton <jlayton@poochiereds.net> | 2015-12-08 07:23:48 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2016-01-08 16:47:51 -0500 |
commit | 6b9b21073d3b250e17812cd562fffc9006962b39 (patch) | |
tree | d8f01815c10c3f8affc866a913307e4ec53a7391 /fs/nfsd | |
parent | 691412b4438da1b77ff3078de0546023d244d841 (diff) |
nfsd: give up on CB_LAYOUTRECALLs after two lease periods
Have the CB_LAYOUTRECALL code treat NFS4_OK and NFS4ERR_DELAY returns
equivalently. Change the code to periodically resend CB_LAYOUTRECALLS
until the ls_layouts list is empty or the client returns a different
error code.
If we go for two lease periods without the list being emptied or the
client sending a hard error, then we give up and clean out the list
anyway.
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Tested-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4layouts.c | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index fec49febb75b..76c13b0228b1 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c | |||
@@ -623,24 +623,39 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task) | |||
623 | { | 623 | { |
624 | struct nfs4_layout_stateid *ls = | 624 | struct nfs4_layout_stateid *ls = |
625 | container_of(cb, struct nfs4_layout_stateid, ls_recall); | 625 | container_of(cb, struct nfs4_layout_stateid, ls_recall); |
626 | struct nfsd_net *nn; | ||
627 | ktime_t now, cutoff; | ||
626 | LIST_HEAD(reaplist); | 628 | LIST_HEAD(reaplist); |
627 | 629 | ||
630 | |||
628 | switch (task->tk_status) { | 631 | switch (task->tk_status) { |
629 | case 0: | 632 | case 0: |
630 | return 1; | 633 | case -NFS4ERR_DELAY: |
634 | /* | ||
635 | * Anything left? If not, then call it done. Note that we don't | ||
636 | * take the spinlock since this is an optimization and nothing | ||
637 | * should get added until the cb counter goes to zero. | ||
638 | */ | ||
639 | if (list_empty(&ls->ls_layouts)) | ||
640 | return 1; | ||
641 | |||
642 | /* Poll the client until it's done with the layout */ | ||
643 | now = ktime_get(); | ||
644 | nn = net_generic(ls->ls_stid.sc_client->net, nfsd_net_id); | ||
645 | |||
646 | /* Client gets 2 lease periods to return it */ | ||
647 | cutoff = ktime_add_ns(task->tk_start, | ||
648 | nn->nfsd4_lease * NSEC_PER_SEC * 2); | ||
649 | |||
650 | if (ktime_before(now, cutoff)) { | ||
651 | rpc_delay(task, HZ/100); /* 10 mili-seconds */ | ||
652 | return 0; | ||
653 | } | ||
654 | /* Fallthrough */ | ||
631 | case -NFS4ERR_NOMATCHING_LAYOUT: | 655 | case -NFS4ERR_NOMATCHING_LAYOUT: |
632 | trace_layout_recall_done(&ls->ls_stid.sc_stateid); | 656 | trace_layout_recall_done(&ls->ls_stid.sc_stateid); |
633 | task->tk_status = 0; | 657 | task->tk_status = 0; |
634 | return 1; | 658 | return 1; |
635 | case -NFS4ERR_DELAY: | ||
636 | /* Poll the client until it's done with the layout */ | ||
637 | /* FIXME: cap number of retries. | ||
638 | * The pnfs standard states that we need to only expire | ||
639 | * the client after at-least "lease time" .eg lease-time * 2 | ||
640 | * when failing to communicate a recall | ||
641 | */ | ||
642 | rpc_delay(task, HZ/100); /* 10 mili-seconds */ | ||
643 | return 0; | ||
644 | default: | 659 | default: |
645 | /* | 660 | /* |
646 | * Unknown error or non-responding client, we'll need to fence. | 661 | * Unknown error or non-responding client, we'll need to fence. |