aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2011-08-24 15:07:37 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-08-24 15:07:37 -0400
commit2f60ea6b8ceda61ae08bef71a652eac36ec193b3 (patch)
treef950b29615be254fb7f90a607caf3f307518a34b
parent8534d4ec055d854be6c94e8e5654fa87678ea5f7 (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>
-rw-r--r--fs/nfs/nfs4_fs.h5
-rw-r--r--fs/nfs/nfs4proc.c8
-rw-r--r--fs/nfs/nfs4renewd.c12
3 files changed, 19 insertions, 6 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index 58adfb6e365..e1b66072867 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
59struct nfs4_minor_version_ops { 62struct 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
227struct nfs4_state_maintenance_ops { 230struct 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 b358ec1d171..e89940a2819 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
3389static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred) 3389static 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
5507static int nfs41_proc_async_sequence(struct nfs_client *clp, struct rpc_cred *cred) 5509static 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 df8e7f3ca56..dc484c0eae7 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 }