Previously, the GC (Garbage Collection) logic for performing I/O and marking folios dirty only supported order-0 folios and lacked awareness of higher-order folios. To enable GC to correctly handle higher-order folios, we made two changes:
- In `move_data_page`, we now use `f2fs_iomap_set_range_dirty` to mark only the sub-part of the folio corresponding to `bidx` as dirty, instead of the entire folio. - The `f2fs_submit_page_read` function has been augmented with an `index` parameter, allowing it to precisely identify which sub-page of the current folio is being submitted. Signed-off-by: Nanzhe Zhao <nzz...@126.com> --- fs/f2fs/data.c | 13 +++++++------ fs/f2fs/gc.c | 37 +++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b7bef2a28c8e..5ecd08a3dd0b 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1096,7 +1096,7 @@ static struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, /* This can handle encryption stuffs */ static int f2fs_submit_page_read(struct inode *inode, struct folio *folio, block_t blkaddr, blk_opf_t op_flags, - bool for_write) + pgoff_t index, bool for_write) { struct f2fs_sb_info *sbi = F2FS_I_SB(inode); struct bio *bio; @@ -1109,7 +1109,8 @@ static int f2fs_submit_page_read(struct inode *inode, struct folio *folio, /* wait for GCed page writeback via META_MAPPING */ f2fs_wait_on_block_writeback(inode, blkaddr); - if (!bio_add_folio(bio, folio, PAGE_SIZE, 0)) { + if (!bio_add_folio(bio, folio, PAGE_SIZE, + (index - folio->index) << PAGE_SHIFT)) { iostat_update_and_unbind_ctx(bio); if (bio->bi_private) mempool_free(bio->bi_private, bio_post_read_ctx_pool); @@ -1276,8 +1277,8 @@ struct folio *f2fs_get_read_data_folio(struct inode *inode, pgoff_t index, return folio; } - err = f2fs_submit_page_read(inode, folio, dn.data_blkaddr, - op_flags, for_write); + err = f2fs_submit_page_read(inode, folio, dn.data_blkaddr, op_flags, + index, for_write); if (err) goto put_err; return folio; @@ -3651,8 +3652,8 @@ static int f2fs_write_begin(const struct kiocb *iocb, goto put_folio; } err = f2fs_submit_page_read(use_cow ? - F2FS_I(inode)->cow_inode : inode, - folio, blkaddr, 0, true); + F2FS_I(inode)->cow_inode : inode, folio, + blkaddr, 0, folio->index, true); if (err) goto put_folio; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 098e9f71421e..6d28f01bec42 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1475,22 +1475,31 @@ static int move_data_page(struct inode *inode, block_t bidx, int gc_type, err = -EAGAIN; goto out; } - folio_mark_dirty(folio); folio_set_f2fs_gcing(folio); +#ifdef CONFIG_F2FS_IOMAP_FOLIO_STATE + if (!folio_test_large(folio)) { + folio_mark_dirty(folio); + } else { + f2fs_iomap_set_range_dirty(folio, (bidx - folio->index) << PAGE_SHIFT, + PAGE_SIZE); + } +#else + folio_mark_dirty(folio); +#endif } else { - struct f2fs_io_info fio = { - .sbi = F2FS_I_SB(inode), - .ino = inode->i_ino, - .type = DATA, - .temp = COLD, - .op = REQ_OP_WRITE, - .op_flags = REQ_SYNC, - .old_blkaddr = NULL_ADDR, - .folio = folio, - .encrypted_page = NULL, - .need_lock = LOCK_REQ, - .io_type = FS_GC_DATA_IO, - }; + struct f2fs_io_info fio = { .sbi = F2FS_I_SB(inode), + .ino = inode->i_ino, + .type = DATA, + .temp = COLD, + .op = REQ_OP_WRITE, + .op_flags = REQ_SYNC, + .old_blkaddr = NULL_ADDR, + .folio = folio, + .encrypted_page = NULL, + .need_lock = LOCK_REQ, + .io_type = FS_GC_DATA_IO, + .idx = bidx - folio->index, + .cnt = 1 }; bool is_dirty = folio_test_dirty(folio); retry: -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel