f2fs: add reserved blocks for root user
Jaegeuk Kim
maintainerPATCH 1/1 f2fs: add reserved blocks for root user
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
--- fs/f2fs/f2fs.h | 25 ++++++++++++++++++++----- fs/f2fs/super.c | 24 ++++++++++++++++++++++-- fs/f2fs/sysfs.c | 5 ++++- 3 files changed, 46 insertions(+), 8 deletions(-)
fs/f2fs/f2fs.h +20 -5
@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1557,6 +1558,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /100 ; +} +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,struct inode *inode,blkcnt_t *count)
@@ -1584,13 +1591,18 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,spin_lock (&sbi->stat_lock); sbi->total_valid_block_count += (block_t)(*count); - avail_user_block_count = sbi->user_block_count - - sbi->current_reserved_blocks; + avail_user_block_count = sbi->user_block_count; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->current_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);
@@ -1780,8 +1792,11 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->current_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }
fs/f2fs/super.c +22 -2
@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,
@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},
@@ -488,6 +490,14 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (sbi->current_reserved_blocks > arg) +return -EINVAL ; + sbi->current_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); +break ;case Opt_mode: name =match_strdup (&args[0 ]);
@@ -1006,6 +1016,8 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = total_count - start_count; buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; +if (test_opt (sbi,RESERVE_ROOT )) + buf->f_bfree += sbi->current_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks;
@@ -1136,6 +1148,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->current_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2569,8 +2584,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)le64_to_cpu (sbi->ckpt->valid_block_count); sbi->last_valid_block_count = sbi->total_valid_block_count; sbi->reserved_blocks =0 ; - sbi->current_reserved_blocks =0 ; - +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->current_reserved_blocks >reserve_root_limit (sbi)) { + sbi->current_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->current_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);
fs/f2fs/sysfs.c +4 -1
@@ -162,7 +162,10 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )sbi->user_block_count || + (test_opt (sbi,RESERVE_ROOT ) && + (t < sbi->current_reserved_blocks || + t >reserve_root_limit (sbi)))) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
Quoted 37 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>--- fs/f2fs/f2fs.h | 25 ++++++++++++++++++++----- fs/f2fs/super.c | 24 ++++++++++++++++++++++-- fs/f2fs/sysfs.c | 5 ++++- 3 files changed, 46 insertions(+), 8 deletions(-)fs/f2fs/f2fs.h +7
-0@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1557,6 +1558,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /100 ; +} +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,struct inode *inode,blkcnt_t *count)
fs/f2fs/f2fs.h static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, · line 1596
Quoted 8 lines
fs/f2fs/f2fs.h +3
-2@@ -1584,13 +1591,18 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi,spin_lock (&sbi->stat_lock); sbi->total_valid_block_count += (block_t)(*count); - avail_user_block_count = sbi->user_block_count - - sbi->current_reserved_blocks; + avail_user_block_count = sbi->user_block_count; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE )))
How about adding uid & gid verification also like ext4?
Quoted 48 lines
fs/f2fs/f2fs.h +10
-3+ avail_user_block_count -= sbi->current_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1780,8 +1792,11 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->current_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +2
-0@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},
fs/f2fs/super.c static int parse_options(struct super_block *sb, char *options) · line 498
Quoted 9 lines
fs/f2fs/super.c +6
-0@@ -488,6 +490,14 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (sbi->current_reserved_blocks > arg) +return -EINVAL ; + sbi->current_reserved_blocks = arg;
Previously, we have supported to reserve blocks in fs layer to adjust over-provision ratio dynamically by configuring sysfs interface, which can be used for reserving space of low level storage device for performance or flash lifetime.
I think reserve blocks for root user is another requirement which is different from above one, so I hope we can keep both of these two features available and usable, in order to keep previous one's backward compatibility and also try to support more various features in f2fs.
Thanks,
Quoted 57 lines
fs/f2fs/super.c +14
-2+set_opt (sbi,RESERVE_ROOT ); +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -1006,6 +1016,8 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = total_count - start_count; buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; +if (test_opt (sbi,RESERVE_ROOT )) + buf->f_bfree += sbi->current_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks;@@ -1136,6 +1148,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->current_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2569,8 +2584,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent)le64_to_cpu (sbi->ckpt->valid_block_count); sbi->last_valid_block_count = sbi->total_valid_block_count; sbi->reserved_blocks =0 ; - sbi->current_reserved_blocks =0 ; - +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->current_reserved_blocks >reserve_root_limit (sbi)) { + sbi->current_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->current_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +4
-1@@ -162,7 +162,10 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )sbi->user_block_count || + (test_opt (sbi,RESERVE_ROOT ) && + (t < sbi->current_reserved_blocks || + t >reserve_root_limit (sbi)))) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Jaegeuk Kim
maintainerWe can give another chance to write user data, which can resolve generic/441.
---
Change log from v1:
- skip stop_checkpoint for normal user data
fs/f2fs/data.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/f2fs/data.c +2 -1
@@ -111,7 +111,8 @@ static void f2fs_write_end_io(struct bio *bio)if (unlikely (bio->bi_status)) {mapping_set_error (page->mapping, -EIO ); -f2fs_stop_checkpoint (sbi, true); +if (type ==F2FS_WB_CP_DATA ) +f2fs_stop_checkpoint (sbi, true); }dec_page_count (sbi, type);clear_cold_data (page);
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
Jaegeuk Kim
maintainerThis patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
---
Change log from v2:
- wrong submission. :P
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 26 +++++++++++++++++++++++--- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 47 insertions(+), 8 deletions(-)
fs/f2fs/f2fs.h +22 -4
@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1110,6 +1111,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */
@@ -1562,6 +1564,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /100 ; +} +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,struct inode *inode,blkcnt_t *count)
@@ -1591,11 +1599,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);
@@ -1784,9 +1798,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }
fs/f2fs/super.c +23 -3
@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,
@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},
@@ -488,6 +490,12 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); +break ;case Opt_mode: name =match_strdup (&args[0 ]);
@@ -1005,10 +1013,12 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks + + sbi->root_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - - sbi->current_reserved_blocks; - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;
@@ -1136,6 +1146,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2571,6 +2584,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);
fs/f2fs/sysfs.c +2 -1
@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
Quoted 36 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Change log from v2:
- wrong submission. :Pfs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 26 +++++++++++++++++++++++--- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 47 insertions(+), 8 deletions(-)fs/f2fs/f2fs.h +2
-0@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1110,6 +1111,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */
fs/f2fs/f2fs.h static inline bool f2fs_has_xattr_block(unsigned int ofs) · line 1569
Quoted 6 lines
fs/f2fs/f2fs.h +3
-0@@ -1562,6 +1564,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */
Should be 2% according to below calculation?
fs/f2fs/f2fs.h static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, · line 1603
Quoted 12 lines
fs/f2fs/f2fs.h +5
-0+return (sbi->user_block_count <<1 ) /100 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1591,11 +1599,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE )))
How about adding uid & gid verification also like ext4?
As this is a mount option, in ->remount_fs, we should consider to recover original reserved block number if we encounter some error during remount.
Thanks,
Quoted 118 lines
fs/f2fs/f2fs.h +12
-4+ avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1784,9 +1798,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +23
-3@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,12 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -1005,10 +1013,12 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks + + sbi->root_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - - sbi->current_reserved_blocks; - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1146,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2584,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +2
-1@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Jaegeuk Kim
maintainerQuoted 40 lines · Chao Yu
Quoted 39 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Change log from v2:
- wrong submission. :Pfs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 26 +++++++++++++++++++++++--- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 47 insertions(+), 8 deletions(-)fs/f2fs/f2fs.h +2
-0@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1110,6 +1111,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */ @@ -1562,6 +1564,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; }
Quoted 5 lines
fs/f2fs/f2fs.h static inline bool f2fs_has_xattr_block(unsigned int ofs) · line 1569
Quoted 3 lines
fs/f2fs/f2fs.h +3
-0+static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ Should be 2% according to below calculation?
Oh, right. Fixed.
Quoted 15 lines
fs/f2fs/f2fs.h static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, · line 1603
Quoted 13 lines
fs/f2fs/f2fs.h +5
-0+return (sbi->user_block_count <<1 ) /100 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1591,11 +1599,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE )))How about adding uid & gid verification also like ext4?
Again, that's another feature which requires a mount option. I think it'd be better to add that, once we have a use-case.
Quoted 2 lines
As this is a mount option, in ->remount_fs, we should consider to recover original reserved block number if we encounter some error during remount.
Yup, agreed.
Thanks,
Quoted 121 lines
Thanks,
Quoted 118 lines
fs/f2fs/f2fs.h +12
-4+ avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1784,9 +1798,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +23
-3@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,12 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -1005,10 +1013,12 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks + + sbi->root_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - - sbi->current_reserved_blocks; - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1146,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2584,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +2
-1@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Quoted 4 lines · Jaegeuk Kim
Quoted 1 line
How about adding uid & gid verification also like ext4?
Again, that's another feature which requires a mount option. I think it'd be better to add that, once we have a use-case.
That's OK. ;)
Thanks,
Jaegeuk Kim
maintainerThis patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
---
Change log from v3:
- fix 0.2% calculation
- preserve reserve_root=%u from remount_fs
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 35 ++++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 54 insertions(+), 10 deletions(-)
fs/f2fs/f2fs.h +22 -4
@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1110,6 +1111,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */
@@ -1562,6 +1564,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)
@@ -1591,11 +1599,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);
@@ -1784,9 +1798,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }
fs/f2fs/super.c +30 -5
@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,
@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},
@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);
@@ -994,21 +1008,22 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks + + sbi->root_reserved_blocks; buf->f_bavail = user_block_count -valid_user_blocks (sbi) - - sbi->current_reserved_blocks; - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;
@@ -1136,6 +1151,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2571,6 +2589,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);
fs/f2fs/sysfs.c +2 -1
@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
Jaegeuk Kim
maintainerThis patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
---
Change log from v4:
- fix f_bfree in statfs
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 53 insertions(+), 10 deletions(-)
fs/f2fs/f2fs.h +22 -4
@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -1105,6 +1106,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */
@@ -1554,6 +1556,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)
@@ -1583,11 +1591,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);
@@ -1776,9 +1790,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }
fs/f2fs/super.c +29 -5
@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,
@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},
@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);
@@ -994,21 +1008,21 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; - buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks; - + buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;
@@ -1136,6 +1150,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION
@@ -2571,6 +2588,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);
fs/f2fs/sysfs.c +2 -1
@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Signature · 1 line
2.15.0.531.g2ccb3012c9-goog
Quoted 9 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Change log from v4:
- fixf_bfreein statfs
Could you fix f_bfree calculation issue in another patch prior to this patch? That will be better for history tracking of patches or git bisect when backtracking issues.
One more thing, should we move reserve_root_limit check to parse_option? now, it looks that during remount we can set root_reserved_blocks exceeding our defined limitation.
Thanks,
Quoted 180 lines
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 53 insertions(+), 10 deletions(-)fs/f2fs/f2fs.h +22
-4@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1105,6 +1106,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */ @@ -1554,6 +1556,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1583,11 +1591,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1776,9 +1790,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +29
-5@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -994,21 +1008,21 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; - buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks; - + buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1150,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2588,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +2
-1@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Jaegeuk Kim
maintainerQuoted 8 lines · Chao Yu
Quoted 7 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Quoted 6 lines
Quoted 2 lines
Change log from v4:
- fixf_bfreein statfsCould you fix
f_bfreecalculation issue in another patch prior to this patch? That will be better for history tracking of patches or git bisect when backtracking issues.
I've sent out a new series for this.
Quoted 2 lines
One more thing, should we move
reserve_root_limitcheck toparse_option?
No, since we don't have sbi yet.
Quoted 2 lines
now, it looks that during remount we can set
root_reserved_blocksexceeding our defined limitation.
Oh, I missed the changelog that it won't be changed once getting the flag set.
Thanks,
Quoted 183 lines
Thanks,
Quoted 180 lines
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 53 insertions(+), 10 deletions(-)fs/f2fs/f2fs.h +22
-4@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1105,6 +1106,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */ @@ -1554,6 +1556,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1583,11 +1591,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1776,9 +1790,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +29
-5@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -994,21 +1008,21 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; - buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks; - + buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1150,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2588,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +2
-1@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }
Quoted 19 lines · Jaegeuk Kim
Quoted 8 lines · Chao Yu
Quoted 7 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Quoted 6 lines
Quoted 2 lines
Change log from v4:
- fixf_bfreein statfsCould you fix
f_bfreecalculation issue in another patch prior to this patch? That will be better for history tracking of patches or git bisect when backtracking issues.I've sent out a new series for this.
Quoted 1 line
Quoted 8 lines
Quoted 1 line
One more thing, should we move
reserve_root_limitcheck toparse_option?No, since we don't have sbi yet.
Quoted 2 lines
now, it looks that during remount we can set
root_reserved_blocksexceeding our defined limitation.Oh, I missed the changelog that it won't be changed once getting the flag set.
If the flag is not set previously, and then we remount with that flag being set?
Like:
mount -t f2fs /dev/xxx /mnt/
mount -t f2fs -o remount,reserve_root=xxx /dev/xxx /mnt/
Thanks,
Quoted 189 lines
Thanks,
Quoted 175 lines
Thanks,
Quoted 172 lines
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 53 insertions(+), 10 deletions(-)fs/f2fs/f2fs.h +22
-4@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1105,6 +1106,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */ @@ -1554,6 +1556,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1583,11 +1591,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1776,9 +1790,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +29
-5@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -994,21 +1008,21 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; - buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks; - + buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1150,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2588,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +0
-0@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {Quoted 8 lines
fs/f2fs/sysfs.c static ssize_t f2fs_sbi_store(struct f2fs_attr *a, · line 169
Quoted 8 lines
fs/f2fs/sysfs.c +2
-1spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }.
Jaegeuk Kim
maintainerQuoted 24 lines · Chao Yu
Quoted 23 lines · Jaegeuk Kim
Quoted 8 lines · Chao Yu
Quoted 7 lines · Jaegeuk Kim
This patch allows root to reserve some blocks via mount option.
"-o reserve_root=N" means N x 4KB-sized blocks for root only.
Signed-off-by Jaegeuk Kim <[email protected]>---
Quoted 6 lines
Quoted 2 lines
Change log from v4:
- fixf_bfreein statfsCould you fix
f_bfreecalculation issue in another patch prior to this patch? That will be better for history tracking of patches or git bisect when backtracking issues.I've sent out a new series for this.
Quoted 2 lines
One more thing, should we move
reserve_root_limitcheck toparse_option?No, since we don't have sbi yet.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
now, it looks that during remount we can set
root_reserved_blocksexceeding our defined limitation.Oh, I missed the changelog that it won't be changed once getting the flag set.
If the flag is not set previously, and then we remount with that flag being set?
Right. Will fix.
Quoted 197 lines
Like:
mount -t f2fs
/dev/xxx/mnt/
mount -t f2fs -o remount,reserve_root=xxx/dev/xxx/mnt/Thanks,
Quoted 189 lines
Thanks,
Quoted 175 lines
Thanks,
Quoted 172 lines
fs/f2fs/f2fs.h | 26 ++++++++++++++++++++++---- fs/f2fs/super.c | 34 +++++++++++++++++++++++++++++----- fs/f2fs/sysfs.c | 3 ++- 3 files changed, 53 insertions(+), 10 deletions(-)fs/f2fs/f2fs.h +22
-4@@ -95,6 +95,7 @@ extern char *fault_name[FAULT_MAX];#define F2FS_MOUNT_PRJQUOTA 0x00200000#define F2FS_MOUNT_QUOTA 0x00400000#define F2FS_MOUNT_INLINE_XATTR_SIZE 0x00800000 +#define F2FS_MOUNT_RESERVE_ROOT 0x01000000#define clear_opt (sbi, option) ((sbi)->mount_opt.opt &= ~F2FS_MOUNT_##option)#define set_opt (sbi, option) ((sbi)->mount_opt.opt |= F2FS_MOUNT_##option)@@ -1105,6 +1106,7 @@ struct f2fs_sb_info {block_t last_valid_block_count;/* for recovery */ block_t reserved_blocks;/* configurable reserved blocks */ block_t current_reserved_blocks;/* current reserved blocks */ +block_t root_reserved_blocks;/* root reserved blocks */ unsigned int nquota_files;/* # of quota sysfile */ @@ -1554,6 +1556,12 @@ static inline bool f2fs_has_xattr_block(unsigned int ofs)return ofs ==XATTR_NODE_OFFSET ; } +static inline block_t reserve_root_limit (struct f2fs_sb_info *sbi) +{ +/* limit is 0.2% */ +return (sbi->user_block_count <<1 ) /1000 ; +} +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,struct inode *inode,blkcnt_t *count)@@ -1583,11 +1591,17 @@ static inline int inc_valid_block_count(struct f2fs_sb_info *sbi, sbi->total_valid_block_count += (block_t)(*count); avail_user_block_count = sbi->user_block_count - sbi->current_reserved_blocks; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + avail_user_block_count -= sbi->root_reserved_blocks; +if (unlikely (sbi->total_valid_block_count > avail_user_block_count)) { diff = sbi->total_valid_block_count - avail_user_block_count; +if (diff > *count) + diff = *count; *count -= diff; release = diff; - sbi->total_valid_block_count = avail_user_block_count; + sbi->total_valid_block_count -= diff;if (!*count) {spin_unlock (&sbi->stat_lock);percpu_counter_sub (&sbi->alloc_valid_block_count, diff);@@ -1776,9 +1790,13 @@ 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 ; -if (unlikely (valid_block_count + sbi->current_reserved_blocks > - sbi->user_block_count)) { + valid_block_count = sbi->total_valid_block_count + + sbi->current_reserved_blocks +1 ; + +if (!(test_opt (sbi,RESERVE_ROOT ) &&capable (CAP_SYS_RESOURCE ))) + valid_block_count += sbi->root_reserved_blocks; + +if (unlikely (valid_block_count > sbi->user_block_count)) {spin_unlock (&sbi->stat_lock); goto enospc; }fs/f2fs/super.c +29
-5@@ -107,6 +107,7 @@ enum { Opt_noextent_cache, Opt_noinline_data, Opt_data_flush, + Opt_reserve_root, Opt_mode, Opt_io_size_bits, Opt_fault_injection,@@ -157,6 +158,7 @@ static match_table_t f2fs_tokens = { {Opt_noextent_cache, "noextent_cache"}, {Opt_noinline_data, "noinline_data"}, {Opt_data_flush, "data_flush"}, + {Opt_reserve_root, "reserve_root=%u"}, {Opt_mode, "mode=%s"}, {Opt_io_size_bits, "io_bits=%u"}, {Opt_fault_injection, "fault_injection=%u"},@@ -488,6 +490,18 @@ static int parse_options(struct super_block *sb, char *options)case Opt_data_flush:set_opt (sbi,DATA_FLUSH );break ; +case Opt_reserve_root: +if (args->from &&match_int (args, &arg)) +return -EINVAL ; +if (test_opt (sbi,RESERVE_ROOT )) { +f2fs_msg (sb,KERN_INFO , +"Preserve previous reserve_root=%u" , + sbi->root_reserved_blocks); + }else { + sbi->root_reserved_blocks = arg; +set_opt (sbi,RESERVE_ROOT ); + } +break ;case Opt_mode: name =match_strdup (&args[0 ]);@@ -994,21 +1008,21 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)struct super_block *sb = dentry->d_sb;struct f2fs_sb_info *sbi =F2FS_SB (sb);u64 id =huge_encode_dev (sb->s_bdev->bd_dev); -block_t total_count, user_block_count, start_count, ovp_count; +block_t total_count, user_block_count, start_count;u64 avail_node_count; total_count =le64_to_cpu (sbi->raw_super->block_count); user_block_count = sbi->user_block_count; start_count =le32_to_cpu (sbi->raw_super->segment0_blkaddr); - ovp_count =SM_I (sbi)->ovp_segments << sbi->log_blocks_per_seg; buf->f_type =F2FS_SUPER_MAGIC ; buf->f_bsize = sbi->blocksize; buf->f_blocks = total_count - start_count; - buf->f_bfree = user_block_count -valid_user_blocks (sbi) + ovp_count; - buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + buf->f_bfree = user_block_count -valid_user_blocks (sbi) - sbi->current_reserved_blocks; - + buf->f_bavail = user_block_count -valid_user_blocks (sbi) - + sbi->current_reserved_blocks - + sbi->root_reserved_blocks; avail_node_count = sbi->total_node_count - sbi->nquota_files -F2FS_RESERVED_NODE_NUM ;@@ -1136,6 +1150,9 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)else if (test_opt (sbi,LFS ))seq_puts (seq,"lfs" );seq_printf (seq,",active_logs=%u" , sbi->active_logs); +if (test_opt (sbi,RESERVE_ROOT )) +seq_printf (seq,",reserve_root=%u" , + sbi->root_reserved_blocks);if (F2FS_IO_SIZE_BITS (sbi))seq_printf (seq,",io_size=%uKB" ,F2FS_IO_SIZE_KB (sbi));#ifdef CONFIG_F2FS_FAULT_INJECTION @@ -2571,6 +2588,13 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) sbi->reserved_blocks =0 ; sbi->current_reserved_blocks =0 ; +if (test_opt (sbi,RESERVE_ROOT ) && + sbi->root_reserved_blocks >reserve_root_limit (sbi)) { + sbi->root_reserved_blocks =reserve_root_limit (sbi); +f2fs_msg (sb,KERN_INFO , +"Reduce reserved blocks for root = %u\n" , + sbi->root_reserved_blocks); + }for (i =0 ; i <NR_INODE_TYPE ; i++) {INIT_LIST_HEAD (&sbi->inode_list[i]);spin_lock_init (&sbi->inode_lock[i]);fs/f2fs/sysfs.c +0
-0@@ -162,7 +162,8 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,#endif if (a->struct_type ==RESERVED_BLOCKS ) {Quoted 8 lines
fs/f2fs/sysfs.c static ssize_t f2fs_sbi_store(struct f2fs_attr *a, · line 169
Quoted 8 lines
fs/f2fs/sysfs.c +2
-1spin_lock (&sbi->stat_lock); -if (t > (unsigned long )sbi->user_block_count) { +if (t > (unsigned long )(sbi->user_block_count - + sbi->root_reserved_blocks)) {spin_unlock (&sbi->stat_lock);return -EINVAL ; }.