* [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context
@ 2026-05-28 21:20 Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 1/4] f2fs: Prepare for supporting delayed bio completion Bart Van Assche via Linux-f2fs-devel
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Bart Van Assche via Linux-f2fs-devel @ 2026-05-28 21:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: Bart Van Assche, linux-f2fs-devel
Hi Jaegeuk,
This patch series reduces the amount of time spent in interrupt context for
completing write bios. Please consider this patch series for the next merge
window.
Thanks,
Bart.
Bart Van Assche (4):
f2fs: Prepare for supporting delayed bio completion
f2fs: Rename f2fs_post_read_wq into f2fs_wq
f2fs: Split f2fs_write_end_io()
f2fs: Run f2fs_write_end_io() asynchronously
fs/f2fs/compress.c | 2 +-
fs/f2fs/data.c | 62 +++++++++++++++++++++++++++++++---------------
fs/f2fs/f2fs.h | 8 +++---
fs/f2fs/super.c | 13 +++++++---
fs/f2fs/sysfs.c | 2 ++
5 files changed, 59 insertions(+), 28 deletions(-)
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply [flat|nested] 5+ messages in thread
* [f2fs-dev] [PATCH 1/4] f2fs: Prepare for supporting delayed bio completion
2026-05-28 21:20 [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context Bart Van Assche via Linux-f2fs-devel
@ 2026-05-28 21:20 ` Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 2/4] f2fs: Rename f2fs_post_read_wq into f2fs_wq Bart Van Assche via Linux-f2fs-devel
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche via Linux-f2fs-devel @ 2026-05-28 21:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: Bart Van Assche, linux-f2fs-devel
Use bio frontpadding to allocate memory for a work_struct when
allocating a bio.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
fs/f2fs/data.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 8d4f1e75dee3..1659a57a6d5b 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -40,12 +40,17 @@ struct f2fs_folio_state {
unsigned int read_pages_pending;
};
+struct f2fs_bio {
+ struct work_struct work;
+ struct bio bio;
+};
+
#define F2FS_BIO_POOL_SIZE NR_CURSEG_TYPE
int __init f2fs_init_bioset(void)
{
return bioset_init(&f2fs_bioset, F2FS_BIO_POOL_SIZE,
- 0, BIOSET_NEED_BVECS);
+ offsetof(struct f2fs_bio, bio), BIOSET_NEED_BVECS);
}
void f2fs_destroy_bioset(void)
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [f2fs-dev] [PATCH 2/4] f2fs: Rename f2fs_post_read_wq into f2fs_wq
2026-05-28 21:20 [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 1/4] f2fs: Prepare for supporting delayed bio completion Bart Van Assche via Linux-f2fs-devel
@ 2026-05-28 21:20 ` Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 3/4] f2fs: Split f2fs_write_end_io() Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 4/4] f2fs: Run f2fs_write_end_io() asynchronously Bart Van Assche via Linux-f2fs-devel
3 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche via Linux-f2fs-devel @ 2026-05-28 21:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: Bart Van Assche, linux-f2fs-devel
Rename f2fs_post_read_wq into f2fs_wq. Create it unconditionally.
Prepare for using this workqueue for completing write bios.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
fs/f2fs/compress.c | 2 +-
fs/f2fs/data.c | 22 ++++++++--------------
fs/f2fs/f2fs.h | 6 +++---
fs/f2fs/super.c | 8 ++++----
4 files changed, 16 insertions(+), 22 deletions(-)
diff --git a/fs/f2fs/compress.c b/fs/f2fs/compress.c
index 881e76158b96..b3c016c4094b 100644
--- a/fs/f2fs/compress.c
+++ b/fs/f2fs/compress.c
@@ -1807,7 +1807,7 @@ static void f2fs_put_dic(struct decompress_io_ctx *dic, bool in_task)
f2fs_free_dic(dic, false);
} else {
INIT_WORK(&dic->free_work, f2fs_late_free_dic);
- queue_work(dic->sbi->post_read_wq, &dic->free_work);
+ queue_work(dic->sbi->wq, &dic->free_work);
}
}
}
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 1659a57a6d5b..080d69fa8cd1 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -341,7 +341,7 @@ static void f2fs_read_end_io(struct bio *bio)
f2fs_handle_step_decompress(ctx, intask);
} else if (enabled_steps) {
INIT_WORK(&ctx->work, f2fs_post_read_work);
- queue_work(ctx->sbi->post_read_wq, &ctx->work);
+ queue_work(ctx->sbi->wq, &ctx->work);
return;
}
}
@@ -4477,23 +4477,17 @@ void f2fs_destroy_post_read_processing(void)
kmem_cache_destroy(bio_post_read_ctx_cache);
}
-int f2fs_init_post_read_wq(struct f2fs_sb_info *sbi)
+int f2fs_init_wq(struct f2fs_sb_info *sbi)
{
- if (!f2fs_sb_has_encrypt(sbi) &&
- !f2fs_sb_has_verity(sbi) &&
- !f2fs_sb_has_compression(sbi))
- return 0;
-
- sbi->post_read_wq = alloc_workqueue("f2fs_post_read_wq",
- WQ_UNBOUND | WQ_HIGHPRI,
- num_online_cpus());
- return sbi->post_read_wq ? 0 : -ENOMEM;
+ sbi->wq = alloc_workqueue("f2fs_wq", WQ_UNBOUND | WQ_HIGHPRI,
+ num_online_cpus());
+ return sbi->wq ? 0 : -ENOMEM;
}
-void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi)
+void f2fs_destroy_wq(struct f2fs_sb_info *sbi)
{
- if (sbi->post_read_wq)
- destroy_workqueue(sbi->post_read_wq);
+ if (sbi->wq)
+ destroy_workqueue(sbi->wq);
}
int __init f2fs_init_bio_entry_cache(void)
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 91f506e7c9cf..30353c439d3c 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1969,7 +1969,7 @@ struct f2fs_sb_info {
/* Precomputed FS UUID checksum for seeding other checksums */
__u32 s_chksum_seed;
- struct workqueue_struct *post_read_wq; /* post read workqueue */
+ struct workqueue_struct *wq; /* bio completion workqueue */
/*
* If we are in irq context, let's update error information into
@@ -4193,8 +4193,8 @@ bool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len);
void f2fs_clear_page_cache_dirty_tag(struct folio *folio);
int f2fs_init_post_read_processing(void);
void f2fs_destroy_post_read_processing(void);
-int f2fs_init_post_read_wq(struct f2fs_sb_info *sbi);
-void f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi);
+int f2fs_init_wq(struct f2fs_sb_info *sbi);
+void f2fs_destroy_wq(struct f2fs_sb_info *sbi);
extern const struct iomap_ops f2fs_iomap_ops;
/*
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index ccf806b676f5..5a100f740b3f 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -2074,7 +2074,7 @@ static void f2fs_put_super(struct super_block *sb)
/* flush s_error_work before sbi destroy */
flush_work(&sbi->s_error_work);
- f2fs_destroy_post_read_wq(sbi);
+ f2fs_destroy_wq(sbi);
kvfree(sbi->ckpt);
@@ -5130,9 +5130,9 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
goto free_devices;
}
- err = f2fs_init_post_read_wq(sbi);
+ err = f2fs_init_wq(sbi);
if (err) {
- f2fs_err(sbi, "Failed to initialize post read workqueue");
+ f2fs_err(sbi, "Failed to create workqueue");
goto free_devices;
}
@@ -5419,7 +5419,7 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
f2fs_stop_ckpt_thread(sbi);
/* flush s_error_work before sbi destroy */
flush_work(&sbi->s_error_work);
- f2fs_destroy_post_read_wq(sbi);
+ f2fs_destroy_wq(sbi);
free_devices:
destroy_device_list(sbi);
kvfree(sbi->ckpt);
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [f2fs-dev] [PATCH 3/4] f2fs: Split f2fs_write_end_io()
2026-05-28 21:20 [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 1/4] f2fs: Prepare for supporting delayed bio completion Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 2/4] f2fs: Rename f2fs_post_read_wq into f2fs_wq Bart Van Assche via Linux-f2fs-devel
@ 2026-05-28 21:20 ` Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 4/4] f2fs: Run f2fs_write_end_io() asynchronously Bart Van Assche via Linux-f2fs-devel
3 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche via Linux-f2fs-devel @ 2026-05-28 21:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: Bart Van Assche, linux-f2fs-devel
Prepare for running most of the write completion work asynchronously.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
fs/f2fs/data.c | 14 +++++++++-----
1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 080d69fa8cd1..48c004976c4e 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -349,14 +349,11 @@ static void f2fs_read_end_io(struct bio *bio)
f2fs_verify_and_finish_bio(bio, intask);
}
-static void f2fs_write_end_io(struct bio *bio)
+static void f2fs_write_end_bio(struct bio *bio)
{
- struct f2fs_sb_info *sbi;
+ struct f2fs_sb_info *sbi = bio->bi_private;
struct folio_iter fi;
- iostat_update_and_unbind_ctx(bio);
- sbi = bio->bi_private;
-
if (time_to_inject(sbi, FAULT_WRITE_IO))
bio->bi_status = BLK_STS_IOERR;
@@ -412,6 +409,13 @@ static void f2fs_write_end_io(struct bio *bio)
bio_put(bio);
}
+static void f2fs_write_end_io(struct bio *bio)
+{
+ iostat_update_and_unbind_ctx(bio);
+
+ f2fs_write_end_bio(bio);
+}
+
#ifdef CONFIG_BLK_DEV_ZONED
static void f2fs_zone_write_end_io(struct bio *bio)
{
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [f2fs-dev] [PATCH 4/4] f2fs: Run f2fs_write_end_io() asynchronously
2026-05-28 21:20 [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context Bart Van Assche via Linux-f2fs-devel
` (2 preceding siblings ...)
2026-05-28 21:20 ` [f2fs-dev] [PATCH 3/4] f2fs: Split f2fs_write_end_io() Bart Van Assche via Linux-f2fs-devel
@ 2026-05-28 21:20 ` Bart Van Assche via Linux-f2fs-devel
3 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche via Linux-f2fs-devel @ 2026-05-28 21:20 UTC (permalink / raw)
To: Jaegeuk Kim; +Cc: Bart Van Assche, linux-f2fs-devel
The bio_for_each_segment_all() loop can take more than 10 ms for a large
bio on an ARM little core. This is too much for interrupt context. Hence
perform the write bio completion work asynchronously if a bio is large and
if f2fs_write_end_io() is called from atomic context. This patch reduces
the time spent in f2fs_write_end_io() from about 10 ms to about 150
microseconds on an Arm Cortex-A520 core.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
---
fs/f2fs/data.c | 21 ++++++++++++++++++++-
fs/f2fs/f2fs.h | 2 ++
fs/f2fs/super.c | 5 +++++
fs/f2fs/sysfs.c | 2 ++
4 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 48c004976c4e..6e169490c4cf 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -409,11 +409,30 @@ static void f2fs_write_end_bio(struct bio *bio)
bio_put(bio);
}
+static void f2fs_write_end_io_work(struct work_struct *work)
+{
+ struct bio *bio = &container_of(work, struct f2fs_bio, work)->bio;
+
+ f2fs_write_end_bio(bio);
+}
+
static void f2fs_write_end_io(struct bio *bio)
{
+ struct f2fs_sb_info *sbi;
+
iostat_update_and_unbind_ctx(bio);
- f2fs_write_end_bio(bio);
+ sbi = bio->bi_private;
+
+ if (in_atomic() && bio->bi_iter.bi_size > sbi->max_atc_write_bio_size) {
+ struct work_struct *w;
+
+ w = &container_of(bio, struct f2fs_bio, bio)->work;
+ INIT_WORK(w, f2fs_write_end_io_work);
+ queue_work(sbi->wq, w);
+ } else {
+ f2fs_write_end_bio(bio);
+ }
}
#ifdef CONFIG_BLK_DEV_ZONED
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 30353c439d3c..a6a3e01122e1 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -1763,6 +1763,8 @@ struct f2fs_sb_info {
struct f2fs_sm_info *sm_info; /* segment manager */
/* for bio operations */
+ /* Largest write bio size completed in atomic context (atc). */
+ u32 max_atc_write_bio_size;
struct f2fs_bio_info *write_io[NR_PAGE_TYPE]; /* for write bios */
/* keep migration IO order for LFS mode */
struct f2fs_rwsem io_order_lock;
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 5a100f740b3f..1e822380edb3 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -5007,6 +5007,11 @@ static int f2fs_fill_super(struct super_block *sb, struct fs_context *fc)
sb->s_fs_info = sbi;
sbi->raw_super = raw_super;
+ /*
+ * SZ_16K restricts the time spent on completing writes to about 150
+ * microseconds on an Arm Cortex-A520 core.
+ */
+ sbi->max_atc_write_bio_size = SZ_16K;
INIT_WORK(&sbi->s_error_work, f2fs_record_error_work);
memcpy(sbi->errors, raw_super->s_errors, MAX_F2FS_ERRORS);
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 352e96ad5c3a..70b2e9be8f8b 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1266,6 +1266,7 @@ F2FS_SBI_RW_ATTR(gc_idle_interval, interval_time[GC_TIME]);
F2FS_SBI_RW_ATTR(umount_discard_timeout, interval_time[UMOUNT_DISCARD_TIMEOUT]);
F2FS_SBI_RW_ATTR(gc_pin_file_thresh, gc_pin_file_threshold);
F2FS_SBI_RW_ATTR(gc_reclaimed_segments, gc_reclaimed_segs);
+F2FS_SBI_RW_ATTR(max_atc_write_bio_size, max_atc_write_bio_size);
F2FS_SBI_GENERAL_RW_ATTR(max_victim_search);
F2FS_SBI_GENERAL_RW_ATTR(migration_granularity);
F2FS_SBI_GENERAL_RW_ATTR(migration_window_granularity);
@@ -1508,6 +1509,7 @@ static struct attribute *f2fs_attrs[] = {
ATTR_LIST(seq_file_ra_mul),
ATTR_LIST(gc_segment_mode),
ATTR_LIST(gc_reclaimed_segments),
+ ATTR_LIST(max_atc_write_bio_size),
ATTR_LIST(max_fragment_chunk),
ATTR_LIST(max_fragment_hole),
ATTR_LIST(current_atomic_write),
_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-28 21:21 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-28 21:20 [f2fs-dev] [PATCH 0/4] Reduce the time spent in interrupt context Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 1/4] f2fs: Prepare for supporting delayed bio completion Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 2/4] f2fs: Rename f2fs_post_read_wq into f2fs_wq Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 3/4] f2fs: Split f2fs_write_end_io() Bart Van Assche via Linux-f2fs-devel
2026-05-28 21:20 ` [f2fs-dev] [PATCH 4/4] f2fs: Run f2fs_write_end_io() asynchronously Bart Van Assche via Linux-f2fs-devel
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.