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.
This commit is contained in:
commit
2b666a110b
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue