summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWenjie Qi <qwjhust@gmail.com>2026-08-04 09:48:48 +0800
committerJaegeuk Kim <jaegeuk@kernel.org>2026-08-05 01:30:45 +0000
commit5cb33b00c8fbb6e8f1fa3d281c3036d5f7c7c41f (patch)
tree6f2af3ab37ad23dc5a78f8ca03d9cf777dab8e98
parent3de6b80941152a384ee1b9cf88ac1c9dd4eec6dd (diff)
downloadlinux-5cb33b00c8fbb6e8f1fa3d281c3036d5f7c7c41f.tar.gz
linux-5cb33b00c8fbb6e8f1fa3d281c3036d5f7c7c41f.zip
f2fs: avoid NULL checkpoint thread access in sysfs
checkpoint_merge can be enabled even when no checkpoint merge thread is running. A read-only mount is one case: f2fs does not start f2fs_issue_ckpt there, but ckpt_thread_ioprio is still writable through sysfs. The ckpt_thread_ioprio store path updates the saved ioprio value and, when checkpoint_merge is enabled, calls set_task_ioprio() for the checkpoint thread. If cprc->f2fs_issue_ckpt is NULL, that dereferences a NULL task pointer. Protect ckpt_thread_ioprio sysfs writes with s_umount as well, so the checkpoint thread cannot disappear under the store path while updating its ioprio. Fixes: e65920661708 ("f2fs: add ckpt_thread_ioprio sysfs node") Cc: stable@kernel.org Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com> Reviewed-by: Chao Yu <chao@kernel.org> Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
-rw-r--r--fs/f2fs/sysfs.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index d9f81edca04a..c976549ff1bc 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -557,7 +557,7 @@ out:
return -EINVAL;
cprc->ckpt_thread_ioprio = IOPRIO_PRIO_VALUE(class, level);
- if (test_opt(sbi, MERGE_CHECKPOINT)) {
+ if (cprc->f2fs_issue_ckpt) {
ret = set_task_ioprio(cprc->f2fs_issue_ckpt,
cprc->ckpt_thread_ioprio);
if (ret)
@@ -1007,13 +1007,14 @@ static ssize_t f2fs_sbi_store(struct f2fs_attr *a,
ssize_t ret;
bool gc_entry = (!strcmp(a->attr.name, "gc_urgent") ||
a->struct_type == GC_THREAD);
+ bool thread_entry = !strcmp(a->attr.name, "ckpt_thread_ioprio");
- if (gc_entry) {
+ if (gc_entry || thread_entry) {
if (!down_read_trylock(&sbi->sb->s_umount))
return -EAGAIN;
}
ret = __sbi_store(a, sbi, buf, count);
- if (gc_entry)
+ if (gc_entry || thread_entry)
up_read(&sbi->sb->s_umount);
return ret;