Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2e703f9 authored by Hyunchul Lee's avatar Hyunchul Lee Committed by Jaegeuk Kim
Browse files

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: default avatarHyunchul Lee <cheol.lee@lge.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 0cdd3195
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1040,6 +1040,7 @@ enum {
enum {
	WHINT_MODE_OFF,		/* not pass down write hints */
	WHINT_MODE_USER,	/* try to pass down hints given by users */
	WHINT_MODE_FS,		/* pass down hints with F2FS policy */
};

struct f2fs_sb_info {
+48 −9
Original line number Diff line number Diff line
@@ -2489,6 +2489,32 @@ int rw_hint_to_seg_type(enum rw_hint hint)
 * WRITE_LIFE_MEDIUM     "                        WRITE_LIFE_MEDIUM
 * WRITE_LIFE_LONG       "                        WRITE_LIFE_LONG
 *
 * 3) 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
 */

enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi,
@@ -2496,21 +2522,34 @@ enum rw_hint io_type_to_rw_hint(struct f2fs_sb_info *sbi,
{
	if (sbi->whint_mode == WHINT_MODE_USER) {
		if (type == DATA) {
			switch (temp) {
			case COLD:
				return WRITE_LIFE_EXTREME;
			case HOT:
				return WRITE_LIFE_SHORT;
			default:
			if (temp == WARM)
				return WRITE_LIFE_NOT_SET;
			}
			else if (temp == HOT)
				return WRITE_LIFE_SHORT;
			else if (temp == COLD)
				return WRITE_LIFE_EXTREME;
		} else {
			return WRITE_LIFE_NOT_SET;
		}
	} else {
	} else if (sbi->whint_mode == WHINT_MODE_FS) {
		if (type == DATA) {
			if (temp == WARM)
				return WRITE_LIFE_LONG;
			else if (temp == HOT)
				return WRITE_LIFE_SHORT;
			else if (temp == COLD)
				return WRITE_LIFE_EXTREME;
		} else if (type == NODE) {
			if (temp == WARM || temp == HOT)
				return WRITE_LIFE_NOT_SET;
			else if (temp == COLD)
				return WRITE_LIFE_NONE;
		} else if (type == META) {
			return WRITE_LIFE_MEDIUM;
		}
	}
	return WRITE_LIFE_NOT_SET;
}

static int __get_segment_type_2(struct f2fs_io_info *fio)
{
+5 −0
Original line number Diff line number Diff line
@@ -691,6 +691,9 @@ static int parse_options(struct super_block *sb, char *options)
			} else if (strlen(name) == 3 &&
					!strncmp(name, "off", 3)) {
				sbi->whint_mode = WHINT_MODE_OFF;
			} else if (strlen(name) == 8 &&
					!strncmp(name, "fs-based", 8)) {
				sbi->whint_mode = WHINT_MODE_FS;
			} else {
				kfree(name);
				return -EINVAL;
@@ -1258,6 +1261,8 @@ static int f2fs_show_options(struct seq_file *seq, struct dentry *root)
	f2fs_show_quota_options(seq, sbi->sb);
	if (sbi->whint_mode == WHINT_MODE_USER)
		seq_printf(seq, ",whint_mode=%s", "user-based");
	else if (sbi->whint_mode == WHINT_MODE_FS)
		seq_printf(seq, ",whint_mode=%s", "fs-based");

	return 0;
}