mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/herbert/cryptodev-2.6.git
synced 2026-04-18 03:23:53 -04:00
VFS/nfsd/cachefiles/ovl: introduce start_removing() and end_removing()
start_removing() is similar to start_creating() but will only return a positive dentry with the expectation that it will be removed. This is used by nfsd, cachefiles, and overlayfs. They are changed to also use end_removing() to terminate the action begun by start_removing(). This is a simple alias for end_dirop(). Apart from changes to the error paths, as we no longer need to unlock on a lookup error, an effect on callers is that they don't need to test if the found dentry is positive or negative - they can be sure it is positive. Reviewed-by: Amir Goldstein <amir73il@gmail.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: NeilBrown <neil@brown.name> Link: https://patch.msgid.link/20251113002050.676694-6-neilb@ownmail.net Tested-by: syzbot@syzkaller.appspotmail.com Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
committed by
Christian Brauner
parent
7ab96df840
commit
bd6ede8a06
@@ -260,6 +260,7 @@ static int cachefiles_unlink(struct cachefiles_cache *cache,
|
||||
* - File backed objects are unlinked
|
||||
* - Directory backed objects are stuffed into the graveyard for userspace to
|
||||
* delete
|
||||
* On entry dir must be locked. It will be unlocked on exit.
|
||||
*/
|
||||
int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||
struct cachefiles_object *object,
|
||||
@@ -274,28 +275,30 @@ int cachefiles_bury_object(struct cachefiles_cache *cache,
|
||||
|
||||
_enter(",'%pd','%pd'", dir, rep);
|
||||
|
||||
/* end_removing() will dput() @rep but we need to keep
|
||||
* a ref, so take one now. This also stops the dentry
|
||||
* being negated when unlinked which we need.
|
||||
*/
|
||||
dget(rep);
|
||||
|
||||
if (rep->d_parent != dir) {
|
||||
inode_unlock(d_inode(dir));
|
||||
end_removing(rep);
|
||||
_leave(" = -ESTALE");
|
||||
return -ESTALE;
|
||||
}
|
||||
|
||||
/* non-directories can just be unlinked */
|
||||
if (!d_is_dir(rep)) {
|
||||
dget(rep); /* Stop the dentry being negated if it's only pinned
|
||||
* by a file struct.
|
||||
*/
|
||||
ret = cachefiles_unlink(cache, object, dir, rep, why);
|
||||
dput(rep);
|
||||
end_removing(rep);
|
||||
|
||||
inode_unlock(d_inode(dir));
|
||||
_leave(" = %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* directories have to be moved to the graveyard */
|
||||
_debug("move stale object to graveyard");
|
||||
inode_unlock(d_inode(dir));
|
||||
end_removing(rep);
|
||||
|
||||
try_again:
|
||||
/* first step is to make up a grave dentry in the graveyard */
|
||||
@@ -749,26 +752,20 @@ static struct dentry *cachefiles_lookup_for_cull(struct cachefiles_cache *cache,
|
||||
struct dentry *victim;
|
||||
int ret = -ENOENT;
|
||||
|
||||
inode_lock_nested(d_inode(dir), I_MUTEX_PARENT);
|
||||
victim = start_removing(&nop_mnt_idmap, dir, &QSTR(filename));
|
||||
|
||||
victim = lookup_one(&nop_mnt_idmap, &QSTR(filename), dir);
|
||||
if (IS_ERR(victim))
|
||||
goto lookup_error;
|
||||
if (d_is_negative(victim))
|
||||
goto lookup_put;
|
||||
if (d_inode(victim)->i_flags & S_KERNEL_FILE)
|
||||
goto lookup_busy;
|
||||
return victim;
|
||||
|
||||
lookup_busy:
|
||||
ret = -EBUSY;
|
||||
lookup_put:
|
||||
inode_unlock(d_inode(dir));
|
||||
dput(victim);
|
||||
end_removing(victim);
|
||||
return ERR_PTR(ret);
|
||||
|
||||
lookup_error:
|
||||
inode_unlock(d_inode(dir));
|
||||
ret = PTR_ERR(victim);
|
||||
if (ret == -ENOENT)
|
||||
return ERR_PTR(-ESTALE); /* Probably got retired by the netfs */
|
||||
@@ -816,18 +813,17 @@ int cachefiles_cull(struct cachefiles_cache *cache, struct dentry *dir,
|
||||
|
||||
ret = cachefiles_bury_object(cache, NULL, dir, victim,
|
||||
FSCACHE_OBJECT_WAS_CULLED);
|
||||
dput(victim);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
fscache_count_culled();
|
||||
dput(victim);
|
||||
_leave(" = 0");
|
||||
return 0;
|
||||
|
||||
error_unlock:
|
||||
inode_unlock(d_inode(dir));
|
||||
end_removing(victim);
|
||||
error:
|
||||
dput(victim);
|
||||
if (ret == -ENOENT)
|
||||
return -ESTALE; /* Probably got retired by the netfs */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user