Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0840f672 authored by Dave Wysochanski's avatar Dave Wysochanski Committed by Greg Kroah-Hartman
Browse files

NFSv4: Fix fscache cookie aux_data to ensure change_attr is included



[ Upstream commit 50eaa652b54df1e2b48dc398d9e6114c9ed080eb ]

Commit 402cb8dd ("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: 402cb8dd ("fscache: Attach the index key and aux data to the cookie")
Signed-off-by: default avatarDave Wysochanski <dwysocha@redhat.com>
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent d8b16f4a
Loading
Loading
Loading
Loading
+16 −18
Original line number Diff line number Diff line
@@ -231,6 +231,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.
 */
@@ -244,14 +257,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,
@@ -271,11 +277,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;
}
@@ -315,11 +317,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);