2018-09-10 03:18:31

by Sahitya Tummala

[permalink] [raw]
Subject: [PATCH] f2fs: add new idle interval timing for discard and gc paths

This helps to control the frequency of submission of discard and
GC requests independently, based on the need. The sleep timing of
GC thread is now aligned with this idle time when the dev is busy,
to avoid unnecessary periodic wakeups.

Suggested-by: Chao Yu <[email protected]>
Signed-off-by: Sahitya Tummala <[email protected]>
---
Documentation/ABI/testing/sysfs-fs-f2fs | 17 ++++++++++++++++-
fs/f2fs/f2fs.h | 31 +++++++++++++++++++++++++++----
fs/f2fs/gc.c | 6 ++++--
fs/f2fs/segment.c | 14 +++++---------
fs/f2fs/super.c | 2 ++
fs/f2fs/sysfs.c | 5 +++++
6 files changed, 59 insertions(+), 16 deletions(-)

diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 94a24ae..3ac4177 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -121,7 +121,22 @@ What: /sys/fs/f2fs/<disk>/idle_interval
Date: January 2016
Contact: "Jaegeuk Kim" <[email protected]>
Description:
- Controls the idle timing.
+ Controls the idle timing for all paths other than
+ discard and gc path.
+
+What: /sys/fs/f2fs/<disk>/discard_idle_interval
+Date: September 2018
+Contact: "Chao Yu" <[email protected]>
+Contact: "Sahitya Tummala" <[email protected]>
+Description:
+ Controls the idle timing for discard path.
+
+What: /sys/fs/f2fs/<disk>/gc_idle_interval
+Date: September 2018
+Contact: "Chao Yu" <[email protected]>
+Contact: "Sahitya Tummala" <[email protected]>
+Description:
+ Controls the idle timing for gc path.

What: /sys/fs/f2fs/<disk>/iostat_enable
Date: August 2017
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index abf9256..6070681 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1093,6 +1093,8 @@ enum {
enum {
CP_TIME,
REQ_TIME,
+ DISCARD_TIME,
+ GC_TIME,
MAX_TIME,
};

@@ -1347,14 +1349,35 @@ static inline void f2fs_update_time(struct f2fs_sb_info *sbi, int type)
sbi->last_time[type] = jiffies;
}

-static inline bool f2fs_time_over(struct f2fs_sb_info *sbi, int type)
+static inline bool f2fs_time_over_cp(struct f2fs_sb_info *sbi)
+{
+ unsigned long interval = sbi->interval_time[CP_TIME] * HZ;
+
+ return time_after(jiffies, sbi->last_time[CP_TIME] + interval);
+}
+
+static inline bool f2fs_time_over_req(struct f2fs_sb_info *sbi, int type)
+{
+ unsigned long interval = sbi->interval_time[type] * HZ;
+
+ return time_after(jiffies, sbi->last_time[REQ_TIME] + interval);
+}
+
+static inline unsigned int f2fs_get_wait_time(struct f2fs_sb_info *sbi,
+ int type)
{
unsigned long interval = sbi->interval_time[type] * HZ;
+ unsigned int wait_ms = 0;
+ long delta;
+
+ delta = (sbi->last_time[REQ_TIME] + interval) - jiffies;
+ if (delta > 0)
+ wait_ms = jiffies_to_msecs(delta);

- return time_after(jiffies, sbi->last_time[type] + interval);
+ return wait_ms;
}

-static inline bool is_idle(struct f2fs_sb_info *sbi)
+static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
{
struct block_device *bdev = sbi->sb->s_bdev;
struct request_queue *q = bdev_get_queue(bdev);
@@ -1363,7 +1386,7 @@ static inline bool is_idle(struct f2fs_sb_info *sbi)
if (rl->count[BLK_RW_SYNC] || rl->count[BLK_RW_ASYNC])
return false;

- return f2fs_time_over(sbi, REQ_TIME);
+ return f2fs_time_over_req(sbi, type);
}

/*
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index 5c8d004..c0bafea 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -83,8 +83,10 @@ static int gc_thread_func(void *data)
if (!mutex_trylock(&sbi->gc_mutex))
goto next;

- if (!is_idle(sbi)) {
- increase_sleep_time(gc_th, &wait_ms);
+ if (!is_idle(sbi, GC_TIME)) {
+ wait_ms = f2fs_get_wait_time(sbi, GC_TIME);
+ if (!wait_ms)
+ increase_sleep_time(gc_th, &wait_ms);
mutex_unlock(&sbi->gc_mutex);
goto next;
}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index c5024f8..f8a6a7b 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -511,7 +511,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
else
f2fs_build_free_nids(sbi, false, false);

- if (!is_idle(sbi) &&
+ if (!is_idle(sbi, REQ_TIME) &&
(!excess_dirty_nats(sbi) && !excess_dirty_nodes(sbi)))
return;

@@ -521,7 +521,7 @@ void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi)
excess_prefree_segs(sbi) ||
excess_dirty_nats(sbi) ||
excess_dirty_nodes(sbi) ||
- f2fs_time_over(sbi, CP_TIME)) {
+ f2fs_time_over_cp(sbi)) {
if (test_opt(sbi, DATA_FLUSH)) {
struct blk_plug plug;

@@ -1371,7 +1371,7 @@ static int __issue_discard_cmd(struct f2fs_sb_info *sbi,
f2fs_bug_on(sbi, dc->state != D_PREP);

if (dpolicy->io_aware && i < dpolicy->io_aware_gran &&
- !is_idle(sbi)) {
+ !is_idle(sbi, DISCARD_TIME)) {
io_interrupted = true;
break;
}
@@ -1564,8 +1564,6 @@ static int issue_discard_thread(void *data)
struct discard_policy dpolicy;
unsigned int wait_ms = DEF_MIN_DISCARD_ISSUE_TIME;
int issued;
- unsigned long interval = sbi->interval_time[REQ_TIME] * HZ;
- long delta;

set_freezable();

@@ -1602,10 +1600,8 @@ static int issue_discard_thread(void *data)
__wait_all_discard_cmd(sbi, &dpolicy);
wait_ms = dpolicy.min_interval;
} else if (issued == -1){
- delta = (sbi->last_time[REQ_TIME] + interval) - jiffies;
- if (delta > 0)
- wait_ms = jiffies_to_msecs(delta);
- else
+ wait_ms = f2fs_get_wait_time(sbi, DISCARD_TIME);
+ if (!wait_ms)
wait_ms = dpolicy.mid_interval;
} else {
wait_ms = dpolicy.max_interval;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 896b885..1706f45 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2423,6 +2423,8 @@ static void init_sb_info(struct f2fs_sb_info *sbi)
sbi->dir_level = DEF_DIR_LEVEL;
sbi->interval_time[CP_TIME] = DEF_CP_INTERVAL;
sbi->interval_time[REQ_TIME] = DEF_IDLE_INTERVAL;
+ sbi->interval_time[DISCARD_TIME] = DEF_IDLE_INTERVAL;
+ sbi->interval_time[GC_TIME] = DEF_IDLE_INTERVAL;
clear_sbi_flag(sbi, SBI_NEED_FSCK);

for (i = 0; i < NR_COUNT_TYPE; i++)
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 81c0e53..0afe99c 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -407,6 +407,9 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, cp_interval, interval_time[CP_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, idle_interval, interval_time[REQ_TIME]);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, discard_idle_interval,
+ interval_time[DISCARD_TIME]);
+F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_idle_interval, interval_time[GC_TIME]);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, iostat_enable, iostat_enable);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, readdir_ra, readdir_ra);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, gc_pin_file_thresh, gc_pin_file_threshold);
@@ -460,6 +463,8 @@ static ssize_t f2fs_feature_show(struct f2fs_attr *a,
ATTR_LIST(dirty_nats_ratio),
ATTR_LIST(cp_interval),
ATTR_LIST(idle_interval),
+ ATTR_LIST(discard_idle_interval),
+ ATTR_LIST(gc_idle_interval),
ATTR_LIST(iostat_enable),
ATTR_LIST(readdir_ra),
ATTR_LIST(gc_pin_file_thresh),
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.



2018-09-10 17:40:07

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH] f2fs: add new idle interval timing for discard and gc paths

Hi Sahitya,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on f2fs/dev-test]
[also build test ERROR on next-20180910]
[cannot apply to v4.19-rc3]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Sahitya-Tummala/f2fs-add-new-idle-interval-timing-for-discard-and-gc-paths/20180911-011700
base: https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git dev-test
config: x86_64-randconfig-x013-201836 (attached as .config)
compiler: gcc-7 (Debian 7.3.0-1) 7.3.0
reproduce:
# save the attached .config to linux build tree
make ARCH=x86_64

All errors (new ones prefixed by >>):

fs//f2fs/segment.c: In function '__issue_discard_cmd_orderly':
>> fs//f2fs/segment.c:1314:29: error: too few arguments to function 'is_idle'
if (dpolicy->io_aware && !is_idle(sbi)) {
^~~~~~~
In file included from fs//f2fs/segment.c:22:0:
fs//f2fs/f2fs.h:1381:20: note: declared here
static inline bool is_idle(struct f2fs_sb_info *sbi, int type)
^~~~~~~

vim +/is_idle +1314 fs//f2fs/segment.c

004b6862 Chao Yu 2017-04-14 1283
20ee4382 Chao Yu 2018-07-08 1284 static unsigned int __issue_discard_cmd_orderly(struct f2fs_sb_info *sbi,
20ee4382 Chao Yu 2018-07-08 1285 struct discard_policy *dpolicy)
20ee4382 Chao Yu 2018-07-08 1286 {
20ee4382 Chao Yu 2018-07-08 1287 struct discard_cmd_control *dcc = SM_I(sbi)->dcc_info;
20ee4382 Chao Yu 2018-07-08 1288 struct discard_cmd *prev_dc = NULL, *next_dc = NULL;
20ee4382 Chao Yu 2018-07-08 1289 struct rb_node **insert_p = NULL, *insert_parent = NULL;
20ee4382 Chao Yu 2018-07-08 1290 struct discard_cmd *dc;
20ee4382 Chao Yu 2018-07-08 1291 struct blk_plug plug;
20ee4382 Chao Yu 2018-07-08 1292 unsigned int pos = dcc->next_pos;
20ee4382 Chao Yu 2018-07-08 1293 unsigned int issued = 0;
20ee4382 Chao Yu 2018-07-08 1294 bool io_interrupted = false;
20ee4382 Chao Yu 2018-07-08 1295
20ee4382 Chao Yu 2018-07-08 1296 mutex_lock(&dcc->cmd_lock);
20ee4382 Chao Yu 2018-07-08 1297 dc = (struct discard_cmd *)f2fs_lookup_rb_tree_ret(&dcc->root,
20ee4382 Chao Yu 2018-07-08 1298 NULL, pos,
20ee4382 Chao Yu 2018-07-08 1299 (struct rb_entry **)&prev_dc,
20ee4382 Chao Yu 2018-07-08 1300 (struct rb_entry **)&next_dc,
20ee4382 Chao Yu 2018-07-08 1301 &insert_p, &insert_parent, true);
20ee4382 Chao Yu 2018-07-08 1302 if (!dc)
20ee4382 Chao Yu 2018-07-08 1303 dc = next_dc;
20ee4382 Chao Yu 2018-07-08 1304
20ee4382 Chao Yu 2018-07-08 1305 blk_start_plug(&plug);
20ee4382 Chao Yu 2018-07-08 1306
20ee4382 Chao Yu 2018-07-08 1307 while (dc) {
20ee4382 Chao Yu 2018-07-08 1308 struct rb_node *node;
6b9cb124 Chao Yu 2018-08-08 1309 int err = 0;
20ee4382 Chao Yu 2018-07-08 1310
20ee4382 Chao Yu 2018-07-08 1311 if (dc->state != D_PREP)
20ee4382 Chao Yu 2018-07-08 1312 goto next;
20ee4382 Chao Yu 2018-07-08 1313
20ee4382 Chao Yu 2018-07-08 @1314 if (dpolicy->io_aware && !is_idle(sbi)) {
20ee4382 Chao Yu 2018-07-08 1315 io_interrupted = true;
20ee4382 Chao Yu 2018-07-08 1316 break;
20ee4382 Chao Yu 2018-07-08 1317 }
20ee4382 Chao Yu 2018-07-08 1318
20ee4382 Chao Yu 2018-07-08 1319 dcc->next_pos = dc->lstart + dc->len;
6b9cb124 Chao Yu 2018-08-08 1320 err = __submit_discard_cmd(sbi, dpolicy, dc, &issued);
20ee4382 Chao Yu 2018-07-08 1321
35ec7d57 Chao Yu 2018-08-06 1322 if (issued >= dpolicy->max_requests)
20ee4382 Chao Yu 2018-07-08 1323 break;
20ee4382 Chao Yu 2018-07-08 1324 next:
20ee4382 Chao Yu 2018-07-08 1325 node = rb_next(&dc->rb_node);
6b9cb124 Chao Yu 2018-08-08 1326 if (err)
6b9cb124 Chao Yu 2018-08-08 1327 __remove_discard_cmd(sbi, dc);
20ee4382 Chao Yu 2018-07-08 1328 dc = rb_entry_safe(node, struct discard_cmd, rb_node);
20ee4382 Chao Yu 2018-07-08 1329 }
20ee4382 Chao Yu 2018-07-08 1330
20ee4382 Chao Yu 2018-07-08 1331 blk_finish_plug(&plug);
20ee4382 Chao Yu 2018-07-08 1332
20ee4382 Chao Yu 2018-07-08 1333 if (!dc)
20ee4382 Chao Yu 2018-07-08 1334 dcc->next_pos = 0;
20ee4382 Chao Yu 2018-07-08 1335
20ee4382 Chao Yu 2018-07-08 1336 mutex_unlock(&dcc->cmd_lock);
20ee4382 Chao Yu 2018-07-08 1337
20ee4382 Chao Yu 2018-07-08 1338 if (!issued && io_interrupted)
20ee4382 Chao Yu 2018-07-08 1339 issued = -1;
20ee4382 Chao Yu 2018-07-08 1340
20ee4382 Chao Yu 2018-07-08 1341 return issued;
20ee4382 Chao Yu 2018-07-08 1342 }
20ee4382 Chao Yu 2018-07-08 1343

:::::: The code at line 1314 was first introduced by commit
:::::: 20ee4382322cd9cf6ecfcf4f429ed108c617fb4a f2fs: issue small discard by LBA order

:::::: TO: Chao Yu <[email protected]>
:::::: CC: Jaegeuk Kim <[email protected]>

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (5.03 kB)
.config.gz (28.28 kB)
Download all attachments