aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs4proc.c40
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
279static 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
300static 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
277static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dentry, 306static 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: