summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2026-07-27 12:43:22 +0100
committerMark Brown <broonie@kernel.org>2026-07-27 12:43:22 +0100
commitad9dea0f2f4a98c2025710b05f3c60eb571fc7c2 (patch)
tree187d0f7e9747560e7a6533deb1331eadca52715c /fs
parent28ecf7d9c1968f815799c8262ad20a9348319e36 (diff)
parent6429f3bf6dc33cba42055260f905559c43976eeb (diff)
downloadlinux-next-ad9dea0f2f4a98c2025710b05f3c60eb571fc7c2.tar.gz
linux-next-ad9dea0f2f4a98c2025710b05f3c60eb571fc7c2.zip
Merge branch 'dev' of https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs.git
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/data.c5
-rw-r--r--fs/f2fs/debug.c4
-rw-r--r--fs/f2fs/f2fs.h29
-rw-r--r--fs/f2fs/file.c28
-rw-r--r--fs/f2fs/gc.c36
-rw-r--r--fs/f2fs/gc.h27
-rw-r--r--fs/f2fs/segment.c9
-rw-r--r--fs/f2fs/super.c6
-rw-r--r--fs/f2fs/sysfs.c22
9 files changed, 82 insertions, 84 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index a88ed125d266..1b2d9fe992ea 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1288,10 +1288,11 @@ retry:
if (folio_test_large(folio)) {
pgoff_t folio_index = mapping_align_index(mapping, index);
+ unsigned long nr_pages = folio_nr_pages(folio);
f2fs_folio_put(folio, true);
invalidate_inode_pages2_range(mapping, folio_index,
- folio_index + folio_nr_pages(folio) - 1);
+ folio_index + nr_pages - 1);
f2fs_schedule_timeout(DEFAULT_SCHEDULE_TIMEOUT);
goto retry;
}
@@ -3900,7 +3901,7 @@ repeat:
* Will wait that below with our IO control.
*/
folio = f2fs_filemap_get_folio(mapping, index,
- FGP_LOCK | FGP_WRITE | FGP_CREAT | FGP_NOFS,
+ FGP_LOCK | FGP_WRITE | FGP_CREAT,
mapping_gfp_mask(mapping));
if (IS_ERR(folio)) {
err = PTR_ERR(folio);
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index af88db8fdb71..ff379aff4472 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -352,10 +352,6 @@ static void update_mem_info(struct f2fs_sb_info *sbi)
get_cache:
si->cache_mem = 0;
- /* build gc */
- if (sbi->gc_thread)
- si->cache_mem += sizeof(struct f2fs_gc_kthread);
-
/* build merge flush thread */
if (SM_I(sbi)->fcc_info)
si->cache_mem += sizeof(struct flush_cmd_control);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 8376bbe58ee3..9c73b1895568 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1747,6 +1747,33 @@ struct decompress_io_ctx {
#define MAX_COMPRESS_LOG_SIZE 8
#define MAX_COMPRESS_WINDOW_SIZE(log_size) ((PAGE_SIZE) << (log_size))
+struct f2fs_gc_kthread {
+ struct task_struct *f2fs_gc_task;
+ wait_queue_head_t gc_wait_queue_head;
+
+ /* for gc sleep time */
+ unsigned int urgent_sleep_time;
+ unsigned int min_sleep_time;
+ unsigned int max_sleep_time;
+ unsigned int no_gc_sleep_time;
+
+ /* for changing gc mode */
+ bool gc_wake;
+
+ /* for GC_MERGE mount option */
+ wait_queue_head_t fggc_wq; /*
+ * caller of f2fs_balance_fs()
+ * will wait on this wait queue.
+ */
+
+ /* for gc control for zoned devices */
+ unsigned int no_zoned_gc_percent;
+ unsigned int boost_zoned_gc_percent;
+ unsigned int valid_thresh_ratio;
+ unsigned int boost_gc_multiple;
+ unsigned int boost_gc_greedy;
+};
+
struct f2fs_sb_info {
struct super_block *sb; /* pointer to VFS super block */
struct proc_dir_entry *s_proc; /* proc entry */
@@ -1882,7 +1909,7 @@ struct f2fs_sb_info {
* semaphore for GC, avoid
* race between GC and GC or CP
*/
- struct f2fs_gc_kthread *gc_thread; /* GC thread */
+ struct f2fs_gc_kthread gc_thread; /* GC thread */
struct atgc_management am; /* atgc management */
unsigned int cur_victim_sec; /* current victim section num */
unsigned int gc_mode; /* current GC state */
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 089759366cdc..9d315c3cd9c8 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -1103,17 +1103,23 @@ int f2fs_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
!IS_ALIGNED(attr->ia_size,
F2FS_BLK_TO_BYTES(fi->i_cluster_size)))
return -EINVAL;
- /*
- * To prevent scattered pin block generation, we don't allow
- * smaller/equal size unaligned truncation for pinned file.
- * We only support overwrite IO to pinned file, so don't
- * care about larger size truncation.
- */
- if (f2fs_is_pinned_file(inode) &&
- attr->ia_size <= i_size_read(inode) &&
- !IS_ALIGNED(attr->ia_size,
- F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi))))
- return -EINVAL;
+
+ if (f2fs_is_pinned_file(inode)) {
+ /*
+ * It may break section-aligned fallocate recovery
+ * mechanism, so do not allow larger size truncation.
+ */
+ if (attr->ia_size > i_size_read(inode))
+ return -EINVAL;
+ /*
+ * To prevent scattered pin block generation, we don't
+ * allow smaller/equal size unaligned truncation for
+ * pinned file.
+ */
+ else if (!IS_ALIGNED(attr->ia_size,
+ F2FS_BLK_TO_BYTES(CAP_BLKS_PER_SEC(sbi))))
+ return -EINVAL;
+ }
}
if (is_quota_modification(idmap, inode, attr)) {
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index ffaa7ba76a1b..d04633f872ef 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -31,9 +31,9 @@ static unsigned int count_bits(const unsigned long *addr,
static int gc_thread_func(void *data)
{
struct f2fs_sb_info *sbi = data;
- struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
- wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head;
- wait_queue_head_t *fggc_wq = &sbi->gc_thread->fggc_wq;
+ struct f2fs_gc_kthread *gc_th = &sbi->gc_thread;
+ wait_queue_head_t *wq = &sbi->gc_thread.gc_wait_queue_head;
+ wait_queue_head_t *fggc_wq = &sbi->gc_thread.fggc_wq;
unsigned int wait_ms;
struct f2fs_gc_control gc_control = {
.victim_segno = NULL_SEGNO,
@@ -193,13 +193,9 @@ next:
int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
{
- struct f2fs_gc_kthread *gc_th;
+ struct f2fs_gc_kthread *gc_th = &sbi->gc_thread;
dev_t dev = sbi->sb->s_bdev->bd_dev;
- gc_th = f2fs_kmalloc(sbi, sizeof(struct f2fs_gc_kthread), GFP_KERNEL);
- if (!gc_th)
- return -ENOMEM;
-
gc_th->urgent_sleep_time = DEF_GC_THREAD_URGENT_SLEEP_TIME;
gc_th->valid_thresh_ratio = DEF_GC_THREAD_VALID_THRESH_RATIO;
gc_th->boost_gc_multiple = BOOST_GC_MULTIPLE;
@@ -221,16 +217,14 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
gc_th->gc_wake = false;
- sbi->gc_thread = gc_th;
- init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head);
- init_waitqueue_head(&sbi->gc_thread->fggc_wq);
- sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
+ init_waitqueue_head(&gc_th->gc_wait_queue_head);
+ init_waitqueue_head(&gc_th->fggc_wq);
+ gc_th->f2fs_gc_task = kthread_run(gc_thread_func, sbi,
"f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev));
if (IS_ERR(gc_th->f2fs_gc_task)) {
int err = PTR_ERR(gc_th->f2fs_gc_task);
- kfree(gc_th);
- sbi->gc_thread = NULL;
+ gc_th->f2fs_gc_task = NULL;
return err;
}
@@ -241,14 +235,14 @@ int f2fs_start_gc_thread(struct f2fs_sb_info *sbi)
void f2fs_stop_gc_thread(struct f2fs_sb_info *sbi)
{
- struct f2fs_gc_kthread *gc_th = sbi->gc_thread;
+ struct f2fs_gc_kthread *gc_th = &sbi->gc_thread;
- if (!gc_th)
+ if (!gc_th->f2fs_gc_task)
return;
+
kthread_stop(gc_th->f2fs_gc_task);
+ gc_th->f2fs_gc_task = NULL;
wake_up_all(&gc_th->fggc_wq);
- kfree(gc_th);
- sbi->gc_thread = NULL;
}
static int select_gc_type(struct f2fs_sb_info *sbi, int gc_type)
@@ -796,7 +790,7 @@ int f2fs_get_victim(struct f2fs_sb_info *sbi, unsigned int *result,
if (one_time) {
p.one_time_gc = one_time;
if (has_enough_free_secs(sbi, 0, NR_PERSISTENT_LOG))
- valid_thresh_ratio = sbi->gc_thread->valid_thresh_ratio;
+ valid_thresh_ratio = sbi->gc_thread.valid_thresh_ratio;
}
retry:
@@ -1807,9 +1801,9 @@ static int do_garbage_collect(struct f2fs_sb_info *sbi,
if (f2fs_sb_has_blkzoned(sbi) &&
!has_enough_free_blocks(sbi,
- sbi->gc_thread->boost_zoned_gc_percent))
+ sbi->gc_thread.boost_zoned_gc_percent))
window_granularity *=
- sbi->gc_thread->boost_gc_multiple;
+ sbi->gc_thread.boost_gc_multiple;
end_segno = start_segno + window_granularity;
}
diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h
index 6c4d4567571e..b015742fb455 100644
--- a/fs/f2fs/gc.h
+++ b/fs/f2fs/gc.h
@@ -45,32 +45,7 @@
#define NR_GC_CHECKPOINT_SECS (3) /* data/node/dentry sections */
-struct f2fs_gc_kthread {
- struct task_struct *f2fs_gc_task;
- wait_queue_head_t gc_wait_queue_head;
-
- /* for gc sleep time */
- unsigned int urgent_sleep_time;
- unsigned int min_sleep_time;
- unsigned int max_sleep_time;
- unsigned int no_gc_sleep_time;
-
- /* for changing gc mode */
- bool gc_wake;
-
- /* for GC_MERGE mount option */
- wait_queue_head_t fggc_wq; /*
- * caller of f2fs_balance_fs()
- * will wait on this wait queue.
- */
- /* for gc control for zoned devices */
- unsigned int no_zoned_gc_percent;
- unsigned int boost_zoned_gc_percent;
- unsigned int valid_thresh_ratio;
- unsigned int boost_gc_multiple;
- unsigned int boost_gc_greedy;
-};
struct gc_inode_list {
struct list_head ilist;
@@ -197,6 +172,6 @@ static inline bool need_to_boost_gc(struct f2fs_sb_info *sbi)
{
if (f2fs_sb_has_blkzoned(sbi))
return !has_enough_free_blocks(sbi,
- sbi->gc_thread->boost_zoned_gc_percent);
+ sbi->gc_thread.boost_zoned_gc_percent);
return has_enough_invalid_blocks(sbi);
}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 642668a1847c..ac322d63e3f9 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -452,15 +452,14 @@ void f2fs_balance_fs(struct f2fs_sb_info *sbi, bool need)
f2fs_submit_merged_write(sbi, DATA);
f2fs_submit_all_merged_ipu_writes(sbi);
- if (test_opt(sbi, GC_MERGE) && sbi->gc_thread &&
- sbi->gc_thread->f2fs_gc_task) {
+ if (test_opt(sbi, GC_MERGE) && sbi->gc_thread.f2fs_gc_task) {
DEFINE_WAIT(wait);
- prepare_to_wait(&sbi->gc_thread->fggc_wq, &wait,
+ prepare_to_wait(&sbi->gc_thread.fggc_wq, &wait,
TASK_UNINTERRUPTIBLE);
- wake_up(&sbi->gc_thread->gc_wait_queue_head);
+ wake_up(&sbi->gc_thread.gc_wait_queue_head);
io_schedule();
- finish_wait(&sbi->gc_thread->fggc_wq, &wait);
+ finish_wait(&sbi->gc_thread.fggc_wq, &wait);
} else {
struct f2fs_gc_control gc_control = {
.victim_segno = NULL_SEGNO,
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index bda2205d608b..769d16d54997 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2943,11 +2943,11 @@ static int __f2fs_remount(struct fs_context *fc, struct super_block *sb)
if ((flags & SB_RDONLY) ||
(F2FS_OPTION(sbi).bggc_mode == BGGC_MODE_OFF &&
!test_opt(sbi, GC_MERGE))) {
- if (sbi->gc_thread) {
+ if (sbi->gc_thread.f2fs_gc_task) {
f2fs_stop_gc_thread(sbi);
need_restart_gc = true;
}
- } else if (!sbi->gc_thread) {
+ } else if (!sbi->gc_thread.f2fs_gc_task) {
err = f2fs_start_gc_thread(sbi);
if (err)
goto restore_opts;
@@ -3168,7 +3168,7 @@ static ssize_t f2fs_quota_read(struct super_block *sb, int type, char *data,
repeat:
folio = mapping_read_folio_gfp(mapping, off >> PAGE_SHIFT,
- GFP_NOFS);
+ GFP_KERNEL);
if (IS_ERR(folio)) {
if (PTR_ERR(folio) == -ENOMEM) {
memalloc_retry_wait(GFP_NOFS);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 665687244c93..be92c05a5420 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -75,7 +75,7 @@ static ssize_t f2fs_sbi_show(struct f2fs_attr *a,
static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
{
if (struct_type == GC_THREAD)
- return (unsigned char *)sbi->gc_thread;
+ return (unsigned char *)&sbi->gc_thread;
else if (struct_type == SM_INFO)
return (unsigned char *)SM_I(sbi);
else if (struct_type == DCC_INFO)
@@ -664,20 +664,20 @@ out:
sbi->gc_mode = GC_NORMAL;
} else if (t == 1) {
sbi->gc_mode = GC_URGENT_HIGH;
- if (sbi->gc_thread) {
- sbi->gc_thread->gc_wake = true;
+ if (sbi->gc_thread.f2fs_gc_task) {
+ sbi->gc_thread.gc_wake = true;
wake_up_interruptible_all(
- &sbi->gc_thread->gc_wait_queue_head);
+ &sbi->gc_thread.gc_wait_queue_head);
wake_up_discard_thread(sbi, true);
}
} else if (t == 2) {
sbi->gc_mode = GC_URGENT_LOW;
} else if (t == 3) {
sbi->gc_mode = GC_URGENT_MID;
- if (sbi->gc_thread) {
- sbi->gc_thread->gc_wake = true;
+ if (sbi->gc_thread.f2fs_gc_task) {
+ sbi->gc_thread.gc_wake = true;
wake_up_interruptible_all(
- &sbi->gc_thread->gc_wait_queue_head);
+ &sbi->gc_thread.gc_wait_queue_head);
}
} else {
return -EINVAL;
@@ -934,14 +934,14 @@ out:
if (!strcmp(a->attr.name, "gc_boost_gc_multiple")) {
if (t < 1 || t > SEGS_PER_SEC(sbi))
return -EINVAL;
- sbi->gc_thread->boost_gc_multiple = (unsigned int)t;
+ sbi->gc_thread.boost_gc_multiple = (unsigned int)t;
return count;
}
if (!strcmp(a->attr.name, "gc_boost_gc_greedy")) {
if (t > GC_GREEDY)
return -EINVAL;
- sbi->gc_thread->boost_gc_greedy = (unsigned int)t;
+ sbi->gc_thread.boost_gc_greedy = (unsigned int)t;
return count;
}
@@ -989,8 +989,8 @@ out:
if (sbi->cprc_info.f2fs_issue_ckpt)
set_user_nice(sbi->cprc_info.f2fs_issue_ckpt,
PRIO_TO_NICE(sbi->critical_task_priority));
- if (sbi->gc_thread && sbi->gc_thread->f2fs_gc_task)
- set_user_nice(sbi->gc_thread->f2fs_gc_task,
+ if (sbi->gc_thread.f2fs_gc_task)
+ set_user_nice(sbi->gc_thread.f2fs_gc_task,
PRIO_TO_NICE(sbi->critical_task_priority));
return count;
}