NFS: fix up nfs_setattr_update_inode
authorTrond Myklebust <trond.myklebust@primarydata.com>
Sun, 8 Apr 2018 21:51:11 +0000 (17:51 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 4 Jun 2018 19:03:58 +0000 (15:03 -0400)
Always try to set the attributes, even if we don't have a valid struct
nfs_fattr.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
fs/nfs/inode.c

index a720427e5aa3843888aa1d02058945f2608c86ca..2b7edd011d867d52193a43bdbe715761654c08df 100644 (file)
@@ -671,9 +671,13 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
 
        spin_lock(&inode->i_lock);
        NFS_I(inode)->attr_gencount = fattr->gencount;
-       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
-                       | NFS_INO_INVALID_CTIME);
+       if ((attr->ia_valid & ATTR_SIZE) != 0) {
+               nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+               nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
+               nfs_vmtruncate(inode, attr->ia_size);
+       }
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) {
+               NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_CTIME;
                if ((attr->ia_valid & ATTR_MODE) != 0) {
                        int mode = attr->ia_mode & S_IALLUGO;
                        mode |= inode->i_mode & ~S_IALLUGO;
@@ -683,13 +687,45 @@ void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr,
                        inode->i_uid = attr->ia_uid;
                if ((attr->ia_valid & ATTR_GID) != 0)
                        inode->i_gid = attr->ia_gid;
+               if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+                       inode->i_ctime = fattr->ctime;
+               else
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+                                       | NFS_INO_INVALID_CTIME);
                nfs_set_cache_invalid(inode, NFS_INO_INVALID_ACCESS
                                | NFS_INO_INVALID_ACL);
        }
-       if ((attr->ia_valid & ATTR_SIZE) != 0) {
-               nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
-               nfs_inc_stats(inode, NFSIOS_SETATTRTRUNC);
-               nfs_vmtruncate(inode, attr->ia_size);
+       if (attr->ia_valid & (ATTR_ATIME_SET|ATTR_ATIME)) {
+               NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_ATIME
+                               | NFS_INO_INVALID_CTIME);
+               if (fattr->valid & NFS_ATTR_FATTR_ATIME)
+                       inode->i_atime = fattr->atime;
+               else if (attr->ia_valid & ATTR_ATIME_SET)
+                       inode->i_atime = attr->ia_atime;
+               else
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_ATIME);
+
+               if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+                       inode->i_ctime = fattr->ctime;
+               else
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+                                       | NFS_INO_INVALID_CTIME);
+       }
+       if (attr->ia_valid & (ATTR_MTIME_SET|ATTR_MTIME)) {
+               NFS_I(inode)->cache_validity &= ~(NFS_INO_INVALID_MTIME
+                               | NFS_INO_INVALID_CTIME);
+               if (fattr->valid & NFS_ATTR_FATTR_MTIME)
+                       inode->i_mtime = fattr->mtime;
+               else if (attr->ia_valid & ATTR_MTIME_SET)
+                       inode->i_mtime = attr->ia_mtime;
+               else
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_MTIME);
+
+               if (fattr->valid & NFS_ATTR_FATTR_CTIME)
+                       inode->i_ctime = fattr->ctime;
+               else
+                       nfs_set_cache_invalid(inode, NFS_INO_INVALID_CHANGE
+                                       | NFS_INO_INVALID_CTIME);
        }
        if (fattr->valid)
                nfs_update_inode(inode, fattr);