diff options
| author | Filipe Manana <fdmanana@suse.com> | 2026-01-13 15:39:52 +0300 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-01-14 19:17:47 +0300 |
| commit | 5f84a1092dee7b2687804d71c0dd50edd6f2d32a (patch) | |
| tree | afaaede508da16b102b7657b3658d2a3a50a7f2b | |
| parent | 26aab3a485d500cb89ef7340797982bd066f63a5 (diff) | |
| download | linux-5f84a1092dee7b2687804d71c0dd50edd6f2d32a.tar.xz | |
btrfs: use may_delete_dentry() in btrfs_ioctl_snap_destroy()
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>
| -rw-r--r-- | fs/btrfs/ioctl.c | 58 |
1 files changed, 1 insertions, 57 deletions
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index acb484546b1d..2d0b2619309d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -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; |
