]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
bcachefs: unlock parent dir if entry is not found in subvolume deletion
authorGuoyu Ou <benogy@gmail.com>
Sun, 28 Jan 2024 08:46:17 +0000 (16:46 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 16 Feb 2024 18:14:31 +0000 (19:14 +0100)
commit 6bb3f7f4c3f4da8e09de188f2f63e8f741bba3bd upstream.

Parent dir is locked by user_path_locked_at() before validating the
required dentry. It should be unlocked if we can not perform the
deletion.

This fixes the problem:

$ bcachefs subvolume delete not-exist-entry
BCH_IOCTL_SUBVOLUME_DESTROY ioctl error: No such file or directory
$ bcachefs subvolume delete not-exist-entry

the second will stuck because the parent dir is locked in the previous
deletion.

Signed-off-by: Guoyu Ou <benogy@gmail.com>
Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/bcachefs/fs-ioctl.c

index 99f157534404dc5653b89257801a7648dccdaf67..dbc87747eaafd3dbfef6667571deac986639ecb5 100644 (file)
@@ -463,6 +463,7 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
        if (IS_ERR(victim))
                return PTR_ERR(victim);
 
+       dir = d_inode(path.dentry);
        if (victim->d_sb->s_fs_info != c) {
                ret = -EXDEV;
                goto err;
@@ -471,14 +472,13 @@ static long bch2_ioctl_subvolume_destroy(struct bch_fs *c, struct file *filp,
                ret = -ENOENT;
                goto err;
        }
-       dir = d_inode(path.dentry);
        ret = __bch2_unlink(dir, victim, true);
        if (!ret) {
                fsnotify_rmdir(dir, victim);
                d_delete(victim);
        }
-       inode_unlock(dir);
 err:
+       inode_unlock(dir);
        dput(victim);
        path_put(&path);
        return ret;