Commit 2b666a11 authored by Trond Myklebust's avatar Trond Myklebust

Merge tag 'fscache-fixes-20200508-2' of...

Merge tag 'fscache-fixes-20200508-2' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs

 (1) The reorganisation of bmap() use accidentally caused the return value
     of cachefiles_read_or_alloc_pages() to get corrupted.

 (2) The NFS superblock index key accidentally got changed to include a
     number of kernel pointers - meaning that the key isn't matchable after
     a reboot.

 (3) A redundant check in nfs_fscache_get_super_cookie().

 (4) The NFS change_attr sometimes set in the auxiliary data for the
     caching of an file and sometimes not, which causes the cache to get
     discarded when it shouldn't.

 (5) There's a race between cachefiles_read_waiter() and
     cachefiles_read_copier() that causes an occasional assertion failure.
parents ce99aa62 7bb0c533
...@@ -60,9 +60,9 @@ static int cachefiles_read_waiter(wait_queue_entry_t *wait, unsigned mode, ...@@ -60,9 +60,9 @@ static int cachefiles_read_waiter(wait_queue_entry_t *wait, unsigned mode,
object = container_of(op->op.object, struct cachefiles_object, fscache); object = container_of(op->op.object, struct cachefiles_object, fscache);
spin_lock(&object->work_lock); spin_lock(&object->work_lock);
list_add_tail(&monitor->op_link, &op->to_do); list_add_tail(&monitor->op_link, &op->to_do);
fscache_enqueue_retrieval(op);
spin_unlock(&object->work_lock); spin_unlock(&object->work_lock);
fscache_enqueue_retrieval(op);
fscache_put_retrieval(op); fscache_put_retrieval(op);
return 0; return 0;
} }
...@@ -398,7 +398,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, ...@@ -398,7 +398,7 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
struct inode *inode; struct inode *inode;
sector_t block; sector_t block;
unsigned shift; unsigned shift;
int ret; int ret, ret2;
object = container_of(op->op.object, object = container_of(op->op.object,
struct cachefiles_object, fscache); struct cachefiles_object, fscache);
...@@ -430,8 +430,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, ...@@ -430,8 +430,8 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op,
block = page->index; block = page->index;
block <<= shift; block <<= shift;
ret = bmap(inode, &block); ret2 = bmap(inode, &block);
ASSERT(ret < 0); ASSERT(ret2 == 0);
_debug("%llx -> %llx", _debug("%llx -> %llx",
(unsigned long long) (page->index << shift), (unsigned long long) (page->index << shift),
...@@ -739,8 +739,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, ...@@ -739,8 +739,8 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op,
block = page->index; block = page->index;
block <<= shift; block <<= shift;
ret = bmap(inode, &block); ret2 = bmap(inode, &block);
ASSERT(!ret); ASSERT(ret2 == 0);
_debug("%llx -> %llx", _debug("%llx -> %llx",
(unsigned long long) (page->index << shift), (unsigned long long) (page->index << shift),
......
...@@ -118,8 +118,6 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int ...@@ -118,8 +118,6 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
nfss->fscache_key = NULL; nfss->fscache_key = NULL;
nfss->fscache = NULL; nfss->fscache = NULL;
if (!(nfss->options & NFS_OPTION_FSCACHE))
return;
if (!uniq) { if (!uniq) {
uniq = ""; uniq = "";
ulen = 1; ulen = 1;
...@@ -188,7 +186,8 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int ...@@ -188,7 +186,8 @@ void nfs_fscache_get_super_cookie(struct super_block *sb, const char *uniq, int
/* create a cache index for looking up filehandles */ /* create a cache index for looking up filehandles */
nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache, nfss->fscache = fscache_acquire_cookie(nfss->nfs_client->fscache,
&nfs_fscache_super_index_def, &nfs_fscache_super_index_def,
key, sizeof(*key) + ulen, &key->key,
sizeof(key->key) + ulen,
NULL, 0, NULL, 0,
nfss, 0, true); nfss, 0, true);
dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n", dfprintk(FSCACHE, "NFS: get superblock cookie (0x%p/0x%p)\n",
...@@ -226,6 +225,19 @@ void nfs_fscache_release_super_cookie(struct super_block *sb) ...@@ -226,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. * Initialise the per-inode cache cookie pointer for an NFS inode.
*/ */
...@@ -239,14 +251,7 @@ void nfs_fscache_init_inode(struct inode *inode) ...@@ -239,14 +251,7 @@ void nfs_fscache_init_inode(struct inode *inode)
if (!(nfss->fscache && S_ISREG(inode->i_mode))) if (!(nfss->fscache && S_ISREG(inode->i_mode)))
return; return;
memset(&auxdata, 0, sizeof(auxdata)); nfs_fscache_update_auxdata(&auxdata, nfsi);
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);
nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache, nfsi->fscache = fscache_acquire_cookie(NFS_SB(inode->i_sb)->fscache,
&nfs_fscache_inode_object_def, &nfs_fscache_inode_object_def,
...@@ -266,11 +271,7 @@ void nfs_fscache_clear_inode(struct inode *inode) ...@@ -266,11 +271,7 @@ void nfs_fscache_clear_inode(struct inode *inode)
dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie);
memset(&auxdata, 0, sizeof(auxdata)); nfs_fscache_update_auxdata(&auxdata, nfsi);
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;
fscache_relinquish_cookie(cookie, &auxdata, false); fscache_relinquish_cookie(cookie, &auxdata, false);
nfsi->fscache = NULL; nfsi->fscache = NULL;
} }
...@@ -310,11 +311,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp) ...@@ -310,11 +311,7 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp)
if (!fscache_cookie_valid(cookie)) if (!fscache_cookie_valid(cookie))
return; return;
memset(&auxdata, 0, sizeof(auxdata)); nfs_fscache_update_auxdata(&auxdata, nfsi);
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 (inode_is_open_for_write(inode)) { if (inode_is_open_for_write(inode)) {
dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi);
......
...@@ -1189,7 +1189,6 @@ static void nfs_get_cache_cookie(struct super_block *sb, ...@@ -1189,7 +1189,6 @@ static void nfs_get_cache_cookie(struct super_block *sb,
uniq = ctx->fscache_uniq; uniq = ctx->fscache_uniq;
ulen = strlen(ctx->fscache_uniq); ulen = strlen(ctx->fscache_uniq);
} }
return;
} }
nfs_fscache_get_super_cookie(sb, uniq, ulen); nfs_fscache_get_super_cookie(sb, uniq, ulen);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment