162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * fs/f2fs/data.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 662306a36Sopenharmony_ci * http://www.samsung.com/ 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci#include <linux/fs.h> 962306a36Sopenharmony_ci#include <linux/f2fs_fs.h> 1062306a36Sopenharmony_ci#include <linux/buffer_head.h> 1162306a36Sopenharmony_ci#include <linux/sched/mm.h> 1262306a36Sopenharmony_ci#include <linux/mpage.h> 1362306a36Sopenharmony_ci#include <linux/writeback.h> 1462306a36Sopenharmony_ci#include <linux/pagevec.h> 1562306a36Sopenharmony_ci#include <linux/blkdev.h> 1662306a36Sopenharmony_ci#include <linux/bio.h> 1762306a36Sopenharmony_ci#include <linux/blk-crypto.h> 1862306a36Sopenharmony_ci#include <linux/swap.h> 1962306a36Sopenharmony_ci#include <linux/prefetch.h> 2062306a36Sopenharmony_ci#include <linux/uio.h> 2162306a36Sopenharmony_ci#include <linux/sched/signal.h> 2262306a36Sopenharmony_ci#include <linux/fiemap.h> 2362306a36Sopenharmony_ci#include <linux/iomap.h> 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci#include "f2fs.h" 2662306a36Sopenharmony_ci#include "node.h" 2762306a36Sopenharmony_ci#include "segment.h" 2862306a36Sopenharmony_ci#include "iostat.h" 2962306a36Sopenharmony_ci#include <trace/events/f2fs.h> 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define NUM_PREALLOC_POST_READ_CTXS 128 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_cistatic struct kmem_cache *bio_post_read_ctx_cache; 3462306a36Sopenharmony_cistatic struct kmem_cache *bio_entry_slab; 3562306a36Sopenharmony_cistatic mempool_t *bio_post_read_ctx_pool; 3662306a36Sopenharmony_cistatic struct bio_set f2fs_bioset; 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define F2FS_BIO_POOL_SIZE NR_CURSEG_TYPE 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ciint __init f2fs_init_bioset(void) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci return bioset_init(&f2fs_bioset, F2FS_BIO_POOL_SIZE, 4362306a36Sopenharmony_ci 0, BIOSET_NEED_BVECS); 4462306a36Sopenharmony_ci} 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_civoid f2fs_destroy_bioset(void) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci bioset_exit(&f2fs_bioset); 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cibool f2fs_is_cp_guaranteed(struct page *page) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci struct address_space *mapping = page->mapping; 5462306a36Sopenharmony_ci struct inode *inode; 5562306a36Sopenharmony_ci struct f2fs_sb_info *sbi; 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci if (!mapping) 5862306a36Sopenharmony_ci return false; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci inode = mapping->host; 6162306a36Sopenharmony_ci sbi = F2FS_I_SB(inode); 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi) || 6462306a36Sopenharmony_ci inode->i_ino == F2FS_NODE_INO(sbi) || 6562306a36Sopenharmony_ci S_ISDIR(inode->i_mode)) 6662306a36Sopenharmony_ci return true; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci if ((S_ISREG(inode->i_mode) && IS_NOQUOTA(inode)) || 6962306a36Sopenharmony_ci page_private_gcing(page)) 7062306a36Sopenharmony_ci return true; 7162306a36Sopenharmony_ci return false; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic enum count_type __read_io_type(struct page *page) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct address_space *mapping = page_file_mapping(page); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci if (mapping) { 7962306a36Sopenharmony_ci struct inode *inode = mapping->host; 8062306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi)) 8362306a36Sopenharmony_ci return F2FS_RD_META; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci if (inode->i_ino == F2FS_NODE_INO(sbi)) 8662306a36Sopenharmony_ci return F2FS_RD_NODE; 8762306a36Sopenharmony_ci } 8862306a36Sopenharmony_ci return F2FS_RD_DATA; 8962306a36Sopenharmony_ci} 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* postprocessing steps for read bios */ 9262306a36Sopenharmony_cienum bio_post_read_step { 9362306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION 9462306a36Sopenharmony_ci STEP_DECRYPT = BIT(0), 9562306a36Sopenharmony_ci#else 9662306a36Sopenharmony_ci STEP_DECRYPT = 0, /* compile out the decryption-related code */ 9762306a36Sopenharmony_ci#endif 9862306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 9962306a36Sopenharmony_ci STEP_DECOMPRESS = BIT(1), 10062306a36Sopenharmony_ci#else 10162306a36Sopenharmony_ci STEP_DECOMPRESS = 0, /* compile out the decompression-related code */ 10262306a36Sopenharmony_ci#endif 10362306a36Sopenharmony_ci#ifdef CONFIG_FS_VERITY 10462306a36Sopenharmony_ci STEP_VERITY = BIT(2), 10562306a36Sopenharmony_ci#else 10662306a36Sopenharmony_ci STEP_VERITY = 0, /* compile out the verity-related code */ 10762306a36Sopenharmony_ci#endif 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistruct bio_post_read_ctx { 11162306a36Sopenharmony_ci struct bio *bio; 11262306a36Sopenharmony_ci struct f2fs_sb_info *sbi; 11362306a36Sopenharmony_ci struct work_struct work; 11462306a36Sopenharmony_ci unsigned int enabled_steps; 11562306a36Sopenharmony_ci /* 11662306a36Sopenharmony_ci * decompression_attempted keeps track of whether 11762306a36Sopenharmony_ci * f2fs_end_read_compressed_page() has been called on the pages in the 11862306a36Sopenharmony_ci * bio that belong to a compressed cluster yet. 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ci bool decompression_attempted; 12162306a36Sopenharmony_ci block_t fs_blkaddr; 12262306a36Sopenharmony_ci}; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci/* 12562306a36Sopenharmony_ci * Update and unlock a bio's pages, and free the bio. 12662306a36Sopenharmony_ci * 12762306a36Sopenharmony_ci * This marks pages up-to-date only if there was no error in the bio (I/O error, 12862306a36Sopenharmony_ci * decryption error, or verity error), as indicated by bio->bi_status. 12962306a36Sopenharmony_ci * 13062306a36Sopenharmony_ci * "Compressed pages" (pagecache pages backed by a compressed cluster on-disk) 13162306a36Sopenharmony_ci * aren't marked up-to-date here, as decompression is done on a per-compression- 13262306a36Sopenharmony_ci * cluster basis rather than a per-bio basis. Instead, we only must do two 13362306a36Sopenharmony_ci * things for each compressed page here: call f2fs_end_read_compressed_page() 13462306a36Sopenharmony_ci * with failed=true if an error occurred before it would have normally gotten 13562306a36Sopenharmony_ci * called (i.e., I/O error or decryption error, but *not* verity error), and 13662306a36Sopenharmony_ci * release the bio's reference to the decompress_io_ctx of the page's cluster. 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic void f2fs_finish_read_bio(struct bio *bio, bool in_task) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci struct bio_vec *bv; 14162306a36Sopenharmony_ci struct bvec_iter_all iter_all; 14262306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = bio->bi_private; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci bio_for_each_segment_all(bv, bio, iter_all) { 14562306a36Sopenharmony_ci struct page *page = bv->bv_page; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci if (f2fs_is_compressed_page(page)) { 14862306a36Sopenharmony_ci if (ctx && !ctx->decompression_attempted) 14962306a36Sopenharmony_ci f2fs_end_read_compressed_page(page, true, 0, 15062306a36Sopenharmony_ci in_task); 15162306a36Sopenharmony_ci f2fs_put_page_dic(page, in_task); 15262306a36Sopenharmony_ci continue; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci if (bio->bi_status) 15662306a36Sopenharmony_ci ClearPageUptodate(page); 15762306a36Sopenharmony_ci else 15862306a36Sopenharmony_ci SetPageUptodate(page); 15962306a36Sopenharmony_ci dec_page_count(F2FS_P_SB(page), __read_io_type(page)); 16062306a36Sopenharmony_ci unlock_page(page); 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci if (ctx) 16462306a36Sopenharmony_ci mempool_free(ctx, bio_post_read_ctx_pool); 16562306a36Sopenharmony_ci bio_put(bio); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void f2fs_verify_bio(struct work_struct *work) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = 17162306a36Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 17262306a36Sopenharmony_ci struct bio *bio = ctx->bio; 17362306a36Sopenharmony_ci bool may_have_compressed_pages = (ctx->enabled_steps & STEP_DECOMPRESS); 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci /* 17662306a36Sopenharmony_ci * fsverity_verify_bio() may call readahead() again, and while verity 17762306a36Sopenharmony_ci * will be disabled for this, decryption and/or decompression may still 17862306a36Sopenharmony_ci * be needed, resulting in another bio_post_read_ctx being allocated. 17962306a36Sopenharmony_ci * So to prevent deadlocks we need to release the current ctx to the 18062306a36Sopenharmony_ci * mempool first. This assumes that verity is the last post-read step. 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_ci mempool_free(ctx, bio_post_read_ctx_pool); 18362306a36Sopenharmony_ci bio->bi_private = NULL; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* 18662306a36Sopenharmony_ci * Verify the bio's pages with fs-verity. Exclude compressed pages, 18762306a36Sopenharmony_ci * as those were handled separately by f2fs_end_read_compressed_page(). 18862306a36Sopenharmony_ci */ 18962306a36Sopenharmony_ci if (may_have_compressed_pages) { 19062306a36Sopenharmony_ci struct bio_vec *bv; 19162306a36Sopenharmony_ci struct bvec_iter_all iter_all; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci bio_for_each_segment_all(bv, bio, iter_all) { 19462306a36Sopenharmony_ci struct page *page = bv->bv_page; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (!f2fs_is_compressed_page(page) && 19762306a36Sopenharmony_ci !fsverity_verify_page(page)) { 19862306a36Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 19962306a36Sopenharmony_ci break; 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci } else { 20362306a36Sopenharmony_ci fsverity_verify_bio(bio); 20462306a36Sopenharmony_ci } 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci f2fs_finish_read_bio(bio, true); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci/* 21062306a36Sopenharmony_ci * If the bio's data needs to be verified with fs-verity, then enqueue the 21162306a36Sopenharmony_ci * verity work for the bio. Otherwise finish the bio now. 21262306a36Sopenharmony_ci * 21362306a36Sopenharmony_ci * Note that to avoid deadlocks, the verity work can't be done on the 21462306a36Sopenharmony_ci * decryption/decompression workqueue. This is because verifying the data pages 21562306a36Sopenharmony_ci * can involve reading verity metadata pages from the file, and these verity 21662306a36Sopenharmony_ci * metadata pages may be encrypted and/or compressed. 21762306a36Sopenharmony_ci */ 21862306a36Sopenharmony_cistatic void f2fs_verify_and_finish_bio(struct bio *bio, bool in_task) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = bio->bi_private; 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci if (ctx && (ctx->enabled_steps & STEP_VERITY)) { 22362306a36Sopenharmony_ci INIT_WORK(&ctx->work, f2fs_verify_bio); 22462306a36Sopenharmony_ci fsverity_enqueue_verify_work(&ctx->work); 22562306a36Sopenharmony_ci } else { 22662306a36Sopenharmony_ci f2fs_finish_read_bio(bio, in_task); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci} 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci/* 23162306a36Sopenharmony_ci * Handle STEP_DECOMPRESS by decompressing any compressed clusters whose last 23262306a36Sopenharmony_ci * remaining page was read by @ctx->bio. 23362306a36Sopenharmony_ci * 23462306a36Sopenharmony_ci * Note that a bio may span clusters (even a mix of compressed and uncompressed 23562306a36Sopenharmony_ci * clusters) or be for just part of a cluster. STEP_DECOMPRESS just indicates 23662306a36Sopenharmony_ci * that the bio includes at least one compressed page. The actual decompression 23762306a36Sopenharmony_ci * is done on a per-cluster basis, not a per-bio basis. 23862306a36Sopenharmony_ci */ 23962306a36Sopenharmony_cistatic void f2fs_handle_step_decompress(struct bio_post_read_ctx *ctx, 24062306a36Sopenharmony_ci bool in_task) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct bio_vec *bv; 24362306a36Sopenharmony_ci struct bvec_iter_all iter_all; 24462306a36Sopenharmony_ci bool all_compressed = true; 24562306a36Sopenharmony_ci block_t blkaddr = ctx->fs_blkaddr; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci bio_for_each_segment_all(bv, ctx->bio, iter_all) { 24862306a36Sopenharmony_ci struct page *page = bv->bv_page; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci if (f2fs_is_compressed_page(page)) 25162306a36Sopenharmony_ci f2fs_end_read_compressed_page(page, false, blkaddr, 25262306a36Sopenharmony_ci in_task); 25362306a36Sopenharmony_ci else 25462306a36Sopenharmony_ci all_compressed = false; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci blkaddr++; 25762306a36Sopenharmony_ci } 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci ctx->decompression_attempted = true; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci /* 26262306a36Sopenharmony_ci * Optimization: if all the bio's pages are compressed, then scheduling 26362306a36Sopenharmony_ci * the per-bio verity work is unnecessary, as verity will be fully 26462306a36Sopenharmony_ci * handled at the compression cluster level. 26562306a36Sopenharmony_ci */ 26662306a36Sopenharmony_ci if (all_compressed) 26762306a36Sopenharmony_ci ctx->enabled_steps &= ~STEP_VERITY; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic void f2fs_post_read_work(struct work_struct *work) 27162306a36Sopenharmony_ci{ 27262306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = 27362306a36Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 27462306a36Sopenharmony_ci struct bio *bio = ctx->bio; 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci if ((ctx->enabled_steps & STEP_DECRYPT) && !fscrypt_decrypt_bio(bio)) { 27762306a36Sopenharmony_ci f2fs_finish_read_bio(bio, true); 27862306a36Sopenharmony_ci return; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (ctx->enabled_steps & STEP_DECOMPRESS) 28262306a36Sopenharmony_ci f2fs_handle_step_decompress(ctx, true); 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci f2fs_verify_and_finish_bio(bio, true); 28562306a36Sopenharmony_ci} 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_cistatic void f2fs_read_end_io(struct bio *bio) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio)); 29062306a36Sopenharmony_ci struct bio_post_read_ctx *ctx; 29162306a36Sopenharmony_ci bool intask = in_task(); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci iostat_update_and_unbind_ctx(bio); 29462306a36Sopenharmony_ci ctx = bio->bi_private; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci if (time_to_inject(sbi, FAULT_READ_IO)) 29762306a36Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (bio->bi_status) { 30062306a36Sopenharmony_ci f2fs_finish_read_bio(bio, intask); 30162306a36Sopenharmony_ci return; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if (ctx) { 30562306a36Sopenharmony_ci unsigned int enabled_steps = ctx->enabled_steps & 30662306a36Sopenharmony_ci (STEP_DECRYPT | STEP_DECOMPRESS); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* 30962306a36Sopenharmony_ci * If we have only decompression step between decompression and 31062306a36Sopenharmony_ci * decrypt, we don't need post processing for this. 31162306a36Sopenharmony_ci */ 31262306a36Sopenharmony_ci if (enabled_steps == STEP_DECOMPRESS && 31362306a36Sopenharmony_ci !f2fs_low_mem_mode(sbi)) { 31462306a36Sopenharmony_ci f2fs_handle_step_decompress(ctx, intask); 31562306a36Sopenharmony_ci } else if (enabled_steps) { 31662306a36Sopenharmony_ci INIT_WORK(&ctx->work, f2fs_post_read_work); 31762306a36Sopenharmony_ci queue_work(ctx->sbi->post_read_wq, &ctx->work); 31862306a36Sopenharmony_ci return; 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci f2fs_verify_and_finish_bio(bio, intask); 32362306a36Sopenharmony_ci} 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_cistatic void f2fs_write_end_io(struct bio *bio) 32662306a36Sopenharmony_ci{ 32762306a36Sopenharmony_ci struct f2fs_sb_info *sbi; 32862306a36Sopenharmony_ci struct bio_vec *bvec; 32962306a36Sopenharmony_ci struct bvec_iter_all iter_all; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci iostat_update_and_unbind_ctx(bio); 33262306a36Sopenharmony_ci sbi = bio->bi_private; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (time_to_inject(sbi, FAULT_WRITE_IO)) 33562306a36Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci bio_for_each_segment_all(bvec, bio, iter_all) { 33862306a36Sopenharmony_ci struct page *page = bvec->bv_page; 33962306a36Sopenharmony_ci enum count_type type = WB_DATA_TYPE(page, false); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci if (page_private_dummy(page)) { 34262306a36Sopenharmony_ci clear_page_private_dummy(page); 34362306a36Sopenharmony_ci unlock_page(page); 34462306a36Sopenharmony_ci mempool_free(page, sbi->write_io_dummy); 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci if (unlikely(bio->bi_status)) 34762306a36Sopenharmony_ci f2fs_stop_checkpoint(sbi, true, 34862306a36Sopenharmony_ci STOP_CP_REASON_WRITE_FAIL); 34962306a36Sopenharmony_ci continue; 35062306a36Sopenharmony_ci } 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci fscrypt_finalize_bounce_page(&page); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 35562306a36Sopenharmony_ci if (f2fs_is_compressed_page(page)) { 35662306a36Sopenharmony_ci f2fs_compress_write_end_io(bio, page); 35762306a36Sopenharmony_ci continue; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci#endif 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci if (unlikely(bio->bi_status)) { 36262306a36Sopenharmony_ci mapping_set_error(page->mapping, -EIO); 36362306a36Sopenharmony_ci if (type == F2FS_WB_CP_DATA) 36462306a36Sopenharmony_ci f2fs_stop_checkpoint(sbi, true, 36562306a36Sopenharmony_ci STOP_CP_REASON_WRITE_FAIL); 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && 36962306a36Sopenharmony_ci page->index != nid_of_node(page)); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci dec_page_count(sbi, type); 37262306a36Sopenharmony_ci if (f2fs_in_warm_node_list(sbi, page)) 37362306a36Sopenharmony_ci f2fs_del_fsync_node_entry(sbi, page); 37462306a36Sopenharmony_ci clear_page_private_gcing(page); 37562306a36Sopenharmony_ci end_page_writeback(page); 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci if (!get_pages(sbi, F2FS_WB_CP_DATA) && 37862306a36Sopenharmony_ci wq_has_sleeper(&sbi->cp_wait)) 37962306a36Sopenharmony_ci wake_up(&sbi->cp_wait); 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci bio_put(bio); 38262306a36Sopenharmony_ci} 38362306a36Sopenharmony_ci 38462306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 38562306a36Sopenharmony_cistatic void f2fs_zone_write_end_io(struct bio *bio) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci struct f2fs_bio_info *io = (struct f2fs_bio_info *)bio->bi_private; 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci bio->bi_private = io->bi_private; 39062306a36Sopenharmony_ci complete(&io->zone_wait); 39162306a36Sopenharmony_ci f2fs_write_end_io(bio); 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci#endif 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistruct block_device *f2fs_target_device(struct f2fs_sb_info *sbi, 39662306a36Sopenharmony_ci block_t blk_addr, sector_t *sector) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci struct block_device *bdev = sbi->sb->s_bdev; 39962306a36Sopenharmony_ci int i; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci if (f2fs_is_multi_device(sbi)) { 40262306a36Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) { 40362306a36Sopenharmony_ci if (FDEV(i).start_blk <= blk_addr && 40462306a36Sopenharmony_ci FDEV(i).end_blk >= blk_addr) { 40562306a36Sopenharmony_ci blk_addr -= FDEV(i).start_blk; 40662306a36Sopenharmony_ci bdev = FDEV(i).bdev; 40762306a36Sopenharmony_ci break; 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci } 41062306a36Sopenharmony_ci } 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci if (sector) 41362306a36Sopenharmony_ci *sector = SECTOR_FROM_BLOCK(blk_addr); 41462306a36Sopenharmony_ci return bdev; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ciint f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) 41862306a36Sopenharmony_ci{ 41962306a36Sopenharmony_ci int i; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (!f2fs_is_multi_device(sbi)) 42262306a36Sopenharmony_ci return 0; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) 42562306a36Sopenharmony_ci if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr) 42662306a36Sopenharmony_ci return i; 42762306a36Sopenharmony_ci return 0; 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic blk_opf_t f2fs_io_flags(struct f2fs_io_info *fio) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci unsigned int temp_mask = GENMASK(NR_TEMP_TYPE - 1, 0); 43362306a36Sopenharmony_ci unsigned int fua_flag, meta_flag, io_flag; 43462306a36Sopenharmony_ci blk_opf_t op_flags = 0; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (fio->op != REQ_OP_WRITE) 43762306a36Sopenharmony_ci return 0; 43862306a36Sopenharmony_ci if (fio->type == DATA) 43962306a36Sopenharmony_ci io_flag = fio->sbi->data_io_flag; 44062306a36Sopenharmony_ci else if (fio->type == NODE) 44162306a36Sopenharmony_ci io_flag = fio->sbi->node_io_flag; 44262306a36Sopenharmony_ci else 44362306a36Sopenharmony_ci return 0; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci fua_flag = io_flag & temp_mask; 44662306a36Sopenharmony_ci meta_flag = (io_flag >> NR_TEMP_TYPE) & temp_mask; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* 44962306a36Sopenharmony_ci * data/node io flag bits per temp: 45062306a36Sopenharmony_ci * REQ_META | REQ_FUA | 45162306a36Sopenharmony_ci * 5 | 4 | 3 | 2 | 1 | 0 | 45262306a36Sopenharmony_ci * Cold | Warm | Hot | Cold | Warm | Hot | 45362306a36Sopenharmony_ci */ 45462306a36Sopenharmony_ci if (BIT(fio->temp) & meta_flag) 45562306a36Sopenharmony_ci op_flags |= REQ_META; 45662306a36Sopenharmony_ci if (BIT(fio->temp) & fua_flag) 45762306a36Sopenharmony_ci op_flags |= REQ_FUA; 45862306a36Sopenharmony_ci return op_flags; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) 46262306a36Sopenharmony_ci{ 46362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 46462306a36Sopenharmony_ci struct block_device *bdev; 46562306a36Sopenharmony_ci sector_t sector; 46662306a36Sopenharmony_ci struct bio *bio; 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci bdev = f2fs_target_device(sbi, fio->new_blkaddr, §or); 46962306a36Sopenharmony_ci bio = bio_alloc_bioset(bdev, npages, 47062306a36Sopenharmony_ci fio->op | fio->op_flags | f2fs_io_flags(fio), 47162306a36Sopenharmony_ci GFP_NOIO, &f2fs_bioset); 47262306a36Sopenharmony_ci bio->bi_iter.bi_sector = sector; 47362306a36Sopenharmony_ci if (is_read_io(fio->op)) { 47462306a36Sopenharmony_ci bio->bi_end_io = f2fs_read_end_io; 47562306a36Sopenharmony_ci bio->bi_private = NULL; 47662306a36Sopenharmony_ci } else { 47762306a36Sopenharmony_ci bio->bi_end_io = f2fs_write_end_io; 47862306a36Sopenharmony_ci bio->bi_private = sbi; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci iostat_alloc_and_bind_ctx(sbi, bio, NULL); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci if (fio->io_wbc) 48362306a36Sopenharmony_ci wbc_init_bio(fio->io_wbc, bio); 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci return bio; 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_cistatic void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, 48962306a36Sopenharmony_ci pgoff_t first_idx, 49062306a36Sopenharmony_ci const struct f2fs_io_info *fio, 49162306a36Sopenharmony_ci gfp_t gfp_mask) 49262306a36Sopenharmony_ci{ 49362306a36Sopenharmony_ci /* 49462306a36Sopenharmony_ci * The f2fs garbage collector sets ->encrypted_page when it wants to 49562306a36Sopenharmony_ci * read/write raw data without encryption. 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_ci if (!fio || !fio->encrypted_page) 49862306a36Sopenharmony_ci fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode, 50262306a36Sopenharmony_ci pgoff_t next_idx, 50362306a36Sopenharmony_ci const struct f2fs_io_info *fio) 50462306a36Sopenharmony_ci{ 50562306a36Sopenharmony_ci /* 50662306a36Sopenharmony_ci * The f2fs garbage collector sets ->encrypted_page when it wants to 50762306a36Sopenharmony_ci * read/write raw data without encryption. 50862306a36Sopenharmony_ci */ 50962306a36Sopenharmony_ci if (fio && fio->encrypted_page) 51062306a36Sopenharmony_ci return !bio_has_crypt_ctx(bio); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return fscrypt_mergeable_bio(bio, inode, next_idx); 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_civoid f2fs_submit_read_bio(struct f2fs_sb_info *sbi, struct bio *bio, 51662306a36Sopenharmony_ci enum page_type type) 51762306a36Sopenharmony_ci{ 51862306a36Sopenharmony_ci WARN_ON_ONCE(!is_read_io(bio_op(bio))); 51962306a36Sopenharmony_ci trace_f2fs_submit_read_bio(sbi->sb, type, bio); 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci iostat_update_submit_ctx(bio, type); 52262306a36Sopenharmony_ci submit_bio(bio); 52362306a36Sopenharmony_ci} 52462306a36Sopenharmony_ci 52562306a36Sopenharmony_cistatic void f2fs_align_write_bio(struct f2fs_sb_info *sbi, struct bio *bio) 52662306a36Sopenharmony_ci{ 52762306a36Sopenharmony_ci unsigned int start = 52862306a36Sopenharmony_ci (bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS) % F2FS_IO_SIZE(sbi); 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci if (start == 0) 53162306a36Sopenharmony_ci return; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* fill dummy pages */ 53462306a36Sopenharmony_ci for (; start < F2FS_IO_SIZE(sbi); start++) { 53562306a36Sopenharmony_ci struct page *page = 53662306a36Sopenharmony_ci mempool_alloc(sbi->write_io_dummy, 53762306a36Sopenharmony_ci GFP_NOIO | __GFP_NOFAIL); 53862306a36Sopenharmony_ci f2fs_bug_on(sbi, !page); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci lock_page(page); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 54362306a36Sopenharmony_ci set_page_private_dummy(page); 54462306a36Sopenharmony_ci 54562306a36Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) 54662306a36Sopenharmony_ci f2fs_bug_on(sbi, 1); 54762306a36Sopenharmony_ci } 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic void f2fs_submit_write_bio(struct f2fs_sb_info *sbi, struct bio *bio, 55162306a36Sopenharmony_ci enum page_type type) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci WARN_ON_ONCE(is_read_io(bio_op(bio))); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (type == DATA || type == NODE) { 55662306a36Sopenharmony_ci if (f2fs_lfs_mode(sbi) && current->plug) 55762306a36Sopenharmony_ci blk_finish_plug(current->plug); 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi)) { 56062306a36Sopenharmony_ci f2fs_align_write_bio(sbi, bio); 56162306a36Sopenharmony_ci /* 56262306a36Sopenharmony_ci * In the NODE case, we lose next block address chain. 56362306a36Sopenharmony_ci * So, we need to do checkpoint in f2fs_sync_file. 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_ci if (type == NODE) 56662306a36Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_CP); 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci trace_f2fs_submit_write_bio(sbi->sb, type, bio); 57162306a36Sopenharmony_ci iostat_update_submit_ctx(bio, type); 57262306a36Sopenharmony_ci submit_bio(bio); 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_cistatic void __submit_merged_bio(struct f2fs_bio_info *io) 57662306a36Sopenharmony_ci{ 57762306a36Sopenharmony_ci struct f2fs_io_info *fio = &io->fio; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci if (!io->bio) 58062306a36Sopenharmony_ci return; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (is_read_io(fio->op)) { 58362306a36Sopenharmony_ci trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); 58462306a36Sopenharmony_ci f2fs_submit_read_bio(io->sbi, io->bio, fio->type); 58562306a36Sopenharmony_ci } else { 58662306a36Sopenharmony_ci trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio); 58762306a36Sopenharmony_ci f2fs_submit_write_bio(io->sbi, io->bio, fio->type); 58862306a36Sopenharmony_ci } 58962306a36Sopenharmony_ci io->bio = NULL; 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic bool __has_merged_page(struct bio *bio, struct inode *inode, 59362306a36Sopenharmony_ci struct page *page, nid_t ino) 59462306a36Sopenharmony_ci{ 59562306a36Sopenharmony_ci struct bio_vec *bvec; 59662306a36Sopenharmony_ci struct bvec_iter_all iter_all; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_ci if (!bio) 59962306a36Sopenharmony_ci return false; 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (!inode && !page && !ino) 60262306a36Sopenharmony_ci return true; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci bio_for_each_segment_all(bvec, bio, iter_all) { 60562306a36Sopenharmony_ci struct page *target = bvec->bv_page; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci if (fscrypt_is_bounce_page(target)) { 60862306a36Sopenharmony_ci target = fscrypt_pagecache_page(target); 60962306a36Sopenharmony_ci if (IS_ERR(target)) 61062306a36Sopenharmony_ci continue; 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci if (f2fs_is_compressed_page(target)) { 61362306a36Sopenharmony_ci target = f2fs_compress_control_page(target); 61462306a36Sopenharmony_ci if (IS_ERR(target)) 61562306a36Sopenharmony_ci continue; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci if (inode && inode == target->mapping->host) 61962306a36Sopenharmony_ci return true; 62062306a36Sopenharmony_ci if (page && page == target) 62162306a36Sopenharmony_ci return true; 62262306a36Sopenharmony_ci if (ino && ino == ino_of_node(target)) 62362306a36Sopenharmony_ci return true; 62462306a36Sopenharmony_ci } 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci return false; 62762306a36Sopenharmony_ci} 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ciint f2fs_init_write_merge_io(struct f2fs_sb_info *sbi) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci int i; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci for (i = 0; i < NR_PAGE_TYPE; i++) { 63462306a36Sopenharmony_ci int n = (i == META) ? 1 : NR_TEMP_TYPE; 63562306a36Sopenharmony_ci int j; 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci sbi->write_io[i] = f2fs_kmalloc(sbi, 63862306a36Sopenharmony_ci array_size(n, sizeof(struct f2fs_bio_info)), 63962306a36Sopenharmony_ci GFP_KERNEL); 64062306a36Sopenharmony_ci if (!sbi->write_io[i]) 64162306a36Sopenharmony_ci return -ENOMEM; 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci for (j = HOT; j < n; j++) { 64462306a36Sopenharmony_ci init_f2fs_rwsem(&sbi->write_io[i][j].io_rwsem); 64562306a36Sopenharmony_ci sbi->write_io[i][j].sbi = sbi; 64662306a36Sopenharmony_ci sbi->write_io[i][j].bio = NULL; 64762306a36Sopenharmony_ci spin_lock_init(&sbi->write_io[i][j].io_lock); 64862306a36Sopenharmony_ci INIT_LIST_HEAD(&sbi->write_io[i][j].io_list); 64962306a36Sopenharmony_ci INIT_LIST_HEAD(&sbi->write_io[i][j].bio_list); 65062306a36Sopenharmony_ci init_f2fs_rwsem(&sbi->write_io[i][j].bio_list_lock); 65162306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 65262306a36Sopenharmony_ci init_completion(&sbi->write_io[i][j].zone_wait); 65362306a36Sopenharmony_ci sbi->write_io[i][j].zone_pending_bio = NULL; 65462306a36Sopenharmony_ci sbi->write_io[i][j].bi_private = NULL; 65562306a36Sopenharmony_ci#endif 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci } 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci return 0; 66062306a36Sopenharmony_ci} 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cistatic void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi, 66362306a36Sopenharmony_ci enum page_type type, enum temp_type temp) 66462306a36Sopenharmony_ci{ 66562306a36Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(type); 66662306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + temp; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci f2fs_down_write(&io->io_rwsem); 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_ci if (!io->bio) 67162306a36Sopenharmony_ci goto unlock_out; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci /* change META to META_FLUSH in the checkpoint procedure */ 67462306a36Sopenharmony_ci if (type >= META_FLUSH) { 67562306a36Sopenharmony_ci io->fio.type = META_FLUSH; 67662306a36Sopenharmony_ci io->bio->bi_opf |= REQ_META | REQ_PRIO | REQ_SYNC; 67762306a36Sopenharmony_ci if (!test_opt(sbi, NOBARRIER)) 67862306a36Sopenharmony_ci io->bio->bi_opf |= REQ_PREFLUSH | REQ_FUA; 67962306a36Sopenharmony_ci } 68062306a36Sopenharmony_ci __submit_merged_bio(io); 68162306a36Sopenharmony_ciunlock_out: 68262306a36Sopenharmony_ci f2fs_up_write(&io->io_rwsem); 68362306a36Sopenharmony_ci} 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic void __submit_merged_write_cond(struct f2fs_sb_info *sbi, 68662306a36Sopenharmony_ci struct inode *inode, struct page *page, 68762306a36Sopenharmony_ci nid_t ino, enum page_type type, bool force) 68862306a36Sopenharmony_ci{ 68962306a36Sopenharmony_ci enum temp_type temp; 69062306a36Sopenharmony_ci bool ret = true; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { 69362306a36Sopenharmony_ci if (!force) { 69462306a36Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(type); 69562306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + temp; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci f2fs_down_read(&io->io_rwsem); 69862306a36Sopenharmony_ci ret = __has_merged_page(io->bio, inode, page, ino); 69962306a36Sopenharmony_ci f2fs_up_read(&io->io_rwsem); 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci if (ret) 70262306a36Sopenharmony_ci __f2fs_submit_merged_write(sbi, type, temp); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* TODO: use HOT temp only for meta pages now. */ 70562306a36Sopenharmony_ci if (type >= META) 70662306a36Sopenharmony_ci break; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_civoid f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci __submit_merged_write_cond(sbi, NULL, NULL, 0, type, true); 71362306a36Sopenharmony_ci} 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_civoid f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, 71662306a36Sopenharmony_ci struct inode *inode, struct page *page, 71762306a36Sopenharmony_ci nid_t ino, enum page_type type) 71862306a36Sopenharmony_ci{ 71962306a36Sopenharmony_ci __submit_merged_write_cond(sbi, inode, page, ino, type, false); 72062306a36Sopenharmony_ci} 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_civoid f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) 72362306a36Sopenharmony_ci{ 72462306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 72562306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 72662306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, META); 72762306a36Sopenharmony_ci} 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci/* 73062306a36Sopenharmony_ci * Fill the locked page with data located in the block address. 73162306a36Sopenharmony_ci * A caller needs to unlock the page on failure. 73262306a36Sopenharmony_ci */ 73362306a36Sopenharmony_ciint f2fs_submit_page_bio(struct f2fs_io_info *fio) 73462306a36Sopenharmony_ci{ 73562306a36Sopenharmony_ci struct bio *bio; 73662306a36Sopenharmony_ci struct page *page = fio->encrypted_page ? 73762306a36Sopenharmony_ci fio->encrypted_page : fio->page; 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, 74062306a36Sopenharmony_ci fio->is_por ? META_POR : (__is_meta_io(fio) ? 74162306a36Sopenharmony_ci META_GENERIC : DATA_GENERIC_ENHANCE))) { 74262306a36Sopenharmony_ci f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR); 74362306a36Sopenharmony_ci return -EFSCORRUPTED; 74462306a36Sopenharmony_ci } 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_ci trace_f2fs_submit_page_bio(page, fio); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* Allocate a new bio */ 74962306a36Sopenharmony_ci bio = __bio_alloc(fio, 1); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, 75262306a36Sopenharmony_ci fio->page->index, fio, GFP_NOIO); 75362306a36Sopenharmony_ci 75462306a36Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { 75562306a36Sopenharmony_ci bio_put(bio); 75662306a36Sopenharmony_ci return -EFAULT; 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (fio->io_wbc && !is_read_io(fio->op)) 76062306a36Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci inc_page_count(fio->sbi, is_read_io(fio->op) ? 76362306a36Sopenharmony_ci __read_io_type(page) : WB_DATA_TYPE(fio->page, false)); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (is_read_io(bio_op(bio))) 76662306a36Sopenharmony_ci f2fs_submit_read_bio(fio->sbi, bio, fio->type); 76762306a36Sopenharmony_ci else 76862306a36Sopenharmony_ci f2fs_submit_write_bio(fio->sbi, bio, fio->type); 76962306a36Sopenharmony_ci return 0; 77062306a36Sopenharmony_ci} 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_cistatic bool page_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, 77362306a36Sopenharmony_ci block_t last_blkaddr, block_t cur_blkaddr) 77462306a36Sopenharmony_ci{ 77562306a36Sopenharmony_ci if (unlikely(sbi->max_io_bytes && 77662306a36Sopenharmony_ci bio->bi_iter.bi_size >= sbi->max_io_bytes)) 77762306a36Sopenharmony_ci return false; 77862306a36Sopenharmony_ci if (last_blkaddr + 1 != cur_blkaddr) 77962306a36Sopenharmony_ci return false; 78062306a36Sopenharmony_ci return bio->bi_bdev == f2fs_target_device(sbi, cur_blkaddr, NULL); 78162306a36Sopenharmony_ci} 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_cistatic bool io_type_is_mergeable(struct f2fs_bio_info *io, 78462306a36Sopenharmony_ci struct f2fs_io_info *fio) 78562306a36Sopenharmony_ci{ 78662306a36Sopenharmony_ci if (io->fio.op != fio->op) 78762306a36Sopenharmony_ci return false; 78862306a36Sopenharmony_ci return io->fio.op_flags == fio->op_flags; 78962306a36Sopenharmony_ci} 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_cistatic bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, 79262306a36Sopenharmony_ci struct f2fs_bio_info *io, 79362306a36Sopenharmony_ci struct f2fs_io_info *fio, 79462306a36Sopenharmony_ci block_t last_blkaddr, 79562306a36Sopenharmony_ci block_t cur_blkaddr) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE)) { 79862306a36Sopenharmony_ci unsigned int filled_blocks = 79962306a36Sopenharmony_ci F2FS_BYTES_TO_BLK(bio->bi_iter.bi_size); 80062306a36Sopenharmony_ci unsigned int io_size = F2FS_IO_SIZE(sbi); 80162306a36Sopenharmony_ci unsigned int left_vecs = bio->bi_max_vecs - bio->bi_vcnt; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci /* IOs in bio is aligned and left space of vectors is not enough */ 80462306a36Sopenharmony_ci if (!(filled_blocks % io_size) && left_vecs < io_size) 80562306a36Sopenharmony_ci return false; 80662306a36Sopenharmony_ci } 80762306a36Sopenharmony_ci if (!page_is_mergeable(sbi, bio, last_blkaddr, cur_blkaddr)) 80862306a36Sopenharmony_ci return false; 80962306a36Sopenharmony_ci return io_type_is_mergeable(io, fio); 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, 81362306a36Sopenharmony_ci struct page *page, enum temp_type temp) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 81662306a36Sopenharmony_ci struct bio_entry *be; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS, true, NULL); 81962306a36Sopenharmony_ci be->bio = bio; 82062306a36Sopenharmony_ci bio_get(bio); 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) 82362306a36Sopenharmony_ci f2fs_bug_on(sbi, 1); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci f2fs_down_write(&io->bio_list_lock); 82662306a36Sopenharmony_ci list_add_tail(&be->list, &io->bio_list); 82762306a36Sopenharmony_ci f2fs_up_write(&io->bio_list_lock); 82862306a36Sopenharmony_ci} 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_cistatic void del_bio_entry(struct bio_entry *be) 83162306a36Sopenharmony_ci{ 83262306a36Sopenharmony_ci list_del(&be->list); 83362306a36Sopenharmony_ci kmem_cache_free(bio_entry_slab, be); 83462306a36Sopenharmony_ci} 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, 83762306a36Sopenharmony_ci struct page *page) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 84062306a36Sopenharmony_ci enum temp_type temp; 84162306a36Sopenharmony_ci bool found = false; 84262306a36Sopenharmony_ci int ret = -EAGAIN; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { 84562306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 84662306a36Sopenharmony_ci struct list_head *head = &io->bio_list; 84762306a36Sopenharmony_ci struct bio_entry *be; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci f2fs_down_write(&io->bio_list_lock); 85062306a36Sopenharmony_ci list_for_each_entry(be, head, list) { 85162306a36Sopenharmony_ci if (be->bio != *bio) 85262306a36Sopenharmony_ci continue; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci found = true; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci f2fs_bug_on(sbi, !page_is_mergeable(sbi, *bio, 85762306a36Sopenharmony_ci *fio->last_block, 85862306a36Sopenharmony_ci fio->new_blkaddr)); 85962306a36Sopenharmony_ci if (f2fs_crypt_mergeable_bio(*bio, 86062306a36Sopenharmony_ci fio->page->mapping->host, 86162306a36Sopenharmony_ci fio->page->index, fio) && 86262306a36Sopenharmony_ci bio_add_page(*bio, page, PAGE_SIZE, 0) == 86362306a36Sopenharmony_ci PAGE_SIZE) { 86462306a36Sopenharmony_ci ret = 0; 86562306a36Sopenharmony_ci break; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci /* page can't be merged into bio; submit the bio */ 86962306a36Sopenharmony_ci del_bio_entry(be); 87062306a36Sopenharmony_ci f2fs_submit_write_bio(sbi, *bio, DATA); 87162306a36Sopenharmony_ci break; 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci f2fs_up_write(&io->bio_list_lock); 87462306a36Sopenharmony_ci } 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci if (ret) { 87762306a36Sopenharmony_ci bio_put(*bio); 87862306a36Sopenharmony_ci *bio = NULL; 87962306a36Sopenharmony_ci } 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci return ret; 88262306a36Sopenharmony_ci} 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_civoid f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi, 88562306a36Sopenharmony_ci struct bio **bio, struct page *page) 88662306a36Sopenharmony_ci{ 88762306a36Sopenharmony_ci enum temp_type temp; 88862306a36Sopenharmony_ci bool found = false; 88962306a36Sopenharmony_ci struct bio *target = bio ? *bio : NULL; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci f2fs_bug_on(sbi, !target && !page); 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { 89462306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 89562306a36Sopenharmony_ci struct list_head *head = &io->bio_list; 89662306a36Sopenharmony_ci struct bio_entry *be; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci if (list_empty(head)) 89962306a36Sopenharmony_ci continue; 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci f2fs_down_read(&io->bio_list_lock); 90262306a36Sopenharmony_ci list_for_each_entry(be, head, list) { 90362306a36Sopenharmony_ci if (target) 90462306a36Sopenharmony_ci found = (target == be->bio); 90562306a36Sopenharmony_ci else 90662306a36Sopenharmony_ci found = __has_merged_page(be->bio, NULL, 90762306a36Sopenharmony_ci page, 0); 90862306a36Sopenharmony_ci if (found) 90962306a36Sopenharmony_ci break; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci f2fs_up_read(&io->bio_list_lock); 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (!found) 91462306a36Sopenharmony_ci continue; 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci found = false; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci f2fs_down_write(&io->bio_list_lock); 91962306a36Sopenharmony_ci list_for_each_entry(be, head, list) { 92062306a36Sopenharmony_ci if (target) 92162306a36Sopenharmony_ci found = (target == be->bio); 92262306a36Sopenharmony_ci else 92362306a36Sopenharmony_ci found = __has_merged_page(be->bio, NULL, 92462306a36Sopenharmony_ci page, 0); 92562306a36Sopenharmony_ci if (found) { 92662306a36Sopenharmony_ci target = be->bio; 92762306a36Sopenharmony_ci del_bio_entry(be); 92862306a36Sopenharmony_ci break; 92962306a36Sopenharmony_ci } 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci f2fs_up_write(&io->bio_list_lock); 93262306a36Sopenharmony_ci } 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci if (found) 93562306a36Sopenharmony_ci f2fs_submit_write_bio(sbi, target, DATA); 93662306a36Sopenharmony_ci if (bio && *bio) { 93762306a36Sopenharmony_ci bio_put(*bio); 93862306a36Sopenharmony_ci *bio = NULL; 93962306a36Sopenharmony_ci } 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ciint f2fs_merge_page_bio(struct f2fs_io_info *fio) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci struct bio *bio = *fio->bio; 94562306a36Sopenharmony_ci struct page *page = fio->encrypted_page ? 94662306a36Sopenharmony_ci fio->encrypted_page : fio->page; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, 94962306a36Sopenharmony_ci __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) { 95062306a36Sopenharmony_ci f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR); 95162306a36Sopenharmony_ci return -EFSCORRUPTED; 95262306a36Sopenharmony_ci } 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_ci trace_f2fs_submit_page_bio(page, fio); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block, 95762306a36Sopenharmony_ci fio->new_blkaddr)) 95862306a36Sopenharmony_ci f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL); 95962306a36Sopenharmony_cialloc_new: 96062306a36Sopenharmony_ci if (!bio) { 96162306a36Sopenharmony_ci bio = __bio_alloc(fio, BIO_MAX_VECS); 96262306a36Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, 96362306a36Sopenharmony_ci fio->page->index, fio, GFP_NOIO); 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci add_bio_entry(fio->sbi, bio, page, fio->temp); 96662306a36Sopenharmony_ci } else { 96762306a36Sopenharmony_ci if (add_ipu_page(fio, &bio, page)) 96862306a36Sopenharmony_ci goto alloc_new; 96962306a36Sopenharmony_ci } 97062306a36Sopenharmony_ci 97162306a36Sopenharmony_ci if (fio->io_wbc) 97262306a36Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci inc_page_count(fio->sbi, WB_DATA_TYPE(page, false)); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci *fio->last_block = fio->new_blkaddr; 97762306a36Sopenharmony_ci *fio->bio = bio; 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci return 0; 98062306a36Sopenharmony_ci} 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 98362306a36Sopenharmony_cistatic bool is_end_zone_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr) 98462306a36Sopenharmony_ci{ 98562306a36Sopenharmony_ci int devi = 0; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci if (f2fs_is_multi_device(sbi)) { 98862306a36Sopenharmony_ci devi = f2fs_target_device_index(sbi, blkaddr); 98962306a36Sopenharmony_ci if (blkaddr < FDEV(devi).start_blk || 99062306a36Sopenharmony_ci blkaddr > FDEV(devi).end_blk) { 99162306a36Sopenharmony_ci f2fs_err(sbi, "Invalid block %x", blkaddr); 99262306a36Sopenharmony_ci return false; 99362306a36Sopenharmony_ci } 99462306a36Sopenharmony_ci blkaddr -= FDEV(devi).start_blk; 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci return bdev_zoned_model(FDEV(devi).bdev) == BLK_ZONED_HM && 99762306a36Sopenharmony_ci f2fs_blkz_is_seq(sbi, devi, blkaddr) && 99862306a36Sopenharmony_ci (blkaddr % sbi->blocks_per_blkz == sbi->blocks_per_blkz - 1); 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci#endif 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_civoid f2fs_submit_page_write(struct f2fs_io_info *fio) 100362306a36Sopenharmony_ci{ 100462306a36Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 100562306a36Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); 100662306a36Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp; 100762306a36Sopenharmony_ci struct page *bio_page; 100862306a36Sopenharmony_ci enum count_type type; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci f2fs_bug_on(sbi, is_read_io(fio->op)); 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci f2fs_down_write(&io->io_rwsem); 101362306a36Sopenharmony_cinext: 101462306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 101562306a36Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi) && btype < META && io->zone_pending_bio) { 101662306a36Sopenharmony_ci wait_for_completion_io(&io->zone_wait); 101762306a36Sopenharmony_ci bio_put(io->zone_pending_bio); 101862306a36Sopenharmony_ci io->zone_pending_bio = NULL; 101962306a36Sopenharmony_ci io->bi_private = NULL; 102062306a36Sopenharmony_ci } 102162306a36Sopenharmony_ci#endif 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci if (fio->in_list) { 102462306a36Sopenharmony_ci spin_lock(&io->io_lock); 102562306a36Sopenharmony_ci if (list_empty(&io->io_list)) { 102662306a36Sopenharmony_ci spin_unlock(&io->io_lock); 102762306a36Sopenharmony_ci goto out; 102862306a36Sopenharmony_ci } 102962306a36Sopenharmony_ci fio = list_first_entry(&io->io_list, 103062306a36Sopenharmony_ci struct f2fs_io_info, list); 103162306a36Sopenharmony_ci list_del(&fio->list); 103262306a36Sopenharmony_ci spin_unlock(&io->io_lock); 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci verify_fio_blkaddr(fio); 103662306a36Sopenharmony_ci 103762306a36Sopenharmony_ci if (fio->encrypted_page) 103862306a36Sopenharmony_ci bio_page = fio->encrypted_page; 103962306a36Sopenharmony_ci else if (fio->compressed_page) 104062306a36Sopenharmony_ci bio_page = fio->compressed_page; 104162306a36Sopenharmony_ci else 104262306a36Sopenharmony_ci bio_page = fio->page; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci /* set submitted = true as a return value */ 104562306a36Sopenharmony_ci fio->submitted = 1; 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci type = WB_DATA_TYPE(bio_page, fio->compressed_page); 104862306a36Sopenharmony_ci inc_page_count(sbi, type); 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci if (io->bio && 105162306a36Sopenharmony_ci (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, 105262306a36Sopenharmony_ci fio->new_blkaddr) || 105362306a36Sopenharmony_ci !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, 105462306a36Sopenharmony_ci bio_page->index, fio))) 105562306a36Sopenharmony_ci __submit_merged_bio(io); 105662306a36Sopenharmony_cialloc_new: 105762306a36Sopenharmony_ci if (io->bio == NULL) { 105862306a36Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi) && 105962306a36Sopenharmony_ci (fio->type == DATA || fio->type == NODE) && 106062306a36Sopenharmony_ci fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) { 106162306a36Sopenharmony_ci dec_page_count(sbi, WB_DATA_TYPE(bio_page, 106262306a36Sopenharmony_ci fio->compressed_page)); 106362306a36Sopenharmony_ci fio->retry = 1; 106462306a36Sopenharmony_ci goto skip; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci io->bio = __bio_alloc(fio, BIO_MAX_VECS); 106762306a36Sopenharmony_ci f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, 106862306a36Sopenharmony_ci bio_page->index, fio, GFP_NOIO); 106962306a36Sopenharmony_ci io->fio = *fio; 107062306a36Sopenharmony_ci } 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) { 107362306a36Sopenharmony_ci __submit_merged_bio(io); 107462306a36Sopenharmony_ci goto alloc_new; 107562306a36Sopenharmony_ci } 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci if (fio->io_wbc) 107862306a36Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci io->last_block_in_bio = fio->new_blkaddr; 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci trace_f2fs_submit_page_write(fio->page, fio); 108362306a36Sopenharmony_ci#ifdef CONFIG_BLK_DEV_ZONED 108462306a36Sopenharmony_ci if (f2fs_sb_has_blkzoned(sbi) && btype < META && 108562306a36Sopenharmony_ci is_end_zone_blkaddr(sbi, fio->new_blkaddr)) { 108662306a36Sopenharmony_ci bio_get(io->bio); 108762306a36Sopenharmony_ci reinit_completion(&io->zone_wait); 108862306a36Sopenharmony_ci io->bi_private = io->bio->bi_private; 108962306a36Sopenharmony_ci io->bio->bi_private = io; 109062306a36Sopenharmony_ci io->bio->bi_end_io = f2fs_zone_write_end_io; 109162306a36Sopenharmony_ci io->zone_pending_bio = io->bio; 109262306a36Sopenharmony_ci __submit_merged_bio(io); 109362306a36Sopenharmony_ci } 109462306a36Sopenharmony_ci#endif 109562306a36Sopenharmony_ciskip: 109662306a36Sopenharmony_ci if (fio->in_list) 109762306a36Sopenharmony_ci goto next; 109862306a36Sopenharmony_ciout: 109962306a36Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || 110062306a36Sopenharmony_ci !f2fs_is_checkpoint_ready(sbi)) 110162306a36Sopenharmony_ci __submit_merged_bio(io); 110262306a36Sopenharmony_ci f2fs_up_write(&io->io_rwsem); 110362306a36Sopenharmony_ci} 110462306a36Sopenharmony_ci 110562306a36Sopenharmony_cistatic struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, 110662306a36Sopenharmony_ci unsigned nr_pages, blk_opf_t op_flag, 110762306a36Sopenharmony_ci pgoff_t first_idx, bool for_write) 110862306a36Sopenharmony_ci{ 110962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 111062306a36Sopenharmony_ci struct bio *bio; 111162306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = NULL; 111262306a36Sopenharmony_ci unsigned int post_read_steps = 0; 111362306a36Sopenharmony_ci sector_t sector; 111462306a36Sopenharmony_ci struct block_device *bdev = f2fs_target_device(sbi, blkaddr, §or); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci bio = bio_alloc_bioset(bdev, bio_max_segs(nr_pages), 111762306a36Sopenharmony_ci REQ_OP_READ | op_flag, 111862306a36Sopenharmony_ci for_write ? GFP_NOIO : GFP_KERNEL, &f2fs_bioset); 111962306a36Sopenharmony_ci if (!bio) 112062306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 112162306a36Sopenharmony_ci bio->bi_iter.bi_sector = sector; 112262306a36Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS); 112362306a36Sopenharmony_ci bio->bi_end_io = f2fs_read_end_io; 112462306a36Sopenharmony_ci 112562306a36Sopenharmony_ci if (fscrypt_inode_uses_fs_layer_crypto(inode)) 112662306a36Sopenharmony_ci post_read_steps |= STEP_DECRYPT; 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci if (f2fs_need_verity(inode, first_idx)) 112962306a36Sopenharmony_ci post_read_steps |= STEP_VERITY; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci /* 113262306a36Sopenharmony_ci * STEP_DECOMPRESS is handled specially, since a compressed file might 113362306a36Sopenharmony_ci * contain both compressed and uncompressed clusters. We'll allocate a 113462306a36Sopenharmony_ci * bio_post_read_ctx if the file is compressed, but the caller is 113562306a36Sopenharmony_ci * responsible for enabling STEP_DECOMPRESS if it's actually needed. 113662306a36Sopenharmony_ci */ 113762306a36Sopenharmony_ci 113862306a36Sopenharmony_ci if (post_read_steps || f2fs_compressed_file(inode)) { 113962306a36Sopenharmony_ci /* Due to the mempool, this never fails. */ 114062306a36Sopenharmony_ci ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); 114162306a36Sopenharmony_ci ctx->bio = bio; 114262306a36Sopenharmony_ci ctx->sbi = sbi; 114362306a36Sopenharmony_ci ctx->enabled_steps = post_read_steps; 114462306a36Sopenharmony_ci ctx->fs_blkaddr = blkaddr; 114562306a36Sopenharmony_ci ctx->decompression_attempted = false; 114662306a36Sopenharmony_ci bio->bi_private = ctx; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci iostat_alloc_and_bind_ctx(sbi, bio, ctx); 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci return bio; 115162306a36Sopenharmony_ci} 115262306a36Sopenharmony_ci 115362306a36Sopenharmony_ci/* This can handle encryption stuffs */ 115462306a36Sopenharmony_cistatic int f2fs_submit_page_read(struct inode *inode, struct page *page, 115562306a36Sopenharmony_ci block_t blkaddr, blk_opf_t op_flags, 115662306a36Sopenharmony_ci bool for_write) 115762306a36Sopenharmony_ci{ 115862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 115962306a36Sopenharmony_ci struct bio *bio; 116062306a36Sopenharmony_ci 116162306a36Sopenharmony_ci bio = f2fs_grab_read_bio(inode, blkaddr, 1, op_flags, 116262306a36Sopenharmony_ci page->index, for_write); 116362306a36Sopenharmony_ci if (IS_ERR(bio)) 116462306a36Sopenharmony_ci return PTR_ERR(bio); 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci /* wait for GCed page writeback via META_MAPPING */ 116762306a36Sopenharmony_ci f2fs_wait_on_block_writeback(inode, blkaddr); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { 117062306a36Sopenharmony_ci iostat_update_and_unbind_ctx(bio); 117162306a36Sopenharmony_ci if (bio->bi_private) 117262306a36Sopenharmony_ci mempool_free(bio->bi_private, bio_post_read_ctx_pool); 117362306a36Sopenharmony_ci bio_put(bio); 117462306a36Sopenharmony_ci return -EFAULT; 117562306a36Sopenharmony_ci } 117662306a36Sopenharmony_ci inc_page_count(sbi, F2FS_RD_DATA); 117762306a36Sopenharmony_ci f2fs_update_iostat(sbi, NULL, FS_DATA_READ_IO, F2FS_BLKSIZE); 117862306a36Sopenharmony_ci f2fs_submit_read_bio(sbi, bio, DATA); 117962306a36Sopenharmony_ci return 0; 118062306a36Sopenharmony_ci} 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_cistatic void __set_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci __le32 *addr = get_dnode_addr(dn->inode, dn->node_page); 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_ci dn->data_blkaddr = blkaddr; 118762306a36Sopenharmony_ci addr[dn->ofs_in_node] = cpu_to_le32(dn->data_blkaddr); 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_ci/* 119162306a36Sopenharmony_ci * Lock ordering for the change of data block address: 119262306a36Sopenharmony_ci * ->data_page 119362306a36Sopenharmony_ci * ->node_page 119462306a36Sopenharmony_ci * update block addresses in the node page 119562306a36Sopenharmony_ci */ 119662306a36Sopenharmony_civoid f2fs_set_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr) 119762306a36Sopenharmony_ci{ 119862306a36Sopenharmony_ci f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); 119962306a36Sopenharmony_ci __set_data_blkaddr(dn, blkaddr); 120062306a36Sopenharmony_ci if (set_page_dirty(dn->node_page)) 120162306a36Sopenharmony_ci dn->node_changed = true; 120262306a36Sopenharmony_ci} 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_civoid f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr) 120562306a36Sopenharmony_ci{ 120662306a36Sopenharmony_ci f2fs_set_data_blkaddr(dn, blkaddr); 120762306a36Sopenharmony_ci f2fs_update_read_extent_cache(dn); 120862306a36Sopenharmony_ci} 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci/* dn->ofs_in_node will be returned with up-to-date last block pointer */ 121162306a36Sopenharmony_ciint f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 121462306a36Sopenharmony_ci int err; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci if (!count) 121762306a36Sopenharmony_ci return 0; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 122062306a36Sopenharmony_ci return -EPERM; 122162306a36Sopenharmony_ci err = inc_valid_block_count(sbi, dn->inode, &count, true); 122262306a36Sopenharmony_ci if (unlikely(err)) 122362306a36Sopenharmony_ci return err; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci trace_f2fs_reserve_new_blocks(dn->inode, dn->nid, 122662306a36Sopenharmony_ci dn->ofs_in_node, count); 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); 122962306a36Sopenharmony_ci 123062306a36Sopenharmony_ci for (; count > 0; dn->ofs_in_node++) { 123162306a36Sopenharmony_ci block_t blkaddr = f2fs_data_blkaddr(dn); 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci if (blkaddr == NULL_ADDR) { 123462306a36Sopenharmony_ci __set_data_blkaddr(dn, NEW_ADDR); 123562306a36Sopenharmony_ci count--; 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci } 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci if (set_page_dirty(dn->node_page)) 124062306a36Sopenharmony_ci dn->node_changed = true; 124162306a36Sopenharmony_ci return 0; 124262306a36Sopenharmony_ci} 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci/* Should keep dn->ofs_in_node unchanged */ 124562306a36Sopenharmony_ciint f2fs_reserve_new_block(struct dnode_of_data *dn) 124662306a36Sopenharmony_ci{ 124762306a36Sopenharmony_ci unsigned int ofs_in_node = dn->ofs_in_node; 124862306a36Sopenharmony_ci int ret; 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci ret = f2fs_reserve_new_blocks(dn, 1); 125162306a36Sopenharmony_ci dn->ofs_in_node = ofs_in_node; 125262306a36Sopenharmony_ci return ret; 125362306a36Sopenharmony_ci} 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ciint f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index) 125662306a36Sopenharmony_ci{ 125762306a36Sopenharmony_ci bool need_put = dn->inode_page ? false : true; 125862306a36Sopenharmony_ci int err; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(dn, index, ALLOC_NODE); 126162306a36Sopenharmony_ci if (err) 126262306a36Sopenharmony_ci return err; 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_ci if (dn->data_blkaddr == NULL_ADDR) 126562306a36Sopenharmony_ci err = f2fs_reserve_new_block(dn); 126662306a36Sopenharmony_ci if (err || need_put) 126762306a36Sopenharmony_ci f2fs_put_dnode(dn); 126862306a36Sopenharmony_ci return err; 126962306a36Sopenharmony_ci} 127062306a36Sopenharmony_ci 127162306a36Sopenharmony_cistruct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index, 127262306a36Sopenharmony_ci blk_opf_t op_flags, bool for_write, 127362306a36Sopenharmony_ci pgoff_t *next_pgofs) 127462306a36Sopenharmony_ci{ 127562306a36Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 127662306a36Sopenharmony_ci struct dnode_of_data dn; 127762306a36Sopenharmony_ci struct page *page; 127862306a36Sopenharmony_ci int err; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, for_write); 128162306a36Sopenharmony_ci if (!page) 128262306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci if (f2fs_lookup_read_extent_cache_block(inode, index, 128562306a36Sopenharmony_ci &dn.data_blkaddr)) { 128662306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr, 128762306a36Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 128862306a36Sopenharmony_ci err = -EFSCORRUPTED; 128962306a36Sopenharmony_ci f2fs_handle_error(F2FS_I_SB(inode), 129062306a36Sopenharmony_ci ERROR_INVALID_BLKADDR); 129162306a36Sopenharmony_ci goto put_err; 129262306a36Sopenharmony_ci } 129362306a36Sopenharmony_ci goto got_it; 129462306a36Sopenharmony_ci } 129562306a36Sopenharmony_ci 129662306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 129762306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); 129862306a36Sopenharmony_ci if (err) { 129962306a36Sopenharmony_ci if (err == -ENOENT && next_pgofs) 130062306a36Sopenharmony_ci *next_pgofs = f2fs_get_next_page_offset(&dn, index); 130162306a36Sopenharmony_ci goto put_err; 130262306a36Sopenharmony_ci } 130362306a36Sopenharmony_ci f2fs_put_dnode(&dn); 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci if (unlikely(dn.data_blkaddr == NULL_ADDR)) { 130662306a36Sopenharmony_ci err = -ENOENT; 130762306a36Sopenharmony_ci if (next_pgofs) 130862306a36Sopenharmony_ci *next_pgofs = index + 1; 130962306a36Sopenharmony_ci goto put_err; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci if (dn.data_blkaddr != NEW_ADDR && 131262306a36Sopenharmony_ci !f2fs_is_valid_blkaddr(F2FS_I_SB(inode), 131362306a36Sopenharmony_ci dn.data_blkaddr, 131462306a36Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 131562306a36Sopenharmony_ci err = -EFSCORRUPTED; 131662306a36Sopenharmony_ci f2fs_handle_error(F2FS_I_SB(inode), 131762306a36Sopenharmony_ci ERROR_INVALID_BLKADDR); 131862306a36Sopenharmony_ci goto put_err; 131962306a36Sopenharmony_ci } 132062306a36Sopenharmony_cigot_it: 132162306a36Sopenharmony_ci if (PageUptodate(page)) { 132262306a36Sopenharmony_ci unlock_page(page); 132362306a36Sopenharmony_ci return page; 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci 132662306a36Sopenharmony_ci /* 132762306a36Sopenharmony_ci * A new dentry page is allocated but not able to be written, since its 132862306a36Sopenharmony_ci * new inode page couldn't be allocated due to -ENOSPC. 132962306a36Sopenharmony_ci * In such the case, its blkaddr can be remained as NEW_ADDR. 133062306a36Sopenharmony_ci * see, f2fs_add_link -> f2fs_get_new_data_page -> 133162306a36Sopenharmony_ci * f2fs_init_inode_metadata. 133262306a36Sopenharmony_ci */ 133362306a36Sopenharmony_ci if (dn.data_blkaddr == NEW_ADDR) { 133462306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 133562306a36Sopenharmony_ci if (!PageUptodate(page)) 133662306a36Sopenharmony_ci SetPageUptodate(page); 133762306a36Sopenharmony_ci unlock_page(page); 133862306a36Sopenharmony_ci return page; 133962306a36Sopenharmony_ci } 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci err = f2fs_submit_page_read(inode, page, dn.data_blkaddr, 134262306a36Sopenharmony_ci op_flags, for_write); 134362306a36Sopenharmony_ci if (err) 134462306a36Sopenharmony_ci goto put_err; 134562306a36Sopenharmony_ci return page; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ciput_err: 134862306a36Sopenharmony_ci f2fs_put_page(page, 1); 134962306a36Sopenharmony_ci return ERR_PTR(err); 135062306a36Sopenharmony_ci} 135162306a36Sopenharmony_ci 135262306a36Sopenharmony_cistruct page *f2fs_find_data_page(struct inode *inode, pgoff_t index, 135362306a36Sopenharmony_ci pgoff_t *next_pgofs) 135462306a36Sopenharmony_ci{ 135562306a36Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 135662306a36Sopenharmony_ci struct page *page; 135762306a36Sopenharmony_ci 135862306a36Sopenharmony_ci page = find_get_page(mapping, index); 135962306a36Sopenharmony_ci if (page && PageUptodate(page)) 136062306a36Sopenharmony_ci return page; 136162306a36Sopenharmony_ci f2fs_put_page(page, 0); 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_ci page = f2fs_get_read_data_page(inode, index, 0, false, next_pgofs); 136462306a36Sopenharmony_ci if (IS_ERR(page)) 136562306a36Sopenharmony_ci return page; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci if (PageUptodate(page)) 136862306a36Sopenharmony_ci return page; 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci wait_on_page_locked(page); 137162306a36Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 137262306a36Sopenharmony_ci f2fs_put_page(page, 0); 137362306a36Sopenharmony_ci return ERR_PTR(-EIO); 137462306a36Sopenharmony_ci } 137562306a36Sopenharmony_ci return page; 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci/* 137962306a36Sopenharmony_ci * If it tries to access a hole, return an error. 138062306a36Sopenharmony_ci * Because, the callers, functions in dir.c and GC, should be able to know 138162306a36Sopenharmony_ci * whether this page exists or not. 138262306a36Sopenharmony_ci */ 138362306a36Sopenharmony_cistruct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, 138462306a36Sopenharmony_ci bool for_write) 138562306a36Sopenharmony_ci{ 138662306a36Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 138762306a36Sopenharmony_ci struct page *page; 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci page = f2fs_get_read_data_page(inode, index, 0, for_write, NULL); 139062306a36Sopenharmony_ci if (IS_ERR(page)) 139162306a36Sopenharmony_ci return page; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci /* wait for read completion */ 139462306a36Sopenharmony_ci lock_page(page); 139562306a36Sopenharmony_ci if (unlikely(page->mapping != mapping || !PageUptodate(page))) { 139662306a36Sopenharmony_ci f2fs_put_page(page, 1); 139762306a36Sopenharmony_ci return ERR_PTR(-EIO); 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci return page; 140062306a36Sopenharmony_ci} 140162306a36Sopenharmony_ci 140262306a36Sopenharmony_ci/* 140362306a36Sopenharmony_ci * Caller ensures that this data page is never allocated. 140462306a36Sopenharmony_ci * A new zero-filled data page is allocated in the page cache. 140562306a36Sopenharmony_ci * 140662306a36Sopenharmony_ci * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and 140762306a36Sopenharmony_ci * f2fs_unlock_op(). 140862306a36Sopenharmony_ci * Note that, ipage is set only by make_empty_dir, and if any error occur, 140962306a36Sopenharmony_ci * ipage should be released by this function. 141062306a36Sopenharmony_ci */ 141162306a36Sopenharmony_cistruct page *f2fs_get_new_data_page(struct inode *inode, 141262306a36Sopenharmony_ci struct page *ipage, pgoff_t index, bool new_i_size) 141362306a36Sopenharmony_ci{ 141462306a36Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 141562306a36Sopenharmony_ci struct page *page; 141662306a36Sopenharmony_ci struct dnode_of_data dn; 141762306a36Sopenharmony_ci int err; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, true); 142062306a36Sopenharmony_ci if (!page) { 142162306a36Sopenharmony_ci /* 142262306a36Sopenharmony_ci * before exiting, we should make sure ipage will be released 142362306a36Sopenharmony_ci * if any error occur. 142462306a36Sopenharmony_ci */ 142562306a36Sopenharmony_ci f2fs_put_page(ipage, 1); 142662306a36Sopenharmony_ci return ERR_PTR(-ENOMEM); 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci set_new_dnode(&dn, inode, ipage, NULL, 0); 143062306a36Sopenharmony_ci err = f2fs_reserve_block(&dn, index); 143162306a36Sopenharmony_ci if (err) { 143262306a36Sopenharmony_ci f2fs_put_page(page, 1); 143362306a36Sopenharmony_ci return ERR_PTR(err); 143462306a36Sopenharmony_ci } 143562306a36Sopenharmony_ci if (!ipage) 143662306a36Sopenharmony_ci f2fs_put_dnode(&dn); 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_ci if (PageUptodate(page)) 143962306a36Sopenharmony_ci goto got_it; 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci if (dn.data_blkaddr == NEW_ADDR) { 144262306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 144362306a36Sopenharmony_ci if (!PageUptodate(page)) 144462306a36Sopenharmony_ci SetPageUptodate(page); 144562306a36Sopenharmony_ci } else { 144662306a36Sopenharmony_ci f2fs_put_page(page, 1); 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci /* if ipage exists, blkaddr should be NEW_ADDR */ 144962306a36Sopenharmony_ci f2fs_bug_on(F2FS_I_SB(inode), ipage); 145062306a36Sopenharmony_ci page = f2fs_get_lock_data_page(inode, index, true); 145162306a36Sopenharmony_ci if (IS_ERR(page)) 145262306a36Sopenharmony_ci return page; 145362306a36Sopenharmony_ci } 145462306a36Sopenharmony_cigot_it: 145562306a36Sopenharmony_ci if (new_i_size && i_size_read(inode) < 145662306a36Sopenharmony_ci ((loff_t)(index + 1) << PAGE_SHIFT)) 145762306a36Sopenharmony_ci f2fs_i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT)); 145862306a36Sopenharmony_ci return page; 145962306a36Sopenharmony_ci} 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_cistatic int __allocate_data_block(struct dnode_of_data *dn, int seg_type) 146262306a36Sopenharmony_ci{ 146362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 146462306a36Sopenharmony_ci struct f2fs_summary sum; 146562306a36Sopenharmony_ci struct node_info ni; 146662306a36Sopenharmony_ci block_t old_blkaddr; 146762306a36Sopenharmony_ci blkcnt_t count = 1; 146862306a36Sopenharmony_ci int err; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 147162306a36Sopenharmony_ci return -EPERM; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &ni, false); 147462306a36Sopenharmony_ci if (err) 147562306a36Sopenharmony_ci return err; 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci dn->data_blkaddr = f2fs_data_blkaddr(dn); 147862306a36Sopenharmony_ci if (dn->data_blkaddr == NULL_ADDR) { 147962306a36Sopenharmony_ci err = inc_valid_block_count(sbi, dn->inode, &count, true); 148062306a36Sopenharmony_ci if (unlikely(err)) 148162306a36Sopenharmony_ci return err; 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); 148562306a36Sopenharmony_ci old_blkaddr = dn->data_blkaddr; 148662306a36Sopenharmony_ci f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, 148762306a36Sopenharmony_ci &sum, seg_type, NULL); 148862306a36Sopenharmony_ci if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) 148962306a36Sopenharmony_ci f2fs_invalidate_internal_cache(sbi, old_blkaddr); 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci f2fs_update_data_blkaddr(dn, dn->data_blkaddr); 149262306a36Sopenharmony_ci return 0; 149362306a36Sopenharmony_ci} 149462306a36Sopenharmony_ci 149562306a36Sopenharmony_cistatic void f2fs_map_lock(struct f2fs_sb_info *sbi, int flag) 149662306a36Sopenharmony_ci{ 149762306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) 149862306a36Sopenharmony_ci f2fs_down_read(&sbi->node_change); 149962306a36Sopenharmony_ci else 150062306a36Sopenharmony_ci f2fs_lock_op(sbi); 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic void f2fs_map_unlock(struct f2fs_sb_info *sbi, int flag) 150462306a36Sopenharmony_ci{ 150562306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) 150662306a36Sopenharmony_ci f2fs_up_read(&sbi->node_change); 150762306a36Sopenharmony_ci else 150862306a36Sopenharmony_ci f2fs_unlock_op(sbi); 150962306a36Sopenharmony_ci} 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ciint f2fs_get_block_locked(struct dnode_of_data *dn, pgoff_t index) 151262306a36Sopenharmony_ci{ 151362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 151462306a36Sopenharmony_ci int err = 0; 151562306a36Sopenharmony_ci 151662306a36Sopenharmony_ci f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO); 151762306a36Sopenharmony_ci if (!f2fs_lookup_read_extent_cache_block(dn->inode, index, 151862306a36Sopenharmony_ci &dn->data_blkaddr)) 151962306a36Sopenharmony_ci err = f2fs_reserve_block(dn, index); 152062306a36Sopenharmony_ci f2fs_map_unlock(sbi, F2FS_GET_BLOCK_PRE_AIO); 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci return err; 152362306a36Sopenharmony_ci} 152462306a36Sopenharmony_ci 152562306a36Sopenharmony_cistatic int f2fs_map_no_dnode(struct inode *inode, 152662306a36Sopenharmony_ci struct f2fs_map_blocks *map, struct dnode_of_data *dn, 152762306a36Sopenharmony_ci pgoff_t pgoff) 152862306a36Sopenharmony_ci{ 152962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 153062306a36Sopenharmony_ci 153162306a36Sopenharmony_ci /* 153262306a36Sopenharmony_ci * There is one exceptional case that read_node_page() may return 153362306a36Sopenharmony_ci * -ENOENT due to filesystem has been shutdown or cp_error, return 153462306a36Sopenharmony_ci * -EIO in that case. 153562306a36Sopenharmony_ci */ 153662306a36Sopenharmony_ci if (map->m_may_create && 153762306a36Sopenharmony_ci (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || f2fs_cp_error(sbi))) 153862306a36Sopenharmony_ci return -EIO; 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci if (map->m_next_pgofs) 154162306a36Sopenharmony_ci *map->m_next_pgofs = f2fs_get_next_page_offset(dn, pgoff); 154262306a36Sopenharmony_ci if (map->m_next_extent) 154362306a36Sopenharmony_ci *map->m_next_extent = f2fs_get_next_page_offset(dn, pgoff); 154462306a36Sopenharmony_ci return 0; 154562306a36Sopenharmony_ci} 154662306a36Sopenharmony_ci 154762306a36Sopenharmony_cistatic bool f2fs_map_blocks_cached(struct inode *inode, 154862306a36Sopenharmony_ci struct f2fs_map_blocks *map, int flag) 154962306a36Sopenharmony_ci{ 155062306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 155162306a36Sopenharmony_ci unsigned int maxblocks = map->m_len; 155262306a36Sopenharmony_ci pgoff_t pgoff = (pgoff_t)map->m_lblk; 155362306a36Sopenharmony_ci struct extent_info ei = {}; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci if (!f2fs_lookup_read_extent_cache(inode, pgoff, &ei)) 155662306a36Sopenharmony_ci return false; 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci map->m_pblk = ei.blk + pgoff - ei.fofs; 155962306a36Sopenharmony_ci map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgoff); 156062306a36Sopenharmony_ci map->m_flags = F2FS_MAP_MAPPED; 156162306a36Sopenharmony_ci if (map->m_next_extent) 156262306a36Sopenharmony_ci *map->m_next_extent = pgoff + map->m_len; 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci /* for hardware encryption, but to avoid potential issue in future */ 156562306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_DIO) 156662306a36Sopenharmony_ci f2fs_wait_on_block_writeback_range(inode, 156762306a36Sopenharmony_ci map->m_pblk, map->m_len); 156862306a36Sopenharmony_ci 156962306a36Sopenharmony_ci if (f2fs_allow_multi_device_dio(sbi, flag)) { 157062306a36Sopenharmony_ci int bidx = f2fs_target_device_index(sbi, map->m_pblk); 157162306a36Sopenharmony_ci struct f2fs_dev_info *dev = &sbi->devs[bidx]; 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci map->m_bdev = dev->bdev; 157462306a36Sopenharmony_ci map->m_pblk -= dev->start_blk; 157562306a36Sopenharmony_ci map->m_len = min(map->m_len, dev->end_blk + 1 - map->m_pblk); 157662306a36Sopenharmony_ci } else { 157762306a36Sopenharmony_ci map->m_bdev = inode->i_sb->s_bdev; 157862306a36Sopenharmony_ci } 157962306a36Sopenharmony_ci return true; 158062306a36Sopenharmony_ci} 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci/* 158362306a36Sopenharmony_ci * f2fs_map_blocks() tries to find or build mapping relationship which 158462306a36Sopenharmony_ci * maps continuous logical blocks to physical blocks, and return such 158562306a36Sopenharmony_ci * info via f2fs_map_blocks structure. 158662306a36Sopenharmony_ci */ 158762306a36Sopenharmony_ciint f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) 158862306a36Sopenharmony_ci{ 158962306a36Sopenharmony_ci unsigned int maxblocks = map->m_len; 159062306a36Sopenharmony_ci struct dnode_of_data dn; 159162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 159262306a36Sopenharmony_ci int mode = map->m_may_create ? ALLOC_NODE : LOOKUP_NODE; 159362306a36Sopenharmony_ci pgoff_t pgofs, end_offset, end; 159462306a36Sopenharmony_ci int err = 0, ofs = 1; 159562306a36Sopenharmony_ci unsigned int ofs_in_node, last_ofs_in_node; 159662306a36Sopenharmony_ci blkcnt_t prealloc; 159762306a36Sopenharmony_ci block_t blkaddr; 159862306a36Sopenharmony_ci unsigned int start_pgofs; 159962306a36Sopenharmony_ci int bidx = 0; 160062306a36Sopenharmony_ci bool is_hole; 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci if (!maxblocks) 160362306a36Sopenharmony_ci return 0; 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_ci if (!map->m_may_create && f2fs_map_blocks_cached(inode, map, flag)) 160662306a36Sopenharmony_ci goto out; 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci map->m_bdev = inode->i_sb->s_bdev; 160962306a36Sopenharmony_ci map->m_multidev_dio = 161062306a36Sopenharmony_ci f2fs_allow_multi_device_dio(F2FS_I_SB(inode), flag); 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci map->m_len = 0; 161362306a36Sopenharmony_ci map->m_flags = 0; 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci /* it only supports block size == page size */ 161662306a36Sopenharmony_ci pgofs = (pgoff_t)map->m_lblk; 161762306a36Sopenharmony_ci end = pgofs + maxblocks; 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_cinext_dnode: 162062306a36Sopenharmony_ci if (map->m_may_create) 162162306a36Sopenharmony_ci f2fs_map_lock(sbi, flag); 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci /* When reading holes, we need its node page */ 162462306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 162562306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, pgofs, mode); 162662306a36Sopenharmony_ci if (err) { 162762306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_BMAP) 162862306a36Sopenharmony_ci map->m_pblk = 0; 162962306a36Sopenharmony_ci if (err == -ENOENT) 163062306a36Sopenharmony_ci err = f2fs_map_no_dnode(inode, map, &dn, pgofs); 163162306a36Sopenharmony_ci goto unlock_out; 163262306a36Sopenharmony_ci } 163362306a36Sopenharmony_ci 163462306a36Sopenharmony_ci start_pgofs = pgofs; 163562306a36Sopenharmony_ci prealloc = 0; 163662306a36Sopenharmony_ci last_ofs_in_node = ofs_in_node = dn.ofs_in_node; 163762306a36Sopenharmony_ci end_offset = ADDRS_PER_PAGE(dn.node_page, inode); 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cinext_block: 164062306a36Sopenharmony_ci blkaddr = f2fs_data_blkaddr(&dn); 164162306a36Sopenharmony_ci is_hole = !__is_valid_data_blkaddr(blkaddr); 164262306a36Sopenharmony_ci if (!is_hole && 164362306a36Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) { 164462306a36Sopenharmony_ci err = -EFSCORRUPTED; 164562306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); 164662306a36Sopenharmony_ci goto sync_out; 164762306a36Sopenharmony_ci } 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ci /* use out-place-update for direct IO under LFS mode */ 165062306a36Sopenharmony_ci if (map->m_may_create && 165162306a36Sopenharmony_ci (is_hole || (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO))) { 165262306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 165362306a36Sopenharmony_ci err = -EIO; 165462306a36Sopenharmony_ci goto sync_out; 165562306a36Sopenharmony_ci } 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci switch (flag) { 165862306a36Sopenharmony_ci case F2FS_GET_BLOCK_PRE_AIO: 165962306a36Sopenharmony_ci if (blkaddr == NULL_ADDR) { 166062306a36Sopenharmony_ci prealloc++; 166162306a36Sopenharmony_ci last_ofs_in_node = dn.ofs_in_node; 166262306a36Sopenharmony_ci } 166362306a36Sopenharmony_ci break; 166462306a36Sopenharmony_ci case F2FS_GET_BLOCK_PRE_DIO: 166562306a36Sopenharmony_ci case F2FS_GET_BLOCK_DIO: 166662306a36Sopenharmony_ci err = __allocate_data_block(&dn, map->m_seg_type); 166762306a36Sopenharmony_ci if (err) 166862306a36Sopenharmony_ci goto sync_out; 166962306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_DIO) 167062306a36Sopenharmony_ci file_need_truncate(inode); 167162306a36Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 167262306a36Sopenharmony_ci break; 167362306a36Sopenharmony_ci default: 167462306a36Sopenharmony_ci WARN_ON_ONCE(1); 167562306a36Sopenharmony_ci err = -EIO; 167662306a36Sopenharmony_ci goto sync_out; 167762306a36Sopenharmony_ci } 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci blkaddr = dn.data_blkaddr; 168062306a36Sopenharmony_ci if (is_hole) 168162306a36Sopenharmony_ci map->m_flags |= F2FS_MAP_NEW; 168262306a36Sopenharmony_ci } else if (is_hole) { 168362306a36Sopenharmony_ci if (f2fs_compressed_file(inode) && 168462306a36Sopenharmony_ci f2fs_sanity_check_cluster(&dn) && 168562306a36Sopenharmony_ci (flag != F2FS_GET_BLOCK_FIEMAP || 168662306a36Sopenharmony_ci IS_ENABLED(CONFIG_F2FS_CHECK_FS))) { 168762306a36Sopenharmony_ci err = -EFSCORRUPTED; 168862306a36Sopenharmony_ci f2fs_handle_error(sbi, 168962306a36Sopenharmony_ci ERROR_CORRUPTED_CLUSTER); 169062306a36Sopenharmony_ci goto sync_out; 169162306a36Sopenharmony_ci } 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci switch (flag) { 169462306a36Sopenharmony_ci case F2FS_GET_BLOCK_PRECACHE: 169562306a36Sopenharmony_ci goto sync_out; 169662306a36Sopenharmony_ci case F2FS_GET_BLOCK_BMAP: 169762306a36Sopenharmony_ci map->m_pblk = 0; 169862306a36Sopenharmony_ci goto sync_out; 169962306a36Sopenharmony_ci case F2FS_GET_BLOCK_FIEMAP: 170062306a36Sopenharmony_ci if (blkaddr == NULL_ADDR) { 170162306a36Sopenharmony_ci if (map->m_next_pgofs) 170262306a36Sopenharmony_ci *map->m_next_pgofs = pgofs + 1; 170362306a36Sopenharmony_ci goto sync_out; 170462306a36Sopenharmony_ci } 170562306a36Sopenharmony_ci break; 170662306a36Sopenharmony_ci default: 170762306a36Sopenharmony_ci /* for defragment case */ 170862306a36Sopenharmony_ci if (map->m_next_pgofs) 170962306a36Sopenharmony_ci *map->m_next_pgofs = pgofs + 1; 171062306a36Sopenharmony_ci goto sync_out; 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci } 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) 171562306a36Sopenharmony_ci goto skip; 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci if (map->m_multidev_dio) 171862306a36Sopenharmony_ci bidx = f2fs_target_device_index(sbi, blkaddr); 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (map->m_len == 0) { 172162306a36Sopenharmony_ci /* reserved delalloc block should be mapped for fiemap. */ 172262306a36Sopenharmony_ci if (blkaddr == NEW_ADDR) 172362306a36Sopenharmony_ci map->m_flags |= F2FS_MAP_DELALLOC; 172462306a36Sopenharmony_ci map->m_flags |= F2FS_MAP_MAPPED; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci map->m_pblk = blkaddr; 172762306a36Sopenharmony_ci map->m_len = 1; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci if (map->m_multidev_dio) 173062306a36Sopenharmony_ci map->m_bdev = FDEV(bidx).bdev; 173162306a36Sopenharmony_ci } else if ((map->m_pblk != NEW_ADDR && 173262306a36Sopenharmony_ci blkaddr == (map->m_pblk + ofs)) || 173362306a36Sopenharmony_ci (map->m_pblk == NEW_ADDR && blkaddr == NEW_ADDR) || 173462306a36Sopenharmony_ci flag == F2FS_GET_BLOCK_PRE_DIO) { 173562306a36Sopenharmony_ci if (map->m_multidev_dio && map->m_bdev != FDEV(bidx).bdev) 173662306a36Sopenharmony_ci goto sync_out; 173762306a36Sopenharmony_ci ofs++; 173862306a36Sopenharmony_ci map->m_len++; 173962306a36Sopenharmony_ci } else { 174062306a36Sopenharmony_ci goto sync_out; 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci 174362306a36Sopenharmony_ciskip: 174462306a36Sopenharmony_ci dn.ofs_in_node++; 174562306a36Sopenharmony_ci pgofs++; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci /* preallocate blocks in batch for one dnode page */ 174862306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO && 174962306a36Sopenharmony_ci (pgofs == end || dn.ofs_in_node == end_offset)) { 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci dn.ofs_in_node = ofs_in_node; 175262306a36Sopenharmony_ci err = f2fs_reserve_new_blocks(&dn, prealloc); 175362306a36Sopenharmony_ci if (err) 175462306a36Sopenharmony_ci goto sync_out; 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci map->m_len += dn.ofs_in_node - ofs_in_node; 175762306a36Sopenharmony_ci if (prealloc && dn.ofs_in_node != last_ofs_in_node + 1) { 175862306a36Sopenharmony_ci err = -ENOSPC; 175962306a36Sopenharmony_ci goto sync_out; 176062306a36Sopenharmony_ci } 176162306a36Sopenharmony_ci dn.ofs_in_node = end_offset; 176262306a36Sopenharmony_ci } 176362306a36Sopenharmony_ci 176462306a36Sopenharmony_ci if (pgofs >= end) 176562306a36Sopenharmony_ci goto sync_out; 176662306a36Sopenharmony_ci else if (dn.ofs_in_node < end_offset) 176762306a36Sopenharmony_ci goto next_block; 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRECACHE) { 177062306a36Sopenharmony_ci if (map->m_flags & F2FS_MAP_MAPPED) { 177162306a36Sopenharmony_ci unsigned int ofs = start_pgofs - map->m_lblk; 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_ci f2fs_update_read_extent_cache_range(&dn, 177462306a36Sopenharmony_ci start_pgofs, map->m_pblk + ofs, 177562306a36Sopenharmony_ci map->m_len - ofs); 177662306a36Sopenharmony_ci } 177762306a36Sopenharmony_ci } 177862306a36Sopenharmony_ci 177962306a36Sopenharmony_ci f2fs_put_dnode(&dn); 178062306a36Sopenharmony_ci 178162306a36Sopenharmony_ci if (map->m_may_create) { 178262306a36Sopenharmony_ci f2fs_map_unlock(sbi, flag); 178362306a36Sopenharmony_ci f2fs_balance_fs(sbi, dn.node_changed); 178462306a36Sopenharmony_ci } 178562306a36Sopenharmony_ci goto next_dnode; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_cisync_out: 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_DIO && map->m_flags & F2FS_MAP_MAPPED) { 179062306a36Sopenharmony_ci /* 179162306a36Sopenharmony_ci * for hardware encryption, but to avoid potential issue 179262306a36Sopenharmony_ci * in future 179362306a36Sopenharmony_ci */ 179462306a36Sopenharmony_ci f2fs_wait_on_block_writeback_range(inode, 179562306a36Sopenharmony_ci map->m_pblk, map->m_len); 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci if (map->m_multidev_dio) { 179862306a36Sopenharmony_ci block_t blk_addr = map->m_pblk; 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci bidx = f2fs_target_device_index(sbi, map->m_pblk); 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_ci map->m_bdev = FDEV(bidx).bdev; 180362306a36Sopenharmony_ci map->m_pblk -= FDEV(bidx).start_blk; 180462306a36Sopenharmony_ci 180562306a36Sopenharmony_ci if (map->m_may_create) 180662306a36Sopenharmony_ci f2fs_update_device_state(sbi, inode->i_ino, 180762306a36Sopenharmony_ci blk_addr, map->m_len); 180862306a36Sopenharmony_ci 180962306a36Sopenharmony_ci f2fs_bug_on(sbi, blk_addr + map->m_len > 181062306a36Sopenharmony_ci FDEV(bidx).end_blk + 1); 181162306a36Sopenharmony_ci } 181262306a36Sopenharmony_ci } 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRECACHE) { 181562306a36Sopenharmony_ci if (map->m_flags & F2FS_MAP_MAPPED) { 181662306a36Sopenharmony_ci unsigned int ofs = start_pgofs - map->m_lblk; 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci f2fs_update_read_extent_cache_range(&dn, 181962306a36Sopenharmony_ci start_pgofs, map->m_pblk + ofs, 182062306a36Sopenharmony_ci map->m_len - ofs); 182162306a36Sopenharmony_ci } 182262306a36Sopenharmony_ci if (map->m_next_extent) 182362306a36Sopenharmony_ci *map->m_next_extent = pgofs + 1; 182462306a36Sopenharmony_ci } 182562306a36Sopenharmony_ci f2fs_put_dnode(&dn); 182662306a36Sopenharmony_ciunlock_out: 182762306a36Sopenharmony_ci if (map->m_may_create) { 182862306a36Sopenharmony_ci f2fs_map_unlock(sbi, flag); 182962306a36Sopenharmony_ci f2fs_balance_fs(sbi, dn.node_changed); 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ciout: 183262306a36Sopenharmony_ci trace_f2fs_map_blocks(inode, map, flag, err); 183362306a36Sopenharmony_ci return err; 183462306a36Sopenharmony_ci} 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_cibool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len) 183762306a36Sopenharmony_ci{ 183862306a36Sopenharmony_ci struct f2fs_map_blocks map; 183962306a36Sopenharmony_ci block_t last_lblk; 184062306a36Sopenharmony_ci int err; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci if (pos + len > i_size_read(inode)) 184362306a36Sopenharmony_ci return false; 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci map.m_lblk = F2FS_BYTES_TO_BLK(pos); 184662306a36Sopenharmony_ci map.m_next_pgofs = NULL; 184762306a36Sopenharmony_ci map.m_next_extent = NULL; 184862306a36Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 184962306a36Sopenharmony_ci map.m_may_create = false; 185062306a36Sopenharmony_ci last_lblk = F2FS_BLK_ALIGN(pos + len); 185162306a36Sopenharmony_ci 185262306a36Sopenharmony_ci while (map.m_lblk < last_lblk) { 185362306a36Sopenharmony_ci map.m_len = last_lblk - map.m_lblk; 185462306a36Sopenharmony_ci err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DEFAULT); 185562306a36Sopenharmony_ci if (err || map.m_len == 0) 185662306a36Sopenharmony_ci return false; 185762306a36Sopenharmony_ci map.m_lblk += map.m_len; 185862306a36Sopenharmony_ci } 185962306a36Sopenharmony_ci return true; 186062306a36Sopenharmony_ci} 186162306a36Sopenharmony_ci 186262306a36Sopenharmony_cistatic inline u64 bytes_to_blks(struct inode *inode, u64 bytes) 186362306a36Sopenharmony_ci{ 186462306a36Sopenharmony_ci return (bytes >> inode->i_blkbits); 186562306a36Sopenharmony_ci} 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_cistatic inline u64 blks_to_bytes(struct inode *inode, u64 blks) 186862306a36Sopenharmony_ci{ 186962306a36Sopenharmony_ci return (blks << inode->i_blkbits); 187062306a36Sopenharmony_ci} 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_cistatic int f2fs_xattr_fiemap(struct inode *inode, 187362306a36Sopenharmony_ci struct fiemap_extent_info *fieinfo) 187462306a36Sopenharmony_ci{ 187562306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 187662306a36Sopenharmony_ci struct page *page; 187762306a36Sopenharmony_ci struct node_info ni; 187862306a36Sopenharmony_ci __u64 phys = 0, len; 187962306a36Sopenharmony_ci __u32 flags; 188062306a36Sopenharmony_ci nid_t xnid = F2FS_I(inode)->i_xattr_nid; 188162306a36Sopenharmony_ci int err = 0; 188262306a36Sopenharmony_ci 188362306a36Sopenharmony_ci if (f2fs_has_inline_xattr(inode)) { 188462306a36Sopenharmony_ci int offset; 188562306a36Sopenharmony_ci 188662306a36Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), 188762306a36Sopenharmony_ci inode->i_ino, false); 188862306a36Sopenharmony_ci if (!page) 188962306a36Sopenharmony_ci return -ENOMEM; 189062306a36Sopenharmony_ci 189162306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, inode->i_ino, &ni, false); 189262306a36Sopenharmony_ci if (err) { 189362306a36Sopenharmony_ci f2fs_put_page(page, 1); 189462306a36Sopenharmony_ci return err; 189562306a36Sopenharmony_ci } 189662306a36Sopenharmony_ci 189762306a36Sopenharmony_ci phys = blks_to_bytes(inode, ni.blk_addr); 189862306a36Sopenharmony_ci offset = offsetof(struct f2fs_inode, i_addr) + 189962306a36Sopenharmony_ci sizeof(__le32) * (DEF_ADDRS_PER_INODE - 190062306a36Sopenharmony_ci get_inline_xattr_addrs(inode)); 190162306a36Sopenharmony_ci 190262306a36Sopenharmony_ci phys += offset; 190362306a36Sopenharmony_ci len = inline_xattr_size(inode); 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci f2fs_put_page(page, 1); 190662306a36Sopenharmony_ci 190762306a36Sopenharmony_ci flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED; 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci if (!xnid) 191062306a36Sopenharmony_ci flags |= FIEMAP_EXTENT_LAST; 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); 191362306a36Sopenharmony_ci trace_f2fs_fiemap(inode, 0, phys, len, flags, err); 191462306a36Sopenharmony_ci if (err) 191562306a36Sopenharmony_ci return err; 191662306a36Sopenharmony_ci } 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci if (xnid) { 191962306a36Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false); 192062306a36Sopenharmony_ci if (!page) 192162306a36Sopenharmony_ci return -ENOMEM; 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci err = f2fs_get_node_info(sbi, xnid, &ni, false); 192462306a36Sopenharmony_ci if (err) { 192562306a36Sopenharmony_ci f2fs_put_page(page, 1); 192662306a36Sopenharmony_ci return err; 192762306a36Sopenharmony_ci } 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci phys = blks_to_bytes(inode, ni.blk_addr); 193062306a36Sopenharmony_ci len = inode->i_sb->s_blocksize; 193162306a36Sopenharmony_ci 193262306a36Sopenharmony_ci f2fs_put_page(page, 1); 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci flags = FIEMAP_EXTENT_LAST; 193562306a36Sopenharmony_ci } 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci if (phys) { 193862306a36Sopenharmony_ci err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); 193962306a36Sopenharmony_ci trace_f2fs_fiemap(inode, 0, phys, len, flags, err); 194062306a36Sopenharmony_ci } 194162306a36Sopenharmony_ci 194262306a36Sopenharmony_ci return (err < 0 ? err : 0); 194362306a36Sopenharmony_ci} 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_cistatic loff_t max_inode_blocks(struct inode *inode) 194662306a36Sopenharmony_ci{ 194762306a36Sopenharmony_ci loff_t result = ADDRS_PER_INODE(inode); 194862306a36Sopenharmony_ci loff_t leaf_count = ADDRS_PER_BLOCK(inode); 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci /* two direct node blocks */ 195162306a36Sopenharmony_ci result += (leaf_count * 2); 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_ci /* two indirect node blocks */ 195462306a36Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 195562306a36Sopenharmony_ci result += (leaf_count * 2); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci /* one double indirect node block */ 195862306a36Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 195962306a36Sopenharmony_ci result += leaf_count; 196062306a36Sopenharmony_ci 196162306a36Sopenharmony_ci return result; 196262306a36Sopenharmony_ci} 196362306a36Sopenharmony_ci 196462306a36Sopenharmony_ciint f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 196562306a36Sopenharmony_ci u64 start, u64 len) 196662306a36Sopenharmony_ci{ 196762306a36Sopenharmony_ci struct f2fs_map_blocks map; 196862306a36Sopenharmony_ci sector_t start_blk, last_blk; 196962306a36Sopenharmony_ci pgoff_t next_pgofs; 197062306a36Sopenharmony_ci u64 logical = 0, phys = 0, size = 0; 197162306a36Sopenharmony_ci u32 flags = 0; 197262306a36Sopenharmony_ci int ret = 0; 197362306a36Sopenharmony_ci bool compr_cluster = false, compr_appended; 197462306a36Sopenharmony_ci unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; 197562306a36Sopenharmony_ci unsigned int count_in_cluster = 0; 197662306a36Sopenharmony_ci loff_t maxbytes; 197762306a36Sopenharmony_ci 197862306a36Sopenharmony_ci if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { 197962306a36Sopenharmony_ci ret = f2fs_precache_extents(inode); 198062306a36Sopenharmony_ci if (ret) 198162306a36Sopenharmony_ci return ret; 198262306a36Sopenharmony_ci } 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ci ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_XATTR); 198562306a36Sopenharmony_ci if (ret) 198662306a36Sopenharmony_ci return ret; 198762306a36Sopenharmony_ci 198862306a36Sopenharmony_ci inode_lock(inode); 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci maxbytes = max_file_blocks(inode) << F2FS_BLKSIZE_BITS; 199162306a36Sopenharmony_ci if (start > maxbytes) { 199262306a36Sopenharmony_ci ret = -EFBIG; 199362306a36Sopenharmony_ci goto out; 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci 199662306a36Sopenharmony_ci if (len > maxbytes || (maxbytes - len) < start) 199762306a36Sopenharmony_ci len = maxbytes - start; 199862306a36Sopenharmony_ci 199962306a36Sopenharmony_ci if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { 200062306a36Sopenharmony_ci ret = f2fs_xattr_fiemap(inode, fieinfo); 200162306a36Sopenharmony_ci goto out; 200262306a36Sopenharmony_ci } 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) { 200562306a36Sopenharmony_ci ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); 200662306a36Sopenharmony_ci if (ret != -EAGAIN) 200762306a36Sopenharmony_ci goto out; 200862306a36Sopenharmony_ci } 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci if (bytes_to_blks(inode, len) == 0) 201162306a36Sopenharmony_ci len = blks_to_bytes(inode, 1); 201262306a36Sopenharmony_ci 201362306a36Sopenharmony_ci start_blk = bytes_to_blks(inode, start); 201462306a36Sopenharmony_ci last_blk = bytes_to_blks(inode, start + len - 1); 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_cinext: 201762306a36Sopenharmony_ci memset(&map, 0, sizeof(map)); 201862306a36Sopenharmony_ci map.m_lblk = start_blk; 201962306a36Sopenharmony_ci map.m_len = bytes_to_blks(inode, len); 202062306a36Sopenharmony_ci map.m_next_pgofs = &next_pgofs; 202162306a36Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 202262306a36Sopenharmony_ci 202362306a36Sopenharmony_ci if (compr_cluster) { 202462306a36Sopenharmony_ci map.m_lblk += 1; 202562306a36Sopenharmony_ci map.m_len = cluster_size - count_in_cluster; 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci ret = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); 202962306a36Sopenharmony_ci if (ret) 203062306a36Sopenharmony_ci goto out; 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci /* HOLE */ 203362306a36Sopenharmony_ci if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) { 203462306a36Sopenharmony_ci start_blk = next_pgofs; 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode, 203762306a36Sopenharmony_ci max_inode_blocks(inode))) 203862306a36Sopenharmony_ci goto prep_next; 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci flags |= FIEMAP_EXTENT_LAST; 204162306a36Sopenharmony_ci } 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_ci compr_appended = false; 204462306a36Sopenharmony_ci /* In a case of compressed cluster, append this to the last extent */ 204562306a36Sopenharmony_ci if (compr_cluster && ((map.m_flags & F2FS_MAP_DELALLOC) || 204662306a36Sopenharmony_ci !(map.m_flags & F2FS_MAP_FLAGS))) { 204762306a36Sopenharmony_ci compr_appended = true; 204862306a36Sopenharmony_ci goto skip_fill; 204962306a36Sopenharmony_ci } 205062306a36Sopenharmony_ci 205162306a36Sopenharmony_ci if (size) { 205262306a36Sopenharmony_ci flags |= FIEMAP_EXTENT_MERGED; 205362306a36Sopenharmony_ci if (IS_ENCRYPTED(inode)) 205462306a36Sopenharmony_ci flags |= FIEMAP_EXTENT_DATA_ENCRYPTED; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci ret = fiemap_fill_next_extent(fieinfo, logical, 205762306a36Sopenharmony_ci phys, size, flags); 205862306a36Sopenharmony_ci trace_f2fs_fiemap(inode, logical, phys, size, flags, ret); 205962306a36Sopenharmony_ci if (ret) 206062306a36Sopenharmony_ci goto out; 206162306a36Sopenharmony_ci size = 0; 206262306a36Sopenharmony_ci } 206362306a36Sopenharmony_ci 206462306a36Sopenharmony_ci if (start_blk > last_blk) 206562306a36Sopenharmony_ci goto out; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ciskip_fill: 206862306a36Sopenharmony_ci if (map.m_pblk == COMPRESS_ADDR) { 206962306a36Sopenharmony_ci compr_cluster = true; 207062306a36Sopenharmony_ci count_in_cluster = 1; 207162306a36Sopenharmony_ci } else if (compr_appended) { 207262306a36Sopenharmony_ci unsigned int appended_blks = cluster_size - 207362306a36Sopenharmony_ci count_in_cluster + 1; 207462306a36Sopenharmony_ci size += blks_to_bytes(inode, appended_blks); 207562306a36Sopenharmony_ci start_blk += appended_blks; 207662306a36Sopenharmony_ci compr_cluster = false; 207762306a36Sopenharmony_ci } else { 207862306a36Sopenharmony_ci logical = blks_to_bytes(inode, start_blk); 207962306a36Sopenharmony_ci phys = __is_valid_data_blkaddr(map.m_pblk) ? 208062306a36Sopenharmony_ci blks_to_bytes(inode, map.m_pblk) : 0; 208162306a36Sopenharmony_ci size = blks_to_bytes(inode, map.m_len); 208262306a36Sopenharmony_ci flags = 0; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci if (compr_cluster) { 208562306a36Sopenharmony_ci flags = FIEMAP_EXTENT_ENCODED; 208662306a36Sopenharmony_ci count_in_cluster += map.m_len; 208762306a36Sopenharmony_ci if (count_in_cluster == cluster_size) { 208862306a36Sopenharmony_ci compr_cluster = false; 208962306a36Sopenharmony_ci size += blks_to_bytes(inode, 1); 209062306a36Sopenharmony_ci } 209162306a36Sopenharmony_ci } else if (map.m_flags & F2FS_MAP_DELALLOC) { 209262306a36Sopenharmony_ci flags = FIEMAP_EXTENT_UNWRITTEN; 209362306a36Sopenharmony_ci } 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci start_blk += bytes_to_blks(inode, size); 209662306a36Sopenharmony_ci } 209762306a36Sopenharmony_ci 209862306a36Sopenharmony_ciprep_next: 209962306a36Sopenharmony_ci cond_resched(); 210062306a36Sopenharmony_ci if (fatal_signal_pending(current)) 210162306a36Sopenharmony_ci ret = -EINTR; 210262306a36Sopenharmony_ci else 210362306a36Sopenharmony_ci goto next; 210462306a36Sopenharmony_ciout: 210562306a36Sopenharmony_ci if (ret == 1) 210662306a36Sopenharmony_ci ret = 0; 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci inode_unlock(inode); 210962306a36Sopenharmony_ci return ret; 211062306a36Sopenharmony_ci} 211162306a36Sopenharmony_ci 211262306a36Sopenharmony_cistatic inline loff_t f2fs_readpage_limit(struct inode *inode) 211362306a36Sopenharmony_ci{ 211462306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode)) 211562306a36Sopenharmony_ci return inode->i_sb->s_maxbytes; 211662306a36Sopenharmony_ci 211762306a36Sopenharmony_ci return i_size_read(inode); 211862306a36Sopenharmony_ci} 211962306a36Sopenharmony_ci 212062306a36Sopenharmony_cistatic int f2fs_read_single_page(struct inode *inode, struct page *page, 212162306a36Sopenharmony_ci unsigned nr_pages, 212262306a36Sopenharmony_ci struct f2fs_map_blocks *map, 212362306a36Sopenharmony_ci struct bio **bio_ret, 212462306a36Sopenharmony_ci sector_t *last_block_in_bio, 212562306a36Sopenharmony_ci bool is_readahead) 212662306a36Sopenharmony_ci{ 212762306a36Sopenharmony_ci struct bio *bio = *bio_ret; 212862306a36Sopenharmony_ci const unsigned blocksize = blks_to_bytes(inode, 1); 212962306a36Sopenharmony_ci sector_t block_in_file; 213062306a36Sopenharmony_ci sector_t last_block; 213162306a36Sopenharmony_ci sector_t last_block_in_file; 213262306a36Sopenharmony_ci sector_t block_nr; 213362306a36Sopenharmony_ci int ret = 0; 213462306a36Sopenharmony_ci 213562306a36Sopenharmony_ci block_in_file = (sector_t)page_index(page); 213662306a36Sopenharmony_ci last_block = block_in_file + nr_pages; 213762306a36Sopenharmony_ci last_block_in_file = bytes_to_blks(inode, 213862306a36Sopenharmony_ci f2fs_readpage_limit(inode) + blocksize - 1); 213962306a36Sopenharmony_ci if (last_block > last_block_in_file) 214062306a36Sopenharmony_ci last_block = last_block_in_file; 214162306a36Sopenharmony_ci 214262306a36Sopenharmony_ci /* just zeroing out page which is beyond EOF */ 214362306a36Sopenharmony_ci if (block_in_file >= last_block) 214462306a36Sopenharmony_ci goto zero_out; 214562306a36Sopenharmony_ci /* 214662306a36Sopenharmony_ci * Map blocks using the previous result first. 214762306a36Sopenharmony_ci */ 214862306a36Sopenharmony_ci if ((map->m_flags & F2FS_MAP_MAPPED) && 214962306a36Sopenharmony_ci block_in_file > map->m_lblk && 215062306a36Sopenharmony_ci block_in_file < (map->m_lblk + map->m_len)) 215162306a36Sopenharmony_ci goto got_it; 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci /* 215462306a36Sopenharmony_ci * Then do more f2fs_map_blocks() calls until we are 215562306a36Sopenharmony_ci * done with this page. 215662306a36Sopenharmony_ci */ 215762306a36Sopenharmony_ci map->m_lblk = block_in_file; 215862306a36Sopenharmony_ci map->m_len = last_block - block_in_file; 215962306a36Sopenharmony_ci 216062306a36Sopenharmony_ci ret = f2fs_map_blocks(inode, map, F2FS_GET_BLOCK_DEFAULT); 216162306a36Sopenharmony_ci if (ret) 216262306a36Sopenharmony_ci goto out; 216362306a36Sopenharmony_cigot_it: 216462306a36Sopenharmony_ci if ((map->m_flags & F2FS_MAP_MAPPED)) { 216562306a36Sopenharmony_ci block_nr = map->m_pblk + block_in_file - map->m_lblk; 216662306a36Sopenharmony_ci SetPageMappedToDisk(page); 216762306a36Sopenharmony_ci 216862306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr, 216962306a36Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 217062306a36Sopenharmony_ci ret = -EFSCORRUPTED; 217162306a36Sopenharmony_ci f2fs_handle_error(F2FS_I_SB(inode), 217262306a36Sopenharmony_ci ERROR_INVALID_BLKADDR); 217362306a36Sopenharmony_ci goto out; 217462306a36Sopenharmony_ci } 217562306a36Sopenharmony_ci } else { 217662306a36Sopenharmony_cizero_out: 217762306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 217862306a36Sopenharmony_ci if (f2fs_need_verity(inode, page->index) && 217962306a36Sopenharmony_ci !fsverity_verify_page(page)) { 218062306a36Sopenharmony_ci ret = -EIO; 218162306a36Sopenharmony_ci goto out; 218262306a36Sopenharmony_ci } 218362306a36Sopenharmony_ci if (!PageUptodate(page)) 218462306a36Sopenharmony_ci SetPageUptodate(page); 218562306a36Sopenharmony_ci unlock_page(page); 218662306a36Sopenharmony_ci goto out; 218762306a36Sopenharmony_ci } 218862306a36Sopenharmony_ci 218962306a36Sopenharmony_ci /* 219062306a36Sopenharmony_ci * This page will go to BIO. Do we need to send this 219162306a36Sopenharmony_ci * BIO off first? 219262306a36Sopenharmony_ci */ 219362306a36Sopenharmony_ci if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio, 219462306a36Sopenharmony_ci *last_block_in_bio, block_nr) || 219562306a36Sopenharmony_ci !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { 219662306a36Sopenharmony_cisubmit_and_realloc: 219762306a36Sopenharmony_ci f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA); 219862306a36Sopenharmony_ci bio = NULL; 219962306a36Sopenharmony_ci } 220062306a36Sopenharmony_ci if (bio == NULL) { 220162306a36Sopenharmony_ci bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, 220262306a36Sopenharmony_ci is_readahead ? REQ_RAHEAD : 0, page->index, 220362306a36Sopenharmony_ci false); 220462306a36Sopenharmony_ci if (IS_ERR(bio)) { 220562306a36Sopenharmony_ci ret = PTR_ERR(bio); 220662306a36Sopenharmony_ci bio = NULL; 220762306a36Sopenharmony_ci goto out; 220862306a36Sopenharmony_ci } 220962306a36Sopenharmony_ci } 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci /* 221262306a36Sopenharmony_ci * If the page is under writeback, we need to wait for 221362306a36Sopenharmony_ci * its completion to see the correct decrypted data. 221462306a36Sopenharmony_ci */ 221562306a36Sopenharmony_ci f2fs_wait_on_block_writeback(inode, block_nr); 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_ci if (bio_add_page(bio, page, blocksize, 0) < blocksize) 221862306a36Sopenharmony_ci goto submit_and_realloc; 221962306a36Sopenharmony_ci 222062306a36Sopenharmony_ci inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); 222162306a36Sopenharmony_ci f2fs_update_iostat(F2FS_I_SB(inode), NULL, FS_DATA_READ_IO, 222262306a36Sopenharmony_ci F2FS_BLKSIZE); 222362306a36Sopenharmony_ci *last_block_in_bio = block_nr; 222462306a36Sopenharmony_ciout: 222562306a36Sopenharmony_ci *bio_ret = bio; 222662306a36Sopenharmony_ci return ret; 222762306a36Sopenharmony_ci} 222862306a36Sopenharmony_ci 222962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 223062306a36Sopenharmony_ciint f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, 223162306a36Sopenharmony_ci unsigned nr_pages, sector_t *last_block_in_bio, 223262306a36Sopenharmony_ci bool is_readahead, bool for_write) 223362306a36Sopenharmony_ci{ 223462306a36Sopenharmony_ci struct dnode_of_data dn; 223562306a36Sopenharmony_ci struct inode *inode = cc->inode; 223662306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 223762306a36Sopenharmony_ci struct bio *bio = *bio_ret; 223862306a36Sopenharmony_ci unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size; 223962306a36Sopenharmony_ci sector_t last_block_in_file; 224062306a36Sopenharmony_ci const unsigned blocksize = blks_to_bytes(inode, 1); 224162306a36Sopenharmony_ci struct decompress_io_ctx *dic = NULL; 224262306a36Sopenharmony_ci struct extent_info ei = {}; 224362306a36Sopenharmony_ci bool from_dnode = true; 224462306a36Sopenharmony_ci int i; 224562306a36Sopenharmony_ci int ret = 0; 224662306a36Sopenharmony_ci 224762306a36Sopenharmony_ci f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc)); 224862306a36Sopenharmony_ci 224962306a36Sopenharmony_ci last_block_in_file = bytes_to_blks(inode, 225062306a36Sopenharmony_ci f2fs_readpage_limit(inode) + blocksize - 1); 225162306a36Sopenharmony_ci 225262306a36Sopenharmony_ci /* get rid of pages beyond EOF */ 225362306a36Sopenharmony_ci for (i = 0; i < cc->cluster_size; i++) { 225462306a36Sopenharmony_ci struct page *page = cc->rpages[i]; 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci if (!page) 225762306a36Sopenharmony_ci continue; 225862306a36Sopenharmony_ci if ((sector_t)page->index >= last_block_in_file) { 225962306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 226062306a36Sopenharmony_ci if (!PageUptodate(page)) 226162306a36Sopenharmony_ci SetPageUptodate(page); 226262306a36Sopenharmony_ci } else if (!PageUptodate(page)) { 226362306a36Sopenharmony_ci continue; 226462306a36Sopenharmony_ci } 226562306a36Sopenharmony_ci unlock_page(page); 226662306a36Sopenharmony_ci if (for_write) 226762306a36Sopenharmony_ci put_page(page); 226862306a36Sopenharmony_ci cc->rpages[i] = NULL; 226962306a36Sopenharmony_ci cc->nr_rpages--; 227062306a36Sopenharmony_ci } 227162306a36Sopenharmony_ci 227262306a36Sopenharmony_ci /* we are done since all pages are beyond EOF */ 227362306a36Sopenharmony_ci if (f2fs_cluster_is_empty(cc)) 227462306a36Sopenharmony_ci goto out; 227562306a36Sopenharmony_ci 227662306a36Sopenharmony_ci if (f2fs_lookup_read_extent_cache(inode, start_idx, &ei)) 227762306a36Sopenharmony_ci from_dnode = false; 227862306a36Sopenharmony_ci 227962306a36Sopenharmony_ci if (!from_dnode) 228062306a36Sopenharmony_ci goto skip_reading_dnode; 228162306a36Sopenharmony_ci 228262306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 228362306a36Sopenharmony_ci ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); 228462306a36Sopenharmony_ci if (ret) 228562306a36Sopenharmony_ci goto out; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 228862306a36Sopenharmony_ci ret = -EIO; 228962306a36Sopenharmony_ci goto out_put_dnode; 229062306a36Sopenharmony_ci } 229162306a36Sopenharmony_ci f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); 229262306a36Sopenharmony_ci 229362306a36Sopenharmony_ciskip_reading_dnode: 229462306a36Sopenharmony_ci for (i = 1; i < cc->cluster_size; i++) { 229562306a36Sopenharmony_ci block_t blkaddr; 229662306a36Sopenharmony_ci 229762306a36Sopenharmony_ci blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page, 229862306a36Sopenharmony_ci dn.ofs_in_node + i) : 229962306a36Sopenharmony_ci ei.blk + i - 1; 230062306a36Sopenharmony_ci 230162306a36Sopenharmony_ci if (!__is_valid_data_blkaddr(blkaddr)) 230262306a36Sopenharmony_ci break; 230362306a36Sopenharmony_ci 230462306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) { 230562306a36Sopenharmony_ci ret = -EFAULT; 230662306a36Sopenharmony_ci goto out_put_dnode; 230762306a36Sopenharmony_ci } 230862306a36Sopenharmony_ci cc->nr_cpages++; 230962306a36Sopenharmony_ci 231062306a36Sopenharmony_ci if (!from_dnode && i >= ei.c_len) 231162306a36Sopenharmony_ci break; 231262306a36Sopenharmony_ci } 231362306a36Sopenharmony_ci 231462306a36Sopenharmony_ci /* nothing to decompress */ 231562306a36Sopenharmony_ci if (cc->nr_cpages == 0) { 231662306a36Sopenharmony_ci ret = 0; 231762306a36Sopenharmony_ci goto out_put_dnode; 231862306a36Sopenharmony_ci } 231962306a36Sopenharmony_ci 232062306a36Sopenharmony_ci dic = f2fs_alloc_dic(cc); 232162306a36Sopenharmony_ci if (IS_ERR(dic)) { 232262306a36Sopenharmony_ci ret = PTR_ERR(dic); 232362306a36Sopenharmony_ci goto out_put_dnode; 232462306a36Sopenharmony_ci } 232562306a36Sopenharmony_ci 232662306a36Sopenharmony_ci for (i = 0; i < cc->nr_cpages; i++) { 232762306a36Sopenharmony_ci struct page *page = dic->cpages[i]; 232862306a36Sopenharmony_ci block_t blkaddr; 232962306a36Sopenharmony_ci struct bio_post_read_ctx *ctx; 233062306a36Sopenharmony_ci 233162306a36Sopenharmony_ci blkaddr = from_dnode ? data_blkaddr(dn.inode, dn.node_page, 233262306a36Sopenharmony_ci dn.ofs_in_node + i + 1) : 233362306a36Sopenharmony_ci ei.blk + i; 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci f2fs_wait_on_block_writeback(inode, blkaddr); 233662306a36Sopenharmony_ci 233762306a36Sopenharmony_ci if (f2fs_load_compressed_page(sbi, page, blkaddr)) { 233862306a36Sopenharmony_ci if (atomic_dec_and_test(&dic->remaining_pages)) { 233962306a36Sopenharmony_ci f2fs_decompress_cluster(dic, true); 234062306a36Sopenharmony_ci break; 234162306a36Sopenharmony_ci } 234262306a36Sopenharmony_ci continue; 234362306a36Sopenharmony_ci } 234462306a36Sopenharmony_ci 234562306a36Sopenharmony_ci if (bio && (!page_is_mergeable(sbi, bio, 234662306a36Sopenharmony_ci *last_block_in_bio, blkaddr) || 234762306a36Sopenharmony_ci !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { 234862306a36Sopenharmony_cisubmit_and_realloc: 234962306a36Sopenharmony_ci f2fs_submit_read_bio(sbi, bio, DATA); 235062306a36Sopenharmony_ci bio = NULL; 235162306a36Sopenharmony_ci } 235262306a36Sopenharmony_ci 235362306a36Sopenharmony_ci if (!bio) { 235462306a36Sopenharmony_ci bio = f2fs_grab_read_bio(inode, blkaddr, nr_pages, 235562306a36Sopenharmony_ci is_readahead ? REQ_RAHEAD : 0, 235662306a36Sopenharmony_ci page->index, for_write); 235762306a36Sopenharmony_ci if (IS_ERR(bio)) { 235862306a36Sopenharmony_ci ret = PTR_ERR(bio); 235962306a36Sopenharmony_ci f2fs_decompress_end_io(dic, ret, true); 236062306a36Sopenharmony_ci f2fs_put_dnode(&dn); 236162306a36Sopenharmony_ci *bio_ret = NULL; 236262306a36Sopenharmony_ci return ret; 236362306a36Sopenharmony_ci } 236462306a36Sopenharmony_ci } 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci if (bio_add_page(bio, page, blocksize, 0) < blocksize) 236762306a36Sopenharmony_ci goto submit_and_realloc; 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci ctx = get_post_read_ctx(bio); 237062306a36Sopenharmony_ci ctx->enabled_steps |= STEP_DECOMPRESS; 237162306a36Sopenharmony_ci refcount_inc(&dic->refcnt); 237262306a36Sopenharmony_ci 237362306a36Sopenharmony_ci inc_page_count(sbi, F2FS_RD_DATA); 237462306a36Sopenharmony_ci f2fs_update_iostat(sbi, inode, FS_DATA_READ_IO, F2FS_BLKSIZE); 237562306a36Sopenharmony_ci *last_block_in_bio = blkaddr; 237662306a36Sopenharmony_ci } 237762306a36Sopenharmony_ci 237862306a36Sopenharmony_ci if (from_dnode) 237962306a36Sopenharmony_ci f2fs_put_dnode(&dn); 238062306a36Sopenharmony_ci 238162306a36Sopenharmony_ci *bio_ret = bio; 238262306a36Sopenharmony_ci return 0; 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ciout_put_dnode: 238562306a36Sopenharmony_ci if (from_dnode) 238662306a36Sopenharmony_ci f2fs_put_dnode(&dn); 238762306a36Sopenharmony_ciout: 238862306a36Sopenharmony_ci for (i = 0; i < cc->cluster_size; i++) { 238962306a36Sopenharmony_ci if (cc->rpages[i]) { 239062306a36Sopenharmony_ci ClearPageUptodate(cc->rpages[i]); 239162306a36Sopenharmony_ci unlock_page(cc->rpages[i]); 239262306a36Sopenharmony_ci } 239362306a36Sopenharmony_ci } 239462306a36Sopenharmony_ci *bio_ret = bio; 239562306a36Sopenharmony_ci return ret; 239662306a36Sopenharmony_ci} 239762306a36Sopenharmony_ci#endif 239862306a36Sopenharmony_ci 239962306a36Sopenharmony_ci/* 240062306a36Sopenharmony_ci * This function was originally taken from fs/mpage.c, and customized for f2fs. 240162306a36Sopenharmony_ci * Major change was from block_size == page_size in f2fs by default. 240262306a36Sopenharmony_ci */ 240362306a36Sopenharmony_cistatic int f2fs_mpage_readpages(struct inode *inode, 240462306a36Sopenharmony_ci struct readahead_control *rac, struct page *page) 240562306a36Sopenharmony_ci{ 240662306a36Sopenharmony_ci struct bio *bio = NULL; 240762306a36Sopenharmony_ci sector_t last_block_in_bio = 0; 240862306a36Sopenharmony_ci struct f2fs_map_blocks map; 240962306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 241062306a36Sopenharmony_ci struct compress_ctx cc = { 241162306a36Sopenharmony_ci .inode = inode, 241262306a36Sopenharmony_ci .log_cluster_size = F2FS_I(inode)->i_log_cluster_size, 241362306a36Sopenharmony_ci .cluster_size = F2FS_I(inode)->i_cluster_size, 241462306a36Sopenharmony_ci .cluster_idx = NULL_CLUSTER, 241562306a36Sopenharmony_ci .rpages = NULL, 241662306a36Sopenharmony_ci .cpages = NULL, 241762306a36Sopenharmony_ci .nr_rpages = 0, 241862306a36Sopenharmony_ci .nr_cpages = 0, 241962306a36Sopenharmony_ci }; 242062306a36Sopenharmony_ci pgoff_t nc_cluster_idx = NULL_CLUSTER; 242162306a36Sopenharmony_ci#endif 242262306a36Sopenharmony_ci unsigned nr_pages = rac ? readahead_count(rac) : 1; 242362306a36Sopenharmony_ci unsigned max_nr_pages = nr_pages; 242462306a36Sopenharmony_ci int ret = 0; 242562306a36Sopenharmony_ci 242662306a36Sopenharmony_ci map.m_pblk = 0; 242762306a36Sopenharmony_ci map.m_lblk = 0; 242862306a36Sopenharmony_ci map.m_len = 0; 242962306a36Sopenharmony_ci map.m_flags = 0; 243062306a36Sopenharmony_ci map.m_next_pgofs = NULL; 243162306a36Sopenharmony_ci map.m_next_extent = NULL; 243262306a36Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 243362306a36Sopenharmony_ci map.m_may_create = false; 243462306a36Sopenharmony_ci 243562306a36Sopenharmony_ci for (; nr_pages; nr_pages--) { 243662306a36Sopenharmony_ci if (rac) { 243762306a36Sopenharmony_ci page = readahead_page(rac); 243862306a36Sopenharmony_ci prefetchw(&page->flags); 243962306a36Sopenharmony_ci } 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 244262306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 244362306a36Sopenharmony_ci /* there are remained compressed pages, submit them */ 244462306a36Sopenharmony_ci if (!f2fs_cluster_can_merge_page(&cc, page->index)) { 244562306a36Sopenharmony_ci ret = f2fs_read_multi_pages(&cc, &bio, 244662306a36Sopenharmony_ci max_nr_pages, 244762306a36Sopenharmony_ci &last_block_in_bio, 244862306a36Sopenharmony_ci rac != NULL, false); 244962306a36Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 245062306a36Sopenharmony_ci if (ret) 245162306a36Sopenharmony_ci goto set_error_page; 245262306a36Sopenharmony_ci } 245362306a36Sopenharmony_ci if (cc.cluster_idx == NULL_CLUSTER) { 245462306a36Sopenharmony_ci if (nc_cluster_idx == 245562306a36Sopenharmony_ci page->index >> cc.log_cluster_size) { 245662306a36Sopenharmony_ci goto read_single_page; 245762306a36Sopenharmony_ci } 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_ci ret = f2fs_is_compressed_cluster(inode, page->index); 246062306a36Sopenharmony_ci if (ret < 0) 246162306a36Sopenharmony_ci goto set_error_page; 246262306a36Sopenharmony_ci else if (!ret) { 246362306a36Sopenharmony_ci nc_cluster_idx = 246462306a36Sopenharmony_ci page->index >> cc.log_cluster_size; 246562306a36Sopenharmony_ci goto read_single_page; 246662306a36Sopenharmony_ci } 246762306a36Sopenharmony_ci 246862306a36Sopenharmony_ci nc_cluster_idx = NULL_CLUSTER; 246962306a36Sopenharmony_ci } 247062306a36Sopenharmony_ci ret = f2fs_init_compress_ctx(&cc); 247162306a36Sopenharmony_ci if (ret) 247262306a36Sopenharmony_ci goto set_error_page; 247362306a36Sopenharmony_ci 247462306a36Sopenharmony_ci f2fs_compress_ctx_add_page(&cc, page); 247562306a36Sopenharmony_ci 247662306a36Sopenharmony_ci goto next_page; 247762306a36Sopenharmony_ci } 247862306a36Sopenharmony_ciread_single_page: 247962306a36Sopenharmony_ci#endif 248062306a36Sopenharmony_ci 248162306a36Sopenharmony_ci ret = f2fs_read_single_page(inode, page, max_nr_pages, &map, 248262306a36Sopenharmony_ci &bio, &last_block_in_bio, rac); 248362306a36Sopenharmony_ci if (ret) { 248462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 248562306a36Sopenharmony_ciset_error_page: 248662306a36Sopenharmony_ci#endif 248762306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 248862306a36Sopenharmony_ci unlock_page(page); 248962306a36Sopenharmony_ci } 249062306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 249162306a36Sopenharmony_cinext_page: 249262306a36Sopenharmony_ci#endif 249362306a36Sopenharmony_ci if (rac) 249462306a36Sopenharmony_ci put_page(page); 249562306a36Sopenharmony_ci 249662306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 249762306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 249862306a36Sopenharmony_ci /* last page */ 249962306a36Sopenharmony_ci if (nr_pages == 1 && !f2fs_cluster_is_empty(&cc)) { 250062306a36Sopenharmony_ci ret = f2fs_read_multi_pages(&cc, &bio, 250162306a36Sopenharmony_ci max_nr_pages, 250262306a36Sopenharmony_ci &last_block_in_bio, 250362306a36Sopenharmony_ci rac != NULL, false); 250462306a36Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 250562306a36Sopenharmony_ci } 250662306a36Sopenharmony_ci } 250762306a36Sopenharmony_ci#endif 250862306a36Sopenharmony_ci } 250962306a36Sopenharmony_ci if (bio) 251062306a36Sopenharmony_ci f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA); 251162306a36Sopenharmony_ci return ret; 251262306a36Sopenharmony_ci} 251362306a36Sopenharmony_ci 251462306a36Sopenharmony_cistatic int f2fs_read_data_folio(struct file *file, struct folio *folio) 251562306a36Sopenharmony_ci{ 251662306a36Sopenharmony_ci struct page *page = &folio->page; 251762306a36Sopenharmony_ci struct inode *inode = page_file_mapping(page)->host; 251862306a36Sopenharmony_ci int ret = -EAGAIN; 251962306a36Sopenharmony_ci 252062306a36Sopenharmony_ci trace_f2fs_readpage(page, DATA); 252162306a36Sopenharmony_ci 252262306a36Sopenharmony_ci if (!f2fs_is_compress_backend_ready(inode)) { 252362306a36Sopenharmony_ci unlock_page(page); 252462306a36Sopenharmony_ci return -EOPNOTSUPP; 252562306a36Sopenharmony_ci } 252662306a36Sopenharmony_ci 252762306a36Sopenharmony_ci /* If the file has inline data, try to read it directly */ 252862306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) 252962306a36Sopenharmony_ci ret = f2fs_read_inline_data(inode, page); 253062306a36Sopenharmony_ci if (ret == -EAGAIN) 253162306a36Sopenharmony_ci ret = f2fs_mpage_readpages(inode, NULL, page); 253262306a36Sopenharmony_ci return ret; 253362306a36Sopenharmony_ci} 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_cistatic void f2fs_readahead(struct readahead_control *rac) 253662306a36Sopenharmony_ci{ 253762306a36Sopenharmony_ci struct inode *inode = rac->mapping->host; 253862306a36Sopenharmony_ci 253962306a36Sopenharmony_ci trace_f2fs_readpages(inode, readahead_index(rac), readahead_count(rac)); 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci if (!f2fs_is_compress_backend_ready(inode)) 254262306a36Sopenharmony_ci return; 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci /* If the file has inline data, skip readahead */ 254562306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) 254662306a36Sopenharmony_ci return; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci f2fs_mpage_readpages(inode, rac, NULL); 254962306a36Sopenharmony_ci} 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ciint f2fs_encrypt_one_page(struct f2fs_io_info *fio) 255262306a36Sopenharmony_ci{ 255362306a36Sopenharmony_ci struct inode *inode = fio->page->mapping->host; 255462306a36Sopenharmony_ci struct page *mpage, *page; 255562306a36Sopenharmony_ci gfp_t gfp_flags = GFP_NOFS; 255662306a36Sopenharmony_ci 255762306a36Sopenharmony_ci if (!f2fs_encrypted_file(inode)) 255862306a36Sopenharmony_ci return 0; 255962306a36Sopenharmony_ci 256062306a36Sopenharmony_ci page = fio->compressed_page ? fio->compressed_page : fio->page; 256162306a36Sopenharmony_ci 256262306a36Sopenharmony_ci if (fscrypt_inode_uses_inline_crypto(inode)) 256362306a36Sopenharmony_ci return 0; 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_ciretry_encrypt: 256662306a36Sopenharmony_ci fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page, 256762306a36Sopenharmony_ci PAGE_SIZE, 0, gfp_flags); 256862306a36Sopenharmony_ci if (IS_ERR(fio->encrypted_page)) { 256962306a36Sopenharmony_ci /* flush pending IOs and wait for a while in the ENOMEM case */ 257062306a36Sopenharmony_ci if (PTR_ERR(fio->encrypted_page) == -ENOMEM) { 257162306a36Sopenharmony_ci f2fs_flush_merged_writes(fio->sbi); 257262306a36Sopenharmony_ci memalloc_retry_wait(GFP_NOFS); 257362306a36Sopenharmony_ci gfp_flags |= __GFP_NOFAIL; 257462306a36Sopenharmony_ci goto retry_encrypt; 257562306a36Sopenharmony_ci } 257662306a36Sopenharmony_ci return PTR_ERR(fio->encrypted_page); 257762306a36Sopenharmony_ci } 257862306a36Sopenharmony_ci 257962306a36Sopenharmony_ci mpage = find_lock_page(META_MAPPING(fio->sbi), fio->old_blkaddr); 258062306a36Sopenharmony_ci if (mpage) { 258162306a36Sopenharmony_ci if (PageUptodate(mpage)) 258262306a36Sopenharmony_ci memcpy(page_address(mpage), 258362306a36Sopenharmony_ci page_address(fio->encrypted_page), PAGE_SIZE); 258462306a36Sopenharmony_ci f2fs_put_page(mpage, 1); 258562306a36Sopenharmony_ci } 258662306a36Sopenharmony_ci return 0; 258762306a36Sopenharmony_ci} 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_cistatic inline bool check_inplace_update_policy(struct inode *inode, 259062306a36Sopenharmony_ci struct f2fs_io_info *fio) 259162306a36Sopenharmony_ci{ 259262306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci if (IS_F2FS_IPU_HONOR_OPU_WRITE(sbi) && 259562306a36Sopenharmony_ci is_inode_flag_set(inode, FI_OPU_WRITE)) 259662306a36Sopenharmony_ci return false; 259762306a36Sopenharmony_ci if (IS_F2FS_IPU_FORCE(sbi)) 259862306a36Sopenharmony_ci return true; 259962306a36Sopenharmony_ci if (IS_F2FS_IPU_SSR(sbi) && f2fs_need_SSR(sbi)) 260062306a36Sopenharmony_ci return true; 260162306a36Sopenharmony_ci if (IS_F2FS_IPU_UTIL(sbi) && utilization(sbi) > SM_I(sbi)->min_ipu_util) 260262306a36Sopenharmony_ci return true; 260362306a36Sopenharmony_ci if (IS_F2FS_IPU_SSR_UTIL(sbi) && f2fs_need_SSR(sbi) && 260462306a36Sopenharmony_ci utilization(sbi) > SM_I(sbi)->min_ipu_util) 260562306a36Sopenharmony_ci return true; 260662306a36Sopenharmony_ci 260762306a36Sopenharmony_ci /* 260862306a36Sopenharmony_ci * IPU for rewrite async pages 260962306a36Sopenharmony_ci */ 261062306a36Sopenharmony_ci if (IS_F2FS_IPU_ASYNC(sbi) && fio && fio->op == REQ_OP_WRITE && 261162306a36Sopenharmony_ci !(fio->op_flags & REQ_SYNC) && !IS_ENCRYPTED(inode)) 261262306a36Sopenharmony_ci return true; 261362306a36Sopenharmony_ci 261462306a36Sopenharmony_ci /* this is only set during fdatasync */ 261562306a36Sopenharmony_ci if (IS_F2FS_IPU_FSYNC(sbi) && is_inode_flag_set(inode, FI_NEED_IPU)) 261662306a36Sopenharmony_ci return true; 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 261962306a36Sopenharmony_ci !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) 262062306a36Sopenharmony_ci return true; 262162306a36Sopenharmony_ci 262262306a36Sopenharmony_ci return false; 262362306a36Sopenharmony_ci} 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_cibool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio) 262662306a36Sopenharmony_ci{ 262762306a36Sopenharmony_ci /* swap file is migrating in aligned write mode */ 262862306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) 262962306a36Sopenharmony_ci return false; 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci if (f2fs_is_pinned_file(inode)) 263262306a36Sopenharmony_ci return true; 263362306a36Sopenharmony_ci 263462306a36Sopenharmony_ci /* if this is cold file, we should overwrite to avoid fragmentation */ 263562306a36Sopenharmony_ci if (file_is_cold(inode) && !is_inode_flag_set(inode, FI_OPU_WRITE)) 263662306a36Sopenharmony_ci return true; 263762306a36Sopenharmony_ci 263862306a36Sopenharmony_ci return check_inplace_update_policy(inode, fio); 263962306a36Sopenharmony_ci} 264062306a36Sopenharmony_ci 264162306a36Sopenharmony_cibool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) 264262306a36Sopenharmony_ci{ 264362306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_ci /* The below cases were checked when setting it. */ 264662306a36Sopenharmony_ci if (f2fs_is_pinned_file(inode)) 264762306a36Sopenharmony_ci return false; 264862306a36Sopenharmony_ci if (fio && is_sbi_flag_set(sbi, SBI_NEED_FSCK)) 264962306a36Sopenharmony_ci return true; 265062306a36Sopenharmony_ci if (f2fs_lfs_mode(sbi)) 265162306a36Sopenharmony_ci return true; 265262306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 265362306a36Sopenharmony_ci return true; 265462306a36Sopenharmony_ci if (IS_NOQUOTA(inode)) 265562306a36Sopenharmony_ci return true; 265662306a36Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 265762306a36Sopenharmony_ci return true; 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci /* swap file is migrating in aligned write mode */ 266062306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_ALIGNED_WRITE)) 266162306a36Sopenharmony_ci return true; 266262306a36Sopenharmony_ci 266362306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_OPU_WRITE)) 266462306a36Sopenharmony_ci return true; 266562306a36Sopenharmony_ci 266662306a36Sopenharmony_ci if (fio) { 266762306a36Sopenharmony_ci if (page_private_gcing(fio->page)) 266862306a36Sopenharmony_ci return true; 266962306a36Sopenharmony_ci if (page_private_dummy(fio->page)) 267062306a36Sopenharmony_ci return true; 267162306a36Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 267262306a36Sopenharmony_ci f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) 267362306a36Sopenharmony_ci return true; 267462306a36Sopenharmony_ci } 267562306a36Sopenharmony_ci return false; 267662306a36Sopenharmony_ci} 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_cistatic inline bool need_inplace_update(struct f2fs_io_info *fio) 267962306a36Sopenharmony_ci{ 268062306a36Sopenharmony_ci struct inode *inode = fio->page->mapping->host; 268162306a36Sopenharmony_ci 268262306a36Sopenharmony_ci if (f2fs_should_update_outplace(inode, fio)) 268362306a36Sopenharmony_ci return false; 268462306a36Sopenharmony_ci 268562306a36Sopenharmony_ci return f2fs_should_update_inplace(inode, fio); 268662306a36Sopenharmony_ci} 268762306a36Sopenharmony_ci 268862306a36Sopenharmony_ciint f2fs_do_write_data_page(struct f2fs_io_info *fio) 268962306a36Sopenharmony_ci{ 269062306a36Sopenharmony_ci struct page *page = fio->page; 269162306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 269262306a36Sopenharmony_ci struct dnode_of_data dn; 269362306a36Sopenharmony_ci struct node_info ni; 269462306a36Sopenharmony_ci bool ipu_force = false; 269562306a36Sopenharmony_ci int err = 0; 269662306a36Sopenharmony_ci 269762306a36Sopenharmony_ci /* Use COW inode to make dnode_of_data for atomic write */ 269862306a36Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 269962306a36Sopenharmony_ci set_new_dnode(&dn, F2FS_I(inode)->cow_inode, NULL, NULL, 0); 270062306a36Sopenharmony_ci else 270162306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 270262306a36Sopenharmony_ci 270362306a36Sopenharmony_ci if (need_inplace_update(fio) && 270462306a36Sopenharmony_ci f2fs_lookup_read_extent_cache_block(inode, page->index, 270562306a36Sopenharmony_ci &fio->old_blkaddr)) { 270662306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 270762306a36Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 270862306a36Sopenharmony_ci f2fs_handle_error(fio->sbi, 270962306a36Sopenharmony_ci ERROR_INVALID_BLKADDR); 271062306a36Sopenharmony_ci return -EFSCORRUPTED; 271162306a36Sopenharmony_ci } 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci ipu_force = true; 271462306a36Sopenharmony_ci fio->need_lock = LOCK_DONE; 271562306a36Sopenharmony_ci goto got_it; 271662306a36Sopenharmony_ci } 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci /* Deadlock due to between page->lock and f2fs_lock_op */ 271962306a36Sopenharmony_ci if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) 272062306a36Sopenharmony_ci return -EAGAIN; 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); 272362306a36Sopenharmony_ci if (err) 272462306a36Sopenharmony_ci goto out; 272562306a36Sopenharmony_ci 272662306a36Sopenharmony_ci fio->old_blkaddr = dn.data_blkaddr; 272762306a36Sopenharmony_ci 272862306a36Sopenharmony_ci /* This page is already truncated */ 272962306a36Sopenharmony_ci if (fio->old_blkaddr == NULL_ADDR) { 273062306a36Sopenharmony_ci ClearPageUptodate(page); 273162306a36Sopenharmony_ci clear_page_private_gcing(page); 273262306a36Sopenharmony_ci goto out_writepage; 273362306a36Sopenharmony_ci } 273462306a36Sopenharmony_cigot_it: 273562306a36Sopenharmony_ci if (__is_valid_data_blkaddr(fio->old_blkaddr) && 273662306a36Sopenharmony_ci !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 273762306a36Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 273862306a36Sopenharmony_ci err = -EFSCORRUPTED; 273962306a36Sopenharmony_ci f2fs_handle_error(fio->sbi, ERROR_INVALID_BLKADDR); 274062306a36Sopenharmony_ci goto out_writepage; 274162306a36Sopenharmony_ci } 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_ci /* wait for GCed page writeback via META_MAPPING */ 274462306a36Sopenharmony_ci if (fio->post_read) 274562306a36Sopenharmony_ci f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci /* 274862306a36Sopenharmony_ci * If current allocation needs SSR, 274962306a36Sopenharmony_ci * it had better in-place writes for updated data. 275062306a36Sopenharmony_ci */ 275162306a36Sopenharmony_ci if (ipu_force || 275262306a36Sopenharmony_ci (__is_valid_data_blkaddr(fio->old_blkaddr) && 275362306a36Sopenharmony_ci need_inplace_update(fio))) { 275462306a36Sopenharmony_ci err = f2fs_encrypt_one_page(fio); 275562306a36Sopenharmony_ci if (err) 275662306a36Sopenharmony_ci goto out_writepage; 275762306a36Sopenharmony_ci 275862306a36Sopenharmony_ci set_page_writeback(page); 275962306a36Sopenharmony_ci f2fs_put_dnode(&dn); 276062306a36Sopenharmony_ci if (fio->need_lock == LOCK_REQ) 276162306a36Sopenharmony_ci f2fs_unlock_op(fio->sbi); 276262306a36Sopenharmony_ci err = f2fs_inplace_write_data(fio); 276362306a36Sopenharmony_ci if (err) { 276462306a36Sopenharmony_ci if (fscrypt_inode_uses_fs_layer_crypto(inode)) 276562306a36Sopenharmony_ci fscrypt_finalize_bounce_page(&fio->encrypted_page); 276662306a36Sopenharmony_ci if (PageWriteback(page)) 276762306a36Sopenharmony_ci end_page_writeback(page); 276862306a36Sopenharmony_ci } else { 276962306a36Sopenharmony_ci set_inode_flag(inode, FI_UPDATE_WRITE); 277062306a36Sopenharmony_ci } 277162306a36Sopenharmony_ci trace_f2fs_do_write_data_page(fio->page, IPU); 277262306a36Sopenharmony_ci return err; 277362306a36Sopenharmony_ci } 277462306a36Sopenharmony_ci 277562306a36Sopenharmony_ci if (fio->need_lock == LOCK_RETRY) { 277662306a36Sopenharmony_ci if (!f2fs_trylock_op(fio->sbi)) { 277762306a36Sopenharmony_ci err = -EAGAIN; 277862306a36Sopenharmony_ci goto out_writepage; 277962306a36Sopenharmony_ci } 278062306a36Sopenharmony_ci fio->need_lock = LOCK_REQ; 278162306a36Sopenharmony_ci } 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci err = f2fs_get_node_info(fio->sbi, dn.nid, &ni, false); 278462306a36Sopenharmony_ci if (err) 278562306a36Sopenharmony_ci goto out_writepage; 278662306a36Sopenharmony_ci 278762306a36Sopenharmony_ci fio->version = ni.version; 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci err = f2fs_encrypt_one_page(fio); 279062306a36Sopenharmony_ci if (err) 279162306a36Sopenharmony_ci goto out_writepage; 279262306a36Sopenharmony_ci 279362306a36Sopenharmony_ci set_page_writeback(page); 279462306a36Sopenharmony_ci 279562306a36Sopenharmony_ci if (fio->compr_blocks && fio->old_blkaddr == COMPRESS_ADDR) 279662306a36Sopenharmony_ci f2fs_i_compr_blocks_update(inode, fio->compr_blocks - 1, false); 279762306a36Sopenharmony_ci 279862306a36Sopenharmony_ci /* LFS mode write path */ 279962306a36Sopenharmony_ci f2fs_outplace_write_data(&dn, fio); 280062306a36Sopenharmony_ci trace_f2fs_do_write_data_page(page, OPU); 280162306a36Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 280262306a36Sopenharmony_ciout_writepage: 280362306a36Sopenharmony_ci f2fs_put_dnode(&dn); 280462306a36Sopenharmony_ciout: 280562306a36Sopenharmony_ci if (fio->need_lock == LOCK_REQ) 280662306a36Sopenharmony_ci f2fs_unlock_op(fio->sbi); 280762306a36Sopenharmony_ci return err; 280862306a36Sopenharmony_ci} 280962306a36Sopenharmony_ci 281062306a36Sopenharmony_ciint f2fs_write_single_data_page(struct page *page, int *submitted, 281162306a36Sopenharmony_ci struct bio **bio, 281262306a36Sopenharmony_ci sector_t *last_block, 281362306a36Sopenharmony_ci struct writeback_control *wbc, 281462306a36Sopenharmony_ci enum iostat_type io_type, 281562306a36Sopenharmony_ci int compr_blocks, 281662306a36Sopenharmony_ci bool allow_balance) 281762306a36Sopenharmony_ci{ 281862306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 281962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 282062306a36Sopenharmony_ci loff_t i_size = i_size_read(inode); 282162306a36Sopenharmony_ci const pgoff_t end_index = ((unsigned long long)i_size) 282262306a36Sopenharmony_ci >> PAGE_SHIFT; 282362306a36Sopenharmony_ci loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT; 282462306a36Sopenharmony_ci unsigned offset = 0; 282562306a36Sopenharmony_ci bool need_balance_fs = false; 282662306a36Sopenharmony_ci bool quota_inode = IS_NOQUOTA(inode); 282762306a36Sopenharmony_ci int err = 0; 282862306a36Sopenharmony_ci struct f2fs_io_info fio = { 282962306a36Sopenharmony_ci .sbi = sbi, 283062306a36Sopenharmony_ci .ino = inode->i_ino, 283162306a36Sopenharmony_ci .type = DATA, 283262306a36Sopenharmony_ci .op = REQ_OP_WRITE, 283362306a36Sopenharmony_ci .op_flags = wbc_to_write_flags(wbc), 283462306a36Sopenharmony_ci .old_blkaddr = NULL_ADDR, 283562306a36Sopenharmony_ci .page = page, 283662306a36Sopenharmony_ci .encrypted_page = NULL, 283762306a36Sopenharmony_ci .submitted = 0, 283862306a36Sopenharmony_ci .compr_blocks = compr_blocks, 283962306a36Sopenharmony_ci .need_lock = compr_blocks ? LOCK_DONE : LOCK_RETRY, 284062306a36Sopenharmony_ci .post_read = f2fs_post_read_required(inode) ? 1 : 0, 284162306a36Sopenharmony_ci .io_type = io_type, 284262306a36Sopenharmony_ci .io_wbc = wbc, 284362306a36Sopenharmony_ci .bio = bio, 284462306a36Sopenharmony_ci .last_block = last_block, 284562306a36Sopenharmony_ci }; 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci trace_f2fs_writepage(page, DATA); 284862306a36Sopenharmony_ci 284962306a36Sopenharmony_ci /* we should bypass data pages to proceed the kworker jobs */ 285062306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 285162306a36Sopenharmony_ci mapping_set_error(page->mapping, -EIO); 285262306a36Sopenharmony_ci /* 285362306a36Sopenharmony_ci * don't drop any dirty dentry pages for keeping lastest 285462306a36Sopenharmony_ci * directory structure. 285562306a36Sopenharmony_ci */ 285662306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) && 285762306a36Sopenharmony_ci !is_sbi_flag_set(sbi, SBI_IS_CLOSE)) 285862306a36Sopenharmony_ci goto redirty_out; 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_ci /* keep data pages in remount-ro mode */ 286162306a36Sopenharmony_ci if (F2FS_OPTION(sbi).errors == MOUNT_ERRORS_READONLY) 286262306a36Sopenharmony_ci goto redirty_out; 286362306a36Sopenharmony_ci goto out; 286462306a36Sopenharmony_ci } 286562306a36Sopenharmony_ci 286662306a36Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 286762306a36Sopenharmony_ci goto redirty_out; 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_ci if (page->index < end_index || 287062306a36Sopenharmony_ci f2fs_verity_in_progress(inode) || 287162306a36Sopenharmony_ci compr_blocks) 287262306a36Sopenharmony_ci goto write; 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_ci /* 287562306a36Sopenharmony_ci * If the offset is out-of-range of file size, 287662306a36Sopenharmony_ci * this page does not have to be written to disk. 287762306a36Sopenharmony_ci */ 287862306a36Sopenharmony_ci offset = i_size & (PAGE_SIZE - 1); 287962306a36Sopenharmony_ci if ((page->index >= end_index + 1) || !offset) 288062306a36Sopenharmony_ci goto out; 288162306a36Sopenharmony_ci 288262306a36Sopenharmony_ci zero_user_segment(page, offset, PAGE_SIZE); 288362306a36Sopenharmony_ciwrite: 288462306a36Sopenharmony_ci /* Dentry/quota blocks are controlled by checkpoint */ 288562306a36Sopenharmony_ci if (S_ISDIR(inode->i_mode) || quota_inode) { 288662306a36Sopenharmony_ci /* 288762306a36Sopenharmony_ci * We need to wait for node_write to avoid block allocation during 288862306a36Sopenharmony_ci * checkpoint. This can only happen to quota writes which can cause 288962306a36Sopenharmony_ci * the below discard race condition. 289062306a36Sopenharmony_ci */ 289162306a36Sopenharmony_ci if (quota_inode) 289262306a36Sopenharmony_ci f2fs_down_read(&sbi->node_write); 289362306a36Sopenharmony_ci 289462306a36Sopenharmony_ci fio.need_lock = LOCK_DONE; 289562306a36Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci if (quota_inode) 289862306a36Sopenharmony_ci f2fs_up_read(&sbi->node_write); 289962306a36Sopenharmony_ci 290062306a36Sopenharmony_ci goto done; 290162306a36Sopenharmony_ci } 290262306a36Sopenharmony_ci 290362306a36Sopenharmony_ci if (!wbc->for_reclaim) 290462306a36Sopenharmony_ci need_balance_fs = true; 290562306a36Sopenharmony_ci else if (has_not_enough_free_secs(sbi, 0, 0)) 290662306a36Sopenharmony_ci goto redirty_out; 290762306a36Sopenharmony_ci else 290862306a36Sopenharmony_ci set_inode_flag(inode, FI_HOT_DATA); 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci err = -EAGAIN; 291162306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 291262306a36Sopenharmony_ci err = f2fs_write_inline_data(inode, page); 291362306a36Sopenharmony_ci if (!err) 291462306a36Sopenharmony_ci goto out; 291562306a36Sopenharmony_ci } 291662306a36Sopenharmony_ci 291762306a36Sopenharmony_ci if (err == -EAGAIN) { 291862306a36Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 291962306a36Sopenharmony_ci if (err == -EAGAIN) { 292062306a36Sopenharmony_ci f2fs_bug_on(sbi, compr_blocks); 292162306a36Sopenharmony_ci fio.need_lock = LOCK_REQ; 292262306a36Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 292362306a36Sopenharmony_ci } 292462306a36Sopenharmony_ci } 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci if (err) { 292762306a36Sopenharmony_ci file_set_keep_isize(inode); 292862306a36Sopenharmony_ci } else { 292962306a36Sopenharmony_ci spin_lock(&F2FS_I(inode)->i_size_lock); 293062306a36Sopenharmony_ci if (F2FS_I(inode)->last_disk_size < psize) 293162306a36Sopenharmony_ci F2FS_I(inode)->last_disk_size = psize; 293262306a36Sopenharmony_ci spin_unlock(&F2FS_I(inode)->i_size_lock); 293362306a36Sopenharmony_ci } 293462306a36Sopenharmony_ci 293562306a36Sopenharmony_cidone: 293662306a36Sopenharmony_ci if (err && err != -ENOENT) 293762306a36Sopenharmony_ci goto redirty_out; 293862306a36Sopenharmony_ci 293962306a36Sopenharmony_ciout: 294062306a36Sopenharmony_ci inode_dec_dirty_pages(inode); 294162306a36Sopenharmony_ci if (err) { 294262306a36Sopenharmony_ci ClearPageUptodate(page); 294362306a36Sopenharmony_ci clear_page_private_gcing(page); 294462306a36Sopenharmony_ci } 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci if (wbc->for_reclaim) { 294762306a36Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA); 294862306a36Sopenharmony_ci clear_inode_flag(inode, FI_HOT_DATA); 294962306a36Sopenharmony_ci f2fs_remove_dirty_inode(inode); 295062306a36Sopenharmony_ci submitted = NULL; 295162306a36Sopenharmony_ci } 295262306a36Sopenharmony_ci unlock_page(page); 295362306a36Sopenharmony_ci if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) && 295462306a36Sopenharmony_ci !F2FS_I(inode)->wb_task && allow_balance) 295562306a36Sopenharmony_ci f2fs_balance_fs(sbi, need_balance_fs); 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 295862306a36Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 295962306a36Sopenharmony_ci if (bio && *bio) 296062306a36Sopenharmony_ci f2fs_submit_merged_ipu_write(sbi, bio, NULL); 296162306a36Sopenharmony_ci submitted = NULL; 296262306a36Sopenharmony_ci } 296362306a36Sopenharmony_ci 296462306a36Sopenharmony_ci if (submitted) 296562306a36Sopenharmony_ci *submitted = fio.submitted; 296662306a36Sopenharmony_ci 296762306a36Sopenharmony_ci return 0; 296862306a36Sopenharmony_ci 296962306a36Sopenharmony_ciredirty_out: 297062306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 297162306a36Sopenharmony_ci /* 297262306a36Sopenharmony_ci * pageout() in MM translates EAGAIN, so calls handle_write_error() 297362306a36Sopenharmony_ci * -> mapping_set_error() -> set_bit(AS_EIO, ...). 297462306a36Sopenharmony_ci * file_write_and_wait_range() will see EIO error, which is critical 297562306a36Sopenharmony_ci * to return value of fsync() followed by atomic_write failure to user. 297662306a36Sopenharmony_ci */ 297762306a36Sopenharmony_ci if (!err || wbc->for_reclaim) 297862306a36Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 297962306a36Sopenharmony_ci unlock_page(page); 298062306a36Sopenharmony_ci return err; 298162306a36Sopenharmony_ci} 298262306a36Sopenharmony_ci 298362306a36Sopenharmony_cistatic int f2fs_write_data_page(struct page *page, 298462306a36Sopenharmony_ci struct writeback_control *wbc) 298562306a36Sopenharmony_ci{ 298662306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 298762306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 298862306a36Sopenharmony_ci 298962306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) 299062306a36Sopenharmony_ci goto out; 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 299362306a36Sopenharmony_ci if (f2fs_is_compressed_cluster(inode, page->index)) { 299462306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 299562306a36Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 299662306a36Sopenharmony_ci } 299762306a36Sopenharmony_ci } 299862306a36Sopenharmony_ciout: 299962306a36Sopenharmony_ci#endif 300062306a36Sopenharmony_ci 300162306a36Sopenharmony_ci return f2fs_write_single_data_page(page, NULL, NULL, NULL, 300262306a36Sopenharmony_ci wbc, FS_DATA_IO, 0, true); 300362306a36Sopenharmony_ci} 300462306a36Sopenharmony_ci 300562306a36Sopenharmony_ci/* 300662306a36Sopenharmony_ci * This function was copied from write_cache_pages from mm/page-writeback.c. 300762306a36Sopenharmony_ci * The major change is making write step of cold data page separately from 300862306a36Sopenharmony_ci * warm/hot data page. 300962306a36Sopenharmony_ci */ 301062306a36Sopenharmony_cistatic int f2fs_write_cache_pages(struct address_space *mapping, 301162306a36Sopenharmony_ci struct writeback_control *wbc, 301262306a36Sopenharmony_ci enum iostat_type io_type) 301362306a36Sopenharmony_ci{ 301462306a36Sopenharmony_ci int ret = 0; 301562306a36Sopenharmony_ci int done = 0, retry = 0; 301662306a36Sopenharmony_ci struct page *pages_local[F2FS_ONSTACK_PAGES]; 301762306a36Sopenharmony_ci struct page **pages = pages_local; 301862306a36Sopenharmony_ci struct folio_batch fbatch; 301962306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 302062306a36Sopenharmony_ci struct bio *bio = NULL; 302162306a36Sopenharmony_ci sector_t last_block; 302262306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 302362306a36Sopenharmony_ci struct inode *inode = mapping->host; 302462306a36Sopenharmony_ci struct compress_ctx cc = { 302562306a36Sopenharmony_ci .inode = inode, 302662306a36Sopenharmony_ci .log_cluster_size = F2FS_I(inode)->i_log_cluster_size, 302762306a36Sopenharmony_ci .cluster_size = F2FS_I(inode)->i_cluster_size, 302862306a36Sopenharmony_ci .cluster_idx = NULL_CLUSTER, 302962306a36Sopenharmony_ci .rpages = NULL, 303062306a36Sopenharmony_ci .nr_rpages = 0, 303162306a36Sopenharmony_ci .cpages = NULL, 303262306a36Sopenharmony_ci .valid_nr_cpages = 0, 303362306a36Sopenharmony_ci .rbuf = NULL, 303462306a36Sopenharmony_ci .cbuf = NULL, 303562306a36Sopenharmony_ci .rlen = PAGE_SIZE * F2FS_I(inode)->i_cluster_size, 303662306a36Sopenharmony_ci .private = NULL, 303762306a36Sopenharmony_ci }; 303862306a36Sopenharmony_ci#endif 303962306a36Sopenharmony_ci int nr_folios, p, idx; 304062306a36Sopenharmony_ci int nr_pages; 304162306a36Sopenharmony_ci unsigned int max_pages = F2FS_ONSTACK_PAGES; 304262306a36Sopenharmony_ci pgoff_t index; 304362306a36Sopenharmony_ci pgoff_t end; /* Inclusive */ 304462306a36Sopenharmony_ci pgoff_t done_index; 304562306a36Sopenharmony_ci int range_whole = 0; 304662306a36Sopenharmony_ci xa_mark_t tag; 304762306a36Sopenharmony_ci int nwritten = 0; 304862306a36Sopenharmony_ci int submitted = 0; 304962306a36Sopenharmony_ci int i; 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 305262306a36Sopenharmony_ci if (f2fs_compressed_file(inode) && 305362306a36Sopenharmony_ci 1 << cc.log_cluster_size > F2FS_ONSTACK_PAGES) { 305462306a36Sopenharmony_ci pages = f2fs_kzalloc(sbi, sizeof(struct page *) << 305562306a36Sopenharmony_ci cc.log_cluster_size, GFP_NOFS | __GFP_NOFAIL); 305662306a36Sopenharmony_ci max_pages = 1 << cc.log_cluster_size; 305762306a36Sopenharmony_ci } 305862306a36Sopenharmony_ci#endif 305962306a36Sopenharmony_ci 306062306a36Sopenharmony_ci folio_batch_init(&fbatch); 306162306a36Sopenharmony_ci 306262306a36Sopenharmony_ci if (get_dirty_pages(mapping->host) <= 306362306a36Sopenharmony_ci SM_I(F2FS_M_SB(mapping))->min_hot_blocks) 306462306a36Sopenharmony_ci set_inode_flag(mapping->host, FI_HOT_DATA); 306562306a36Sopenharmony_ci else 306662306a36Sopenharmony_ci clear_inode_flag(mapping->host, FI_HOT_DATA); 306762306a36Sopenharmony_ci 306862306a36Sopenharmony_ci if (wbc->range_cyclic) { 306962306a36Sopenharmony_ci index = mapping->writeback_index; /* prev offset */ 307062306a36Sopenharmony_ci end = -1; 307162306a36Sopenharmony_ci } else { 307262306a36Sopenharmony_ci index = wbc->range_start >> PAGE_SHIFT; 307362306a36Sopenharmony_ci end = wbc->range_end >> PAGE_SHIFT; 307462306a36Sopenharmony_ci if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) 307562306a36Sopenharmony_ci range_whole = 1; 307662306a36Sopenharmony_ci } 307762306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) 307862306a36Sopenharmony_ci tag = PAGECACHE_TAG_TOWRITE; 307962306a36Sopenharmony_ci else 308062306a36Sopenharmony_ci tag = PAGECACHE_TAG_DIRTY; 308162306a36Sopenharmony_ciretry: 308262306a36Sopenharmony_ci retry = 0; 308362306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) 308462306a36Sopenharmony_ci tag_pages_for_writeback(mapping, index, end); 308562306a36Sopenharmony_ci done_index = index; 308662306a36Sopenharmony_ci while (!done && !retry && (index <= end)) { 308762306a36Sopenharmony_ci nr_pages = 0; 308862306a36Sopenharmony_ciagain: 308962306a36Sopenharmony_ci nr_folios = filemap_get_folios_tag(mapping, &index, end, 309062306a36Sopenharmony_ci tag, &fbatch); 309162306a36Sopenharmony_ci if (nr_folios == 0) { 309262306a36Sopenharmony_ci if (nr_pages) 309362306a36Sopenharmony_ci goto write; 309462306a36Sopenharmony_ci break; 309562306a36Sopenharmony_ci } 309662306a36Sopenharmony_ci 309762306a36Sopenharmony_ci for (i = 0; i < nr_folios; i++) { 309862306a36Sopenharmony_ci struct folio *folio = fbatch.folios[i]; 309962306a36Sopenharmony_ci 310062306a36Sopenharmony_ci idx = 0; 310162306a36Sopenharmony_ci p = folio_nr_pages(folio); 310262306a36Sopenharmony_ciadd_more: 310362306a36Sopenharmony_ci pages[nr_pages] = folio_page(folio, idx); 310462306a36Sopenharmony_ci folio_get(folio); 310562306a36Sopenharmony_ci if (++nr_pages == max_pages) { 310662306a36Sopenharmony_ci index = folio->index + idx + 1; 310762306a36Sopenharmony_ci folio_batch_release(&fbatch); 310862306a36Sopenharmony_ci goto write; 310962306a36Sopenharmony_ci } 311062306a36Sopenharmony_ci if (++idx < p) 311162306a36Sopenharmony_ci goto add_more; 311262306a36Sopenharmony_ci } 311362306a36Sopenharmony_ci folio_batch_release(&fbatch); 311462306a36Sopenharmony_ci goto again; 311562306a36Sopenharmony_ciwrite: 311662306a36Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 311762306a36Sopenharmony_ci struct page *page = pages[i]; 311862306a36Sopenharmony_ci struct folio *folio = page_folio(page); 311962306a36Sopenharmony_ci bool need_readd; 312062306a36Sopenharmony_cireadd: 312162306a36Sopenharmony_ci need_readd = false; 312262306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 312362306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 312462306a36Sopenharmony_ci void *fsdata = NULL; 312562306a36Sopenharmony_ci struct page *pagep; 312662306a36Sopenharmony_ci int ret2; 312762306a36Sopenharmony_ci 312862306a36Sopenharmony_ci ret = f2fs_init_compress_ctx(&cc); 312962306a36Sopenharmony_ci if (ret) { 313062306a36Sopenharmony_ci done = 1; 313162306a36Sopenharmony_ci break; 313262306a36Sopenharmony_ci } 313362306a36Sopenharmony_ci 313462306a36Sopenharmony_ci if (!f2fs_cluster_can_merge_page(&cc, 313562306a36Sopenharmony_ci folio->index)) { 313662306a36Sopenharmony_ci ret = f2fs_write_multi_pages(&cc, 313762306a36Sopenharmony_ci &submitted, wbc, io_type); 313862306a36Sopenharmony_ci if (!ret) 313962306a36Sopenharmony_ci need_readd = true; 314062306a36Sopenharmony_ci goto result; 314162306a36Sopenharmony_ci } 314262306a36Sopenharmony_ci 314362306a36Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 314462306a36Sopenharmony_ci goto lock_folio; 314562306a36Sopenharmony_ci 314662306a36Sopenharmony_ci if (!f2fs_cluster_is_empty(&cc)) 314762306a36Sopenharmony_ci goto lock_folio; 314862306a36Sopenharmony_ci 314962306a36Sopenharmony_ci if (f2fs_all_cluster_page_ready(&cc, 315062306a36Sopenharmony_ci pages, i, nr_pages, true)) 315162306a36Sopenharmony_ci goto lock_folio; 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci ret2 = f2fs_prepare_compress_overwrite( 315462306a36Sopenharmony_ci inode, &pagep, 315562306a36Sopenharmony_ci folio->index, &fsdata); 315662306a36Sopenharmony_ci if (ret2 < 0) { 315762306a36Sopenharmony_ci ret = ret2; 315862306a36Sopenharmony_ci done = 1; 315962306a36Sopenharmony_ci break; 316062306a36Sopenharmony_ci } else if (ret2 && 316162306a36Sopenharmony_ci (!f2fs_compress_write_end(inode, 316262306a36Sopenharmony_ci fsdata, folio->index, 1) || 316362306a36Sopenharmony_ci !f2fs_all_cluster_page_ready(&cc, 316462306a36Sopenharmony_ci pages, i, nr_pages, 316562306a36Sopenharmony_ci false))) { 316662306a36Sopenharmony_ci retry = 1; 316762306a36Sopenharmony_ci break; 316862306a36Sopenharmony_ci } 316962306a36Sopenharmony_ci } 317062306a36Sopenharmony_ci#endif 317162306a36Sopenharmony_ci /* give a priority to WB_SYNC threads */ 317262306a36Sopenharmony_ci if (atomic_read(&sbi->wb_sync_req[DATA]) && 317362306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 317462306a36Sopenharmony_ci done = 1; 317562306a36Sopenharmony_ci break; 317662306a36Sopenharmony_ci } 317762306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 317862306a36Sopenharmony_cilock_folio: 317962306a36Sopenharmony_ci#endif 318062306a36Sopenharmony_ci done_index = folio->index; 318162306a36Sopenharmony_ciretry_write: 318262306a36Sopenharmony_ci folio_lock(folio); 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci if (unlikely(folio->mapping != mapping)) { 318562306a36Sopenharmony_cicontinue_unlock: 318662306a36Sopenharmony_ci folio_unlock(folio); 318762306a36Sopenharmony_ci continue; 318862306a36Sopenharmony_ci } 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_ci if (!folio_test_dirty(folio)) { 319162306a36Sopenharmony_ci /* someone wrote it for us */ 319262306a36Sopenharmony_ci goto continue_unlock; 319362306a36Sopenharmony_ci } 319462306a36Sopenharmony_ci 319562306a36Sopenharmony_ci if (folio_test_writeback(folio)) { 319662306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_NONE) 319762306a36Sopenharmony_ci goto continue_unlock; 319862306a36Sopenharmony_ci f2fs_wait_on_page_writeback(&folio->page, DATA, true, true); 319962306a36Sopenharmony_ci } 320062306a36Sopenharmony_ci 320162306a36Sopenharmony_ci if (!folio_clear_dirty_for_io(folio)) 320262306a36Sopenharmony_ci goto continue_unlock; 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 320562306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 320662306a36Sopenharmony_ci folio_get(folio); 320762306a36Sopenharmony_ci f2fs_compress_ctx_add_page(&cc, &folio->page); 320862306a36Sopenharmony_ci continue; 320962306a36Sopenharmony_ci } 321062306a36Sopenharmony_ci#endif 321162306a36Sopenharmony_ci ret = f2fs_write_single_data_page(&folio->page, 321262306a36Sopenharmony_ci &submitted, &bio, &last_block, 321362306a36Sopenharmony_ci wbc, io_type, 0, true); 321462306a36Sopenharmony_ci if (ret == AOP_WRITEPAGE_ACTIVATE) 321562306a36Sopenharmony_ci folio_unlock(folio); 321662306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 321762306a36Sopenharmony_ciresult: 321862306a36Sopenharmony_ci#endif 321962306a36Sopenharmony_ci nwritten += submitted; 322062306a36Sopenharmony_ci wbc->nr_to_write -= submitted; 322162306a36Sopenharmony_ci 322262306a36Sopenharmony_ci if (unlikely(ret)) { 322362306a36Sopenharmony_ci /* 322462306a36Sopenharmony_ci * keep nr_to_write, since vfs uses this to 322562306a36Sopenharmony_ci * get # of written pages. 322662306a36Sopenharmony_ci */ 322762306a36Sopenharmony_ci if (ret == AOP_WRITEPAGE_ACTIVATE) { 322862306a36Sopenharmony_ci ret = 0; 322962306a36Sopenharmony_ci goto next; 323062306a36Sopenharmony_ci } else if (ret == -EAGAIN) { 323162306a36Sopenharmony_ci ret = 0; 323262306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) { 323362306a36Sopenharmony_ci f2fs_io_schedule_timeout( 323462306a36Sopenharmony_ci DEFAULT_IO_TIMEOUT); 323562306a36Sopenharmony_ci goto retry_write; 323662306a36Sopenharmony_ci } 323762306a36Sopenharmony_ci goto next; 323862306a36Sopenharmony_ci } 323962306a36Sopenharmony_ci done_index = folio_next_index(folio); 324062306a36Sopenharmony_ci done = 1; 324162306a36Sopenharmony_ci break; 324262306a36Sopenharmony_ci } 324362306a36Sopenharmony_ci 324462306a36Sopenharmony_ci if (wbc->nr_to_write <= 0 && 324562306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 324662306a36Sopenharmony_ci done = 1; 324762306a36Sopenharmony_ci break; 324862306a36Sopenharmony_ci } 324962306a36Sopenharmony_cinext: 325062306a36Sopenharmony_ci if (need_readd) 325162306a36Sopenharmony_ci goto readd; 325262306a36Sopenharmony_ci } 325362306a36Sopenharmony_ci release_pages(pages, nr_pages); 325462306a36Sopenharmony_ci cond_resched(); 325562306a36Sopenharmony_ci } 325662306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 325762306a36Sopenharmony_ci /* flush remained pages in compress cluster */ 325862306a36Sopenharmony_ci if (f2fs_compressed_file(inode) && !f2fs_cluster_is_empty(&cc)) { 325962306a36Sopenharmony_ci ret = f2fs_write_multi_pages(&cc, &submitted, wbc, io_type); 326062306a36Sopenharmony_ci nwritten += submitted; 326162306a36Sopenharmony_ci wbc->nr_to_write -= submitted; 326262306a36Sopenharmony_ci if (ret) { 326362306a36Sopenharmony_ci done = 1; 326462306a36Sopenharmony_ci retry = 0; 326562306a36Sopenharmony_ci } 326662306a36Sopenharmony_ci } 326762306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) 326862306a36Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 326962306a36Sopenharmony_ci#endif 327062306a36Sopenharmony_ci if (retry) { 327162306a36Sopenharmony_ci index = 0; 327262306a36Sopenharmony_ci end = -1; 327362306a36Sopenharmony_ci goto retry; 327462306a36Sopenharmony_ci } 327562306a36Sopenharmony_ci if (wbc->range_cyclic && !done) 327662306a36Sopenharmony_ci done_index = 0; 327762306a36Sopenharmony_ci if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) 327862306a36Sopenharmony_ci mapping->writeback_index = done_index; 327962306a36Sopenharmony_ci 328062306a36Sopenharmony_ci if (nwritten) 328162306a36Sopenharmony_ci f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, 328262306a36Sopenharmony_ci NULL, 0, DATA); 328362306a36Sopenharmony_ci /* submit cached bio of IPU write */ 328462306a36Sopenharmony_ci if (bio) 328562306a36Sopenharmony_ci f2fs_submit_merged_ipu_write(sbi, &bio, NULL); 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 328862306a36Sopenharmony_ci if (pages != pages_local) 328962306a36Sopenharmony_ci kfree(pages); 329062306a36Sopenharmony_ci#endif 329162306a36Sopenharmony_ci 329262306a36Sopenharmony_ci return ret; 329362306a36Sopenharmony_ci} 329462306a36Sopenharmony_ci 329562306a36Sopenharmony_cistatic inline bool __should_serialize_io(struct inode *inode, 329662306a36Sopenharmony_ci struct writeback_control *wbc) 329762306a36Sopenharmony_ci{ 329862306a36Sopenharmony_ci /* to avoid deadlock in path of data flush */ 329962306a36Sopenharmony_ci if (F2FS_I(inode)->wb_task) 330062306a36Sopenharmony_ci return false; 330162306a36Sopenharmony_ci 330262306a36Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 330362306a36Sopenharmony_ci return false; 330462306a36Sopenharmony_ci if (IS_NOQUOTA(inode)) 330562306a36Sopenharmony_ci return false; 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci if (f2fs_need_compress_data(inode)) 330862306a36Sopenharmony_ci return true; 330962306a36Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_ALL) 331062306a36Sopenharmony_ci return true; 331162306a36Sopenharmony_ci if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks) 331262306a36Sopenharmony_ci return true; 331362306a36Sopenharmony_ci return false; 331462306a36Sopenharmony_ci} 331562306a36Sopenharmony_ci 331662306a36Sopenharmony_cistatic int __f2fs_write_data_pages(struct address_space *mapping, 331762306a36Sopenharmony_ci struct writeback_control *wbc, 331862306a36Sopenharmony_ci enum iostat_type io_type) 331962306a36Sopenharmony_ci{ 332062306a36Sopenharmony_ci struct inode *inode = mapping->host; 332162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 332262306a36Sopenharmony_ci struct blk_plug plug; 332362306a36Sopenharmony_ci int ret; 332462306a36Sopenharmony_ci bool locked = false; 332562306a36Sopenharmony_ci 332662306a36Sopenharmony_ci /* deal with chardevs and other special file */ 332762306a36Sopenharmony_ci if (!mapping->a_ops->writepage) 332862306a36Sopenharmony_ci return 0; 332962306a36Sopenharmony_ci 333062306a36Sopenharmony_ci /* skip writing if there is no dirty page in this inode */ 333162306a36Sopenharmony_ci if (!get_dirty_pages(inode) && wbc->sync_mode == WB_SYNC_NONE) 333262306a36Sopenharmony_ci return 0; 333362306a36Sopenharmony_ci 333462306a36Sopenharmony_ci /* during POR, we don't need to trigger writepage at all. */ 333562306a36Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 333662306a36Sopenharmony_ci goto skip_write; 333762306a36Sopenharmony_ci 333862306a36Sopenharmony_ci if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) && 333962306a36Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && 334062306a36Sopenharmony_ci get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) && 334162306a36Sopenharmony_ci f2fs_available_free_memory(sbi, DIRTY_DENTS)) 334262306a36Sopenharmony_ci goto skip_write; 334362306a36Sopenharmony_ci 334462306a36Sopenharmony_ci /* skip writing in file defragment preparing stage */ 334562306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_SKIP_WRITES)) 334662306a36Sopenharmony_ci goto skip_write; 334762306a36Sopenharmony_ci 334862306a36Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, DATA); 334962306a36Sopenharmony_ci 335062306a36Sopenharmony_ci /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */ 335162306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 335262306a36Sopenharmony_ci atomic_inc(&sbi->wb_sync_req[DATA]); 335362306a36Sopenharmony_ci else if (atomic_read(&sbi->wb_sync_req[DATA])) { 335462306a36Sopenharmony_ci /* to avoid potential deadlock */ 335562306a36Sopenharmony_ci if (current->plug) 335662306a36Sopenharmony_ci blk_finish_plug(current->plug); 335762306a36Sopenharmony_ci goto skip_write; 335862306a36Sopenharmony_ci } 335962306a36Sopenharmony_ci 336062306a36Sopenharmony_ci if (__should_serialize_io(inode, wbc)) { 336162306a36Sopenharmony_ci mutex_lock(&sbi->writepages); 336262306a36Sopenharmony_ci locked = true; 336362306a36Sopenharmony_ci } 336462306a36Sopenharmony_ci 336562306a36Sopenharmony_ci blk_start_plug(&plug); 336662306a36Sopenharmony_ci ret = f2fs_write_cache_pages(mapping, wbc, io_type); 336762306a36Sopenharmony_ci blk_finish_plug(&plug); 336862306a36Sopenharmony_ci 336962306a36Sopenharmony_ci if (locked) 337062306a36Sopenharmony_ci mutex_unlock(&sbi->writepages); 337162306a36Sopenharmony_ci 337262306a36Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 337362306a36Sopenharmony_ci atomic_dec(&sbi->wb_sync_req[DATA]); 337462306a36Sopenharmony_ci /* 337562306a36Sopenharmony_ci * if some pages were truncated, we cannot guarantee its mapping->host 337662306a36Sopenharmony_ci * to detect pending bios. 337762306a36Sopenharmony_ci */ 337862306a36Sopenharmony_ci 337962306a36Sopenharmony_ci f2fs_remove_dirty_inode(inode); 338062306a36Sopenharmony_ci return ret; 338162306a36Sopenharmony_ci 338262306a36Sopenharmony_ciskip_write: 338362306a36Sopenharmony_ci wbc->pages_skipped += get_dirty_pages(inode); 338462306a36Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, DATA); 338562306a36Sopenharmony_ci return 0; 338662306a36Sopenharmony_ci} 338762306a36Sopenharmony_ci 338862306a36Sopenharmony_cistatic int f2fs_write_data_pages(struct address_space *mapping, 338962306a36Sopenharmony_ci struct writeback_control *wbc) 339062306a36Sopenharmony_ci{ 339162306a36Sopenharmony_ci struct inode *inode = mapping->host; 339262306a36Sopenharmony_ci 339362306a36Sopenharmony_ci return __f2fs_write_data_pages(mapping, wbc, 339462306a36Sopenharmony_ci F2FS_I(inode)->cp_task == current ? 339562306a36Sopenharmony_ci FS_CP_DATA_IO : FS_DATA_IO); 339662306a36Sopenharmony_ci} 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_civoid f2fs_write_failed(struct inode *inode, loff_t to) 339962306a36Sopenharmony_ci{ 340062306a36Sopenharmony_ci loff_t i_size = i_size_read(inode); 340162306a36Sopenharmony_ci 340262306a36Sopenharmony_ci if (IS_NOQUOTA(inode)) 340362306a36Sopenharmony_ci return; 340462306a36Sopenharmony_ci 340562306a36Sopenharmony_ci /* In the fs-verity case, f2fs_end_enable_verity() does the truncate */ 340662306a36Sopenharmony_ci if (to > i_size && !f2fs_verity_in_progress(inode)) { 340762306a36Sopenharmony_ci f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 340862306a36Sopenharmony_ci filemap_invalidate_lock(inode->i_mapping); 340962306a36Sopenharmony_ci 341062306a36Sopenharmony_ci truncate_pagecache(inode, i_size); 341162306a36Sopenharmony_ci f2fs_truncate_blocks(inode, i_size, true); 341262306a36Sopenharmony_ci 341362306a36Sopenharmony_ci filemap_invalidate_unlock(inode->i_mapping); 341462306a36Sopenharmony_ci f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 341562306a36Sopenharmony_ci } 341662306a36Sopenharmony_ci} 341762306a36Sopenharmony_ci 341862306a36Sopenharmony_cistatic int prepare_write_begin(struct f2fs_sb_info *sbi, 341962306a36Sopenharmony_ci struct page *page, loff_t pos, unsigned len, 342062306a36Sopenharmony_ci block_t *blk_addr, bool *node_changed) 342162306a36Sopenharmony_ci{ 342262306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 342362306a36Sopenharmony_ci pgoff_t index = page->index; 342462306a36Sopenharmony_ci struct dnode_of_data dn; 342562306a36Sopenharmony_ci struct page *ipage; 342662306a36Sopenharmony_ci bool locked = false; 342762306a36Sopenharmony_ci int flag = F2FS_GET_BLOCK_PRE_AIO; 342862306a36Sopenharmony_ci int err = 0; 342962306a36Sopenharmony_ci 343062306a36Sopenharmony_ci /* 343162306a36Sopenharmony_ci * If a whole page is being written and we already preallocated all the 343262306a36Sopenharmony_ci * blocks, then there is no need to get a block address now. 343362306a36Sopenharmony_ci */ 343462306a36Sopenharmony_ci if (len == PAGE_SIZE && is_inode_flag_set(inode, FI_PREALLOCATED_ALL)) 343562306a36Sopenharmony_ci return 0; 343662306a36Sopenharmony_ci 343762306a36Sopenharmony_ci /* f2fs_lock_op avoids race between write CP and convert_inline_page */ 343862306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 343962306a36Sopenharmony_ci if (pos + len > MAX_INLINE_DATA(inode)) 344062306a36Sopenharmony_ci flag = F2FS_GET_BLOCK_DEFAULT; 344162306a36Sopenharmony_ci f2fs_map_lock(sbi, flag); 344262306a36Sopenharmony_ci locked = true; 344362306a36Sopenharmony_ci } else if ((pos & PAGE_MASK) >= i_size_read(inode)) { 344462306a36Sopenharmony_ci f2fs_map_lock(sbi, flag); 344562306a36Sopenharmony_ci locked = true; 344662306a36Sopenharmony_ci } 344762306a36Sopenharmony_ci 344862306a36Sopenharmony_cirestart: 344962306a36Sopenharmony_ci /* check inline_data */ 345062306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 345162306a36Sopenharmony_ci if (IS_ERR(ipage)) { 345262306a36Sopenharmony_ci err = PTR_ERR(ipage); 345362306a36Sopenharmony_ci goto unlock_out; 345462306a36Sopenharmony_ci } 345562306a36Sopenharmony_ci 345662306a36Sopenharmony_ci set_new_dnode(&dn, inode, ipage, ipage, 0); 345762306a36Sopenharmony_ci 345862306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 345962306a36Sopenharmony_ci if (pos + len <= MAX_INLINE_DATA(inode)) { 346062306a36Sopenharmony_ci f2fs_do_read_inline_data(page, ipage); 346162306a36Sopenharmony_ci set_inode_flag(inode, FI_DATA_EXIST); 346262306a36Sopenharmony_ci if (inode->i_nlink) 346362306a36Sopenharmony_ci set_page_private_inline(ipage); 346462306a36Sopenharmony_ci goto out; 346562306a36Sopenharmony_ci } 346662306a36Sopenharmony_ci err = f2fs_convert_inline_page(&dn, page); 346762306a36Sopenharmony_ci if (err || dn.data_blkaddr != NULL_ADDR) 346862306a36Sopenharmony_ci goto out; 346962306a36Sopenharmony_ci } 347062306a36Sopenharmony_ci 347162306a36Sopenharmony_ci if (!f2fs_lookup_read_extent_cache_block(inode, index, 347262306a36Sopenharmony_ci &dn.data_blkaddr)) { 347362306a36Sopenharmony_ci if (locked) { 347462306a36Sopenharmony_ci err = f2fs_reserve_block(&dn, index); 347562306a36Sopenharmony_ci goto out; 347662306a36Sopenharmony_ci } 347762306a36Sopenharmony_ci 347862306a36Sopenharmony_ci /* hole case */ 347962306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); 348062306a36Sopenharmony_ci if (!err && dn.data_blkaddr != NULL_ADDR) 348162306a36Sopenharmony_ci goto out; 348262306a36Sopenharmony_ci f2fs_put_dnode(&dn); 348362306a36Sopenharmony_ci f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO); 348462306a36Sopenharmony_ci WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO); 348562306a36Sopenharmony_ci locked = true; 348662306a36Sopenharmony_ci goto restart; 348762306a36Sopenharmony_ci } 348862306a36Sopenharmony_ciout: 348962306a36Sopenharmony_ci if (!err) { 349062306a36Sopenharmony_ci /* convert_inline_page can make node_changed */ 349162306a36Sopenharmony_ci *blk_addr = dn.data_blkaddr; 349262306a36Sopenharmony_ci *node_changed = dn.node_changed; 349362306a36Sopenharmony_ci } 349462306a36Sopenharmony_ci f2fs_put_dnode(&dn); 349562306a36Sopenharmony_ciunlock_out: 349662306a36Sopenharmony_ci if (locked) 349762306a36Sopenharmony_ci f2fs_map_unlock(sbi, flag); 349862306a36Sopenharmony_ci return err; 349962306a36Sopenharmony_ci} 350062306a36Sopenharmony_ci 350162306a36Sopenharmony_cistatic int __find_data_block(struct inode *inode, pgoff_t index, 350262306a36Sopenharmony_ci block_t *blk_addr) 350362306a36Sopenharmony_ci{ 350462306a36Sopenharmony_ci struct dnode_of_data dn; 350562306a36Sopenharmony_ci struct page *ipage; 350662306a36Sopenharmony_ci int err = 0; 350762306a36Sopenharmony_ci 350862306a36Sopenharmony_ci ipage = f2fs_get_node_page(F2FS_I_SB(inode), inode->i_ino); 350962306a36Sopenharmony_ci if (IS_ERR(ipage)) 351062306a36Sopenharmony_ci return PTR_ERR(ipage); 351162306a36Sopenharmony_ci 351262306a36Sopenharmony_ci set_new_dnode(&dn, inode, ipage, ipage, 0); 351362306a36Sopenharmony_ci 351462306a36Sopenharmony_ci if (!f2fs_lookup_read_extent_cache_block(inode, index, 351562306a36Sopenharmony_ci &dn.data_blkaddr)) { 351662306a36Sopenharmony_ci /* hole case */ 351762306a36Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); 351862306a36Sopenharmony_ci if (err) { 351962306a36Sopenharmony_ci dn.data_blkaddr = NULL_ADDR; 352062306a36Sopenharmony_ci err = 0; 352162306a36Sopenharmony_ci } 352262306a36Sopenharmony_ci } 352362306a36Sopenharmony_ci *blk_addr = dn.data_blkaddr; 352462306a36Sopenharmony_ci f2fs_put_dnode(&dn); 352562306a36Sopenharmony_ci return err; 352662306a36Sopenharmony_ci} 352762306a36Sopenharmony_ci 352862306a36Sopenharmony_cistatic int __reserve_data_block(struct inode *inode, pgoff_t index, 352962306a36Sopenharmony_ci block_t *blk_addr, bool *node_changed) 353062306a36Sopenharmony_ci{ 353162306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 353262306a36Sopenharmony_ci struct dnode_of_data dn; 353362306a36Sopenharmony_ci struct page *ipage; 353462306a36Sopenharmony_ci int err = 0; 353562306a36Sopenharmony_ci 353662306a36Sopenharmony_ci f2fs_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO); 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 353962306a36Sopenharmony_ci if (IS_ERR(ipage)) { 354062306a36Sopenharmony_ci err = PTR_ERR(ipage); 354162306a36Sopenharmony_ci goto unlock_out; 354262306a36Sopenharmony_ci } 354362306a36Sopenharmony_ci set_new_dnode(&dn, inode, ipage, ipage, 0); 354462306a36Sopenharmony_ci 354562306a36Sopenharmony_ci if (!f2fs_lookup_read_extent_cache_block(dn.inode, index, 354662306a36Sopenharmony_ci &dn.data_blkaddr)) 354762306a36Sopenharmony_ci err = f2fs_reserve_block(&dn, index); 354862306a36Sopenharmony_ci 354962306a36Sopenharmony_ci *blk_addr = dn.data_blkaddr; 355062306a36Sopenharmony_ci *node_changed = dn.node_changed; 355162306a36Sopenharmony_ci f2fs_put_dnode(&dn); 355262306a36Sopenharmony_ci 355362306a36Sopenharmony_ciunlock_out: 355462306a36Sopenharmony_ci f2fs_map_unlock(sbi, F2FS_GET_BLOCK_PRE_AIO); 355562306a36Sopenharmony_ci return err; 355662306a36Sopenharmony_ci} 355762306a36Sopenharmony_ci 355862306a36Sopenharmony_cistatic int prepare_atomic_write_begin(struct f2fs_sb_info *sbi, 355962306a36Sopenharmony_ci struct page *page, loff_t pos, unsigned int len, 356062306a36Sopenharmony_ci block_t *blk_addr, bool *node_changed, bool *use_cow) 356162306a36Sopenharmony_ci{ 356262306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 356362306a36Sopenharmony_ci struct inode *cow_inode = F2FS_I(inode)->cow_inode; 356462306a36Sopenharmony_ci pgoff_t index = page->index; 356562306a36Sopenharmony_ci int err = 0; 356662306a36Sopenharmony_ci block_t ori_blk_addr = NULL_ADDR; 356762306a36Sopenharmony_ci 356862306a36Sopenharmony_ci /* If pos is beyond the end of file, reserve a new block in COW inode */ 356962306a36Sopenharmony_ci if ((pos & PAGE_MASK) >= i_size_read(inode)) 357062306a36Sopenharmony_ci goto reserve_block; 357162306a36Sopenharmony_ci 357262306a36Sopenharmony_ci /* Look for the block in COW inode first */ 357362306a36Sopenharmony_ci err = __find_data_block(cow_inode, index, blk_addr); 357462306a36Sopenharmony_ci if (err) { 357562306a36Sopenharmony_ci return err; 357662306a36Sopenharmony_ci } else if (*blk_addr != NULL_ADDR) { 357762306a36Sopenharmony_ci *use_cow = true; 357862306a36Sopenharmony_ci return 0; 357962306a36Sopenharmony_ci } 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_ci if (is_inode_flag_set(inode, FI_ATOMIC_REPLACE)) 358262306a36Sopenharmony_ci goto reserve_block; 358362306a36Sopenharmony_ci 358462306a36Sopenharmony_ci /* Look for the block in the original inode */ 358562306a36Sopenharmony_ci err = __find_data_block(inode, index, &ori_blk_addr); 358662306a36Sopenharmony_ci if (err) 358762306a36Sopenharmony_ci return err; 358862306a36Sopenharmony_ci 358962306a36Sopenharmony_cireserve_block: 359062306a36Sopenharmony_ci /* Finally, we should reserve a new block in COW inode for the update */ 359162306a36Sopenharmony_ci err = __reserve_data_block(cow_inode, index, blk_addr, node_changed); 359262306a36Sopenharmony_ci if (err) 359362306a36Sopenharmony_ci return err; 359462306a36Sopenharmony_ci inc_atomic_write_cnt(inode); 359562306a36Sopenharmony_ci 359662306a36Sopenharmony_ci if (ori_blk_addr != NULL_ADDR) 359762306a36Sopenharmony_ci *blk_addr = ori_blk_addr; 359862306a36Sopenharmony_ci return 0; 359962306a36Sopenharmony_ci} 360062306a36Sopenharmony_ci 360162306a36Sopenharmony_cistatic int f2fs_write_begin(struct file *file, struct address_space *mapping, 360262306a36Sopenharmony_ci loff_t pos, unsigned len, struct page **pagep, void **fsdata) 360362306a36Sopenharmony_ci{ 360462306a36Sopenharmony_ci struct inode *inode = mapping->host; 360562306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 360662306a36Sopenharmony_ci struct page *page = NULL; 360762306a36Sopenharmony_ci pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; 360862306a36Sopenharmony_ci bool need_balance = false; 360962306a36Sopenharmony_ci bool use_cow = false; 361062306a36Sopenharmony_ci block_t blkaddr = NULL_ADDR; 361162306a36Sopenharmony_ci int err = 0; 361262306a36Sopenharmony_ci 361362306a36Sopenharmony_ci trace_f2fs_write_begin(inode, pos, len); 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci if (!f2fs_is_checkpoint_ready(sbi)) { 361662306a36Sopenharmony_ci err = -ENOSPC; 361762306a36Sopenharmony_ci goto fail; 361862306a36Sopenharmony_ci } 361962306a36Sopenharmony_ci 362062306a36Sopenharmony_ci /* 362162306a36Sopenharmony_ci * We should check this at this moment to avoid deadlock on inode page 362262306a36Sopenharmony_ci * and #0 page. The locking rule for inline_data conversion should be: 362362306a36Sopenharmony_ci * lock_page(page #0) -> lock_page(inode_page) 362462306a36Sopenharmony_ci */ 362562306a36Sopenharmony_ci if (index != 0) { 362662306a36Sopenharmony_ci err = f2fs_convert_inline_inode(inode); 362762306a36Sopenharmony_ci if (err) 362862306a36Sopenharmony_ci goto fail; 362962306a36Sopenharmony_ci } 363062306a36Sopenharmony_ci 363162306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 363262306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 363362306a36Sopenharmony_ci int ret; 363462306a36Sopenharmony_ci 363562306a36Sopenharmony_ci *fsdata = NULL; 363662306a36Sopenharmony_ci 363762306a36Sopenharmony_ci if (len == PAGE_SIZE && !(f2fs_is_atomic_file(inode))) 363862306a36Sopenharmony_ci goto repeat; 363962306a36Sopenharmony_ci 364062306a36Sopenharmony_ci ret = f2fs_prepare_compress_overwrite(inode, pagep, 364162306a36Sopenharmony_ci index, fsdata); 364262306a36Sopenharmony_ci if (ret < 0) { 364362306a36Sopenharmony_ci err = ret; 364462306a36Sopenharmony_ci goto fail; 364562306a36Sopenharmony_ci } else if (ret) { 364662306a36Sopenharmony_ci return 0; 364762306a36Sopenharmony_ci } 364862306a36Sopenharmony_ci } 364962306a36Sopenharmony_ci#endif 365062306a36Sopenharmony_ci 365162306a36Sopenharmony_cirepeat: 365262306a36Sopenharmony_ci /* 365362306a36Sopenharmony_ci * Do not use grab_cache_page_write_begin() to avoid deadlock due to 365462306a36Sopenharmony_ci * wait_for_stable_page. Will wait that below with our IO control. 365562306a36Sopenharmony_ci */ 365662306a36Sopenharmony_ci page = f2fs_pagecache_get_page(mapping, index, 365762306a36Sopenharmony_ci FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS); 365862306a36Sopenharmony_ci if (!page) { 365962306a36Sopenharmony_ci err = -ENOMEM; 366062306a36Sopenharmony_ci goto fail; 366162306a36Sopenharmony_ci } 366262306a36Sopenharmony_ci 366362306a36Sopenharmony_ci /* TODO: cluster can be compressed due to race with .writepage */ 366462306a36Sopenharmony_ci 366562306a36Sopenharmony_ci *pagep = page; 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 366862306a36Sopenharmony_ci err = prepare_atomic_write_begin(sbi, page, pos, len, 366962306a36Sopenharmony_ci &blkaddr, &need_balance, &use_cow); 367062306a36Sopenharmony_ci else 367162306a36Sopenharmony_ci err = prepare_write_begin(sbi, page, pos, len, 367262306a36Sopenharmony_ci &blkaddr, &need_balance); 367362306a36Sopenharmony_ci if (err) 367462306a36Sopenharmony_ci goto fail; 367562306a36Sopenharmony_ci 367662306a36Sopenharmony_ci if (need_balance && !IS_NOQUOTA(inode) && 367762306a36Sopenharmony_ci has_not_enough_free_secs(sbi, 0, 0)) { 367862306a36Sopenharmony_ci unlock_page(page); 367962306a36Sopenharmony_ci f2fs_balance_fs(sbi, true); 368062306a36Sopenharmony_ci lock_page(page); 368162306a36Sopenharmony_ci if (page->mapping != mapping) { 368262306a36Sopenharmony_ci /* The page got truncated from under us */ 368362306a36Sopenharmony_ci f2fs_put_page(page, 1); 368462306a36Sopenharmony_ci goto repeat; 368562306a36Sopenharmony_ci } 368662306a36Sopenharmony_ci } 368762306a36Sopenharmony_ci 368862306a36Sopenharmony_ci f2fs_wait_on_page_writeback(page, DATA, false, true); 368962306a36Sopenharmony_ci 369062306a36Sopenharmony_ci if (len == PAGE_SIZE || PageUptodate(page)) 369162306a36Sopenharmony_ci return 0; 369262306a36Sopenharmony_ci 369362306a36Sopenharmony_ci if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && 369462306a36Sopenharmony_ci !f2fs_verity_in_progress(inode)) { 369562306a36Sopenharmony_ci zero_user_segment(page, len, PAGE_SIZE); 369662306a36Sopenharmony_ci return 0; 369762306a36Sopenharmony_ci } 369862306a36Sopenharmony_ci 369962306a36Sopenharmony_ci if (blkaddr == NEW_ADDR) { 370062306a36Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 370162306a36Sopenharmony_ci SetPageUptodate(page); 370262306a36Sopenharmony_ci } else { 370362306a36Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, 370462306a36Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 370562306a36Sopenharmony_ci err = -EFSCORRUPTED; 370662306a36Sopenharmony_ci f2fs_handle_error(sbi, ERROR_INVALID_BLKADDR); 370762306a36Sopenharmony_ci goto fail; 370862306a36Sopenharmony_ci } 370962306a36Sopenharmony_ci err = f2fs_submit_page_read(use_cow ? 371062306a36Sopenharmony_ci F2FS_I(inode)->cow_inode : inode, page, 371162306a36Sopenharmony_ci blkaddr, 0, true); 371262306a36Sopenharmony_ci if (err) 371362306a36Sopenharmony_ci goto fail; 371462306a36Sopenharmony_ci 371562306a36Sopenharmony_ci lock_page(page); 371662306a36Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 371762306a36Sopenharmony_ci f2fs_put_page(page, 1); 371862306a36Sopenharmony_ci goto repeat; 371962306a36Sopenharmony_ci } 372062306a36Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 372162306a36Sopenharmony_ci err = -EIO; 372262306a36Sopenharmony_ci goto fail; 372362306a36Sopenharmony_ci } 372462306a36Sopenharmony_ci } 372562306a36Sopenharmony_ci return 0; 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_cifail: 372862306a36Sopenharmony_ci f2fs_put_page(page, 1); 372962306a36Sopenharmony_ci f2fs_write_failed(inode, pos + len); 373062306a36Sopenharmony_ci return err; 373162306a36Sopenharmony_ci} 373262306a36Sopenharmony_ci 373362306a36Sopenharmony_cistatic int f2fs_write_end(struct file *file, 373462306a36Sopenharmony_ci struct address_space *mapping, 373562306a36Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, 373662306a36Sopenharmony_ci struct page *page, void *fsdata) 373762306a36Sopenharmony_ci{ 373862306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 373962306a36Sopenharmony_ci 374062306a36Sopenharmony_ci trace_f2fs_write_end(inode, pos, len, copied); 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ci /* 374362306a36Sopenharmony_ci * This should be come from len == PAGE_SIZE, and we expect copied 374462306a36Sopenharmony_ci * should be PAGE_SIZE. Otherwise, we treat it with zero copied and 374562306a36Sopenharmony_ci * let generic_perform_write() try to copy data again through copied=0. 374662306a36Sopenharmony_ci */ 374762306a36Sopenharmony_ci if (!PageUptodate(page)) { 374862306a36Sopenharmony_ci if (unlikely(copied != len)) 374962306a36Sopenharmony_ci copied = 0; 375062306a36Sopenharmony_ci else 375162306a36Sopenharmony_ci SetPageUptodate(page); 375262306a36Sopenharmony_ci } 375362306a36Sopenharmony_ci 375462306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 375562306a36Sopenharmony_ci /* overwrite compressed file */ 375662306a36Sopenharmony_ci if (f2fs_compressed_file(inode) && fsdata) { 375762306a36Sopenharmony_ci f2fs_compress_write_end(inode, fsdata, page->index, copied); 375862306a36Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 375962306a36Sopenharmony_ci 376062306a36Sopenharmony_ci if (pos + copied > i_size_read(inode) && 376162306a36Sopenharmony_ci !f2fs_verity_in_progress(inode)) 376262306a36Sopenharmony_ci f2fs_i_size_write(inode, pos + copied); 376362306a36Sopenharmony_ci return copied; 376462306a36Sopenharmony_ci } 376562306a36Sopenharmony_ci#endif 376662306a36Sopenharmony_ci 376762306a36Sopenharmony_ci if (!copied) 376862306a36Sopenharmony_ci goto unlock_out; 376962306a36Sopenharmony_ci 377062306a36Sopenharmony_ci set_page_dirty(page); 377162306a36Sopenharmony_ci 377262306a36Sopenharmony_ci if (pos + copied > i_size_read(inode) && 377362306a36Sopenharmony_ci !f2fs_verity_in_progress(inode)) { 377462306a36Sopenharmony_ci f2fs_i_size_write(inode, pos + copied); 377562306a36Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 377662306a36Sopenharmony_ci f2fs_i_size_write(F2FS_I(inode)->cow_inode, 377762306a36Sopenharmony_ci pos + copied); 377862306a36Sopenharmony_ci } 377962306a36Sopenharmony_ciunlock_out: 378062306a36Sopenharmony_ci f2fs_put_page(page, 1); 378162306a36Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 378262306a36Sopenharmony_ci return copied; 378362306a36Sopenharmony_ci} 378462306a36Sopenharmony_ci 378562306a36Sopenharmony_civoid f2fs_invalidate_folio(struct folio *folio, size_t offset, size_t length) 378662306a36Sopenharmony_ci{ 378762306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 378862306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 378962306a36Sopenharmony_ci 379062306a36Sopenharmony_ci if (inode->i_ino >= F2FS_ROOT_INO(sbi) && 379162306a36Sopenharmony_ci (offset || length != folio_size(folio))) 379262306a36Sopenharmony_ci return; 379362306a36Sopenharmony_ci 379462306a36Sopenharmony_ci if (folio_test_dirty(folio)) { 379562306a36Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi)) { 379662306a36Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_META); 379762306a36Sopenharmony_ci } else if (inode->i_ino == F2FS_NODE_INO(sbi)) { 379862306a36Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 379962306a36Sopenharmony_ci } else { 380062306a36Sopenharmony_ci inode_dec_dirty_pages(inode); 380162306a36Sopenharmony_ci f2fs_remove_dirty_inode(inode); 380262306a36Sopenharmony_ci } 380362306a36Sopenharmony_ci } 380462306a36Sopenharmony_ci clear_page_private_all(&folio->page); 380562306a36Sopenharmony_ci} 380662306a36Sopenharmony_ci 380762306a36Sopenharmony_cibool f2fs_release_folio(struct folio *folio, gfp_t wait) 380862306a36Sopenharmony_ci{ 380962306a36Sopenharmony_ci /* If this is dirty folio, keep private data */ 381062306a36Sopenharmony_ci if (folio_test_dirty(folio)) 381162306a36Sopenharmony_ci return false; 381262306a36Sopenharmony_ci 381362306a36Sopenharmony_ci clear_page_private_all(&folio->page); 381462306a36Sopenharmony_ci return true; 381562306a36Sopenharmony_ci} 381662306a36Sopenharmony_ci 381762306a36Sopenharmony_cistatic bool f2fs_dirty_data_folio(struct address_space *mapping, 381862306a36Sopenharmony_ci struct folio *folio) 381962306a36Sopenharmony_ci{ 382062306a36Sopenharmony_ci struct inode *inode = mapping->host; 382162306a36Sopenharmony_ci 382262306a36Sopenharmony_ci trace_f2fs_set_page_dirty(&folio->page, DATA); 382362306a36Sopenharmony_ci 382462306a36Sopenharmony_ci if (!folio_test_uptodate(folio)) 382562306a36Sopenharmony_ci folio_mark_uptodate(folio); 382662306a36Sopenharmony_ci BUG_ON(folio_test_swapcache(folio)); 382762306a36Sopenharmony_ci 382862306a36Sopenharmony_ci if (filemap_dirty_folio(mapping, folio)) { 382962306a36Sopenharmony_ci f2fs_update_dirty_folio(inode, folio); 383062306a36Sopenharmony_ci return true; 383162306a36Sopenharmony_ci } 383262306a36Sopenharmony_ci return false; 383362306a36Sopenharmony_ci} 383462306a36Sopenharmony_ci 383562306a36Sopenharmony_ci 383662306a36Sopenharmony_cistatic sector_t f2fs_bmap_compress(struct inode *inode, sector_t block) 383762306a36Sopenharmony_ci{ 383862306a36Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 383962306a36Sopenharmony_ci struct dnode_of_data dn; 384062306a36Sopenharmony_ci sector_t start_idx, blknr = 0; 384162306a36Sopenharmony_ci int ret; 384262306a36Sopenharmony_ci 384362306a36Sopenharmony_ci start_idx = round_down(block, F2FS_I(inode)->i_cluster_size); 384462306a36Sopenharmony_ci 384562306a36Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 384662306a36Sopenharmony_ci ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); 384762306a36Sopenharmony_ci if (ret) 384862306a36Sopenharmony_ci return 0; 384962306a36Sopenharmony_ci 385062306a36Sopenharmony_ci if (dn.data_blkaddr != COMPRESS_ADDR) { 385162306a36Sopenharmony_ci dn.ofs_in_node += block - start_idx; 385262306a36Sopenharmony_ci blknr = f2fs_data_blkaddr(&dn); 385362306a36Sopenharmony_ci if (!__is_valid_data_blkaddr(blknr)) 385462306a36Sopenharmony_ci blknr = 0; 385562306a36Sopenharmony_ci } 385662306a36Sopenharmony_ci 385762306a36Sopenharmony_ci f2fs_put_dnode(&dn); 385862306a36Sopenharmony_ci return blknr; 385962306a36Sopenharmony_ci#else 386062306a36Sopenharmony_ci return 0; 386162306a36Sopenharmony_ci#endif 386262306a36Sopenharmony_ci} 386362306a36Sopenharmony_ci 386462306a36Sopenharmony_ci 386562306a36Sopenharmony_cistatic sector_t f2fs_bmap(struct address_space *mapping, sector_t block) 386662306a36Sopenharmony_ci{ 386762306a36Sopenharmony_ci struct inode *inode = mapping->host; 386862306a36Sopenharmony_ci sector_t blknr = 0; 386962306a36Sopenharmony_ci 387062306a36Sopenharmony_ci if (f2fs_has_inline_data(inode)) 387162306a36Sopenharmony_ci goto out; 387262306a36Sopenharmony_ci 387362306a36Sopenharmony_ci /* make sure allocating whole blocks */ 387462306a36Sopenharmony_ci if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) 387562306a36Sopenharmony_ci filemap_write_and_wait(mapping); 387662306a36Sopenharmony_ci 387762306a36Sopenharmony_ci /* Block number less than F2FS MAX BLOCKS */ 387862306a36Sopenharmony_ci if (unlikely(block >= max_file_blocks(inode))) 387962306a36Sopenharmony_ci goto out; 388062306a36Sopenharmony_ci 388162306a36Sopenharmony_ci if (f2fs_compressed_file(inode)) { 388262306a36Sopenharmony_ci blknr = f2fs_bmap_compress(inode, block); 388362306a36Sopenharmony_ci } else { 388462306a36Sopenharmony_ci struct f2fs_map_blocks map; 388562306a36Sopenharmony_ci 388662306a36Sopenharmony_ci memset(&map, 0, sizeof(map)); 388762306a36Sopenharmony_ci map.m_lblk = block; 388862306a36Sopenharmony_ci map.m_len = 1; 388962306a36Sopenharmony_ci map.m_next_pgofs = NULL; 389062306a36Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 389162306a36Sopenharmony_ci 389262306a36Sopenharmony_ci if (!f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_BMAP)) 389362306a36Sopenharmony_ci blknr = map.m_pblk; 389462306a36Sopenharmony_ci } 389562306a36Sopenharmony_ciout: 389662306a36Sopenharmony_ci trace_f2fs_bmap(inode, block, blknr); 389762306a36Sopenharmony_ci return blknr; 389862306a36Sopenharmony_ci} 389962306a36Sopenharmony_ci 390062306a36Sopenharmony_ci#ifdef CONFIG_SWAP 390162306a36Sopenharmony_cistatic int f2fs_migrate_blocks(struct inode *inode, block_t start_blk, 390262306a36Sopenharmony_ci unsigned int blkcnt) 390362306a36Sopenharmony_ci{ 390462306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 390562306a36Sopenharmony_ci unsigned int blkofs; 390662306a36Sopenharmony_ci unsigned int blk_per_sec = BLKS_PER_SEC(sbi); 390762306a36Sopenharmony_ci unsigned int secidx = start_blk / blk_per_sec; 390862306a36Sopenharmony_ci unsigned int end_sec = secidx + blkcnt / blk_per_sec; 390962306a36Sopenharmony_ci int ret = 0; 391062306a36Sopenharmony_ci 391162306a36Sopenharmony_ci f2fs_down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 391262306a36Sopenharmony_ci filemap_invalidate_lock(inode->i_mapping); 391362306a36Sopenharmony_ci 391462306a36Sopenharmony_ci set_inode_flag(inode, FI_ALIGNED_WRITE); 391562306a36Sopenharmony_ci set_inode_flag(inode, FI_OPU_WRITE); 391662306a36Sopenharmony_ci 391762306a36Sopenharmony_ci for (; secidx < end_sec; secidx++) { 391862306a36Sopenharmony_ci f2fs_down_write(&sbi->pin_sem); 391962306a36Sopenharmony_ci 392062306a36Sopenharmony_ci f2fs_lock_op(sbi); 392162306a36Sopenharmony_ci f2fs_allocate_new_section(sbi, CURSEG_COLD_DATA_PINNED, false); 392262306a36Sopenharmony_ci f2fs_unlock_op(sbi); 392362306a36Sopenharmony_ci 392462306a36Sopenharmony_ci set_inode_flag(inode, FI_SKIP_WRITES); 392562306a36Sopenharmony_ci 392662306a36Sopenharmony_ci for (blkofs = 0; blkofs < blk_per_sec; blkofs++) { 392762306a36Sopenharmony_ci struct page *page; 392862306a36Sopenharmony_ci unsigned int blkidx = secidx * blk_per_sec + blkofs; 392962306a36Sopenharmony_ci 393062306a36Sopenharmony_ci page = f2fs_get_lock_data_page(inode, blkidx, true); 393162306a36Sopenharmony_ci if (IS_ERR(page)) { 393262306a36Sopenharmony_ci f2fs_up_write(&sbi->pin_sem); 393362306a36Sopenharmony_ci ret = PTR_ERR(page); 393462306a36Sopenharmony_ci goto done; 393562306a36Sopenharmony_ci } 393662306a36Sopenharmony_ci 393762306a36Sopenharmony_ci set_page_dirty(page); 393862306a36Sopenharmony_ci f2fs_put_page(page, 1); 393962306a36Sopenharmony_ci } 394062306a36Sopenharmony_ci 394162306a36Sopenharmony_ci clear_inode_flag(inode, FI_SKIP_WRITES); 394262306a36Sopenharmony_ci 394362306a36Sopenharmony_ci ret = filemap_fdatawrite(inode->i_mapping); 394462306a36Sopenharmony_ci 394562306a36Sopenharmony_ci f2fs_up_write(&sbi->pin_sem); 394662306a36Sopenharmony_ci 394762306a36Sopenharmony_ci if (ret) 394862306a36Sopenharmony_ci break; 394962306a36Sopenharmony_ci } 395062306a36Sopenharmony_ci 395162306a36Sopenharmony_cidone: 395262306a36Sopenharmony_ci clear_inode_flag(inode, FI_SKIP_WRITES); 395362306a36Sopenharmony_ci clear_inode_flag(inode, FI_OPU_WRITE); 395462306a36Sopenharmony_ci clear_inode_flag(inode, FI_ALIGNED_WRITE); 395562306a36Sopenharmony_ci 395662306a36Sopenharmony_ci filemap_invalidate_unlock(inode->i_mapping); 395762306a36Sopenharmony_ci f2fs_up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 395862306a36Sopenharmony_ci 395962306a36Sopenharmony_ci return ret; 396062306a36Sopenharmony_ci} 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_cistatic int check_swap_activate(struct swap_info_struct *sis, 396362306a36Sopenharmony_ci struct file *swap_file, sector_t *span) 396462306a36Sopenharmony_ci{ 396562306a36Sopenharmony_ci struct address_space *mapping = swap_file->f_mapping; 396662306a36Sopenharmony_ci struct inode *inode = mapping->host; 396762306a36Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 396862306a36Sopenharmony_ci sector_t cur_lblock; 396962306a36Sopenharmony_ci sector_t last_lblock; 397062306a36Sopenharmony_ci sector_t pblock; 397162306a36Sopenharmony_ci sector_t lowest_pblock = -1; 397262306a36Sopenharmony_ci sector_t highest_pblock = 0; 397362306a36Sopenharmony_ci int nr_extents = 0; 397462306a36Sopenharmony_ci unsigned long nr_pblocks; 397562306a36Sopenharmony_ci unsigned int blks_per_sec = BLKS_PER_SEC(sbi); 397662306a36Sopenharmony_ci unsigned int sec_blks_mask = BLKS_PER_SEC(sbi) - 1; 397762306a36Sopenharmony_ci unsigned int not_aligned = 0; 397862306a36Sopenharmony_ci int ret = 0; 397962306a36Sopenharmony_ci 398062306a36Sopenharmony_ci /* 398162306a36Sopenharmony_ci * Map all the blocks into the extent list. This code doesn't try 398262306a36Sopenharmony_ci * to be very smart. 398362306a36Sopenharmony_ci */ 398462306a36Sopenharmony_ci cur_lblock = 0; 398562306a36Sopenharmony_ci last_lblock = bytes_to_blks(inode, i_size_read(inode)); 398662306a36Sopenharmony_ci 398762306a36Sopenharmony_ci while (cur_lblock < last_lblock && cur_lblock < sis->max) { 398862306a36Sopenharmony_ci struct f2fs_map_blocks map; 398962306a36Sopenharmony_ciretry: 399062306a36Sopenharmony_ci cond_resched(); 399162306a36Sopenharmony_ci 399262306a36Sopenharmony_ci memset(&map, 0, sizeof(map)); 399362306a36Sopenharmony_ci map.m_lblk = cur_lblock; 399462306a36Sopenharmony_ci map.m_len = last_lblock - cur_lblock; 399562306a36Sopenharmony_ci map.m_next_pgofs = NULL; 399662306a36Sopenharmony_ci map.m_next_extent = NULL; 399762306a36Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 399862306a36Sopenharmony_ci map.m_may_create = false; 399962306a36Sopenharmony_ci 400062306a36Sopenharmony_ci ret = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); 400162306a36Sopenharmony_ci if (ret) 400262306a36Sopenharmony_ci goto out; 400362306a36Sopenharmony_ci 400462306a36Sopenharmony_ci /* hole */ 400562306a36Sopenharmony_ci if (!(map.m_flags & F2FS_MAP_FLAGS)) { 400662306a36Sopenharmony_ci f2fs_err(sbi, "Swapfile has holes"); 400762306a36Sopenharmony_ci ret = -EINVAL; 400862306a36Sopenharmony_ci goto out; 400962306a36Sopenharmony_ci } 401062306a36Sopenharmony_ci 401162306a36Sopenharmony_ci pblock = map.m_pblk; 401262306a36Sopenharmony_ci nr_pblocks = map.m_len; 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_ci if ((pblock - SM_I(sbi)->main_blkaddr) & sec_blks_mask || 401562306a36Sopenharmony_ci nr_pblocks & sec_blks_mask) { 401662306a36Sopenharmony_ci not_aligned++; 401762306a36Sopenharmony_ci 401862306a36Sopenharmony_ci nr_pblocks = roundup(nr_pblocks, blks_per_sec); 401962306a36Sopenharmony_ci if (cur_lblock + nr_pblocks > sis->max) 402062306a36Sopenharmony_ci nr_pblocks -= blks_per_sec; 402162306a36Sopenharmony_ci 402262306a36Sopenharmony_ci if (!nr_pblocks) { 402362306a36Sopenharmony_ci /* this extent is last one */ 402462306a36Sopenharmony_ci nr_pblocks = map.m_len; 402562306a36Sopenharmony_ci f2fs_warn(sbi, "Swapfile: last extent is not aligned to section"); 402662306a36Sopenharmony_ci goto next; 402762306a36Sopenharmony_ci } 402862306a36Sopenharmony_ci 402962306a36Sopenharmony_ci ret = f2fs_migrate_blocks(inode, cur_lblock, 403062306a36Sopenharmony_ci nr_pblocks); 403162306a36Sopenharmony_ci if (ret) 403262306a36Sopenharmony_ci goto out; 403362306a36Sopenharmony_ci goto retry; 403462306a36Sopenharmony_ci } 403562306a36Sopenharmony_cinext: 403662306a36Sopenharmony_ci if (cur_lblock + nr_pblocks >= sis->max) 403762306a36Sopenharmony_ci nr_pblocks = sis->max - cur_lblock; 403862306a36Sopenharmony_ci 403962306a36Sopenharmony_ci if (cur_lblock) { /* exclude the header page */ 404062306a36Sopenharmony_ci if (pblock < lowest_pblock) 404162306a36Sopenharmony_ci lowest_pblock = pblock; 404262306a36Sopenharmony_ci if (pblock + nr_pblocks - 1 > highest_pblock) 404362306a36Sopenharmony_ci highest_pblock = pblock + nr_pblocks - 1; 404462306a36Sopenharmony_ci } 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci /* 404762306a36Sopenharmony_ci * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks 404862306a36Sopenharmony_ci */ 404962306a36Sopenharmony_ci ret = add_swap_extent(sis, cur_lblock, nr_pblocks, pblock); 405062306a36Sopenharmony_ci if (ret < 0) 405162306a36Sopenharmony_ci goto out; 405262306a36Sopenharmony_ci nr_extents += ret; 405362306a36Sopenharmony_ci cur_lblock += nr_pblocks; 405462306a36Sopenharmony_ci } 405562306a36Sopenharmony_ci ret = nr_extents; 405662306a36Sopenharmony_ci *span = 1 + highest_pblock - lowest_pblock; 405762306a36Sopenharmony_ci if (cur_lblock == 0) 405862306a36Sopenharmony_ci cur_lblock = 1; /* force Empty message */ 405962306a36Sopenharmony_ci sis->max = cur_lblock; 406062306a36Sopenharmony_ci sis->pages = cur_lblock - 1; 406162306a36Sopenharmony_ci sis->highest_bit = cur_lblock - 1; 406262306a36Sopenharmony_ciout: 406362306a36Sopenharmony_ci if (not_aligned) 406462306a36Sopenharmony_ci f2fs_warn(sbi, "Swapfile (%u) is not align to section: 1) creat(), 2) ioctl(F2FS_IOC_SET_PIN_FILE), 3) fallocate(%u * N)", 406562306a36Sopenharmony_ci not_aligned, blks_per_sec * F2FS_BLKSIZE); 406662306a36Sopenharmony_ci return ret; 406762306a36Sopenharmony_ci} 406862306a36Sopenharmony_ci 406962306a36Sopenharmony_cistatic int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, 407062306a36Sopenharmony_ci sector_t *span) 407162306a36Sopenharmony_ci{ 407262306a36Sopenharmony_ci struct inode *inode = file_inode(file); 407362306a36Sopenharmony_ci int ret; 407462306a36Sopenharmony_ci 407562306a36Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 407662306a36Sopenharmony_ci return -EINVAL; 407762306a36Sopenharmony_ci 407862306a36Sopenharmony_ci if (f2fs_readonly(F2FS_I_SB(inode)->sb)) 407962306a36Sopenharmony_ci return -EROFS; 408062306a36Sopenharmony_ci 408162306a36Sopenharmony_ci if (f2fs_lfs_mode(F2FS_I_SB(inode))) { 408262306a36Sopenharmony_ci f2fs_err(F2FS_I_SB(inode), 408362306a36Sopenharmony_ci "Swapfile not supported in LFS mode"); 408462306a36Sopenharmony_ci return -EINVAL; 408562306a36Sopenharmony_ci } 408662306a36Sopenharmony_ci 408762306a36Sopenharmony_ci ret = f2fs_convert_inline_inode(inode); 408862306a36Sopenharmony_ci if (ret) 408962306a36Sopenharmony_ci return ret; 409062306a36Sopenharmony_ci 409162306a36Sopenharmony_ci if (!f2fs_disable_compressed_file(inode)) 409262306a36Sopenharmony_ci return -EINVAL; 409362306a36Sopenharmony_ci 409462306a36Sopenharmony_ci f2fs_precache_extents(inode); 409562306a36Sopenharmony_ci 409662306a36Sopenharmony_ci ret = check_swap_activate(sis, file, span); 409762306a36Sopenharmony_ci if (ret < 0) 409862306a36Sopenharmony_ci return ret; 409962306a36Sopenharmony_ci 410062306a36Sopenharmony_ci stat_inc_swapfile_inode(inode); 410162306a36Sopenharmony_ci set_inode_flag(inode, FI_PIN_FILE); 410262306a36Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 410362306a36Sopenharmony_ci return ret; 410462306a36Sopenharmony_ci} 410562306a36Sopenharmony_ci 410662306a36Sopenharmony_cistatic void f2fs_swap_deactivate(struct file *file) 410762306a36Sopenharmony_ci{ 410862306a36Sopenharmony_ci struct inode *inode = file_inode(file); 410962306a36Sopenharmony_ci 411062306a36Sopenharmony_ci stat_dec_swapfile_inode(inode); 411162306a36Sopenharmony_ci clear_inode_flag(inode, FI_PIN_FILE); 411262306a36Sopenharmony_ci} 411362306a36Sopenharmony_ci#else 411462306a36Sopenharmony_cistatic int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, 411562306a36Sopenharmony_ci sector_t *span) 411662306a36Sopenharmony_ci{ 411762306a36Sopenharmony_ci return -EOPNOTSUPP; 411862306a36Sopenharmony_ci} 411962306a36Sopenharmony_ci 412062306a36Sopenharmony_cistatic void f2fs_swap_deactivate(struct file *file) 412162306a36Sopenharmony_ci{ 412262306a36Sopenharmony_ci} 412362306a36Sopenharmony_ci#endif 412462306a36Sopenharmony_ci 412562306a36Sopenharmony_ciconst struct address_space_operations f2fs_dblock_aops = { 412662306a36Sopenharmony_ci .read_folio = f2fs_read_data_folio, 412762306a36Sopenharmony_ci .readahead = f2fs_readahead, 412862306a36Sopenharmony_ci .writepage = f2fs_write_data_page, 412962306a36Sopenharmony_ci .writepages = f2fs_write_data_pages, 413062306a36Sopenharmony_ci .write_begin = f2fs_write_begin, 413162306a36Sopenharmony_ci .write_end = f2fs_write_end, 413262306a36Sopenharmony_ci .dirty_folio = f2fs_dirty_data_folio, 413362306a36Sopenharmony_ci .migrate_folio = filemap_migrate_folio, 413462306a36Sopenharmony_ci .invalidate_folio = f2fs_invalidate_folio, 413562306a36Sopenharmony_ci .release_folio = f2fs_release_folio, 413662306a36Sopenharmony_ci .bmap = f2fs_bmap, 413762306a36Sopenharmony_ci .swap_activate = f2fs_swap_activate, 413862306a36Sopenharmony_ci .swap_deactivate = f2fs_swap_deactivate, 413962306a36Sopenharmony_ci}; 414062306a36Sopenharmony_ci 414162306a36Sopenharmony_civoid f2fs_clear_page_cache_dirty_tag(struct page *page) 414262306a36Sopenharmony_ci{ 414362306a36Sopenharmony_ci struct address_space *mapping = page_mapping(page); 414462306a36Sopenharmony_ci unsigned long flags; 414562306a36Sopenharmony_ci 414662306a36Sopenharmony_ci xa_lock_irqsave(&mapping->i_pages, flags); 414762306a36Sopenharmony_ci __xa_clear_mark(&mapping->i_pages, page_index(page), 414862306a36Sopenharmony_ci PAGECACHE_TAG_DIRTY); 414962306a36Sopenharmony_ci xa_unlock_irqrestore(&mapping->i_pages, flags); 415062306a36Sopenharmony_ci} 415162306a36Sopenharmony_ci 415262306a36Sopenharmony_ciint __init f2fs_init_post_read_processing(void) 415362306a36Sopenharmony_ci{ 415462306a36Sopenharmony_ci bio_post_read_ctx_cache = 415562306a36Sopenharmony_ci kmem_cache_create("f2fs_bio_post_read_ctx", 415662306a36Sopenharmony_ci sizeof(struct bio_post_read_ctx), 0, 0, NULL); 415762306a36Sopenharmony_ci if (!bio_post_read_ctx_cache) 415862306a36Sopenharmony_ci goto fail; 415962306a36Sopenharmony_ci bio_post_read_ctx_pool = 416062306a36Sopenharmony_ci mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, 416162306a36Sopenharmony_ci bio_post_read_ctx_cache); 416262306a36Sopenharmony_ci if (!bio_post_read_ctx_pool) 416362306a36Sopenharmony_ci goto fail_free_cache; 416462306a36Sopenharmony_ci return 0; 416562306a36Sopenharmony_ci 416662306a36Sopenharmony_cifail_free_cache: 416762306a36Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 416862306a36Sopenharmony_cifail: 416962306a36Sopenharmony_ci return -ENOMEM; 417062306a36Sopenharmony_ci} 417162306a36Sopenharmony_ci 417262306a36Sopenharmony_civoid f2fs_destroy_post_read_processing(void) 417362306a36Sopenharmony_ci{ 417462306a36Sopenharmony_ci mempool_destroy(bio_post_read_ctx_pool); 417562306a36Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 417662306a36Sopenharmony_ci} 417762306a36Sopenharmony_ci 417862306a36Sopenharmony_ciint f2fs_init_post_read_wq(struct f2fs_sb_info *sbi) 417962306a36Sopenharmony_ci{ 418062306a36Sopenharmony_ci if (!f2fs_sb_has_encrypt(sbi) && 418162306a36Sopenharmony_ci !f2fs_sb_has_verity(sbi) && 418262306a36Sopenharmony_ci !f2fs_sb_has_compression(sbi)) 418362306a36Sopenharmony_ci return 0; 418462306a36Sopenharmony_ci 418562306a36Sopenharmony_ci sbi->post_read_wq = alloc_workqueue("f2fs_post_read_wq", 418662306a36Sopenharmony_ci WQ_UNBOUND | WQ_HIGHPRI, 418762306a36Sopenharmony_ci num_online_cpus()); 418862306a36Sopenharmony_ci return sbi->post_read_wq ? 0 : -ENOMEM; 418962306a36Sopenharmony_ci} 419062306a36Sopenharmony_ci 419162306a36Sopenharmony_civoid f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi) 419262306a36Sopenharmony_ci{ 419362306a36Sopenharmony_ci if (sbi->post_read_wq) 419462306a36Sopenharmony_ci destroy_workqueue(sbi->post_read_wq); 419562306a36Sopenharmony_ci} 419662306a36Sopenharmony_ci 419762306a36Sopenharmony_ciint __init f2fs_init_bio_entry_cache(void) 419862306a36Sopenharmony_ci{ 419962306a36Sopenharmony_ci bio_entry_slab = f2fs_kmem_cache_create("f2fs_bio_entry_slab", 420062306a36Sopenharmony_ci sizeof(struct bio_entry)); 420162306a36Sopenharmony_ci return bio_entry_slab ? 0 : -ENOMEM; 420262306a36Sopenharmony_ci} 420362306a36Sopenharmony_ci 420462306a36Sopenharmony_civoid f2fs_destroy_bio_entry_cache(void) 420562306a36Sopenharmony_ci{ 420662306a36Sopenharmony_ci kmem_cache_destroy(bio_entry_slab); 420762306a36Sopenharmony_ci} 420862306a36Sopenharmony_ci 420962306a36Sopenharmony_cistatic int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, 421062306a36Sopenharmony_ci unsigned int flags, struct iomap *iomap, 421162306a36Sopenharmony_ci struct iomap *srcmap) 421262306a36Sopenharmony_ci{ 421362306a36Sopenharmony_ci struct f2fs_map_blocks map = {}; 421462306a36Sopenharmony_ci pgoff_t next_pgofs = 0; 421562306a36Sopenharmony_ci int err; 421662306a36Sopenharmony_ci 421762306a36Sopenharmony_ci map.m_lblk = bytes_to_blks(inode, offset); 421862306a36Sopenharmony_ci map.m_len = bytes_to_blks(inode, offset + length - 1) - map.m_lblk + 1; 421962306a36Sopenharmony_ci map.m_next_pgofs = &next_pgofs; 422062306a36Sopenharmony_ci map.m_seg_type = f2fs_rw_hint_to_seg_type(inode->i_write_hint); 422162306a36Sopenharmony_ci if (flags & IOMAP_WRITE) 422262306a36Sopenharmony_ci map.m_may_create = true; 422362306a36Sopenharmony_ci 422462306a36Sopenharmony_ci err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_DIO); 422562306a36Sopenharmony_ci if (err) 422662306a36Sopenharmony_ci return err; 422762306a36Sopenharmony_ci 422862306a36Sopenharmony_ci iomap->offset = blks_to_bytes(inode, map.m_lblk); 422962306a36Sopenharmony_ci 423062306a36Sopenharmony_ci /* 423162306a36Sopenharmony_ci * When inline encryption is enabled, sometimes I/O to an encrypted file 423262306a36Sopenharmony_ci * has to be broken up to guarantee DUN contiguity. Handle this by 423362306a36Sopenharmony_ci * limiting the length of the mapping returned. 423462306a36Sopenharmony_ci */ 423562306a36Sopenharmony_ci map.m_len = fscrypt_limit_io_blocks(inode, map.m_lblk, map.m_len); 423662306a36Sopenharmony_ci 423762306a36Sopenharmony_ci /* 423862306a36Sopenharmony_ci * We should never see delalloc or compressed extents here based on 423962306a36Sopenharmony_ci * prior flushing and checks. 424062306a36Sopenharmony_ci */ 424162306a36Sopenharmony_ci if (WARN_ON_ONCE(map.m_pblk == NEW_ADDR)) 424262306a36Sopenharmony_ci return -EINVAL; 424362306a36Sopenharmony_ci if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR)) 424462306a36Sopenharmony_ci return -EINVAL; 424562306a36Sopenharmony_ci 424662306a36Sopenharmony_ci if (map.m_pblk != NULL_ADDR) { 424762306a36Sopenharmony_ci iomap->length = blks_to_bytes(inode, map.m_len); 424862306a36Sopenharmony_ci iomap->type = IOMAP_MAPPED; 424962306a36Sopenharmony_ci iomap->flags |= IOMAP_F_MERGED; 425062306a36Sopenharmony_ci iomap->bdev = map.m_bdev; 425162306a36Sopenharmony_ci iomap->addr = blks_to_bytes(inode, map.m_pblk); 425262306a36Sopenharmony_ci } else { 425362306a36Sopenharmony_ci if (flags & IOMAP_WRITE) 425462306a36Sopenharmony_ci return -ENOTBLK; 425562306a36Sopenharmony_ci iomap->length = blks_to_bytes(inode, next_pgofs) - 425662306a36Sopenharmony_ci iomap->offset; 425762306a36Sopenharmony_ci iomap->type = IOMAP_HOLE; 425862306a36Sopenharmony_ci iomap->addr = IOMAP_NULL_ADDR; 425962306a36Sopenharmony_ci } 426062306a36Sopenharmony_ci 426162306a36Sopenharmony_ci if (map.m_flags & F2FS_MAP_NEW) 426262306a36Sopenharmony_ci iomap->flags |= IOMAP_F_NEW; 426362306a36Sopenharmony_ci if ((inode->i_state & I_DIRTY_DATASYNC) || 426462306a36Sopenharmony_ci offset + length > i_size_read(inode)) 426562306a36Sopenharmony_ci iomap->flags |= IOMAP_F_DIRTY; 426662306a36Sopenharmony_ci 426762306a36Sopenharmony_ci return 0; 426862306a36Sopenharmony_ci} 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_ciconst struct iomap_ops f2fs_iomap_ops = { 427162306a36Sopenharmony_ci .iomap_begin = f2fs_iomap_begin, 427262306a36Sopenharmony_ci}; 4273