NFSv4: Fix fscache cookie aux_data to ensure change_attr is included
authorDave Wysochanski <dwysocha@redhat.com>
Thu, 16 Apr 2020 10:06:08 +0000 (06:06 -0400)
committerDavid Howells <dhowells@redhat.com>
Fri, 8 May 2020 21:20:24 +0000 (22:20 +0100)
Commit 402cb8dda949 ("fscache: Attach the index key and aux data to
the cookie") added the aux_data and aux_data_len to parameters to
fscache_acquire_cookie(), and updated the callers in the NFS client.
In the process it modified the aux_data to include the change_attr,
but missed adding change_attr to a couple places where aux_data was
used.  Specifically, when opening a file and the change_attr is not
added, the following attempt to lookup an object will fail inside
cachefiles_check_object_xattr() = -116 due to
nfs_fscache_inode_check_aux() failing memcmp on auxdata and returning
FSCACHE_CHECKAUX_OBSOLETE.

Fix this by adding nfs_fscache_update_auxdata() to set the auxdata
from all relevant fields in the inode, including the change_attr.

Fixes: 402cb8dda949 ("fscache: Attach the index key and aux data to the cookie")
Signed-off-by: Dave Wysochanski <dwysocha@redhat.com>
Signed-off-by: David Howells <dhowells@redhat.com>
fs/nfs/fscache.c

index f517184..a60df88 100644 (file)
@@ -225,6 +225,19 @@ void nfs_fscache_release_super_cookie(struct super_block *sb)
        }
 }
 
+static void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
+                                 struct nfs_inode *nfsi)
+{
+       memset(auxdata, 0, sizeof(*auxdata));
+       auxdata->mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
+       auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
+       auxdata->ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
+       auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
+
+       if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
+               auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
+}
+
 /*
  * Initialise the per-inode cache cookie pointer for an NFS inode.
  */
@@ -238,14 +251,7 @@ void nfs_fscache_init_inode(struct inode *inode)
        if (!(nfss->fscache && S_ISREG(inode->i_mode)))
                return;
 
-       memset(&auxdata, 0, sizeof(auxdata));
-       auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
-       auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
-       auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
-       auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
-
-       if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
-               auxdata.change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
+       nfs_fscache_update_auxdata(&auxdata, nfsi);
 
        nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
                                               &nfs_fscache_inode_object_def,
@@ -265,11 +271,7 @@ void nfs_fscache_clear_inode(struct inode *inode)
 
        dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
 
-       memset(&auxdata, 0, sizeof(auxdata));
-       auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
-       auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
-       auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
-       auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
+       nfs_fscache_update_auxdata(&auxdata, nfsi);
        fscache_relinquish_cookie(cookie, &auxdata, false);
        nfsi->fscache = NULL;
 }
@@ -309,11 +311,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
        if (!fscache_cookie_valid(cookie))
                return;
 
-       memset(&auxdata, 0, sizeof(auxdata));
-       auxdata.mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
-       auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
-       auxdata.ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
-       auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
+       nfs_fscache_update_auxdata(&auxdata, nfsi);
 
        if (inode_is_open_for_write(inode)) {
                dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);