aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c20
-rw-r--r--fs/nfs/nfs4xdr.c9
2 files changed, 27 insertions, 2 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3cc75445a68d..fee2d14b158b 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -943,6 +943,22 @@ static struct nfs4_state *nfs4_open_delegated(struct inode *inode, int flags, st
943} 943}
944 944
945/* 945/*
946 * on an EXCLUSIVE create, the server should send back a bitmask with FATTR4-*
947 * fields corresponding to attributes that were used to store the verifier.
948 * Make sure we clobber those fields in the later setattr call
949 */
950static inline void nfs4_exclusive_attrset(struct nfs4_opendata *opendata, struct iattr *sattr)
951{
952 if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_ACCESS) &&
953 !(sattr->ia_valid & ATTR_ATIME_SET))
954 sattr->ia_valid |= ATTR_ATIME;
955
956 if ((opendata->o_res.attrset[1] & FATTR4_WORD1_TIME_MODIFY) &&
957 !(sattr->ia_valid & ATTR_MTIME_SET))
958 sattr->ia_valid |= ATTR_MTIME;
959}
960
961/*
946 * Returns a referenced nfs4_state 962 * Returns a referenced nfs4_state
947 */ 963 */
948static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) 964static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res)
@@ -973,6 +989,9 @@ static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct
973 if (status != 0) 989 if (status != 0)
974 goto err_opendata_free; 990 goto err_opendata_free;
975 991
992 if (opendata->o_arg.open_flags & O_EXCL)
993 nfs4_exclusive_attrset(opendata, sattr);
994
976 status = -ENOMEM; 995 status = -ENOMEM;
977 state = nfs4_opendata_to_nfs4_state(opendata); 996 state = nfs4_opendata_to_nfs4_state(opendata);
978 if (state == NULL) 997 if (state == NULL)
@@ -1784,6 +1803,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1784 status = nfs4_do_setattr(state->inode, &fattr, sattr, state); 1803 status = nfs4_do_setattr(state->inode, &fattr, sattr, state);
1785 if (status == 0) 1804 if (status == 0)
1786 nfs_setattr_update_inode(state->inode, sattr); 1805 nfs_setattr_update_inode(state->inode, sattr);
1806 nfs_post_op_update_inode(state->inode, &fattr);
1787 } 1807 }
1788 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) 1808 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
1789 status = nfs4_intent_set_file(nd, &path, state); 1809 status = nfs4_intent_set_file(nd, &path, state);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 8003c91ccb9a..1fcca516e6ee 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -3269,7 +3269,7 @@ static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
3269static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) 3269static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
3270{ 3270{
3271 __be32 *p; 3271 __be32 *p;
3272 uint32_t bmlen; 3272 uint32_t savewords, bmlen, i;
3273 int status; 3273 int status;
3274 3274
3275 status = decode_op_hdr(xdr, OP_OPEN); 3275 status = decode_op_hdr(xdr, OP_OPEN);
@@ -3287,7 +3287,12 @@ static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
3287 goto xdr_error; 3287 goto xdr_error;
3288 3288
3289 READ_BUF(bmlen << 2); 3289 READ_BUF(bmlen << 2);
3290 p += bmlen; 3290 savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
3291 for (i = 0; i < savewords; ++i)
3292 READ32(res->attrset[i]);
3293 for (; i < NFS4_BITMAP_SIZE; i++)
3294 res->attrset[i] = 0;
3295
3291 return decode_delegation(xdr, res); 3296 return decode_delegation(xdr, res);
3292xdr_error: 3297xdr_error:
3293 dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen); 3298 dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen);