| From 8c69881fa24f0bf89cabd12018afc3a981a5cdba Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 16 Apr 2020 06:06:08 -0400 |
| Subject: NFSv4: Fix fscache cookie aux_data to ensure change_attr is included |
| |
| From: Dave Wysochanski <dwysocha@redhat.com> |
| |
| [ Upstream commit 50eaa652b54df1e2b48dc398d9e6114c9ed080eb ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/nfs/fscache.c | 34 ++++++++++++++++------------------ |
| 1 file changed, 16 insertions(+), 18 deletions(-) |
| |
| diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c |
| index f517184156068..a60df88efc404 100644 |
| --- a/fs/nfs/fscache.c |
| +++ b/fs/nfs/fscache.c |
| @@ -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); |
| -- |
| 2.20.1 |
| |