在 8/8/2025 8:54 AM, Chao Yu 写道: > Chunhai, can we test selinux case as well? It may need to revert selinux fix > to find out the problem scenario first.
Yes. I tried reverting the selinux fix, but couldn't reproduce the problem. Thanks, > > Thanks, > > On 2025/8/8 06:57, Jaegeuk Kim wrote: >> By the way, can we also add some testcases in xfstests to check all this >> works as intended? >> >> On 08/07, Chunhai Guo wrote: >>> This patch allows privileged users to reserve nodes via the >>> 'reserve_node' mount option, which is similar to the existing >>> 'reserve_root' option. >>> >>> "-o reserve_node=<N>" means <N> nodes are reserved for privileged >>> users only. >>> >>> Signed-off-by: Chunhai Guo <guochun...@vivo.com> >>> --- >>> v5->v6: Modified F2FS_SPEC_reserve_node from (1<<24) to (1<<25) following >>> Zhiguo's suggestion in v5. >>> v4->v5: Apply Chao's suggestion from v4. >>> v3->v4: Rebase this patch on >>> https://lore.kernel.org/linux-f2fs-devel/20250731060338.1136086-1-c...@kernel.org >>> v2->v3: Apply Chao's suggestion from v2. >>> v1->v2: Add two missing handling parts. >>> v1: >>> https://lore.kernel.org/linux-f2fs-devel/20250729095238.607433-1-guochun...@vivo.com/ >>> --- >>> Documentation/filesystems/f2fs.rst | 9 ++++--- >>> fs/f2fs/f2fs.h | 17 ++++++++---- >>> fs/f2fs/super.c | 43 +++++++++++++++++++++++++----- >>> 3 files changed, 54 insertions(+), 15 deletions(-) >>> >>> diff --git a/Documentation/filesystems/f2fs.rst >>> b/Documentation/filesystems/f2fs.rst >>> index 5cad369ceb92..e06cbb823bb7 100644 >>> --- a/Documentation/filesystems/f2fs.rst >>> +++ b/Documentation/filesystems/f2fs.rst >>> @@ -173,9 +173,12 @@ data_flush Enable data flushing before >>> checkpoint in order to >>> persist data of regular and symlink. >>> reserve_root=%d Support configuring reserved space which is >>> used for >>> allocation from a privileged user with specified uid or >>> - gid, unit: 4KB, the default limit is 0.2% of user >>> blocks. >>> -resuid=%d The user ID which may use the reserved blocks. >>> -resgid=%d The group ID which may use the reserved blocks. >>> + gid, unit: 4KB, the default limit is 12.5% of user >>> blocks. >>> +reserve_node=%d Support configuring reserved nodes which are >>> used for >>> + allocation from a privileged user with specified uid or >>> + gid, the default limit is 12.5% of all nodes. >>> +resuid=%d The user ID which may use the reserved blocks and >>> nodes. >>> +resgid=%d The group ID which may use the reserved blocks and >>> nodes. >>> fault_injection=%d Enable fault injection in all supported types >>> with >>> specified injection rate. >>> fault_type=%d Support configuring fault injection type, >>> should be >>> diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h >>> index f19472eb2789..047964d66736 100644 >>> --- a/fs/f2fs/f2fs.h >>> +++ b/fs/f2fs/f2fs.h >>> @@ -131,6 +131,7 @@ extern const char *f2fs_fault_name[FAULT_MAX]; >>> * string rather than using the MS_LAZYTIME flag, so this must remain. >>> */ >>> #define F2FS_MOUNT_LAZYTIME 0x40000000 >>> +#define F2FS_MOUNT_RESERVE_NODE 0x80000000 >>> >>> #define F2FS_OPTION(sbi) ((sbi)->mount_opt) >>> #define clear_opt(sbi, option) (F2FS_OPTION(sbi).opt &= >>> ~F2FS_MOUNT_##option) >>> @@ -178,6 +179,7 @@ struct f2fs_rwsem { >>> struct f2fs_mount_info { >>> unsigned int opt; >>> block_t root_reserved_blocks; /* root reserved blocks */ >>> + block_t root_reserved_nodes; /* root reserved nodes */ >>> kuid_t s_resuid; /* reserved blocks for uid */ >>> kgid_t s_resgid; /* reserved blocks for gid */ >>> int active_logs; /* # of active logs */ >>> @@ -2407,7 +2409,7 @@ static inline bool f2fs_has_xattr_block(unsigned int >>> ofs) >>> return ofs == XATTR_NODE_OFFSET; >>> } >>> >>> -static inline bool __allow_reserved_blocks(struct f2fs_sb_info *sbi, >>> +static inline bool __allow_reserved_root(struct f2fs_sb_info *sbi, >>> struct inode *inode, bool cap) >>> { >>> if (!inode) >>> @@ -2432,7 +2434,7 @@ static inline unsigned int >>> get_available_block_count(struct f2fs_sb_info *sbi, >>> avail_user_block_count = sbi->user_block_count - >>> sbi->current_reserved_blocks; >>> >>> - if (test_opt(sbi, RESERVE_ROOT) && !__allow_reserved_blocks(sbi, inode, >>> cap)) >>> + if (test_opt(sbi, RESERVE_ROOT) && !__allow_reserved_root(sbi, inode, >>> cap)) >>> avail_user_block_count -= F2FS_OPTION(sbi).root_reserved_blocks; >>> >>> if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED))) { >>> @@ -2790,7 +2792,7 @@ static inline int inc_valid_node_count(struct >>> f2fs_sb_info *sbi, >>> struct inode *inode, bool is_inode) >>> { >>> block_t valid_block_count; >>> - unsigned int valid_node_count; >>> + unsigned int valid_node_count, avail_user_node_count; >>> unsigned int avail_user_block_count; >>> int err; >>> >>> @@ -2812,15 +2814,20 @@ static inline int inc_valid_node_count(struct >>> f2fs_sb_info *sbi, >>> spin_lock(&sbi->stat_lock); >>> >>> valid_block_count = sbi->total_valid_block_count + 1; >>> - avail_user_block_count = get_available_block_count(sbi, inode, false); >>> + avail_user_block_count = get_available_block_count(sbi, inode, >>> + test_opt(sbi, RESERVE_NODE)); >>> >>> if (unlikely(valid_block_count > avail_user_block_count)) { >>> spin_unlock(&sbi->stat_lock); >>> goto enospc; >>> } >>> >>> + avail_user_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM; >>> + if (test_opt(sbi, RESERVE_NODE) && >>> + !__allow_reserved_root(sbi, inode, true)) >>> + avail_user_node_count -= F2FS_OPTION(sbi).root_reserved_nodes; >>> valid_node_count = sbi->total_valid_node_count + 1; >>> - if (unlikely(valid_node_count > sbi->total_node_count)) { >>> + if (unlikely(valid_node_count > avail_user_node_count)) { >>> spin_unlock(&sbi->stat_lock); >>> goto enospc; >>> } >>> diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c >>> index 3f8bc42e0968..f37004780ce0 100644 >>> --- a/fs/f2fs/super.c >>> +++ b/fs/f2fs/super.c >>> @@ -143,6 +143,7 @@ enum { >>> Opt_extent_cache, >>> Opt_data_flush, >>> Opt_reserve_root, >>> + Opt_reserve_node, >>> Opt_resgid, >>> Opt_resuid, >>> Opt_mode, >>> @@ -273,6 +274,7 @@ static const struct fs_parameter_spec >>> f2fs_param_specs[] = { >>> fsparam_flag_no("extent_cache", Opt_extent_cache), >>> fsparam_flag("data_flush", Opt_data_flush), >>> fsparam_u32("reserve_root", Opt_reserve_root), >>> + fsparam_u32("reserve_node", Opt_reserve_node), >>> fsparam_gid("resgid", Opt_resgid), >>> fsparam_uid("resuid", Opt_resuid), >>> fsparam_enum("mode", Opt_mode, f2fs_param_mode), >>> @@ -346,6 +348,7 @@ static match_table_t f2fs_checkpoint_tokens = { >>> #define F2FS_SPEC_memory_mode (1 << 22) >>> #define F2FS_SPEC_errors (1 << 23) >>> #define F2FS_SPEC_lookup_mode (1 << 24) >>> +#define F2FS_SPEC_reserve_node (1 << 25) >>> >>> struct f2fs_fs_context { >>> struct f2fs_mount_info info; >>> @@ -447,22 +450,30 @@ static void f2fs_destroy_casefold_cache(void) { } >>> >>> static inline void limit_reserve_root(struct f2fs_sb_info *sbi) >>> { >>> - block_t limit = min((sbi->user_block_count >> 3), >>> + block_t block_limit = min((sbi->user_block_count >> 3), >>> sbi->user_block_count - sbi->reserved_blocks); >>> + block_t node_limit = sbi->total_node_count >> 3; >>> >>> /* limit is 12.5% */ >>> if (test_opt(sbi, RESERVE_ROOT) && >>> - F2FS_OPTION(sbi).root_reserved_blocks > limit) { >>> - F2FS_OPTION(sbi).root_reserved_blocks = limit; >>> + F2FS_OPTION(sbi).root_reserved_blocks > block_limit) { >>> + F2FS_OPTION(sbi).root_reserved_blocks = block_limit; >>> f2fs_info(sbi, "Reduce reserved blocks for root = %u", >>> F2FS_OPTION(sbi).root_reserved_blocks); >>> } >>> - if (!test_opt(sbi, RESERVE_ROOT) && >>> + if (test_opt(sbi, RESERVE_NODE) && >>> + F2FS_OPTION(sbi).root_reserved_nodes > node_limit) { >>> + F2FS_OPTION(sbi).root_reserved_nodes = node_limit; >>> + f2fs_info(sbi, "Reduce reserved nodes for root = %u", >>> + F2FS_OPTION(sbi).root_reserved_nodes); >>> + } >>> + if (!test_opt(sbi, RESERVE_ROOT) && !test_opt(sbi, RESERVE_NODE) && >>> (!uid_eq(F2FS_OPTION(sbi).s_resuid, >>> make_kuid(&init_user_ns, F2FS_DEF_RESUID)) || >>> !gid_eq(F2FS_OPTION(sbi).s_resgid, >>> make_kgid(&init_user_ns, F2FS_DEF_RESGID)))) >>> - f2fs_info(sbi, "Ignore s_resuid=%u, s_resgid=%u w/o >>> reserve_root", >>> + f2fs_info(sbi, "Ignore s_resuid=%u, s_resgid=%u w/o >>> reserve_root" >>> + " and reserve_node", >>> from_kuid_munged(&init_user_ns, >>> F2FS_OPTION(sbi).s_resuid), >>> from_kgid_munged(&init_user_ns, >>> @@ -851,6 +862,11 @@ static int f2fs_parse_param(struct fs_context *fc, >>> struct fs_parameter *param) >>> F2FS_CTX_INFO(ctx).root_reserved_blocks = result.uint_32; >>> ctx->spec_mask |= F2FS_SPEC_reserve_root; >>> break; >>> + case Opt_reserve_node: >>> + ctx_set_opt(ctx, F2FS_MOUNT_RESERVE_NODE); >>> + F2FS_CTX_INFO(ctx).root_reserved_nodes = result.uint_32; >>> + ctx->spec_mask |= F2FS_SPEC_reserve_node; >>> + break; >>> case Opt_resuid: >>> F2FS_CTX_INFO(ctx).s_resuid = result.uid; >>> ctx->spec_mask |= F2FS_SPEC_resuid; >>> @@ -1438,6 +1454,14 @@ static int f2fs_check_opt_consistency(struct >>> fs_context *fc, >>> ctx_clear_opt(ctx, F2FS_MOUNT_RESERVE_ROOT); >>> ctx->opt_mask &= ~F2FS_MOUNT_RESERVE_ROOT; >>> } >>> + if (test_opt(sbi, RESERVE_NODE) && >>> + (ctx->opt_mask & F2FS_MOUNT_RESERVE_NODE) && >>> + ctx_test_opt(ctx, F2FS_MOUNT_RESERVE_NODE)) { >>> + f2fs_info(sbi, "Preserve previous reserve_node=%u", >>> + F2FS_OPTION(sbi).root_reserved_nodes); >>> + ctx_clear_opt(ctx, F2FS_MOUNT_RESERVE_NODE); >>> + ctx->opt_mask &= ~F2FS_MOUNT_RESERVE_NODE; >>> + } >>> >>> err = f2fs_check_test_dummy_encryption(fc, sb); >>> if (err) >>> @@ -1637,6 +1661,9 @@ static void f2fs_apply_options(struct fs_context *fc, >>> struct super_block *sb) >>> if (ctx->spec_mask & F2FS_SPEC_reserve_root) >>> F2FS_OPTION(sbi).root_reserved_blocks = >>> F2FS_CTX_INFO(ctx).root_reserved_blocks; >>> + if (ctx->spec_mask & F2FS_SPEC_reserve_node) >>> + F2FS_OPTION(sbi).root_reserved_nodes = >>> + F2FS_CTX_INFO(ctx).root_reserved_nodes; >>> if (ctx->spec_mask & F2FS_SPEC_resgid) >>> F2FS_OPTION(sbi).s_resgid = F2FS_CTX_INFO(ctx).s_resgid; >>> if (ctx->spec_mask & F2FS_SPEC_resuid) >>> @@ -2359,9 +2386,11 @@ static int f2fs_show_options(struct seq_file *seq, >>> struct dentry *root) >>> else if (F2FS_OPTION(sbi).fs_mode == FS_MODE_FRAGMENT_BLK) >>> seq_puts(seq, "fragment:block"); >>> seq_printf(seq, ",active_logs=%u", F2FS_OPTION(sbi).active_logs); >>> - if (test_opt(sbi, RESERVE_ROOT)) >>> - seq_printf(seq, ",reserve_root=%u,resuid=%u,resgid=%u", >>> + if (test_opt(sbi, RESERVE_ROOT) || test_opt(sbi, RESERVE_NODE)) >>> + seq_printf(seq, ",reserve_root=%u,reserve_node=%u,resuid=%u," >>> + "resgid=%u", >>> F2FS_OPTION(sbi).root_reserved_blocks, >>> + F2FS_OPTION(sbi).root_reserved_nodes, >>> from_kuid_munged(&init_user_ns, >>> F2FS_OPTION(sbi).s_resuid), >>> from_kgid_munged(&init_user_ns, >>> -- >>> 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel