Commit e6592066 authored by Daeho Jeong's avatar Daeho Jeong Committed by Jaegeuk Kim
Browse files

f2fs: add ckpt_thread_ioprio sysfs node



Added "ckpt_thread_ioprio" sysfs node to give a way to change checkpoint
merge daemon's io priority. Its default value is "be,3", which means
"BE" I/O class and I/O priority "3". We can select the class between "rt"
and "be", and set the I/O priority within valid range of it.
"," delimiter is necessary in between I/O class and priority number.

Signed-off-by: default avatarDaeho Jeong <daehojeong@google.com>
Reviewed-by: default avatarChao Yu <yuchao0@huawei.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
parent 261eeb9c
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -400,3 +400,12 @@ Description: Show status of f2fs superblock in real time.
		0x1000 SBI_QUOTA_NEED_REPAIR quota file may be corrupted
		0x2000 SBI_IS_RESIZEFS       resizefs is in process
		====== ===================== =================================

What:		/sys/fs/f2fs/<disk>/ckpt_thread_ioprio
Date:		January 2021
Contact:	"Daeho Jeong" <daehojeong@google.com>
Description:	Give a way to change checkpoint merge daemon's io priority.
		Its default value is "be,3", which means "BE" I/O class and
		I/O priority "3". We can select the class between "rt" and "be",
		and set the I/O priority within valid range of it. "," delimiter
		is necessary in between I/O class and priority number.
+2 −1
Original line number Diff line number Diff line
@@ -1851,7 +1851,7 @@ int f2fs_start_ckpt_thread(struct f2fs_sb_info *sbi)
		return -ENOMEM;
	}

	set_task_ioprio(cprc->f2fs_issue_ckpt, DEFAULT_CHECKPOINT_IOPRIO);
	set_task_ioprio(cprc->f2fs_issue_ckpt, cprc->ckpt_thread_ioprio);

	return 0;
}
@@ -1877,6 +1877,7 @@ void f2fs_init_ckpt_req_control(struct f2fs_sb_info *sbi)
	atomic_set(&cprc->issued_ckpt, 0);
	atomic_set(&cprc->total_ckpt, 0);
	atomic_set(&cprc->queued_ckpt, 0);
	cprc->ckpt_thread_ioprio = DEFAULT_CHECKPOINT_IOPRIO;
	init_waitqueue_head(&cprc->ckpt_wait_queue);
	init_llist_head(&cprc->issue_list);
	spin_lock_init(&cprc->stat_lock);
+1 −0
Original line number Diff line number Diff line
@@ -277,6 +277,7 @@ struct ckpt_req {

struct ckpt_req_control {
	struct task_struct *f2fs_issue_ckpt;	/* checkpoint task */
	int ckpt_thread_ioprio;			/* checkpoint merge thread ioprio */
	wait_queue_head_t ckpt_wait_queue;	/* waiting queue for wake-up */
	atomic_t issued_ckpt;		/* # of actually issued ckpts */
	atomic_t total_ckpt;		/* # of total ckpts */
+55 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/f2fs_fs.h>
#include <linux/seq_file.h>
#include <linux/unicode.h>
#include <linux/ioprio.h>

#include "f2fs.h"
#include "segment.h"
@@ -34,6 +35,7 @@ enum {
	FAULT_INFO_TYPE,	/* struct f2fs_fault_info */
#endif
	RESERVED_BLOCKS,	/* struct f2fs_sb_info */
	CPRC_INFO,	/* struct ckpt_req_control */
};

struct f2fs_attr {
@@ -70,6 +72,8 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
	else if (struct_type == STAT_INFO)
		return (unsigned char *)F2FS_STAT(sbi);
#endif
	else if (struct_type == CPRC_INFO)
		return (unsigned char *)&sbi->cprc_info;
	return NULL;
}

@@ -261,6 +265,23 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
		return len;
	}

	if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {
		struct ckpt_req_control *cprc = &sbi->cprc_info;
		int len = 0;
		int class = IOPRIO_PRIO_CLASS(cprc->ckpt_thread_ioprio);
		int data = IOPRIO_PRIO_DATA(cprc->ckpt_thread_ioprio);

		if (class == IOPRIO_CLASS_RT)
			len += scnprintf(buf + len, PAGE_SIZE - len, "rt,");
		else if (class == IOPRIO_CLASS_BE)
			len += scnprintf(buf + len, PAGE_SIZE - len, "be,");
		else
			return -EINVAL;

		len += scnprintf(buf + len, PAGE_SIZE - len, "%d\n", data);
		return len;
	}

	ui = (unsigned int *)(ptr + a->offset);

	return sprintf(buf, "%u\n", *ui);
@@ -314,6 +335,38 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
		return ret ? ret : count;
	}

	if (!strcmp(a->attr.name, "ckpt_thread_ioprio")) {
		const char *name = strim((char *)buf);
		struct ckpt_req_control *cprc = &sbi->cprc_info;
		int class;
		long data;
		int ret;

		if (!strncmp(name, "rt,", 3))
			class = IOPRIO_CLASS_RT;
		else if (!strncmp(name, "be,", 3))
			class = IOPRIO_CLASS_BE;
		else
			return -EINVAL;

		name += 3;
		ret = kstrtol(name, 10, &data);
		if (ret)
			return ret;
		if (data >= IOPRIO_BE_NR || data < 0)
			return -EINVAL;

		cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, data);
		if (test_opt(sbi, MERGE_CHECKPOINT)) {
			ret = set_task_ioprio(cprc->f2fs_issue_ckpt,
					cprc->ckpt_thread_ioprio);
			if (ret)
				return ret;
		}

		return count;
	}

	ui = (unsigned int *)(ptr + a->offset);

	ret = kstrtoul(skip_spaces(buf), 0, &t);
@@ -573,6 +626,7 @@ F2FS_RW_ATTR(FAULT_INFO_TYPE, f2fs_fault_info, inject_type, inject_type);
#endif
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, data_io_flag, data_io_flag);
F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, node_io_flag, node_io_flag);
F2FS_RW_ATTR(CPRC_INFO, ckpt_req_control, ckpt_thread_ioprio, ckpt_thread_ioprio);
F2FS_GENERAL_RO_ATTR(dirty_segments);
F2FS_GENERAL_RO_ATTR(free_segments);
F2FS_GENERAL_RO_ATTR(lifetime_write_kbytes);
@@ -658,6 +712,7 @@ static struct attribute *f2fs_attrs[] = {
#endif
	ATTR_LIST(data_io_flag),
	ATTR_LIST(node_io_flag),
	ATTR_LIST(ckpt_thread_ioprio),
	ATTR_LIST(dirty_segments),
	ATTR_LIST(free_segments),
	ATTR_LIST(unusable),