forked from mirrors/linux
		
	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: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
		
							parent
							
								
									578c647879
								
							
						
					
					
						commit
						7c2e59632b
					
				
					 2 changed files with 69 additions and 4 deletions
				
			
		| 
						 | 
					@ -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 {
 | 
				
			||||||
#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 {
 | 
				
			||||||
	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)
 | 
				
			||||||
	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,
 | 
				
			||||||
	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,
 | 
				
			||||||
	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 {
 | 
				
			||||||
	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 = {
 | 
				
			||||||
	{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)
 | 
				
			||||||
			"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)
 | 
				
			||||||
	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)
 | 
				
			||||||
				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)
 | 
				
			||||||
		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)
 | 
				
			||||||
	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,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue