aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-03 03:55:38 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2006-01-06 14:58:51 -0500
commitfa178f29c0f8a0dce748181a5351f4a92fd4f455 (patch)
tree07de5ced8d16d832ebed98c58a2c0498affa12db
parentbeb2a5ec386e5ce6891ebd1c06b913da04354b40 (diff)
NFSv4: Ensure DELEGRETURN returns attributes
Upon return of a write delegation, the server will almost always bump the change attribute. Ensure that we pick up that change so that we don't invalidate our data cache unnecessarily. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/delegation.c2
-rw-r--r--fs/nfs/nfs4proc.c17
-rw-r--r--fs/nfs/nfs4xdr.c33
-rw-r--r--include/linux/nfs_xdr.h6
4 files changed, 41 insertions, 17 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c
index d2ee09b38cee..66cc720e3927 100644
--- a/fs/nfs/delegation.c
+++ b/fs/nfs/delegation.c
@@ -159,8 +159,6 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
159{ 159{
160 int res = 0; 160 int res = 0;
161 161
162 __nfs_revalidate_inode(NFS_SERVER(inode), inode);
163
164 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid); 162 res = nfs4_proc_delegreturn(inode, delegation->cred, &delegation->stateid);
165 nfs_free_delegation(delegation); 163 nfs_free_delegation(delegation);
166 return res; 164 return res;
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index b3349154994b..984ca3454d04 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2920,11 +2920,12 @@ nfs4_proc_setclientid_confirm(struct nfs4_client *clp, struct rpc_cred *cred)
2920 2920
2921struct nfs4_delegreturndata { 2921struct nfs4_delegreturndata {
2922 struct nfs4_delegreturnargs args; 2922 struct nfs4_delegreturnargs args;
2923 struct nfs4_delegreturnres res;
2923 struct nfs_fh fh; 2924 struct nfs_fh fh;
2924 nfs4_stateid stateid; 2925 nfs4_stateid stateid;
2925 struct rpc_cred *cred; 2926 struct rpc_cred *cred;
2926 unsigned long timestamp; 2927 unsigned long timestamp;
2927 const struct nfs_server *server; 2928 struct nfs_fattr fattr;
2928 int rpc_status; 2929 int rpc_status;
2929}; 2930};
2930 2931
@@ -2934,8 +2935,10 @@ static void nfs4_delegreturn_prepare(struct rpc_task *task, void *calldata)
2934 struct rpc_message msg = { 2935 struct rpc_message msg = {
2935 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN], 2936 .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_DELEGRETURN],
2936 .rpc_argp = &data->args, 2937 .rpc_argp = &data->args,
2938 .rpc_resp = &data->res,
2937 .rpc_cred = data->cred, 2939 .rpc_cred = data->cred,
2938 }; 2940 };
2941 nfs_fattr_init(data->res.fattr);
2939 rpc_call_setup(task, &msg, 0); 2942 rpc_call_setup(task, &msg, 0);
2940} 2943}
2941 2944
@@ -2944,7 +2947,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
2944 struct nfs4_delegreturndata *data = calldata; 2947 struct nfs4_delegreturndata *data = calldata;
2945 data->rpc_status = task->tk_status; 2948 data->rpc_status = task->tk_status;
2946 if (data->rpc_status == 0) 2949 if (data->rpc_status == 0)
2947 renew_lease(data->server, data->timestamp); 2950 renew_lease(data->res.server, data->timestamp);
2948} 2951}
2949 2952
2950static void nfs4_delegreturn_release(void *calldata) 2953static void nfs4_delegreturn_release(void *calldata)
@@ -2964,6 +2967,7 @@ const static struct rpc_call_ops nfs4_delegreturn_ops = {
2964static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid) 2967static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid)
2965{ 2968{
2966 struct nfs4_delegreturndata *data; 2969 struct nfs4_delegreturndata *data;
2970 struct nfs_server *server = NFS_SERVER(inode);
2967 struct rpc_task *task; 2971 struct rpc_task *task;
2968 int status; 2972 int status;
2969 2973
@@ -2972,11 +2976,13 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
2972 return -ENOMEM; 2976 return -ENOMEM;
2973 data->args.fhandle = &data->fh; 2977 data->args.fhandle = &data->fh;
2974 data->args.stateid = &data->stateid; 2978 data->args.stateid = &data->stateid;
2979 data->args.bitmask = server->attr_bitmask;
2975 nfs_copy_fh(&data->fh, NFS_FH(inode)); 2980 nfs_copy_fh(&data->fh, NFS_FH(inode));
2976 memcpy(&data->stateid, stateid, sizeof(data->stateid)); 2981 memcpy(&data->stateid, stateid, sizeof(data->stateid));
2982 data->res.fattr = &data->fattr;
2983 data->res.server = server;
2977 data->cred = get_rpccred(cred); 2984 data->cred = get_rpccred(cred);
2978 data->timestamp = jiffies; 2985 data->timestamp = jiffies;
2979 data->server = NFS_SERVER(inode);
2980 data->rpc_status = 0; 2986 data->rpc_status = 0;
2981 2987
2982 task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data); 2988 task = rpc_run_task(NFS_CLIENT(inode), RPC_TASK_ASYNC, &nfs4_delegreturn_ops, data);
@@ -2985,8 +2991,11 @@ static int _nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, co
2985 return PTR_ERR(task); 2991 return PTR_ERR(task);
2986 } 2992 }
2987 status = nfs4_wait_for_completion_rpc_task(task); 2993 status = nfs4_wait_for_completion_rpc_task(task);
2988 if (status == 0) 2994 if (status == 0) {
2989 status = data->rpc_status; 2995 status = data->rpc_status;
2996 if (status == 0)
2997 nfs_post_op_update_inode(inode, &data->fattr);
2998 }
2990 rpc_release_task(task); 2999 rpc_release_task(task);
2991 return status; 3000 return status;
2992} 3001}
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 5d6bda43dfaa..12be1d682164 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -392,9 +392,11 @@ static int nfs_stat_to_errno(int);
392 decode_getattr_maxsz) 392 decode_getattr_maxsz)
393#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \ 393#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
394 encode_putfh_maxsz + \ 394 encode_putfh_maxsz + \
395 encode_delegreturn_maxsz) 395 encode_delegreturn_maxsz + \
396 encode_getattr_maxsz)
396#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \ 397#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
397 decode_delegreturn_maxsz) 398 decode_delegreturn_maxsz + \
399 decode_getattr_maxsz)
398#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \ 400#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
399 encode_putfh_maxsz + \ 401 encode_putfh_maxsz + \
400 encode_getattr_maxsz) 402 encode_getattr_maxsz)
@@ -1983,14 +1985,20 @@ static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const str
1983{ 1985{
1984 struct xdr_stream xdr; 1986 struct xdr_stream xdr;
1985 struct compound_hdr hdr = { 1987 struct compound_hdr hdr = {
1986 .nops = 2, 1988 .nops = 3,
1987 }; 1989 };
1988 int status; 1990 int status;
1989 1991
1990 xdr_init_encode(&xdr, &req->rq_snd_buf, p); 1992 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1991 encode_compound_hdr(&xdr, &hdr); 1993 encode_compound_hdr(&xdr, &hdr);
1992 if ((status = encode_putfh(&xdr, args->fhandle)) == 0) 1994 status = encode_putfh(&xdr, args->fhandle);
1993 status = encode_delegreturn(&xdr, args->stateid); 1995 if (status != 0)
1996 goto out;
1997 status = encode_delegreturn(&xdr, args->stateid);
1998 if (status != 0)
1999 goto out;
2000 status = encode_getfattr(&xdr, args->bitmask);
2001out:
1994 return status; 2002 return status;
1995} 2003}
1996 2004
@@ -4184,7 +4192,7 @@ static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, s
4184/* 4192/*
4185 * DELEGRETURN request 4193 * DELEGRETURN request
4186 */ 4194 */
4187static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy) 4195static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_delegreturnres *res)
4188{ 4196{
4189 struct xdr_stream xdr; 4197 struct xdr_stream xdr;
4190 struct compound_hdr hdr; 4198 struct compound_hdr hdr;
@@ -4192,11 +4200,14 @@ static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *d
4192 4200
4193 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p); 4201 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4194 status = decode_compound_hdr(&xdr, &hdr); 4202 status = decode_compound_hdr(&xdr, &hdr);
4195 if (status == 0) { 4203 if (status != 0)
4196 status = decode_putfh(&xdr); 4204 goto out;
4197 if (status == 0) 4205 status = decode_putfh(&xdr);
4198 status = decode_delegreturn(&xdr); 4206 if (status != 0)
4199 } 4207 goto out;
4208 status = decode_delegreturn(&xdr);
4209 decode_getfattr(&xdr, res->fattr, res->server);
4210out:
4200 return status; 4211 return status;
4201} 4212}
4202 4213
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 9f422fd87673..6d6f69ec5675 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -220,6 +220,12 @@ struct nfs_lockt_res {
220struct nfs4_delegreturnargs { 220struct nfs4_delegreturnargs {
221 const struct nfs_fh *fhandle; 221 const struct nfs_fh *fhandle;
222 const nfs4_stateid *stateid; 222 const nfs4_stateid *stateid;
223 const u32 * bitmask;
224};
225
226struct nfs4_delegreturnres {
227 struct nfs_fattr * fattr;
228 const struct nfs_server *server;
223}; 229};
224 230
225/* 231/*