diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 20 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 9 | ||||
-rw-r--r-- | include/linux/nfs4.h | 1 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 1 |
4 files changed, 29 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 | */ | ||
950 | static 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 | */ |
948 | static int _nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred, struct nfs4_state **res) | 964 | static 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) | |||
3269 | static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res) | 3269 | static 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); |
3292 | xdr_error: | 3297 | xdr_error: |
3293 | dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen); | 3298 | dprintk("%s: Bitmap too large! Length = %u\n", __FUNCTION__, bmlen); |
diff --git a/include/linux/nfs4.h b/include/linux/nfs4.h index 7e7f33a38fc0..8726491de154 100644 --- a/include/linux/nfs4.h +++ b/include/linux/nfs4.h | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/types.h> | 16 | #include <linux/types.h> |
17 | 17 | ||
18 | #define NFS4_BITMAP_SIZE 2 | ||
18 | #define NFS4_VERIFIER_SIZE 8 | 19 | #define NFS4_VERIFIER_SIZE 8 |
19 | #define NFS4_STATEID_SIZE 16 | 20 | #define NFS4_STATEID_SIZE 16 |
20 | #define NFS4_FHSIZE 128 | 21 | #define NFS4_FHSIZE 128 |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 10c26ed0db71..f7100df3a690 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -144,6 +144,7 @@ struct nfs_openres { | |||
144 | nfs4_stateid delegation; | 144 | nfs4_stateid delegation; |
145 | __u32 do_recall; | 145 | __u32 do_recall; |
146 | __u64 maxsize; | 146 | __u64 maxsize; |
147 | __u32 attrset[NFS4_BITMAP_SIZE]; | ||
147 | }; | 148 | }; |
148 | 149 | ||
149 | /* | 150 | /* |