NFSv4.2: SETXATTR should update ctime
authorAnna Schumaker <Anna.Schumaker@Netapp.com>
Thu, 4 May 2023 20:47:16 +0000 (16:47 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 19 Jun 2023 16:10:48 +0000 (12:10 -0400)
Otherwise, `stat` will report a stale value to users.

Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/nfs42proc.c
fs/nfs/nfs42xdr.c
include/linux/nfs_xdr.h

index 93e306bf4430fb96bfce4fdd6e20279727a7412f..63802d19555665a62f3b44b2c6668986e4f34e81 100644 (file)
@@ -1190,15 +1190,19 @@ static int _nfs42_proc_setxattr(struct inode *inode, const char *name,
                                const void *buf, size_t buflen, int flags)
 {
        struct nfs_server *server = NFS_SERVER(inode);
+       __u32 bitmask[NFS_BITMASK_SZ];
        struct page *pages[NFS4XATTR_MAXPAGES];
        struct nfs42_setxattrargs arg = {
                .fh             = NFS_FH(inode),
+               .bitmask        = bitmask,
                .xattr_pages    = pages,
                .xattr_len      = buflen,
                .xattr_name     = name,
                .xattr_flags    = flags,
        };
-       struct nfs42_setxattrres res;
+       struct nfs42_setxattrres res = {
+               .server         = server,
+       };
        struct rpc_message msg = {
                .rpc_proc       = &nfs4_procedures[NFSPROC4_CLNT_SETXATTR],
                .rpc_argp       = &arg,
@@ -1210,13 +1214,22 @@ static int _nfs42_proc_setxattr(struct inode *inode, const char *name,
        if (buflen > server->sxasize)
                return -ERANGE;
 
+       res.fattr = nfs_alloc_fattr();
+       if (!res.fattr)
+               return -ENOMEM;
+
        if (buflen > 0) {
                np = nfs4_buf_to_pages_noslab(buf, buflen, arg.xattr_pages);
-               if (np < 0)
-                       return np;
+               if (np < 0) {
+                       ret = np;
+                       goto out;
+               }
        } else
                np = 0;
 
+       nfs4_bitmask_set(bitmask, server->cache_consistency_bitmask,
+                        inode, NFS_INO_INVALID_CHANGE);
+
        ret = nfs4_call_sync(server->client, server, &msg, &arg.seq_args,
            &res.seq_res, 1);
        trace_nfs4_setxattr(inode, name, ret);
@@ -1224,9 +1237,13 @@ static int _nfs42_proc_setxattr(struct inode *inode, const char *name,
        for (; np > 0; np--)
                put_page(pages[np - 1]);
 
-       if (!ret)
+       if (!ret) {
                nfs4_update_changeattr(inode, &res.cinfo, timestamp, 0);
+               ret = nfs_post_op_update_inode(inode, res.fattr);
+       }
 
+out:
+       kfree(res.fattr);
        return ret;
 }
 
index 215b8700e504c00c91c1ede1fcf23314d65c755c..95234208dc9ee120baa0ea4e707a20a381ea0769 100644 (file)
 #define NFS4_enc_setxattr_sz           (compound_encode_hdr_maxsz + \
                                         encode_sequence_maxsz + \
                                         encode_putfh_maxsz + \
-                                        encode_setxattr_maxsz)
+                                        encode_setxattr_maxsz + \
+                                        encode_getattr_maxsz)
 #define NFS4_dec_setxattr_sz           (compound_decode_hdr_maxsz + \
                                         decode_sequence_maxsz + \
                                         decode_putfh_maxsz + \
-                                        decode_setxattr_maxsz)
+                                        decode_setxattr_maxsz + \
+                                        decode_getattr_maxsz)
 #define NFS4_enc_listxattrs_sz         (compound_encode_hdr_maxsz + \
                                         encode_sequence_maxsz + \
                                         encode_putfh_maxsz + \
@@ -720,6 +722,7 @@ static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
        encode_sequence(xdr, &args->seq_args, &hdr);
        encode_putfh(xdr, args->fh, &hdr);
        encode_setxattr(xdr, args, &hdr);
+       encode_getfattr(xdr, args->bitmask, &hdr);
        encode_nops(&hdr);
 }
 
@@ -1579,8 +1582,10 @@ static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
        status = decode_putfh(xdr);
        if (status)
                goto out;
-
        status = decode_setxattr(xdr, &res->cinfo);
+       if (status)
+               goto out;
+       status = decode_getfattr(xdr, res->fattr, res->server);
 out:
        return status;
 }
index 29a1b39794bf3e66e8f6d13ef896f3f08125812a..12bbb5c636646e7a9318613669385400749c94d2 100644 (file)
@@ -1528,6 +1528,7 @@ struct nfs42_seek_res {
 struct nfs42_setxattrargs {
        struct nfs4_sequence_args       seq_args;
        struct nfs_fh                   *fh;
+       const u32                       *bitmask;
        const char                      *xattr_name;
        u32                             xattr_flags;
        size_t                          xattr_len;
@@ -1537,6 +1538,8 @@ struct nfs42_setxattrargs {
 struct nfs42_setxattrres {
        struct nfs4_sequence_res        seq_res;
        struct nfs4_change_info         cinfo;
+       struct nfs_fattr                *fattr;
+       const struct nfs_server         *server;
 };
 
 struct nfs42_getxattrargs {