Skip to content

Commit ea5dc04

Browse files
lostjeffledhowells
authored andcommitted
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 <[email protected]> Fixes: 1f08c92 ("cachefiles: Implement backing file wrangling") Signed-off-by: Jeffle Xu <[email protected]> Signed-off-by: David Howells <[email protected]> cc: [email protected] 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
1 parent 42e7a03 commit ea5dc04

File tree

1 file changed

+24
-9
lines changed

1 file changed

+24
-9
lines changed

fs/cachefiles/namei.c

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ static void __cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
5757
trace_cachefiles_mark_inactive(object, inode);
5858
}
5959

60+
static void cachefiles_do_unmark_inode_in_use(struct cachefiles_object *object,
61+
struct dentry *dentry)
62+
{
63+
struct inode *inode = d_backing_inode(dentry);
64+
65+
inode_lock(inode);
66+
__cachefiles_unmark_inode_in_use(object, dentry);
67+
inode_unlock(inode);
68+
}
69+
6070
/*
6171
* Unmark a backing inode and tell cachefilesd that there's something that can
6272
* be culled.
@@ -68,9 +78,7 @@ void cachefiles_unmark_inode_in_use(struct cachefiles_object *object,
6878
struct inode *inode = file_inode(file);
6979

7080
if (inode) {
71-
inode_lock(inode);
72-
__cachefiles_unmark_inode_in_use(object, file->f_path.dentry);
73-
inode_unlock(inode);
81+
cachefiles_do_unmark_inode_in_use(object, file->f_path.dentry);
7482

7583
if (!test_bit(CACHEFILES_OBJECT_USING_TMPFILE, &object->flags)) {
7684
atomic_long_add(inode->i_blocks, &cache->b_released);
@@ -484,7 +492,7 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
484492
object, d_backing_inode(path.dentry), ret,
485493
cachefiles_trace_trunc_error);
486494
file = ERR_PTR(ret);
487-
goto out_dput;
495+
goto out_unuse;
488496
}
489497
}
490498

@@ -494,15 +502,20 @@ struct file *cachefiles_create_tmpfile(struct cachefiles_object *object)
494502
trace_cachefiles_vfs_error(object, d_backing_inode(path.dentry),
495503
PTR_ERR(file),
496504
cachefiles_trace_open_error);
497-
goto out_dput;
505+
goto out_unuse;
498506
}
499507
if (unlikely(!file->f_op->read_iter) ||
500508
unlikely(!file->f_op->write_iter)) {
501509
fput(file);
502510
pr_notice("Cache does not support read_iter and write_iter\n");
503511
file = ERR_PTR(-EINVAL);
512+
goto out_unuse;
504513
}
505514

515+
goto out_dput;
516+
517+
out_unuse:
518+
cachefiles_do_unmark_inode_in_use(object, path.dentry);
506519
out_dput:
507520
dput(path.dentry);
508521
out:
@@ -590,14 +603,16 @@ static bool cachefiles_open_file(struct cachefiles_object *object,
590603
check_failed:
591604
fscache_cookie_lookup_negative(object->cookie);
592605
cachefiles_unmark_inode_in_use(object, file);
593-
if (ret == -ESTALE) {
594-
fput(file);
595-
dput(dentry);
606+
fput(file);
607+
dput(dentry);
608+
if (ret == -ESTALE)
596609
return cachefiles_create_file(object);
597-
}
610+
return false;
611+
598612
error_fput:
599613
fput(file);
600614
error:
615+
cachefiles_do_unmark_inode_in_use(object, dentry);
601616
dput(dentry);
602617
return false;
603618
}

0 commit comments

Comments
 (0)