NFS: Default change_attr_type to NFS4_CHANGE_TYPE_IS_UNDEFINED
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Sun, 26 Sep 2021 18:05:04 +0000 (14:05 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 18:16:59 +0000 (19:16 +0100)
[ Upstream commit eea413308f2e6deb00f061f18081a53f3ecc8cc6 ]

Both NFSv3 and NFSv2 generate their change attribute from the ctime
value that was supplied by the server. However the problem is that there
are plenty of servers out there with ctime resolutions of 1ms or worse.
In a modern performance system, this is insufficient when trying to
decide which is the most recent set of attributes when, for instance, a
READ or GETATTR call races with a WRITE or SETATTR.

For this reason, let's revert to labelling the NFSv2/v3 change
attributes as NFS4_CHANGE_TYPE_IS_UNDEFINED. This will ensure we protect
against such races.

Fixes: 7b24dacf0840 ("NFS: Another inode revalidation improvement")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Tested-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
fs/nfs/inode.c
fs/nfs/nfs3xdr.c
fs/nfs/proc.c

index 853213b3a209512c84bfe9c92b55dba6416ac75d..6ea1bde33cb6216879e48748067e65d6df8ddcef 100644 (file)
@@ -1777,8 +1777,10 @@ static int nfs_inode_finish_partial_attr_update(const struct nfs_fattr *fattr,
                NFS_INO_INVALID_BLOCKS | NFS_INO_INVALID_OTHER |
                NFS_INO_INVALID_NLINK;
        unsigned long cache_validity = NFS_I(inode)->cache_validity;
+       enum nfs4_change_attr_type ctype = NFS_SERVER(inode)->change_attr_type;
 
-       if (!(cache_validity & NFS_INO_INVALID_CHANGE) &&
+       if (ctype != NFS4_CHANGE_TYPE_IS_UNDEFINED &&
+           !(cache_validity & NFS_INO_INVALID_CHANGE) &&
            (cache_validity & check_valid) != 0 &&
            (fattr->valid & NFS_ATTR_FATTR_CHANGE) != 0 &&
            nfs_inode_attrs_cmp_monotonic(fattr, inode) == 0)
index e6eca1d7481b8951c593844a7b8fa4ab87ab1f23..9274c9c5efea63e073acf0c5cff2b744a124a944 100644 (file)
@@ -2227,7 +2227,7 @@ static int decode_fsinfo3resok(struct xdr_stream *xdr,
 
        /* ignore properties */
        result->lease_time = 0;
-       result->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA;
+       result->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
        return 0;
 }
 
index ea19dbf123014db5ada823c07a25ea5bd6bf1487..ecc4e717808c4ee5958b30d1b5f513c260a427df 100644 (file)
@@ -91,7 +91,7 @@ nfs_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle,
        info->dtpref = fsinfo.tsize;
        info->maxfilesize = 0x7FFFFFFF;
        info->lease_time = 0;
-       info->change_attr_type = NFS4_CHANGE_TYPE_IS_TIME_METADATA;
+       info->change_attr_type = NFS4_CHANGE_TYPE_IS_UNDEFINED;
        return 0;
 }