NFSv4: Some NFSv4 servers have broken behaviour for the change attribute
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 25 May 2006 05:40:46 +0000 (01:40 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 9 Jun 2006 13:34:04 +0000 (09:34 -0400)
The Linux NFSv4 server violates RFC3530 in that the change attribute is not
guaranteed to be updated for every change to the inode. Our optimisation
for checking whether or not the inode metadata has changed or not is broken
too. Grr....

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

index d0b991a92327f32941a454865c6aed187523d52e..e870e4aae714946dfc29c66e7ac3f889ce70949c 100644 (file)
@@ -1414,9 +1414,8 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
        /* Do atomic weak cache consistency updates */
        nfs_wcc_update_inode(inode, fattr);
 
-       if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0) {
-               if (nfsi->change_attr == fattr->change_attr)
-                       goto out;
+       if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+                       nfsi->change_attr != fattr->change_attr) {
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
                if (!data_unstable)
                        nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE;
@@ -1444,7 +1443,6 @@ static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fat
        if (inode->i_nlink != fattr->nlink)
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR;
 
-out:
        if (!timespec_equal(&inode->i_atime, &fattr->atime))
                nfsi->cache_validity |= NFS_INO_INVALID_ATIME;
 
@@ -1612,15 +1610,13 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr)
                inode->i_blksize = fattr->du.nfs2.blocksize;
        }
 
-       if ((fattr->valid & NFS_ATTR_FATTR_V4)) {
-               if (nfsi->change_attr != fattr->change_attr) {
-                       dprintk("NFS: change_attr change on server for file %s/%ld\n",
-                                       inode->i_sb->s_id, inode->i_ino);
-                       nfsi->change_attr = fattr->change_attr;
-                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
-                       nfsi->cache_change_attribute = jiffies;
-               } else
-                       invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA);
+       if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 &&
+                       nfsi->change_attr != fattr->change_attr) {
+               dprintk("NFS: change_attr change on server for file %s/%ld\n",
+                               inode->i_sb->s_id, inode->i_ino);
+               nfsi->change_attr = fattr->change_attr;
+               invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+               nfsi->cache_change_attribute = jiffies;
        }
 
        /* Update attrtimeo value if we're out of the unstable period */