summaryrefslogtreecommitdiffstats
path: root/fs/f2fs
diff options
context:
space:
mode:
authorChao Yu <yuchao0@huawei.com>2017-06-26 04:24:41 -0400
committerJaegeuk Kim <jaegeuk@kernel.org>2017-07-07 13:34:41 -0400
commitdaeb433e42de97c79622f58681972200eec1d8da (patch)
treeb0f24b7eb9f345be975c63af9513c275f777da1b /fs/f2fs
parentd871cd046f1a5ae816c836cf114d57288bcb00b2 (diff)
f2fs: introduce reserved_blocks in sysfs
In this patch, we add a new sysfs interface, with it, we can control number of reserved blocks in system which could not be used by user, it enable f2fs to let user to configure for adjusting over-provision ratio dynamically instead of changing it by mkfs. So we can expect it will help to reserve more free space for relieving GC in both filesystem and flash device. Signed-off-by: Chao Yu <yuchao0@huawei.com> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r--fs/f2fs/f2fs.h13
-rw-r--r--fs/f2fs/super.c4
-rw-r--r--fs/f2fs/sysfs.c16
3 files changed, 27 insertions, 6 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index c27a6264d9bf..e15d55ccc4bc 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -966,6 +966,8 @@ struct f2fs_sb_info {
966 block_t total_valid_block_count; /* # of valid blocks */ 966 block_t total_valid_block_count; /* # of valid blocks */
967 block_t discard_blks; /* discard command candidats */ 967 block_t discard_blks; /* discard command candidats */
968 block_t last_valid_block_count; /* for recovery */ 968 block_t last_valid_block_count; /* for recovery */
969 block_t reserved_blocks; /* configurable reserved blocks */
970
969 u32 s_next_generation; /* for NFS support */ 971 u32 s_next_generation; /* for NFS support */
970 972
971 /* # of pages, see count_type */ 973 /* # of pages, see count_type */
@@ -1376,6 +1378,7 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
1376 struct inode *inode, blkcnt_t *count) 1378 struct inode *inode, blkcnt_t *count)
1377{ 1379{
1378 blkcnt_t diff; 1380 blkcnt_t diff;
1381 block_t avail_user_block_count;
1379 1382
1380#ifdef CONFIG_F2FS_FAULT_INJECTION 1383#ifdef CONFIG_F2FS_FAULT_INJECTION
1381 if (time_to_inject(sbi, FAULT_BLOCK)) { 1384 if (time_to_inject(sbi, FAULT_BLOCK)) {
@@ -1391,10 +1394,11 @@ static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi,
1391 1394
1392 spin_lock(&sbi->stat_lock); 1395 spin_lock(&sbi->stat_lock);
1393 sbi->total_valid_block_count += (block_t)(*count); 1396 sbi->total_valid_block_count += (block_t)(*count);
1394 if (unlikely(sbi->total_valid_block_count > sbi->user_block_count)) { 1397 avail_user_block_count = sbi->user_block_count - sbi->reserved_blocks;
1395 diff = sbi->total_valid_block_count - sbi->user_block_count; 1398 if (unlikely(sbi->total_valid_block_count > avail_user_block_count)) {
1399 diff = sbi->total_valid_block_count - avail_user_block_count;
1396 *count -= diff; 1400 *count -= diff;
1397 sbi->total_valid_block_count = sbi->user_block_count; 1401 sbi->total_valid_block_count = avail_user_block_count;
1398 if (!*count) { 1402 if (!*count) {
1399 spin_unlock(&sbi->stat_lock); 1403 spin_unlock(&sbi->stat_lock);
1400 percpu_counter_sub(&sbi->alloc_valid_block_count, diff); 1404 percpu_counter_sub(&sbi->alloc_valid_block_count, diff);
@@ -1556,7 +1560,8 @@ static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi,
1556 spin_lock(&sbi->stat_lock); 1560 spin_lock(&sbi->stat_lock);
1557 1561
1558 valid_block_count = sbi->total_valid_block_count + 1; 1562 valid_block_count = sbi->total_valid_block_count + 1;
1559 if (unlikely(valid_block_count > sbi->user_block_count)) { 1563 if (unlikely(valid_block_count + sbi->reserved_blocks >
1564 sbi->user_block_count)) {
1560 spin_unlock(&sbi->stat_lock); 1565 spin_unlock(&sbi->stat_lock);
1561 return false; 1566 return false;
1562 } 1567 }
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 3da6fb276f8b..c45bac6f1795 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -691,7 +691,8 @@ static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf)
691 691
692 buf->f_blocks = total_count - start_count; 692 buf->f_blocks = total_count - start_count;
693 buf->f_bfree = user_block_count - valid_user_blocks(sbi) + ovp_count; 693 buf->f_bfree = user_block_count - valid_user_blocks(sbi) + ovp_count;
694 buf->f_bavail = user_block_count - valid_user_blocks(sbi); 694 buf->f_bavail = user_block_count - valid_user_blocks(sbi) -
695 sbi->reserved_blocks;
695 696
696 avail_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM; 697 avail_node_count = sbi->total_node_count - F2FS_RESERVED_NODE_NUM;
697 698
@@ -1768,6 +1769,7 @@ try_onemore:
1768 sbi->total_valid_block_count = 1769 sbi->total_valid_block_count =
1769 le64_to_cpu(sbi->ckpt->valid_block_count); 1770 le64_to_cpu(sbi->ckpt->valid_block_count);
1770 sbi->last_valid_block_count = sbi->total_valid_block_count; 1771 sbi->last_valid_block_count = sbi->total_valid_block_count;
1772 sbi->reserved_blocks = 0;
1771 1773
1772 for (i = 0; i < NR_INODE_TYPE; i++) { 1774 for (i = 0; i < NR_INODE_TYPE; i++) {
1773 INIT_LIST_HEAD(&sbi->inode_list[i]); 1775 INIT_LIST_HEAD(&sbi->inode_list[i]);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 714a3e47bbe8..9adc202fcd6f 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -30,6 +30,7 @@ enum {
30 FAULT_INFO_RATE, /* struct f2fs_fault_info */ 30 FAULT_INFO_RATE, /* struct f2fs_fault_info */
31 FAULT_INFO_TYPE, /* struct f2fs_fault_info */ 31 FAULT_INFO_TYPE, /* struct f2fs_fault_info */
32#endif 32#endif
33 RESERVED_BLOCKS,
33}; 34};
34 35
35struct f2fs_attr { 36struct f2fs_attr {
@@ -51,7 +52,7 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
51 return (unsigned char *)SM_I(sbi)->dcc_info; 52 return (unsigned char *)SM_I(sbi)->dcc_info;
52 else if (struct_type == NM_INFO) 53 else if (struct_type == NM_INFO)
53 return (unsigned char *)NM_I(sbi); 54 return (unsigned char *)NM_I(sbi);
54 else if (struct_type == F2FS_SBI) 55 else if (struct_type == F2FS_SBI || struct_type == RESERVED_BLOCKS)
55 return (unsigned char *)sbi; 56 return (unsigned char *)sbi;
56#ifdef CONFIG_F2FS_FAULT_INJECTION 57#ifdef CONFIG_F2FS_FAULT_INJECTION
57 else if (struct_type == FAULT_INFO_RATE || 58 else if (struct_type == FAULT_INFO_RATE ||
@@ -111,6 +112,17 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
111 if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX)) 112 if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX))
112 return -EINVAL; 113 return -EINVAL;
113#endif 114#endif
115 if (a->struct_type == RESERVED_BLOCKS) {
116 spin_lock(&sbi->stat_lock);
117 if ((unsigned long)sbi->total_valid_block_count + t >
118 (unsigned long)sbi->user_block_count) {
119 spin_unlock(&sbi->stat_lock);
120 return -EINVAL;
121 }
122 *ui = t;
123 spin_unlock(&sbi->stat_lock);
124 return count;
125 }
114 *ui = t; 126 *ui = t;
115 return count; 127 return count;
116} 128}
@@ -165,6 +177,7 @@ F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time);
165F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); 177F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle);
166F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); 178F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
167F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards); 179F2FS_RW_ATTR(DCC_INFO, discard_cmd_control, max_small_discards, max_discards);
180F2FS_RW_ATTR(RESERVED_BLOCKS, f2fs_sb_info, reserved_blocks, reserved_blocks);
168F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections); 181F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, batched_trim_sections, trim_sections);
169F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); 182F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
170F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); 183F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
@@ -208,6 +221,7 @@ static struct attribute *f2fs_attrs[] = {
208 ATTR_LIST(inject_type), 221 ATTR_LIST(inject_type),
209#endif 222#endif
210 ATTR_LIST(lifetime_write_kbytes), 223 ATTR_LIST(lifetime_write_kbytes),
224 ATTR_LIST(reserved_blocks),
211 NULL, 225 NULL,
212}; 226};
213 227