aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c9
-rw-r--r--fs/nfs/nfs4xdr.c34
-rw-r--r--include/linux/nfs_xdr.h3
3 files changed, 39 insertions, 7 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index f363fd6c7f4..7be3d2d15d6 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -865,6 +865,7 @@ struct nfs4_closedata {
struct nfs4_state *state;
struct nfs_closeargs arg;
struct nfs_closeres res;
+ struct nfs_fattr fattr;
};
static void nfs4_free_closedata(struct nfs4_closedata *calldata)
@@ -904,6 +905,7 @@ static void nfs4_close_done(struct rpc_task *task)
return;
}
}
+ nfs_refresh_inode(calldata->inode, calldata->res.fattr);
state->state = calldata->arg.open_flags;
nfs4_free_closedata(calldata);
}
@@ -941,6 +943,7 @@ static void nfs4_close_begin(struct rpc_task *task)
rpc_exit(task, 0);
return;
}
+ nfs_fattr_init(calldata->res.fattr);
if (mode != 0)
msg.rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_OPEN_DOWNGRADE];
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)
{
+ struct nfs_server *server = NFS_SERVER(inode);
struct nfs4_closedata *calldata;
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);
if (calldata->arg.seqid == NULL)
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);
if (status == 0)
goto out;
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 7f91d613d31..cd9e26cfa86 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -198,17 +198,21 @@ static int nfs_stat_to_errno(int);
#define NFS4_enc_open_downgrade_sz \
(compound_encode_hdr_maxsz + \
encode_putfh_maxsz + \
- op_encode_hdr_maxsz + 7)
+ op_encode_hdr_maxsz + 7 + \
+ encode_getattr_maxsz)
#define NFS4_dec_open_downgrade_sz \
(compound_decode_hdr_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 + \
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 + \
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 + \
encode_putfh_maxsz + \
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 compound_hdr hdr = {
- .nops = 2,
+ .nops = 3,
};
int status;
@@ -1443,6 +1447,9 @@ static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_clos
if(status)
goto out;
status = encode_close(&xdr, args);
+ if (status != 0)
+ goto out;
+ status = encode_getfattr(&xdr, args->bitmask);
out:
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 compound_hdr hdr = {
- .nops = 2,
+ .nops = 3,
};
int status;
@@ -1551,6 +1558,9 @@ static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct
if (status)
goto out;
status = encode_open_downgrade(&xdr, args);
+ if (status != 0)
+ goto out;
+ status = encode_getfattr(&xdr, args->bitmask);
out:
return status;
}
@@ -3403,6 +3413,9 @@ static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, stru
if (status)
goto out;
status = decode_open_downgrade(&xdr, res);
+ if (status != 0)
+ goto out;
+ decode_getfattr(&xdr, res->fattr, res->server);
out:
return status;
}
@@ -3678,6 +3691,15 @@ static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_cl
if (status)
goto out;
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:
return status;
}
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 6485b8b41b8..4f03dc21cf4 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -153,10 +153,13 @@ struct nfs_closeargs {
nfs4_stateid * stateid;
struct nfs_seqid * seqid;
int open_flags;
+ const u32 * bitmask;
};
struct nfs_closeres {
nfs4_stateid stateid;
+ struct nfs_fattr * fattr;
+ const struct nfs_server *server;
};
/*
* * Arguments to the lock,lockt, and locku call.