Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

f2fs: support passing down write hints to block layer with F2FS policy

Add 'whint_mode=fs-based' mount option. In this mode, F2FS passes
down write hints with its policy.

* whint_mode=fs-based. F2FS passes down hints with its policy.

User F2FS Block
---- ---- -----
META WRITE_LIFE_MEDIUM;
HOT_NODE WRITE_LIFE_NOT_SET
WARM_NODE "
COLD_NODE WRITE_LIFE_NONE
ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME
extension list " "

-- buffered io
WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG
WRITE_LIFE_NONE " "
WRITE_LIFE_MEDIUM " "
WRITE_LIFE_LONG " "

-- direct io
WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME
WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT
WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET
WRITE_LIFE_NONE " WRITE_LIFE_NONE
WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM
WRITE_LIFE_LONG " WRITE_LIFE_LONG

Many thanks to Chao Yu and Jaegeuk Kim for comments to
implement this patch.

Signed-off-by: Hyunchul Lee <cheol.lee@lge.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>

authored by

Hyunchul Lee and committed by
Jaegeuk Kim
f2e703f9 0cdd3195

+54 -9
+1
fs/f2fs/f2fs.h
··· 1040 1040 enum { 1041 1041 WHINT_MODE_OFF, /* not pass down write hints */ 1042 1042 WHINT_MODE_USER, /* try to pass down hints given by users */ 1043 + WHINT_MODE_FS, /* pass down hints with F2FS policy */ 1043 1044 }; 1044 1045 1045 1046 struct f2fs_sb_info {
+48 -9
fs/f2fs/segment.c
··· 2489 2489 * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM 2490 2490 * WRITE_LIFE_LONG " WRITE_LIFE_LONG 2491 2491 * 2492 + * 3) whint_mode=fs-based. F2FS passes down hints with its policy. 2493 + * 2494 + * User F2FS Block 2495 + * ---- ---- ----- 2496 + * META WRITE_LIFE_MEDIUM; 2497 + * HOT_NODE WRITE_LIFE_NOT_SET 2498 + * WARM_NODE " 2499 + * COLD_NODE WRITE_LIFE_NONE 2500 + * ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME 2501 + * extension list " " 2502 + * 2503 + * -- buffered io 2504 + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME 2505 + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT 2506 + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_LONG 2507 + * WRITE_LIFE_NONE " " 2508 + * WRITE_LIFE_MEDIUM " " 2509 + * WRITE_LIFE_LONG " " 2510 + * 2511 + * -- direct io 2512 + * WRITE_LIFE_EXTREME COLD_DATA WRITE_LIFE_EXTREME 2513 + * WRITE_LIFE_SHORT HOT_DATA WRITE_LIFE_SHORT 2514 + * WRITE_LIFE_NOT_SET WARM_DATA WRITE_LIFE_NOT_SET 2515 + * WRITE_LIFE_NONE " WRITE_LIFE_NONE 2516 + * WRITE_LIFE_MEDIUM " WRITE_LIFE_MEDIUM 2517 + * WRITE_LIFE_LONG " WRITE_LIFE_LONG 2492 2518 */ 2493 2519 2494 2520 enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi, ··· 2522 2496 { 2523 2497 if (sbi->whint_mode == WHINT_MODE_USER) { 2524 2498 if (type == DATA) { 2525 - switch (temp) { 2526 - case COLD: 2527 - return WRITE_LIFE_EXTREME; 2528 - case HOT: 2529 - return WRITE_LIFE_SHORT; 2530 - default: 2499 + if (temp == WARM) 2531 2500 return WRITE_LIFE_NOT_SET; 2532 - } 2501 + else if (temp == HOT) 2502 + return WRITE_LIFE_SHORT; 2503 + else if (temp == COLD) 2504 + return WRITE_LIFE_EXTREME; 2533 2505 } else { 2534 2506 return WRITE_LIFE_NOT_SET; 2535 2507 } 2536 - } else { 2537 - return WRITE_LIFE_NOT_SET; 2508 + } else if (sbi->whint_mode == WHINT_MODE_FS) { 2509 + if (type == DATA) { 2510 + if (temp == WARM) 2511 + return WRITE_LIFE_LONG; 2512 + else if (temp == HOT) 2513 + return WRITE_LIFE_SHORT; 2514 + else if (temp == COLD) 2515 + return WRITE_LIFE_EXTREME; 2516 + } else if (type == NODE) { 2517 + if (temp == WARM || temp == HOT) 2518 + return WRITE_LIFE_NOT_SET; 2519 + else if (temp == COLD) 2520 + return WRITE_LIFE_NONE; 2521 + } else if (type == META) { 2522 + return WRITE_LIFE_MEDIUM; 2523 + } 2538 2524 } 2525 + return WRITE_LIFE_NOT_SET; 2539 2526 } 2540 2527 2541 2528 static int __get_segment_type_2(struct f2fs_io_info *fio)
+5
fs/f2fs/super.c
··· 691 691 } else if (strlen(name) == 3 && 692 692 !strncmp(name, "off", 3)) { 693 693 sbi->whint_mode = WHINT_MODE_OFF; 694 + } else if (strlen(name) == 8 && 695 + !strncmp(name, "fs-based", 8)) { 696 + sbi->whint_mode = WHINT_MODE_FS; 694 697 } else { 695 698 kfree(name); 696 699 return -EINVAL; ··· 1261 1258 f2fs_show_quota_options(seq, sbi->sb); 1262 1259 if (sbi->whint_mode == WHINT_MODE_USER) 1263 1260 seq_printf(seq, ",whint_mode=%s", "user-based"); 1261 + else if (sbi->whint_mode == WHINT_MODE_FS) 1262 + seq_printf(seq, ",whint_mode=%s", "fs-based"); 1264 1263 1265 1264 return 0; 1266 1265 }