cachefiles: unmark inode in use in error path
Unmark inode in use if error encountered. If the in-use flag leakage
occurs in cachefiles_open_file(), Cachefiles will complain "Inode
already in use" when later another cookie with the same index key is
looked up.
If the in-use flag leakage occurs in cachefiles_create_tmpfile(), though
the "Inode already in use" warning won't be triggered, fix the leakage
anyway.
Reported-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Fixes: 1f08c925e7
("cachefiles: Implement backing file wrangling")
Signed-off-by: Jeffle Xu <jefflexu@linux.alibaba.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-cachefs@redhat.com
Link: https://listman.redhat.com/archives/linux-cachefs/2022-March/006615.html # v1
Link: https://listman.redhat.com/archives/linux-cachefs/2022-March/006618.html # v2
This commit is contained in:
parent
42e7a03d3b
commit
ea5dc04612
@ -57,6 +57,16 @@ static void __cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
|
||||
trace_cachefiles_mark_inactive(object, inode);
|
||||
}
|
||||
|
||||
static void cachefiles_do_unmark_inode_in_use(struct cachefiles_object *object,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
struct inode *inode = d_backing_inode(dentry);
|
||||
|
||||
inode_lock(inode);
|
||||
__cachefiles_unmark_inode_in_use(object, dentry);
|
||||
inode_unlock(inode);
|
||||
}
|
||||
|
||||
/*
|
||||
* Unmark a backing inode and tell cachefilesd that there's something that can
|
||||
* be culled.
|
||||
@ -68,9 +78,7 @@ void cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
|
||||
struct inode *inode = file_inode(file);
|
||||
|
||||
if (inode) {
|
||||
inode_lock(inode);
|
||||
__cachefiles_unmark_inode_in_use(object, file->f_path.dentry);
|
||||
inode_unlock(inode);
|
||||
cachefiles_do_unmark_inode_in_use(object, file->f_path.dentry);
|
||||
|
||||
if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) {
|
||||
atomic_long_add(inode->i_blocks, &cache->b_released);
|
||||
@ -484,7 +492,7 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
|
||||
object, d_backing_inode(path.dentry), ret,
|
||||
cachefiles_trace_trunc_error);
|
||||
file = ERR_PTR(ret);
|
||||
goto out_dput;
|
||||
goto out_unuse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -494,15 +502,20 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
|
||||
trace_cachefiles_vfs_error(object, d_backing_inode(path.dentry),
|
||||
PTR_ERR(file),
|
||||
cachefiles_trace_open_error);
|
||||
goto out_dput;
|
||||
goto out_unuse;
|
||||
}
|
||||
if (unlikely(!file->f_op->read_iter) ||
|
||||
unlikely(!file->f_op->write_iter)) {
|
||||
fput(file);
|
||||
pr_notice("Cache does not support read_iter and write_iter\n");
|
||||
file = ERR_PTR(-EINVAL);
|
||||
goto out_unuse;
|
||||
}
|
||||
|
||||
goto out_dput;
|
||||
|
||||
out_unuse:
|
||||
cachefiles_do_unmark_inode_in_use(object, path.dentry);
|
||||
out_dput:
|
||||
dput(path.dentry);
|
||||
out:
|
||||
@ -590,14 +603,16 @@ static bool cachefiles_open_file(struct cachefiles_object *object,
|
||||
check_failed:
|
||||
fscache_cookie_lookup_negative(object->cookie);
|
||||
cachefiles_unmark_inode_in_use(object, file);
|
||||
if (ret == -ESTALE) {
|
||||
fput(file);
|
||||
dput(dentry);
|
||||
fput(file);
|
||||
dput(dentry);
|
||||
if (ret == -ESTALE)
|
||||
return cachefiles_create_file(object);
|
||||
}
|
||||
return false;
|
||||
|
||||
error_fput:
|
||||
fput(file);
|
||||
error:
|
||||
cachefiles_do_unmark_inode_in_use(object, dentry);
|
||||
dput(dentry);
|
||||
return false;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user