From: Nanzhe <[email protected]> Large folio write paths need to submit I/O for a range inside a folio instead of always submitting the whole folio from offset zero. Add idx and cnt to f2fs_io_info to describe the block offset inside the folio and the number of contiguous blocks covered by the I/O.
Apply the new fields to the bio submit paths that need the subpage offset or contiguous block count. Signed-off-by: Nanzhe <[email protected]> --- fs/f2fs/data.c | 58 ++++++++++++++++++++++++++++++++--------------- fs/f2fs/f2fs.h | 2 ++ fs/f2fs/segment.c | 4 ++-- 3 files changed, 44 insertions(+), 20 deletions(-) diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 9daded9fd16a..904cfaee139e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -752,6 +752,8 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) struct folio *fio_folio = fio->folio; struct folio *data_folio = fio->encrypted_page ? page_folio(fio->encrypted_page) : fio_folio; + pgoff_t fio_lblk = fio_folio->index + fio->idx; + unsigned int fio_cnt = fio->cnt ? fio->cnt : 1; if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, fio->is_por ? META_POR : (__is_meta_io(fio) ? @@ -764,11 +766,13 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) bio = __bio_alloc(fio, 1); f2fs_set_bio_crypt_ctx(bio, fio_folio->mapping->host, - fio_folio->index, fio, GFP_NOIO); - bio_add_folio_nofail(bio, data_folio, folio_size(data_folio), 0); + fio_lblk, fio, GFP_NOIO); + bio_add_folio_nofail(bio, data_folio, + F2FS_BLK_TO_BYTES(fio_cnt), fio->idx << PAGE_SHIFT); if (fio->io_wbc && !is_read_io(fio->op)) - wbc_account_cgroup_owner(fio->io_wbc, fio_folio, PAGE_SIZE); + wbc_account_cgroup_owner(fio->io_wbc, fio_folio, + F2FS_BLK_TO_BYTES(fio_cnt)); inc_page_count(fio->sbi, is_read_io(fio->op) ? __read_io_type(data_folio) : WB_DATA_TYPE(fio->folio, false)); @@ -813,7 +817,8 @@ static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, } static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, - struct folio *folio, enum temp_type temp) + struct folio *folio, size_t len, size_t offset, + enum temp_type temp) { struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; struct bio_entry *be; @@ -822,7 +827,7 @@ static void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, be->bio = bio; bio_get(bio); - bio_add_folio_nofail(bio, folio, folio_size(folio), 0); + bio_add_folio_nofail(bio, folio, len, offset); f2fs_down_write(&io->bio_list_lock); list_add_tail(&be->list, &io->bio_list); @@ -839,6 +844,8 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, struct folio *folio) { struct folio *fio_folio = fio->folio; + pgoff_t fio_lblk = fio_folio->index + fio->idx; + unsigned int fio_cnt = fio->cnt ? fio->cnt : 1; struct f2fs_sb_info *sbi = fio->sbi; enum temp_type temp; bool found = false; @@ -861,8 +868,10 @@ static int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, fio->new_blkaddr)); if (f2fs_crypt_mergeable_bio(*bio, fio_folio->mapping->host, - fio_folio->index, fio) && - bio_add_folio(*bio, folio, folio_size(folio), 0)) { + fio_lblk, fio) && + bio_add_folio(*bio, folio, + F2FS_BLK_TO_BYTES(fio_cnt), + fio->idx << PAGE_SHIFT)) { ret = 0; break; } @@ -976,6 +985,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) struct folio *data_folio = fio->encrypted_page ? page_folio(fio->encrypted_page) : fio->folio; struct folio *folio = fio->folio; + pgoff_t fio_lblk = folio->index + fio->idx; if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) @@ -990,9 +1000,11 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) if (!bio) { bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(bio, folio->mapping->host, - folio->index, fio, GFP_NOIO); + fio_lblk, fio, GFP_NOIO); - add_bio_entry(fio->sbi, bio, data_folio, fio->temp); + add_bio_entry(fio->sbi, bio, data_folio, + F2FS_BLK_TO_BYTES(fio->cnt ? fio->cnt : 1), + fio->idx << PAGE_SHIFT, fio->temp); } else { if (add_ipu_page(fio, &bio, data_folio)) goto alloc_new; @@ -1003,7 +1015,7 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio) inc_page_count(fio->sbi, WB_DATA_TYPE(folio, false)); - *fio->last_block = fio->new_blkaddr; + *fio->last_block = fio->new_blkaddr + (fio->cnt ? fio->cnt - 1 : 0); *fio->bio = bio; return 0; @@ -1039,6 +1051,10 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) struct folio *bio_folio; struct f2fs_lock_context lc; enum count_type type; + pgoff_t fio_lblk; + unsigned int fio_cnt; + size_t bio_offset; + size_t bio_len; f2fs_bug_on(sbi, is_read_io(fio->op)); @@ -1077,6 +1093,9 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) /* set submitted = true as a return value */ fio->submitted = 1; + fio_lblk = fio->folio->index + fio->idx; + fio_cnt = fio->cnt ? fio->cnt : 1; + type = WB_DATA_TYPE(bio_folio, fio->compressed_page); inc_page_count(sbi, type); @@ -1084,26 +1103,29 @@ void f2fs_submit_page_write(struct f2fs_io_info *fio) (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, fio->new_blkaddr) || !f2fs_crypt_mergeable_bio(io->bio, fio_inode(fio), - bio_folio->index, fio))) + fio_lblk, fio))) __submit_merged_bio(io); alloc_new: if (io->bio == NULL) { io->bio = __bio_alloc(fio, BIO_MAX_VECS); f2fs_set_bio_crypt_ctx(io->bio, fio_inode(fio), - bio_folio->index, fio, GFP_NOIO); + fio_lblk, fio, GFP_NOIO); io->fio = *fio; } - if (!bio_add_folio(io->bio, bio_folio, folio_size(bio_folio), 0)) { + bio_offset = fio->idx << PAGE_SHIFT; + bio_len = F2FS_BLK_TO_BYTES(fio_cnt); + + if (!bio_add_folio(io->bio, bio_folio, bio_len, bio_offset)) { __submit_merged_bio(io); goto alloc_new; } if (fio->io_wbc) wbc_account_cgroup_owner(fio->io_wbc, fio->folio, - folio_size(fio->folio)); + F2FS_BLK_TO_BYTES(fio_cnt)); - io->last_block_in_bio = fio->new_blkaddr; + io->last_block_in_bio = fio->new_blkaddr + fio_cnt - 1; trace_f2fs_submit_folio_write(fio->folio, fio); #ifdef CONFIG_BLK_DEV_ZONED @@ -2965,7 +2987,7 @@ bool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) return true; if (fio) { - if (page_private_gcing(fio->page)) + if (folio_test_f2fs_gcing(fio->folio)) return true; if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) @@ -3004,7 +3026,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) set_new_dnode(&dn, inode, NULL, NULL, 0); if (need_inplace_update(fio) && - f2fs_lookup_read_extent_cache_block(inode, folio->index, + f2fs_lookup_read_extent_cache_block(inode, folio->index + fio->idx, &fio->old_blkaddr)) { if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, DATA_GENERIC_ENHANCE)) @@ -3023,7 +3045,7 @@ int f2fs_do_write_data_page(struct f2fs_io_info *fio) if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi, &lc)) return -EAGAIN; - err = f2fs_get_dnode_of_data(&dn, folio->index, LOOKUP_NODE); + err = f2fs_get_dnode_of_data(&dn, folio->index + fio->idx, LOOKUP_NODE); if (err) goto out; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index feedba139f4d..dd262eb41777 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -1352,6 +1352,8 @@ struct f2fs_io_info { blk_opf_t op_flags; /* req_flag_bits */ block_t new_blkaddr; /* new block address to be written */ block_t old_blkaddr; /* old block address before Cow */ + pgoff_t idx; /* start block offset in the folio */ + unsigned int cnt; /* block count in the folio */ union { struct page *page; /* page to be written */ struct folio *folio; diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 1ef4edb77078..0c24557f20cd 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -3710,7 +3710,7 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) return CURSEG_COLD_DATA_PINNED; - if (page_private_gcing(fio->page)) { + if (folio_test_f2fs_gcing(fio->folio)) { if (fio->sbi->am.atgc_enabled && (fio->io_type == FS_DATA_IO) && (fio->sbi->gc_mode != GC_URGENT_HIGH) && @@ -3723,7 +3723,7 @@ static int __get_segment_type_6(struct f2fs_io_info *fio) if (file_is_cold(inode) || f2fs_need_compress_data(inode)) return CURSEG_COLD_DATA; - type = __get_age_segment_type(inode, fio->folio->index); + type = __get_age_segment_type(inode, fio->folio->index + fio->idx); if (type != NO_CHECK_TYPE) return type; -- 2.34.1 _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel
