On 5/29/26 05:20, Bart Van Assche wrote:
> 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 <[email protected]>
> ---
>  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;

Actually, I don't see this problem before, can we disable this by default, and
only enable for your case via sysfs?

>  
>       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),

We need to update Documentation/ABI/testing/sysfs-fs-f2fs as well.

Thanks,

>       ATTR_LIST(max_fragment_chunk),
>       ATTR_LIST(max_fragment_hole),
>       ATTR_LIST(current_atomic_write),



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to