diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-08-24 15:07:37 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2011-08-24 15:07:37 -0400 |
commit | 2f60ea6b8ceda61ae08bef71a652eac36ec193b3 (patch) | |
tree | f950b29615be254fb7f90a607caf3f307518a34b /fs/nfs | |
parent | 8534d4ec055d854be6c94e8e5654fa87678ea5f7 (diff) |
NFSv4: The NFSv4.0 client must send RENEW calls if it holds a delegation
RFC3530 states that if the client holds a delegation, then it is obliged
to continue to send RENEW calls once every lease period in order to allow
the server to return NFS4ERR_CB_PATH_DOWN if the callback path is
unreachable.
This is not required for NFSv4.1, since the server can at any time set
the SEQ4_STATUS_CB_PATH_DOWN_SESSION in any SEQUENCE operation.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 5 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4renewd.c | 12 |
3 files changed, 19 insertions, 6 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 58adfb6e3657..e1b660728675 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -56,6 +56,9 @@ enum nfs4_session_state { | |||
56 | NFS4_SESSION_DRAINING, | 56 | NFS4_SESSION_DRAINING, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | #define NFS4_RENEW_TIMEOUT 0x01 | ||
60 | #define NFS4_RENEW_DELEGATION_CB 0x02 | ||
61 | |||
59 | struct nfs4_minor_version_ops { | 62 | struct nfs4_minor_version_ops { |
60 | u32 minor_version; | 63 | u32 minor_version; |
61 | 64 | ||
@@ -225,7 +228,7 @@ struct nfs4_state_recovery_ops { | |||
225 | }; | 228 | }; |
226 | 229 | ||
227 | struct nfs4_state_maintenance_ops { | 230 | struct nfs4_state_maintenance_ops { |
228 | int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *); | 231 | int (*sched_state_renewal)(struct nfs_client *, struct rpc_cred *, unsigned); |
229 | struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *); | 232 | struct rpc_cred * (*get_state_renewal_cred_locked)(struct nfs_client *); |
230 | int (*renew_lease)(struct nfs_client *, struct rpc_cred *); | 233 | int (*renew_lease)(struct nfs_client *, struct rpc_cred *); |
231 | }; | 234 | }; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index b358ec1d1711..e89940a2819d 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -3386,7 +3386,7 @@ static const struct rpc_call_ops nfs4_renew_ops = { | |||
3386 | .rpc_release = nfs4_renew_release, | 3386 | .rpc_release = nfs4_renew_release, |
3387 | }; | 3387 | }; |
3388 | 3388 | ||
3389 | static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | 3389 | static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags) |
3390 | { | 3390 | { |
3391 | struct rpc_message msg = { | 3391 | struct rpc_message msg = { |
3392 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], | 3392 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_RENEW], |
@@ -3395,6 +3395,8 @@ static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) | |||
3395 | }; | 3395 | }; |
3396 | struct nfs4_renewdata *data; | 3396 | struct nfs4_renewdata *data; |
3397 | 3397 | ||
3398 | if (renew_flags == 0) | ||
3399 | return 0; | ||
3398 | if (!atomic_inc_not_zero(&clp->cl_count)) | 3400 | if (!atomic_inc_not_zero(&clp->cl_count)) |
3399 | return -EIO; | 3401 | return -EIO; |
3400 | data = kmalloc(sizeof(*data), GFP_NOFS); | 3402 | data = kmalloc(sizeof(*data), GFP_NOFS); |
@@ -5504,11 +5506,13 @@ static struct rpc_task *_nfs41_proc_sequence(struct nfs_client *clp, struct rpc_ | |||
5504 | return rpc_run_task(&task_setup_data); | 5506 | return rpc_run_task(&task_setup_data); |
5505 | } | 5507 | } |
5506 | 5508 | ||
5507 | static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) | 5509 | static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred, unsigned renew_flags) |
5508 | { | 5510 | { |
5509 | struct rpc_task *task; | 5511 | struct rpc_task *task; |
5510 | int ret = 0; | 5512 | int ret = 0; |
5511 | 5513 | ||
5514 | if ((renew_flags & NFS4_RENEW_TIMEOUT) == 0) | ||
5515 | return 0; | ||
5512 | task = _nfs41_proc_sequence(clp, cred); | 5516 | task = _nfs41_proc_sequence(clp, cred); |
5513 | if (IS_ERR(task)) | 5517 | if (IS_ERR(task)) |
5514 | ret = PTR_ERR(task); | 5518 | ret = PTR_ERR(task); |
diff --git a/fs/nfs/nfs4renewd.c b/fs/nfs/nfs4renewd.c index df8e7f3ca56d..dc484c0eae7f 100644 --- a/fs/nfs/nfs4renewd.c +++ b/fs/nfs/nfs4renewd.c | |||
@@ -60,6 +60,7 @@ nfs4_renew_state(struct work_struct *work) | |||
60 | struct rpc_cred *cred; | 60 | struct rpc_cred *cred; |
61 | long lease; | 61 | long lease; |
62 | unsigned long last, now; | 62 | unsigned long last, now; |
63 | unsigned renew_flags = 0; | ||
63 | 64 | ||
64 | ops = clp->cl_mvops->state_renewal_ops; | 65 | ops = clp->cl_mvops->state_renewal_ops; |
65 | dprintk("%s: start\n", __func__); | 66 | dprintk("%s: start\n", __func__); |
@@ -72,18 +73,23 @@ nfs4_renew_state(struct work_struct *work) | |||
72 | last = clp->cl_last_renewal; | 73 | last = clp->cl_last_renewal; |
73 | now = jiffies; | 74 | now = jiffies; |
74 | /* Are we close to a lease timeout? */ | 75 | /* Are we close to a lease timeout? */ |
75 | if (time_after(now, last + lease/3)) { | 76 | if (time_after(now, last + lease/3)) |
77 | renew_flags |= NFS4_RENEW_TIMEOUT; | ||
78 | if (nfs_delegations_present(clp)) | ||
79 | renew_flags |= NFS4_RENEW_DELEGATION_CB; | ||
80 | |||
81 | if (renew_flags != 0) { | ||
76 | cred = ops->get_state_renewal_cred_locked(clp); | 82 | cred = ops->get_state_renewal_cred_locked(clp); |
77 | spin_unlock(&clp->cl_lock); | 83 | spin_unlock(&clp->cl_lock); |
78 | if (cred == NULL) { | 84 | if (cred == NULL) { |
79 | if (!nfs_delegations_present(clp)) { | 85 | if (!(renew_flags & NFS4_RENEW_DELEGATION_CB)) { |
80 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); | 86 | set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); |
81 | goto out; | 87 | goto out; |
82 | } | 88 | } |
83 | nfs_expire_all_delegations(clp); | 89 | nfs_expire_all_delegations(clp); |
84 | } else { | 90 | } else { |
85 | /* Queue an asynchronous RENEW. */ | 91 | /* Queue an asynchronous RENEW. */ |
86 | ops->sched_state_renewal(clp, cred); | 92 | ops->sched_state_renewal(clp, cred, renew_flags); |
87 | put_rpccred(cred); | 93 | put_rpccred(cred); |
88 | goto out_exp; | 94 | goto out_exp; |
89 | } | 95 | } |