]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: use may_delete_dentry() in btrfs_ioctl_snap_destroy()
authorFilipe Manana <fdmanana@suse.com>
Tue, 13 Jan 2026 12:39:52 +0000 (12:39 +0000)
committerChristian Brauner <brauner@kernel.org>
Wed, 14 Jan 2026 16:17:47 +0000 (17:17 +0100)
There is no longer the need to use btrfs_may_delete(), which was a copy
of the VFS private function may_delete(), since now that functionality
is exported by the VFS as a function named may_delete_dentry(). In fact
our local copy of may_delete() lacks an update that happened to that
function which is point number 7 in that function's comment:

  "7. If the victim has an unknown uid or gid we can't change the inode."

which corresponds to this code:

/* Inode writeback is not safe when the uid or gid are invalid. */
if (!vfsuid_valid(i_uid_into_vfsuid(idmap, inode)) ||
    !vfsgid_valid(i_gid_into_vfsgid(idmap, inode)))
return -EOVERFLOW;

As long as we keep a separate copy, duplicating code, we are also prone
to updates to the VFS being missed in our local copy.

So change btrfs_ioctl_snap_destroy() to use the VFS function and remove
btrfs_may_delete().

Signed-off-by: Filipe Manana <fdmanana@suse.com>
Link: https://patch.msgid.link/46b13dc5c957deb72a7f085916757a20878a8e73.1768307858.git.fdmanana@suse.com
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: Christian Brauner <brauner@kernel.org>
fs/btrfs/ioctl.c

index acb484546b1da10cb3233b5ba85837f41e584e33..2d0b2619309d76403bdd567c3d2b779abedcd603 100644 (file)
@@ -815,62 +815,6 @@ free_pending:
        return ret;
 }
 
-/*  copy of may_delete in fs/namei.c()
- *     Check whether we can remove a link victim from directory dir, check
- *  whether the type of victim is right.
- *  1. We can't do it if dir is read-only (done in permission())
- *  2. We should have write and exec permissions on dir
- *  3. We can't remove anything from append-only dir
- *  4. We can't do anything with immutable dir (done in permission())
- *  5. If the sticky bit on dir is set we should either
- *     a. be owner of dir, or
- *     b. be owner of victim, or
- *     c. have CAP_FOWNER capability
- *  6. If the victim is append-only or immutable we can't do anything with
- *     links pointing to it.
- *  7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
- *  8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
- *  9. We can't remove a root or mountpoint.
- * 10. We don't allow removal of NFS sillyrenamed files; it's handled by
- *     nfs_async_unlink().
- */
-
-static int btrfs_may_delete(struct mnt_idmap *idmap,
-                           struct inode *dir, struct dentry *victim, int isdir)
-{
-       int ret;
-
-       if (d_really_is_negative(victim))
-               return -ENOENT;
-
-       /* The @victim is not inside @dir. */
-       if (d_inode(victim->d_parent) != dir)
-               return -EINVAL;
-       audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
-
-       ret = inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
-       if (ret)
-               return ret;
-       if (IS_APPEND(dir))
-               return -EPERM;
-       if (check_sticky(idmap, dir, d_inode(victim)) ||
-           IS_APPEND(d_inode(victim)) || IS_IMMUTABLE(d_inode(victim)) ||
-           IS_SWAPFILE(d_inode(victim)))
-               return -EPERM;
-       if (isdir) {
-               if (!d_is_dir(victim))
-                       return -ENOTDIR;
-               if (IS_ROOT(victim))
-                       return -EBUSY;
-       } else if (d_is_dir(victim))
-               return -EISDIR;
-       if (IS_DEADDIR(dir))
-               return -ENOENT;
-       if (victim->d_flags & DCACHE_NFSFS_RENAMED)
-               return -EBUSY;
-       return 0;
-}
-
 /* copy of may_create in fs/namei.c() */
 static inline int btrfs_may_create(struct mnt_idmap *idmap,
                                   struct inode *dir, const struct dentry *child)
@@ -2420,7 +2364,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
        }
 
        /* check if subvolume may be deleted by a user */
-       ret = btrfs_may_delete(idmap, dir, dentry, 1);
+       ret = may_delete_dentry(idmap, dir, dentry, true);
        if (ret)
                goto out_end_removing;