diff options
-rw-r--r-- | fs/nfs/nfs4proc.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index bb1141c48281..c44cfa6be8ff 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -71,6 +71,8 @@ | |||
71 | 71 | ||
72 | #define NFSDBG_FACILITY NFSDBG_PROC | 72 | #define NFSDBG_FACILITY NFSDBG_PROC |
73 | 73 | ||
74 | #define NFS4_BITMASK_SZ 3 | ||
75 | |||
74 | #define NFS4_POLL_RETRY_MIN (HZ/10) | 76 | #define NFS4_POLL_RETRY_MIN (HZ/10) |
75 | #define NFS4_POLL_RETRY_MAX (15*HZ) | 77 | #define NFS4_POLL_RETRY_MAX (15*HZ) |
76 | 78 | ||
@@ -274,6 +276,33 @@ const u32 nfs4_fs_locations_bitmap[3] = { | |||
274 | | FATTR4_WORD1_MOUNTED_ON_FILEID, | 276 | | FATTR4_WORD1_MOUNTED_ON_FILEID, |
275 | }; | 277 | }; |
276 | 278 | ||
279 | static void nfs4_bitmap_copy_adjust(__u32 *dst, const __u32 *src, | ||
280 | struct inode *inode) | ||
281 | { | ||
282 | unsigned long cache_validity; | ||
283 | |||
284 | memcpy(dst, src, NFS4_BITMASK_SZ*sizeof(*dst)); | ||
285 | if (!inode || !nfs4_have_delegation(inode, FMODE_READ)) | ||
286 | return; | ||
287 | |||
288 | cache_validity = READ_ONCE(NFS_I(inode)->cache_validity); | ||
289 | if (!(cache_validity & NFS_INO_REVAL_FORCED)) | ||
290 | cache_validity &= ~(NFS_INO_INVALID_CHANGE | ||
291 | | NFS_INO_INVALID_SIZE); | ||
292 | |||
293 | if (!(cache_validity & NFS_INO_INVALID_SIZE)) | ||
294 | dst[0] &= ~FATTR4_WORD0_SIZE; | ||
295 | |||
296 | if (!(cache_validity & NFS_INO_INVALID_CHANGE)) | ||
297 | dst[0] &= ~FATTR4_WORD0_CHANGE; | ||
298 | } | ||
299 | |||
300 | static void nfs4_bitmap_copy_adjust_setattr(__u32 *dst, | ||
301 | const __u32 *src, struct inode *inode) | ||
302 | { | ||
303 | nfs4_bitmap_copy_adjust(dst, src, inode); | ||
304 | } | ||
305 | |||
277 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, | 306 | static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, |
278 | struct nfs4_readdir_arg *readdir) | 307 | struct nfs4_readdir_arg *readdir) |
279 | { | 308 | { |
@@ -3074,12 +3103,13 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
3074 | struct nfs4_label *olabel) | 3103 | struct nfs4_label *olabel) |
3075 | { | 3104 | { |
3076 | struct nfs_server *server = NFS_SERVER(inode); | 3105 | struct nfs_server *server = NFS_SERVER(inode); |
3106 | __u32 bitmask[NFS4_BITMASK_SZ]; | ||
3077 | struct nfs4_state *state = ctx ? ctx->state : NULL; | 3107 | struct nfs4_state *state = ctx ? ctx->state : NULL; |
3078 | struct nfs_setattrargs arg = { | 3108 | struct nfs_setattrargs arg = { |
3079 | .fh = NFS_FH(inode), | 3109 | .fh = NFS_FH(inode), |
3080 | .iap = sattr, | 3110 | .iap = sattr, |
3081 | .server = server, | 3111 | .server = server, |
3082 | .bitmask = server->attr_bitmask, | 3112 | .bitmask = bitmask, |
3083 | .label = ilabel, | 3113 | .label = ilabel, |
3084 | }; | 3114 | }; |
3085 | struct nfs_setattrres res = { | 3115 | struct nfs_setattrres res = { |
@@ -3094,11 +3124,11 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
3094 | }; | 3124 | }; |
3095 | int err; | 3125 | int err; |
3096 | 3126 | ||
3097 | arg.bitmask = nfs4_bitmask(server, ilabel); | ||
3098 | if (ilabel) | ||
3099 | arg.bitmask = nfs4_bitmask(server, olabel); | ||
3100 | |||
3101 | do { | 3127 | do { |
3128 | nfs4_bitmap_copy_adjust_setattr(bitmask, | ||
3129 | nfs4_bitmask(server, olabel), | ||
3130 | inode); | ||
3131 | |||
3102 | err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx); | 3132 | err = _nfs4_do_setattr(inode, &arg, &res, cred, ctx); |
3103 | switch (err) { | 3133 | switch (err) { |
3104 | case -NFS4ERR_OPENMODE: | 3134 | case -NFS4ERR_OPENMODE: |