Commit b1c57c1caa753cec299e62bb4272da0e85a01ef0

Authored by Jaegeuk Kim
1 parent fb5566da91

f2fs: add a sysfs entry to control max_victim_search

Previously during SSR and GC, the maximum number of retrials to find a victim
segment was hard-coded by MAX_VICTIM_SEARCH, 4096 by default.

This number makes an effect on IO locality, when SSR mode is activated, which
results in performance fluctuation on some low-end devices.

If max_victim_search = 4, the victim will be searched like below.
("D" represents a dirty segment, and "*" indicates a selected victim segment.)

 D1 D2 D3 D4 D5 D6 D7 D8 D9
[   *       ]
      [   *    ]
            [         * ]
	                [ ....]

This patch adds a sysfs entry to control the number dynamically through:
  /sys/fs/f2fs/$dev/max_victim_search

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>

Showing 4 changed files with 12 additions and 3 deletions Side-by-side Diff

... ... @@ -451,6 +451,9 @@
451 451 struct f2fs_gc_kthread *gc_thread; /* GC thread */
452 452 unsigned int cur_victim_sec; /* current victim section num */
453 453  
  454 + /* maximum # of trials to find a victim segment for SSR and GC */
  455 + unsigned int max_victim_search;
  456 +
454 457 /*
455 458 * for stat information.
456 459 * one is for the LFS mode, and the other is for the SSR mode.
... ... @@ -163,8 +163,8 @@
163 163 p->ofs_unit = sbi->segs_per_sec;
164 164 }
165 165  
166   - if (p->max_search > MAX_VICTIM_SEARCH)
167   - p->max_search = MAX_VICTIM_SEARCH;
  166 + if (p->max_search > sbi->max_victim_search)
  167 + p->max_search = sbi->max_victim_search;
168 168  
169 169 p->offset = sbi->last_victim[p->gc_mode];
170 170 }
... ... @@ -20,7 +20,7 @@
20 20 #define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */
21 21  
22 22 /* Search max. number of dirty segments to select a victim segment */
23   -#define MAX_VICTIM_SEARCH 4096 /* covers 8GB */
  23 +#define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */
24 24  
25 25 struct f2fs_gc_kthread {
26 26 struct task_struct *f2fs_gc_task;
... ... @@ -74,6 +74,7 @@
74 74 enum {
75 75 GC_THREAD, /* struct f2fs_gc_thread */
76 76 SM_INFO, /* struct f2fs_sm_info */
  77 + F2FS_SBI, /* struct f2fs_sb_info */
77 78 };
78 79  
79 80 struct f2fs_attr {
... ... @@ -91,6 +92,8 @@
91 92 return (unsigned char *)sbi->gc_thread;
92 93 else if (struct_type == SM_INFO)
93 94 return (unsigned char *)SM_I(sbi);
  95 + else if (struct_type == F2FS_SBI)
  96 + return (unsigned char *)sbi;
94 97 return NULL;
95 98 }
96 99  
... ... @@ -180,6 +183,7 @@
180 183 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
181 184 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
182 185 F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
  186 +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
183 187  
184 188 #define ATTR_LIST(name) (&f2fs_attr_##name.attr)
185 189 static struct attribute *f2fs_attrs[] = {
... ... @@ -191,6 +195,7 @@
191 195 ATTR_LIST(max_small_discards),
192 196 ATTR_LIST(ipu_policy),
193 197 ATTR_LIST(min_ipu_util),
  198 + ATTR_LIST(max_victim_search),
194 199 NULL,
195 200 };
196 201  
... ... @@ -775,6 +780,7 @@
775 780 sbi->node_ino_num = le32_to_cpu(raw_super->node_ino);
776 781 sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino);
777 782 sbi->cur_victim_sec = NULL_SECNO;
  783 + sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH;
778 784  
779 785 for (i = 0; i < NR_COUNT_TYPE; i++)
780 786 atomic_set(&sbi->nr_pages[i], 0);