Commit 7c2e5963 authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: add resgid and resuid to reserve root blocks

This patch adds mount options to reserve some blocks via resgid=%u,resuid=%u.
It only activates with reserve_root=%u.
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 578c6478
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/magic.h> #include <linux/magic.h>
#include <linux/kobject.h> #include <linux/kobject.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/cred.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/bio.h> #include <linux/bio.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
...@@ -131,6 +132,12 @@ struct f2fs_mount_info { ...@@ -131,6 +132,12 @@ struct f2fs_mount_info {
#define F2FS_CLEAR_FEATURE(sb, mask) \ #define F2FS_CLEAR_FEATURE(sb, mask) \
(F2FS_SB(sb)->raw_super->feature &= ~cpu_to_le32(mask)) (F2FS_SB(sb)->raw_super->feature &= ~cpu_to_le32(mask))
/*
* Default values for user and/or group using reserved blocks
*/
#define F2FS_DEF_RESUID 0
#define F2FS_DEF_RESGID 0
/* /*
* For checkpoint manager * For checkpoint manager
*/ */
...@@ -1107,6 +1114,8 @@ struct f2fs_sb_info { ...@@ -1107,6 +1114,8 @@ struct f2fs_sb_info {
block_t reserved_blocks; /* configurable reserved blocks */ block_t reserved_blocks; /* configurable reserved blocks */
block_t current_reserved_blocks; /* current reserved blocks */ block_t current_reserved_blocks; /* current reserved blocks */
block_t root_reserved_blocks; /* root reserved blocks */ block_t root_reserved_blocks; /* root reserved blocks */
kuid_t s_resuid; /* reserved blocks for uid */
kgid_t s_resgid; /* reserved blocks for gid */
unsigned int nquota_files; /* # of quota sysfile */ unsigned int nquota_files; /* # of quota sysfile */
...@@ -1556,6 +1565,20 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs) ...@@ -1556,6 +1565,20 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)
return ofs == XATTR_NODE_OFFSET; return ofs == XATTR_NODE_OFFSET;
} }
static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi)
{
if (!test_opt(sbi, RESERVE_ROOT))
return false;
if (capable(CAP_SYS_RESOURCE))
return true;
if (uid_eq(sbi->s_resuid, current_fsuid()))
return true;
if (!gid_eq(sbi->s_resgid, GLOBAL_ROOT_GID) &&
in_group_p(sbi->s_resgid))
return true;
return false;
}
static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool); static inline void f2fs_i_blocks_write(struct inode *, block_t, bool, bool);
static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
struct inode *inode, blkcnt_t *count) struct inode *inode, blkcnt_t *count)
...@@ -1586,7 +1609,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, ...@@ -1586,7 +1609,7 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,
avail_user_block_count = sbi->user_block_count - avail_user_block_count = sbi->user_block_count -
sbi->current_reserved_blocks; sbi->current_reserved_blocks;
if (!(test_opt(sbi, RESERVE_ROOT) && capable(CAP_SYS_RESOURCE))) if (!__allow_reserved_blocks(sbi))
avail_user_block_count -= sbi->root_reserved_blocks; avail_user_block_count -= sbi->root_reserved_blocks;
if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) { if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
...@@ -1787,7 +1810,7 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi, ...@@ -1787,7 +1810,7 @@ static inline int inc_valid_node_count(struct f2fs_sb_info *sbi,
valid_block_count = sbi->total_valid_block_count + valid_block_count = sbi->total_valid_block_count +
sbi->current_reserved_blocks + 1; sbi->current_reserved_blocks + 1;
if (!(test_opt(sbi, RESERVE_ROOT) && capable(CAP_SYS_RESOURCE))) if (!__allow_reserved_blocks(sbi))
valid_block_count += sbi->root_reserved_blocks; valid_block_count += sbi->root_reserved_blocks;
if (unlikely(valid_block_count > sbi->user_block_count)) { if (unlikely(valid_block_count > sbi->user_block_count)) {
......
...@@ -108,6 +108,8 @@ enum { ...@@ -108,6 +108,8 @@ enum {
Opt_noinline_data, Opt_noinline_data,
Opt_data_flush, Opt_data_flush,
Opt_reserve_root, Opt_reserve_root,
Opt_resgid,
Opt_resuid,
Opt_mode, Opt_mode,
Opt_io_size_bits, Opt_io_size_bits,
Opt_fault_injection, Opt_fault_injection,
...@@ -159,6 +161,8 @@ static match_table_t f2fs_tokens = { ...@@ -159,6 +161,8 @@ static match_table_t f2fs_tokens = {
{Opt_noinline_data, "noinline_data"}, {Opt_noinline_data, "noinline_data"},
{Opt_data_flush, "data_flush"}, {Opt_data_flush, "data_flush"},
{Opt_reserve_root, "reserve_root=%u"}, {Opt_reserve_root, "reserve_root=%u"},
{Opt_resgid, "resgid=%u"},
{Opt_resuid, "resuid=%u"},
{Opt_mode, "mode=%s"}, {Opt_mode, "mode=%s"},
{Opt_io_size_bits, "io_bits=%u"}, {Opt_io_size_bits, "io_bits=%u"},
{Opt_fault_injection, "fault_injection=%u"}, {Opt_fault_injection, "fault_injection=%u"},
...@@ -204,6 +208,15 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi) ...@@ -204,6 +208,15 @@ static inline void limit_reserve_root(struct f2fs_sb_info *sbi)
"Reduce reserved blocks for root = %u", "Reduce reserved blocks for root = %u",
sbi->root_reserved_blocks); sbi->root_reserved_blocks);
} }
if (!test_opt(sbi, RESERVE_ROOT) &&
(!uid_eq(sbi->s_resuid,
make_kuid(&init_user_ns, F2FS_DEF_RESUID)) ||
!gid_eq(sbi->s_resgid,
make_kgid(&init_user_ns, F2FS_DEF_RESGID))))
f2fs_msg(sbi->sb, KERN_INFO,
"Ignore s_resuid=%u, s_resgid=%u w/o reserve_root",
from_kuid_munged(&init_user_ns, sbi->s_resuid),
from_kgid_munged(&init_user_ns, sbi->s_resgid));
} }
static void init_once(void *foo) static void init_once(void *foo)
...@@ -336,6 +349,8 @@ static int parse_options(struct super_block *sb, char *options) ...@@ -336,6 +349,8 @@ static int parse_options(struct super_block *sb, char *options)
substring_t args[MAX_OPT_ARGS]; substring_t args[MAX_OPT_ARGS];
char *p, *name; char *p, *name;
int arg = 0; int arg = 0;
kuid_t uid;
kgid_t gid;
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
int ret; int ret;
#endif #endif
...@@ -515,6 +530,28 @@ static int parse_options(struct super_block *sb, char *options) ...@@ -515,6 +530,28 @@ static int parse_options(struct super_block *sb, char *options)
set_opt(sbi, RESERVE_ROOT); set_opt(sbi, RESERVE_ROOT);
} }
break; break;
case Opt_resuid:
if (args->from && match_int(args, &arg))
return -EINVAL;
uid = make_kuid(current_user_ns(), arg);
if (!uid_valid(uid)) {
f2fs_msg(sb, KERN_ERR,
"Invalid uid value %d", arg);
return -EINVAL;
}
sbi->s_resuid = uid;
break;
case Opt_resgid:
if (args->from && match_int(args, &arg))
return -EINVAL;
gid = make_kgid(current_user_ns(), arg);
if (!gid_valid(gid)) {
f2fs_msg(sb, KERN_ERR,
"Invalid gid value %d", arg);
return -EINVAL;
}
sbi->s_resgid = gid;
break;
case Opt_mode: case Opt_mode:
name = match_strdup(&args[0]); name = match_strdup(&args[0]);
...@@ -1166,8 +1203,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root) ...@@ -1166,8 +1203,10 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
seq_puts(seq, "lfs"); seq_puts(seq, "lfs");
seq_printf(seq, ",active_logs=%u", sbi->active_logs); seq_printf(seq, ",active_logs=%u", sbi->active_logs);
if (test_opt(sbi, RESERVE_ROOT)) if (test_opt(sbi, RESERVE_ROOT))
seq_printf(seq, ",reserve_root=%u", seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u",
sbi->root_reserved_blocks); sbi->root_reserved_blocks,
from_kuid_munged(&init_user_ns, sbi->s_resuid),
from_kgid_munged(&init_user_ns, sbi->s_resgid));
if (F2FS_IO_SIZE_BITS(sbi)) if (F2FS_IO_SIZE_BITS(sbi))
seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi)); seq_printf(seq, ",io_size=%uKB", F2FS_IO_SIZE_KB(sbi));
#ifdef CONFIG_F2FS_FAULT_INJECTION #ifdef CONFIG_F2FS_FAULT_INJECTION
...@@ -2455,6 +2494,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) ...@@ -2455,6 +2494,9 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
sbi->raw_super = raw_super; sbi->raw_super = raw_super;
sbi->s_resuid = make_kuid(&init_user_ns, F2FS_DEF_RESUID);
sbi->s_resgid = make_kgid(&init_user_ns, F2FS_DEF_RESGID);
/* precompute checksum seed for metadata */ /* precompute checksum seed for metadata */
if (f2fs_sb_has_inode_chksum(sb)) if (f2fs_sb_has_inode_chksum(sb))
sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid, sbi->s_chksum_seed = f2fs_chksum(sbi, ~0, raw_super->uuid,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment