Skip to content

Commit f97f020

Browse files
committed
Merge patch series "btrfs: stop duplicating VFS code for subvolume/snapshot dentry"
Filipe Manana <fdmanana@suse.com> says: Currently btrfs has copies of two unexported functions from fs/namei.c used in the snapshot/subvolume creation and deletion. This patchset exports those functions and makes btrfs use them, to avoid duplication and the burden of keeping the copies up to date. * patches from https://patch.msgid.link/cover.1768307858.git.fdmanana@suse.com: btrfs: use may_create_dentry() in btrfs_mksubvol() btrfs: use may_delete_dentry() in btrfs_ioctl_snap_destroy() fs: export may_create() as may_create_dentry() fs: export may_delete() as may_delete_dentry() Link: https://patch.msgid.link/cover.1768307858.git.fdmanana@suse.com Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 8f0b4cc + 6c91c77 commit f97f020

File tree

3 files changed

+26
-88
lines changed

3 files changed

+26
-88
lines changed

fs/btrfs/ioctl.c

Lines changed: 2 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -815,75 +815,6 @@ static int create_snapshot(struct btrfs_root *root, struct inode *dir,
815815
return ret;
816816
}
817817

818-
/* copy of may_delete in fs/namei.c()
819-
* Check whether we can remove a link victim from directory dir, check
820-
* whether the type of victim is right.
821-
* 1. We can't do it if dir is read-only (done in permission())
822-
* 2. We should have write and exec permissions on dir
823-
* 3. We can't remove anything from append-only dir
824-
* 4. We can't do anything with immutable dir (done in permission())
825-
* 5. If the sticky bit on dir is set we should either
826-
* a. be owner of dir, or
827-
* b. be owner of victim, or
828-
* c. have CAP_FOWNER capability
829-
* 6. If the victim is append-only or immutable we can't do anything with
830-
* links pointing to it.
831-
* 7. If we were asked to remove a directory and victim isn't one - ENOTDIR.
832-
* 8. If we were asked to remove a non-directory and victim isn't one - EISDIR.
833-
* 9. We can't remove a root or mountpoint.
834-
* 10. We don't allow removal of NFS sillyrenamed files; it's handled by
835-
* nfs_async_unlink().
836-
*/
837-
838-
static int btrfs_may_delete(struct mnt_idmap *idmap,
839-
struct inode *dir, struct dentry *victim, int isdir)
840-
{
841-
int ret;
842-
843-
if (d_really_is_negative(victim))
844-
return -ENOENT;
845-
846-
/* The @victim is not inside @dir. */
847-
if (d_inode(victim->d_parent) != dir)
848-
return -EINVAL;
849-
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
850-
851-
ret = inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
852-
if (ret)
853-
return ret;
854-
if (IS_APPEND(dir))
855-
return -EPERM;
856-
if (check_sticky(idmap, dir, d_inode(victim)) ||
857-
IS_APPEND(d_inode(victim)) || IS_IMMUTABLE(d_inode(victim)) ||
858-
IS_SWAPFILE(d_inode(victim)))
859-
return -EPERM;
860-
if (isdir) {
861-
if (!d_is_dir(victim))
862-
return -ENOTDIR;
863-
if (IS_ROOT(victim))
864-
return -EBUSY;
865-
} else if (d_is_dir(victim))
866-
return -EISDIR;
867-
if (IS_DEADDIR(dir))
868-
return -ENOENT;
869-
if (victim->d_flags & DCACHE_NFSFS_RENAMED)
870-
return -EBUSY;
871-
return 0;
872-
}
873-
874-
/* copy of may_create in fs/namei.c() */
875-
static inline int btrfs_may_create(struct mnt_idmap *idmap,
876-
struct inode *dir, const struct dentry *child)
877-
{
878-
if (d_really_is_positive(child))
879-
return -EEXIST;
880-
if (IS_DEADDIR(dir))
881-
return -ENOENT;
882-
if (!fsuidgid_has_mapping(dir->i_sb, idmap))
883-
return -EOVERFLOW;
884-
return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
885-
}
886-
887818
/*
888819
* Create a new subvolume below @parent. This is largely modeled after
889820
* sys_mkdirat and vfs_mkdir, but we only do a single component lookup
@@ -905,7 +836,7 @@ static noinline int btrfs_mksubvol(struct dentry *parent,
905836
if (IS_ERR(dentry))
906837
return PTR_ERR(dentry);
907838

908-
ret = btrfs_may_create(idmap, dir, dentry);
839+
ret = may_create_dentry(idmap, dir, dentry);
909840
if (ret)
910841
goto out_dput;
911842

@@ -2420,7 +2351,7 @@ static noinline int btrfs_ioctl_snap_destroy(struct file *file,
24202351
}
24212352

24222353
/* check if subvolume may be deleted by a user */
2423-
ret = btrfs_may_delete(idmap, dir, dentry, 1);
2354+
ret = may_delete_dentry(idmap, dir, dentry, true);
24242355
if (ret)
24252356
goto out_end_removing;
24262357

fs/namei.c

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3604,7 +3604,7 @@ EXPORT_SYMBOL(__check_sticky);
36043604
* 11. We don't allow removal of NFS sillyrenamed files; it's handled by
36053605
* nfs_async_unlink().
36063606
*/
3607-
static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
3607+
int may_delete_dentry(struct mnt_idmap *idmap, struct inode *dir,
36083608
struct dentry *victim, bool isdir)
36093609
{
36103610
struct inode *inode = d_backing_inode(victim);
@@ -3646,6 +3646,7 @@ static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
36463646
return -EBUSY;
36473647
return 0;
36483648
}
3649+
EXPORT_SYMBOL(may_delete_dentry);
36493650

36503651
/* Check whether we can create an object with dentry child in directory
36513652
* dir.
@@ -3656,8 +3657,8 @@ static int may_delete(struct mnt_idmap *idmap, struct inode *dir,
36563657
* 4. We should have write and exec permissions on dir
36573658
* 5. We can't do it if dir is immutable (done in permission())
36583659
*/
3659-
static inline int may_create(struct mnt_idmap *idmap,
3660-
struct inode *dir, struct dentry *child)
3660+
int may_create_dentry(struct mnt_idmap *idmap,
3661+
struct inode *dir, struct dentry *child)
36613662
{
36623663
audit_inode_child(dir, child, AUDIT_TYPE_CHILD_CREATE);
36633664
if (child->d_inode)
@@ -3669,6 +3670,7 @@ static inline int may_create(struct mnt_idmap *idmap,
36693670

36703671
return inode_permission(idmap, dir, MAY_WRITE | MAY_EXEC);
36713672
}
3673+
EXPORT_SYMBOL(may_create_dentry);
36723674

36733675
// p1 != p2, both are on the same filesystem, ->s_vfs_rename_mutex is held
36743676
static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2)
@@ -4115,7 +4117,7 @@ int vfs_create(struct mnt_idmap *idmap, struct dentry *dentry, umode_t mode,
41154117
struct inode *dir = d_inode(dentry->d_parent);
41164118
int error;
41174119

4118-
error = may_create(idmap, dir, dentry);
4120+
error = may_create_dentry(idmap, dir, dentry);
41194121
if (error)
41204122
return error;
41214123

@@ -4141,7 +4143,7 @@ int vfs_mkobj(struct dentry *dentry, umode_t mode,
41414143
void *arg)
41424144
{
41434145
struct inode *dir = dentry->d_parent->d_inode;
4144-
int error = may_create(&nop_mnt_idmap, dir, dentry);
4146+
int error = may_create_dentry(&nop_mnt_idmap, dir, dentry);
41454147
if (error)
41464148
return error;
41474149

@@ -4960,7 +4962,7 @@ int vfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
49604962
struct delegated_inode *delegated_inode)
49614963
{
49624964
bool is_whiteout = S_ISCHR(mode) && dev == WHITEOUT_DEV;
4963-
int error = may_create(idmap, dir, dentry);
4965+
int error = may_create_dentry(idmap, dir, dentry);
49644966

49654967
if (error)
49664968
return error;
@@ -5106,7 +5108,7 @@ struct dentry *vfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
51065108
unsigned max_links = dir->i_sb->s_max_links;
51075109
struct dentry *de;
51085110

5109-
error = may_create(idmap, dir, dentry);
5111+
error = may_create_dentry(idmap, dir, dentry);
51105112
if (error)
51115113
goto err;
51125114

@@ -5209,7 +5211,7 @@ SYSCALL_DEFINE2(mkdir, const char __user *, pathname, umode_t, mode)
52095211
int vfs_rmdir(struct mnt_idmap *idmap, struct inode *dir,
52105212
struct dentry *dentry, struct delegated_inode *delegated_inode)
52115213
{
5212-
int error = may_delete(idmap, dir, dentry, 1);
5214+
int error = may_delete_dentry(idmap, dir, dentry, true);
52135215

52145216
if (error)
52155217
return error;
@@ -5344,7 +5346,7 @@ int vfs_unlink(struct mnt_idmap *idmap, struct inode *dir,
53445346
struct dentry *dentry, struct delegated_inode *delegated_inode)
53455347
{
53465348
struct inode *target = dentry->d_inode;
5347-
int error = may_delete(idmap, dir, dentry, 0);
5349+
int error = may_delete_dentry(idmap, dir, dentry, false);
53485350

53495351
if (error)
53505352
return error;
@@ -5496,7 +5498,7 @@ int vfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
54965498
{
54975499
int error;
54985500

5499-
error = may_create(idmap, dir, dentry);
5501+
error = may_create_dentry(idmap, dir, dentry);
55005502
if (error)
55015503
return error;
55025504

@@ -5604,7 +5606,7 @@ int vfs_link(struct dentry *old_dentry, struct mnt_idmap *idmap,
56045606
if (!inode)
56055607
return -ENOENT;
56065608

5607-
error = may_create(idmap, dir, new_dentry);
5609+
error = may_create_dentry(idmap, dir, new_dentry);
56085610
if (error)
56095611
return error;
56105612

@@ -5816,21 +5818,21 @@ int vfs_rename(struct renamedata *rd)
58165818
if (source == target)
58175819
return 0;
58185820

5819-
error = may_delete(rd->mnt_idmap, old_dir, old_dentry, is_dir);
5821+
error = may_delete_dentry(rd->mnt_idmap, old_dir, old_dentry, is_dir);
58205822
if (error)
58215823
return error;
58225824

58235825
if (!target) {
5824-
error = may_create(rd->mnt_idmap, new_dir, new_dentry);
5826+
error = may_create_dentry(rd->mnt_idmap, new_dir, new_dentry);
58255827
} else {
58265828
new_is_dir = d_is_dir(new_dentry);
58275829

58285830
if (!(flags & RENAME_EXCHANGE))
5829-
error = may_delete(rd->mnt_idmap, new_dir,
5830-
new_dentry, is_dir);
5831+
error = may_delete_dentry(rd->mnt_idmap, new_dir,
5832+
new_dentry, is_dir);
58315833
else
5832-
error = may_delete(rd->mnt_idmap, new_dir,
5833-
new_dentry, new_is_dir);
5834+
error = may_delete_dentry(rd->mnt_idmap, new_dir,
5835+
new_dentry, new_is_dir);
58345836
}
58355837
if (error)
58365838
return error;

include/linux/fs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,6 +2657,11 @@ static inline int path_permission(const struct path *path, int mask)
26572657
int __check_sticky(struct mnt_idmap *idmap, struct inode *dir,
26582658
struct inode *inode);
26592659

2660+
int may_delete_dentry(struct mnt_idmap *idmap, struct inode *dir,
2661+
struct dentry *victim, bool isdir);
2662+
int may_create_dentry(struct mnt_idmap *idmap,
2663+
struct inode *dir, struct dentry *child);
2664+
26602665
static inline bool execute_ok(struct inode *inode)
26612666
{
26622667
return (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode);

0 commit comments

Comments
 (0)