Skip to content

Commit

Permalink
f2fs: support idmapped mounts
Browse files Browse the repository at this point in the history
This patch enables idmapped mounts for f2fs, since all dedicated helpers
for this functionality existsm, so, in this patch we just pass down the
user_namespace argument from the VFS methods to the relevant helpers.

Simple idmap example on f2fs image:

1. truncate -s 128M f2fs.img
2. mkfs.f2fs f2fs.img
3. mount f2fs.img /mnt/f2fs/
4. touch /mnt/f2fs/file

5. ls -ln /mnt/f2fs/
total 0
-rw-r--r-- 1 0 0 0 2月   4 13:17 file

6. ./mount-idmapped --map-mount b:0:1001:1 /mnt/f2fs/ /mnt/scratch_f2fs/

7. ls -ln /mnt/scratch_f2fs/
total 0
-rw-r--r-- 1 1001 1001 0 2月   4 13:17 file

Signed-off-by: Chao Yu <chao@kernel.org>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
  • Loading branch information
chaseyu authored and Jaegeuk Kim committed Feb 12, 2022
1 parent 47c8ebc commit 984fc4e
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 37 deletions.
21 changes: 12 additions & 9 deletions fs/f2fs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ struct posix_acl *f2fs_get_acl(struct inode *inode, int type, bool rcu)
return __f2fs_get_acl(inode, type, NULL);
}

static int f2fs_acl_update_mode(struct inode *inode, umode_t *mode_p,
struct posix_acl **acl)
static int f2fs_acl_update_mode(struct user_namespace *mnt_userns,
struct inode *inode, umode_t *mode_p,
struct posix_acl **acl)
{
umode_t mode = inode->i_mode;
int error;
Expand All @@ -218,14 +219,15 @@ static int f2fs_acl_update_mode(struct inode *inode, umode_t *mode_p,
return error;
if (error == 0)
*acl = NULL;
if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) &&
!capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
if (!in_group_p(i_gid_into_mnt(mnt_userns, inode)) &&
!capable_wrt_inode_uidgid(mnt_userns, inode, CAP_FSETID))
mode &= ~S_ISGID;
*mode_p = mode;
return 0;
}

static int __f2fs_set_acl(struct inode *inode, int type,
static int __f2fs_set_acl(struct user_namespace *mnt_userns,
struct inode *inode, int type,
struct posix_acl *acl, struct page *ipage)
{
int name_index;
Expand All @@ -238,7 +240,8 @@ static int __f2fs_set_acl(struct inode *inode, int type,
case ACL_TYPE_ACCESS:
name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS;
if (acl && !ipage) {
error = f2fs_acl_update_mode(inode, &mode, &acl);
error = f2fs_acl_update_mode(mnt_userns, inode,
&mode, &acl);
if (error)
return error;
set_acl_inode(inode, mode);
Expand Down Expand Up @@ -279,7 +282,7 @@ int f2fs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
if (unlikely(f2fs_cp_error(F2FS_I_SB(inode))))
return -EIO;

return __f2fs_set_acl(inode, type, acl, NULL);
return __f2fs_set_acl(mnt_userns, inode, type, acl, NULL);
}

/*
Expand Down Expand Up @@ -419,15 +422,15 @@ int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage,
f2fs_mark_inode_dirty_sync(inode, true);

if (default_acl) {
error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl,
error = __f2fs_set_acl(NULL, inode, ACL_TYPE_DEFAULT, default_acl,
ipage);
posix_acl_release(default_acl);
} else {
inode->i_default_acl = NULL;
}
if (acl) {
if (!error)
error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl,
error = __f2fs_set_acl(NULL, inode, ACL_TYPE_ACCESS, acl,
ipage);
posix_acl_release(acl);
} else {
Expand Down
23 changes: 14 additions & 9 deletions fs/f2fs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -844,7 +844,7 @@ int f2fs_getattr(struct user_namespace *mnt_userns, const struct path *path,
STATX_ATTR_NODUMP |
STATX_ATTR_VERITY);

generic_fillattr(&init_user_ns, inode, stat);
generic_fillattr(mnt_userns, inode, stat);

/* we need to show initial sectors used for inline_data/dentries */
if ((S_ISREG(inode->i_mode) && f2fs_has_inline_data(inode)) ||
Expand Down Expand Up @@ -904,7 +904,7 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
!f2fs_is_compress_backend_ready(inode))
return -EOPNOTSUPP;

err = setattr_prepare(&init_user_ns, dentry, attr);
err = setattr_prepare(mnt_userns, dentry, attr);
if (err)
return err;

Expand Down Expand Up @@ -980,10 +980,10 @@ int f2fs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
spin_unlock(&F2FS_I(inode)->i_size_lock);
}

__setattr_copy(&init_user_ns, inode, attr);
__setattr_copy(mnt_userns, inode, attr);

if (attr->ia_valid & ATTR_MODE) {
err = posix_acl_chmod(&init_user_ns, inode, f2fs_get_inode_mode(inode));
err = posix_acl_chmod(mnt_userns, inode, f2fs_get_inode_mode(inode));

if (is_inode_flag_set(inode, FI_ACL_MODE)) {
if (!err)
Expand Down Expand Up @@ -1989,11 +1989,12 @@ static int f2fs_ioc_getversion(struct file *filp, unsigned long arg)
static int f2fs_ioc_start_atomic_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
struct f2fs_inode_info *fi = F2FS_I(inode);
struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int ret;

if (!inode_owner_or_capable(&init_user_ns, inode))
if (!inode_owner_or_capable(mnt_userns, inode))
return -EACCES;

if (!S_ISREG(inode->i_mode))
Expand Down Expand Up @@ -2058,9 +2059,10 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
static int f2fs_ioc_commit_atomic_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
int ret;

if (!inode_owner_or_capable(&init_user_ns, inode))
if (!inode_owner_or_capable(mnt_userns, inode))
return -EACCES;

ret = mnt_want_write_file(filp);
Expand Down Expand Up @@ -2100,9 +2102,10 @@ static int f2fs_ioc_commit_atomic_write(struct file *filp)
static int f2fs_ioc_start_volatile_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
int ret;

if (!inode_owner_or_capable(&init_user_ns, inode))
if (!inode_owner_or_capable(mnt_userns, inode))
return -EACCES;

if (!S_ISREG(inode->i_mode))
Expand Down Expand Up @@ -2135,9 +2138,10 @@ static int f2fs_ioc_start_volatile_write(struct file *filp)
static int f2fs_ioc_release_volatile_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
int ret;

if (!inode_owner_or_capable(&init_user_ns, inode))
if (!inode_owner_or_capable(mnt_userns, inode))
return -EACCES;

ret = mnt_want_write_file(filp);
Expand All @@ -2164,9 +2168,10 @@ static int f2fs_ioc_release_volatile_write(struct file *filp)
static int f2fs_ioc_abort_volatile_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
struct user_namespace *mnt_userns = file_mnt_user_ns(filp);
int ret;

if (!inode_owner_or_capable(&init_user_ns, inode))
if (!inode_owner_or_capable(mnt_userns, inode))
return -EACCES;

ret = mnt_want_write_file(filp);
Expand Down
41 changes: 23 additions & 18 deletions fs/f2fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
#include "acl.h"
#include <trace/events/f2fs.h>

static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
static struct inode *f2fs_new_inode(struct user_namespace *mnt_userns,
struct inode *dir, umode_t mode)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
nid_t ino;
Expand All @@ -46,7 +47,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)

nid_free = true;

inode_init_owner(&init_user_ns, inode, dir, mode);
inode_init_owner(mnt_userns, inode, dir, mode);

inode->i_ino = ino;
inode->i_blocks = 0;
Expand All @@ -67,7 +68,7 @@ static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode)
(F2FS_I(dir)->i_flags & F2FS_PROJINHERIT_FL))
F2FS_I(inode)->i_projid = F2FS_I(dir)->i_projid;
else
F2FS_I(inode)->i_projid = make_kprojid(&init_user_ns,
F2FS_I(inode)->i_projid = make_kprojid(mnt_userns,
F2FS_DEF_PROJID);

err = fscrypt_prepare_new_inode(dir, inode, &encrypt);
Expand Down Expand Up @@ -349,7 +350,7 @@ static int f2fs_create(struct user_namespace *mnt_userns, struct inode *dir,
if (err)
return err;

inode = f2fs_new_inode(dir, mode);
inode = f2fs_new_inode(mnt_userns, dir, mode);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -679,7 +680,7 @@ static int f2fs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
if (err)
return err;

inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO);
inode = f2fs_new_inode(mnt_userns, dir, S_IFLNK | S_IRWXUGO);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -750,7 +751,7 @@ static int f2fs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
if (err)
return err;

inode = f2fs_new_inode(dir, S_IFDIR | mode);
inode = f2fs_new_inode(mnt_userns, dir, S_IFDIR | mode);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -807,7 +808,7 @@ static int f2fs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
if (err)
return err;

inode = f2fs_new_inode(dir, mode);
inode = f2fs_new_inode(mnt_userns, dir, mode);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand All @@ -834,8 +835,9 @@ static int f2fs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
return err;
}

static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
umode_t mode, struct inode **whiteout)
static int __f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
struct dentry *dentry, umode_t mode,
struct inode **whiteout)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(dir);
struct inode *inode;
Expand All @@ -845,7 +847,7 @@ static int __f2fs_tmpfile(struct inode *dir, struct dentry *dentry,
if (err)
return err;

inode = f2fs_new_inode(dir, mode);
inode = f2fs_new_inode(mnt_userns, dir, mode);
if (IS_ERR(inode))
return PTR_ERR(inode);

Expand Down Expand Up @@ -909,20 +911,22 @@ static int f2fs_tmpfile(struct user_namespace *mnt_userns, struct inode *dir,
if (!f2fs_is_checkpoint_ready(sbi))
return -ENOSPC;

return __f2fs_tmpfile(dir, dentry, mode, NULL);
return __f2fs_tmpfile(mnt_userns, dir, dentry, mode, NULL);
}

static int f2fs_create_whiteout(struct inode *dir, struct inode **whiteout)
static int f2fs_create_whiteout(struct user_namespace *mnt_userns,
struct inode *dir, struct inode **whiteout)
{
if (unlikely(f2fs_cp_error(F2FS_I_SB(dir))))
return -EIO;

return __f2fs_tmpfile(dir, NULL, S_IFCHR | WHITEOUT_MODE, whiteout);
return __f2fs_tmpfile(mnt_userns, dir, NULL,
S_IFCHR | WHITEOUT_MODE, whiteout);
}

static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags)
static int f2fs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
struct dentry *old_dentry, struct inode *new_dir,
struct dentry *new_dentry, unsigned int flags)
{
struct f2fs_sb_info *sbi = F2FS_I_SB(old_dir);
struct inode *old_inode = d_inode(old_dentry);
Expand Down Expand Up @@ -960,7 +964,7 @@ static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry,
}

if (flags & RENAME_WHITEOUT) {
err = f2fs_create_whiteout(old_dir, &whiteout);
err = f2fs_create_whiteout(mnt_userns, old_dir, &whiteout);
if (err)
return err;
}
Expand Down Expand Up @@ -1300,7 +1304,8 @@ static int f2fs_rename2(struct user_namespace *mnt_userns,
* VFS has already handled the new dentry existence case,
* here, we just deal with "RENAME_NOREPLACE" as regular rename.
*/
return f2fs_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
return f2fs_rename(mnt_userns, old_dir, old_dentry,
new_dir, new_dentry, flags);
}

static const char *f2fs_encrypted_get_link(struct dentry *dentry,
Expand Down
2 changes: 1 addition & 1 deletion fs/f2fs/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -4539,7 +4539,7 @@ static struct file_system_type f2fs_fs_type = {
.name = "f2fs",
.mount = f2fs_mount,
.kill_sb = kill_f2fs_super,
.fs_flags = FS_REQUIRES_DEV,
.fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP,
};
MODULE_ALIAS_FS("f2fs");

Expand Down

0 comments on commit 984fc4e

Please sign in to comment.