浏览代码

NFS: Add optional post-op getattr instruction to the NFSv4 file close.

 "Optional" means that the close call will not fail if the getattr
 at the end of the compound fails.
 If it does succeed, try to refresh inode attributes.

 Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Trond Myklebust 19 年之前
父节点
当前提交
516a6af641
共有 3 个文件被更改,包括 39 次插入7 次删除
  1. 8 1
      fs/nfs/nfs4proc.c
  2. 28 6
      fs/nfs/nfs4xdr.c
  3. 3 0
      include/linux/nfs_xdr.h

+ 8 - 1
fs/nfs/nfs4proc.c

@@ -865,6 +865,7 @@ struct nfs4_closedata {
 	struct nfs4_state *state;
 	struct nfs4_state *state;
 	struct nfs_closeargs arg;
 	struct nfs_closeargs arg;
 	struct nfs_closeres res;
 	struct nfs_closeres res;
+	struct nfs_fattr fattr;
 };
 };
 
 
 static void nfs4_free_closedata(struct nfs4_closedata *calldata)
 static void nfs4_free_closedata(struct nfs4_closedata *calldata)
@@ -904,6 +905,7 @@ static void nfs4_close_done(struct rpc_task *task)
 				return;
 				return;
 			}
 			}
 	}
 	}
+	nfs_refresh_inode(calldata->inode, calldata->res.fattr);
 	state->state = calldata->arg.open_flags;
 	state->state = calldata->arg.open_flags;
 	nfs4_free_closedata(calldata);
 	nfs4_free_closedata(calldata);
 }
 }
@@ -941,6 +943,7 @@ static void nfs4_close_begin(struct rpc_task *task)
 		rpc_exit(task, 0);
 		rpc_exit(task, 0);
 		return;
 		return;
 	}
 	}
+	nfs_fattr_init(calldata->res.fattr);
 	if (mode != 0)
 	if (mode != 0)
 		msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
 		msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
 	calldata->arg.open_flags = mode;
 	calldata->arg.open_flags = mode;
@@ -960,6 +963,7 @@ static void nfs4_close_begin(struct rpc_task *task)
  */
  */
 int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode) 
 {
 {
+	struct nfs_server *server = NFS_SERVER(inode);
 	struct nfs4_closedata *calldata;
 	struct nfs4_closedata *calldata;
 	int status = -ENOMEM;
 	int status = -ENOMEM;
 
 
@@ -974,8 +978,11 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state, mode_t mode)
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
 	if (calldata->arg.seqid == NULL)
 	if (calldata->arg.seqid == NULL)
 		goto out_free_calldata;
 		goto out_free_calldata;
+	calldata->arg.bitmask = server->attr_bitmask;
+	calldata->res.fattr = &calldata->fattr;
+	calldata->res.server = server;
 
 
-	status = nfs4_call_async(NFS_SERVER(inode)->client, nfs4_close_begin,
+	status = nfs4_call_async(server->client, nfs4_close_begin,
 			nfs4_close_done, calldata);
 			nfs4_close_done, calldata);
 	if (status == 0)
 	if (status == 0)
 		goto out;
 		goto out;

+ 28 - 6
fs/nfs/nfs4xdr.c

@@ -198,17 +198,21 @@ static int nfs_stat_to_errno(int);
 #define NFS4_enc_open_downgrade_sz \
 #define NFS4_enc_open_downgrade_sz \
 				(compound_encode_hdr_maxsz + \
 				(compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 7)
+                                op_encode_hdr_maxsz + 7 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_open_downgrade_sz \
 #define NFS4_dec_open_downgrade_sz \
 				(compound_decode_hdr_maxsz + \
 				(compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_close_sz       (compound_encode_hdr_maxsz + \
 #define NFS4_enc_close_sz       (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 encode_putfh_maxsz + \
-                                op_encode_hdr_maxsz + 5)
+                                op_encode_hdr_maxsz + 5 + \
+				encode_getattr_maxsz)
 #define NFS4_dec_close_sz       (compound_decode_hdr_maxsz + \
 #define NFS4_dec_close_sz       (compound_decode_hdr_maxsz + \
                                 decode_putfh_maxsz + \
                                 decode_putfh_maxsz + \
-                                op_decode_hdr_maxsz + 4)
+                                op_decode_hdr_maxsz + 4 + \
+				decode_getattr_maxsz)
 #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
 #define NFS4_enc_setattr_sz     (compound_encode_hdr_maxsz + \
                                 encode_putfh_maxsz + \
                                 encode_putfh_maxsz + \
                                 op_encode_hdr_maxsz + 4 + \
                                 op_encode_hdr_maxsz + 4 + \
@@ -1433,7 +1437,7 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos
 {
 {
         struct xdr_stream xdr;
         struct xdr_stream xdr;
         struct compound_hdr hdr = {
         struct compound_hdr hdr = {
-                .nops   = 2,
+                .nops   = 3,
         };
         };
         int status;
         int status;
 
 
@@ -1443,6 +1447,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos
         if(status)
         if(status)
                 goto out;
                 goto out;
         status = encode_close(&xdr, args);
         status = encode_close(&xdr, args);
+	if (status != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 out:
         return status;
         return status;
 }
 }
@@ -1541,7 +1548,7 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct
 {
 {
 	struct xdr_stream xdr;
 	struct xdr_stream xdr;
 	struct compound_hdr hdr = {
 	struct compound_hdr hdr = {
-		.nops	= 2,
+		.nops	= 3,
 	};
 	};
 	int status;
 	int status;
 
 
@@ -1551,6 +1558,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct
 	if (status)
 	if (status)
 		goto out;
 		goto out;
 	status = encode_open_downgrade(&xdr, args);
 	status = encode_open_downgrade(&xdr, args);
+	if (status != 0)
+		goto out;
+	status = encode_getfattr(&xdr, args->bitmask);
 out:
 out:
 	return status;
 	return status;
 }
 }
@@ -3403,6 +3413,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, stru
         if (status)
         if (status)
                 goto out;
                 goto out;
         status = decode_open_downgrade(&xdr, res);
         status = decode_open_downgrade(&xdr, res);
+	if (status != 0)
+		goto out;
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
 out:
         return status;
         return status;
 }
 }
@@ -3678,6 +3691,15 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_cl
         if (status)
         if (status)
                 goto out;
                 goto out;
         status = decode_close(&xdr, res);
         status = decode_close(&xdr, res);
+	if (status != 0)
+		goto out;
+	/*
+	 * Note: Server may do delete on close for this file
+	 * 	in which case the getattr call will fail with
+	 * 	an ESTALE error. Shouldn't be a problem,
+	 * 	though, since fattr->valid will remain unset.
+	 */
+	decode_getfattr(&xdr, res->fattr, res->server);
 out:
 out:
         return status;
         return status;
 }
 }

+ 3 - 0
include/linux/nfs_xdr.h

@@ -153,10 +153,13 @@ struct nfs_closeargs {
 	nfs4_stateid *		stateid;
 	nfs4_stateid *		stateid;
 	struct nfs_seqid *	seqid;
 	struct nfs_seqid *	seqid;
 	int			open_flags;
 	int			open_flags;
+	const u32 *		bitmask;
 };
 };
 
 
 struct nfs_closeres {
 struct nfs_closeres {
 	nfs4_stateid            stateid;
 	nfs4_stateid            stateid;
+	struct nfs_fattr *	fattr;
+	const struct nfs_server *server;
 };
 };
 /*
 /*
  *  * Arguments to the lock,lockt, and locku call.
  *  * Arguments to the lock,lockt, and locku call.