18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/f2fs/data.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * http://www.samsung.com/ 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci#include <linux/fs.h> 98c2ecf20Sopenharmony_ci#include <linux/f2fs_fs.h> 108c2ecf20Sopenharmony_ci#include <linux/buffer_head.h> 118c2ecf20Sopenharmony_ci#include <linux/mpage.h> 128c2ecf20Sopenharmony_ci#include <linux/writeback.h> 138c2ecf20Sopenharmony_ci#include <linux/backing-dev.h> 148c2ecf20Sopenharmony_ci#include <linux/pagevec.h> 158c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 168c2ecf20Sopenharmony_ci#include <linux/bio.h> 178c2ecf20Sopenharmony_ci#include <linux/blk-crypto.h> 188c2ecf20Sopenharmony_ci#include <linux/swap.h> 198c2ecf20Sopenharmony_ci#include <linux/prefetch.h> 208c2ecf20Sopenharmony_ci#include <linux/uio.h> 218c2ecf20Sopenharmony_ci#include <linux/cleancache.h> 228c2ecf20Sopenharmony_ci#include <linux/sched/signal.h> 238c2ecf20Sopenharmony_ci#include <linux/fiemap.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "f2fs.h" 268c2ecf20Sopenharmony_ci#include "node.h" 278c2ecf20Sopenharmony_ci#include "segment.h" 288c2ecf20Sopenharmony_ci#include "trace.h" 298c2ecf20Sopenharmony_ci#include <trace/events/f2fs.h> 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define NUM_PREALLOC_POST_READ_CTXS 128 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic struct kmem_cache *bio_post_read_ctx_cache; 348c2ecf20Sopenharmony_cistatic struct kmem_cache *bio_entry_slab; 358c2ecf20Sopenharmony_cistatic mempool_t *bio_post_read_ctx_pool; 368c2ecf20Sopenharmony_cistatic struct bio_set f2fs_bioset; 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define F2FS_BIO_POOL_SIZE NR_CURSEG_TYPE 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciint __init f2fs_init_bioset(void) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci if (bioset_init(&f2fs_bioset, F2FS_BIO_POOL_SIZE, 438c2ecf20Sopenharmony_ci 0, BIOSET_NEED_BVECS)) 448c2ecf20Sopenharmony_ci return -ENOMEM; 458c2ecf20Sopenharmony_ci return 0; 468c2ecf20Sopenharmony_ci} 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_civoid f2fs_destroy_bioset(void) 498c2ecf20Sopenharmony_ci{ 508c2ecf20Sopenharmony_ci bioset_exit(&f2fs_bioset); 518c2ecf20Sopenharmony_ci} 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic inline struct bio *__f2fs_bio_alloc(gfp_t gfp_mask, 548c2ecf20Sopenharmony_ci unsigned int nr_iovecs) 558c2ecf20Sopenharmony_ci{ 568c2ecf20Sopenharmony_ci return bio_alloc_bioset(gfp_mask, nr_iovecs, &f2fs_bioset); 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistruct bio *f2fs_bio_alloc(struct f2fs_sb_info *sbi, int npages, bool noio) 608c2ecf20Sopenharmony_ci{ 618c2ecf20Sopenharmony_ci if (noio) { 628c2ecf20Sopenharmony_ci /* No failure on bio allocation */ 638c2ecf20Sopenharmony_ci return __f2fs_bio_alloc(GFP_NOIO, npages); 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci if (time_to_inject(sbi, FAULT_ALLOC_BIO)) { 678c2ecf20Sopenharmony_ci f2fs_show_injection_info(sbi, FAULT_ALLOC_BIO); 688c2ecf20Sopenharmony_ci return NULL; 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return __f2fs_bio_alloc(GFP_KERNEL, npages); 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic bool __is_cp_guaranteed(struct page *page) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct address_space *mapping = page->mapping; 778c2ecf20Sopenharmony_ci struct inode *inode; 788c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci if (!mapping) 818c2ecf20Sopenharmony_ci return false; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci if (f2fs_is_compressed_page(page)) 848c2ecf20Sopenharmony_ci return false; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci inode = mapping->host; 878c2ecf20Sopenharmony_ci sbi = F2FS_I_SB(inode); 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi) || 908c2ecf20Sopenharmony_ci inode->i_ino == F2FS_NODE_INO(sbi) || 918c2ecf20Sopenharmony_ci S_ISDIR(inode->i_mode) || 928c2ecf20Sopenharmony_ci (S_ISREG(inode->i_mode) && 938c2ecf20Sopenharmony_ci (f2fs_is_atomic_file(inode) || IS_NOQUOTA(inode))) || 948c2ecf20Sopenharmony_ci is_cold_data(page)) 958c2ecf20Sopenharmony_ci return true; 968c2ecf20Sopenharmony_ci return false; 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic enum count_type __read_io_type(struct page *page) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct address_space *mapping = page_file_mapping(page); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci if (mapping) { 1048c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 1058c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi)) 1088c2ecf20Sopenharmony_ci return F2FS_RD_META; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_NODE_INO(sbi)) 1118c2ecf20Sopenharmony_ci return F2FS_RD_NODE; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci return F2FS_RD_DATA; 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci/* postprocessing steps for read bios */ 1178c2ecf20Sopenharmony_cienum bio_post_read_step { 1188c2ecf20Sopenharmony_ci STEP_DECRYPT, 1198c2ecf20Sopenharmony_ci STEP_DECOMPRESS_NOWQ, /* handle normal cluster data inplace */ 1208c2ecf20Sopenharmony_ci STEP_DECOMPRESS, /* handle compressed cluster data in workqueue */ 1218c2ecf20Sopenharmony_ci STEP_VERITY, 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct bio_post_read_ctx { 1258c2ecf20Sopenharmony_ci struct bio *bio; 1268c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi; 1278c2ecf20Sopenharmony_ci struct work_struct work; 1288c2ecf20Sopenharmony_ci unsigned int enabled_steps; 1298c2ecf20Sopenharmony_ci}; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_cistatic void __read_end_io(struct bio *bio, bool compr, bool verity) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct page *page; 1348c2ecf20Sopenharmony_ci struct bio_vec *bv; 1358c2ecf20Sopenharmony_ci struct bvec_iter_all iter_all; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci bio_for_each_segment_all(bv, bio, iter_all) { 1388c2ecf20Sopenharmony_ci page = bv->bv_page; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 1418c2ecf20Sopenharmony_ci if (compr && f2fs_is_compressed_page(page)) { 1428c2ecf20Sopenharmony_ci f2fs_decompress_pages(bio, page, verity); 1438c2ecf20Sopenharmony_ci continue; 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci if (verity) 1468c2ecf20Sopenharmony_ci continue; 1478c2ecf20Sopenharmony_ci#endif 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci /* PG_error was set if any post_read step failed */ 1508c2ecf20Sopenharmony_ci if (bio->bi_status || PageError(page)) { 1518c2ecf20Sopenharmony_ci ClearPageUptodate(page); 1528c2ecf20Sopenharmony_ci /* will re-read again later */ 1538c2ecf20Sopenharmony_ci ClearPageError(page); 1548c2ecf20Sopenharmony_ci } else { 1558c2ecf20Sopenharmony_ci SetPageUptodate(page); 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci dec_page_count(F2FS_P_SB(page), __read_io_type(page)); 1588c2ecf20Sopenharmony_ci unlock_page(page); 1598c2ecf20Sopenharmony_ci } 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_cistatic void f2fs_release_read_bio(struct bio *bio); 1638c2ecf20Sopenharmony_cistatic void __f2fs_read_end_io(struct bio *bio, bool compr, bool verity) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci if (!compr) 1668c2ecf20Sopenharmony_ci __read_end_io(bio, false, verity); 1678c2ecf20Sopenharmony_ci f2fs_release_read_bio(bio); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void f2fs_decompress_bio(struct bio *bio, bool verity) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci __read_end_io(bio, true, verity); 1738c2ecf20Sopenharmony_ci} 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_cistatic void bio_post_read_processing(struct bio_post_read_ctx *ctx); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_cistatic void f2fs_decrypt_work(struct bio_post_read_ctx *ctx) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci fscrypt_decrypt_bio(ctx->bio); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic void f2fs_decompress_work(struct bio_post_read_ctx *ctx) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci f2fs_decompress_bio(ctx->bio, ctx->enabled_steps & (1 << STEP_VERITY)); 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 1888c2ecf20Sopenharmony_cistatic void f2fs_verify_pages(struct page **rpages, unsigned int cluster_size) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci f2fs_decompress_end_io(rpages, cluster_size, false, true); 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_cistatic void f2fs_verify_bio(struct bio *bio) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci struct bio_vec *bv; 1968c2ecf20Sopenharmony_ci struct bvec_iter_all iter_all; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci bio_for_each_segment_all(bv, bio, iter_all) { 1998c2ecf20Sopenharmony_ci struct page *page = bv->bv_page; 2008c2ecf20Sopenharmony_ci struct decompress_io_ctx *dic; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci dic = (struct decompress_io_ctx *)page_private(page); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci if (dic) { 2058c2ecf20Sopenharmony_ci if (atomic_dec_return(&dic->verity_pages)) 2068c2ecf20Sopenharmony_ci continue; 2078c2ecf20Sopenharmony_ci f2fs_verify_pages(dic->rpages, 2088c2ecf20Sopenharmony_ci dic->cluster_size); 2098c2ecf20Sopenharmony_ci f2fs_free_dic(dic); 2108c2ecf20Sopenharmony_ci continue; 2118c2ecf20Sopenharmony_ci } 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci if (bio->bi_status || PageError(page)) 2148c2ecf20Sopenharmony_ci goto clear_uptodate; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci if (fsverity_verify_page(page)) { 2178c2ecf20Sopenharmony_ci SetPageUptodate(page); 2188c2ecf20Sopenharmony_ci goto unlock; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ciclear_uptodate: 2218c2ecf20Sopenharmony_ci ClearPageUptodate(page); 2228c2ecf20Sopenharmony_ci ClearPageError(page); 2238c2ecf20Sopenharmony_ciunlock: 2248c2ecf20Sopenharmony_ci dec_page_count(F2FS_P_SB(page), __read_io_type(page)); 2258c2ecf20Sopenharmony_ci unlock_page(page); 2268c2ecf20Sopenharmony_ci } 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci#endif 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic void f2fs_verity_work(struct work_struct *work) 2318c2ecf20Sopenharmony_ci{ 2328c2ecf20Sopenharmony_ci struct bio_post_read_ctx *ctx = 2338c2ecf20Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 2348c2ecf20Sopenharmony_ci struct bio *bio = ctx->bio; 2358c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 2368c2ecf20Sopenharmony_ci unsigned int enabled_steps = ctx->enabled_steps; 2378c2ecf20Sopenharmony_ci#endif 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci /* 2408c2ecf20Sopenharmony_ci * fsverity_verify_bio() may call readpages() again, and while verity 2418c2ecf20Sopenharmony_ci * will be disabled for this, decryption may still be needed, resulting 2428c2ecf20Sopenharmony_ci * in another bio_post_read_ctx being allocated. So to prevent 2438c2ecf20Sopenharmony_ci * deadlocks we need to release the current ctx to the mempool first. 2448c2ecf20Sopenharmony_ci * This assumes that verity is the last post-read step. 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci mempool_free(ctx, bio_post_read_ctx_pool); 2478c2ecf20Sopenharmony_ci bio->bi_private = NULL; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 2508c2ecf20Sopenharmony_ci /* previous step is decompression */ 2518c2ecf20Sopenharmony_ci if (enabled_steps & (1 << STEP_DECOMPRESS)) { 2528c2ecf20Sopenharmony_ci f2fs_verify_bio(bio); 2538c2ecf20Sopenharmony_ci f2fs_release_read_bio(bio); 2548c2ecf20Sopenharmony_ci return; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci#endif 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci fsverity_verify_bio(bio); 2598c2ecf20Sopenharmony_ci __f2fs_read_end_io(bio, false, false); 2608c2ecf20Sopenharmony_ci} 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_cistatic void f2fs_post_read_work(struct work_struct *work) 2638c2ecf20Sopenharmony_ci{ 2648c2ecf20Sopenharmony_ci struct bio_post_read_ctx *ctx = 2658c2ecf20Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_DECRYPT)) 2688c2ecf20Sopenharmony_ci f2fs_decrypt_work(ctx); 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_DECOMPRESS)) 2718c2ecf20Sopenharmony_ci f2fs_decompress_work(ctx); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_VERITY)) { 2748c2ecf20Sopenharmony_ci INIT_WORK(&ctx->work, f2fs_verity_work); 2758c2ecf20Sopenharmony_ci fsverity_enqueue_verify_work(&ctx->work); 2768c2ecf20Sopenharmony_ci return; 2778c2ecf20Sopenharmony_ci } 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci __f2fs_read_end_io(ctx->bio, 2808c2ecf20Sopenharmony_ci ctx->enabled_steps & (1 << STEP_DECOMPRESS), false); 2818c2ecf20Sopenharmony_ci} 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic void f2fs_enqueue_post_read_work(struct f2fs_sb_info *sbi, 2848c2ecf20Sopenharmony_ci struct work_struct *work) 2858c2ecf20Sopenharmony_ci{ 2868c2ecf20Sopenharmony_ci queue_work(sbi->post_read_wq, work); 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_cistatic void bio_post_read_processing(struct bio_post_read_ctx *ctx) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci /* 2928c2ecf20Sopenharmony_ci * We use different work queues for decryption and for verity because 2938c2ecf20Sopenharmony_ci * verity may require reading metadata pages that need decryption, and 2948c2ecf20Sopenharmony_ci * we shouldn't recurse to the same workqueue. 2958c2ecf20Sopenharmony_ci */ 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_DECRYPT) || 2988c2ecf20Sopenharmony_ci ctx->enabled_steps & (1 << STEP_DECOMPRESS)) { 2998c2ecf20Sopenharmony_ci INIT_WORK(&ctx->work, f2fs_post_read_work); 3008c2ecf20Sopenharmony_ci f2fs_enqueue_post_read_work(ctx->sbi, &ctx->work); 3018c2ecf20Sopenharmony_ci return; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_VERITY)) { 3058c2ecf20Sopenharmony_ci INIT_WORK(&ctx->work, f2fs_verity_work); 3068c2ecf20Sopenharmony_ci fsverity_enqueue_verify_work(&ctx->work); 3078c2ecf20Sopenharmony_ci return; 3088c2ecf20Sopenharmony_ci } 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci __f2fs_read_end_io(ctx->bio, false, false); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic bool f2fs_bio_post_read_required(struct bio *bio) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci return bio->bi_private; 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void f2fs_read_end_io(struct bio *bio) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_P_SB(bio_first_page_all(bio)); 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci if (time_to_inject(sbi, FAULT_READ_IO)) { 3238c2ecf20Sopenharmony_ci f2fs_show_injection_info(sbi, FAULT_READ_IO); 3248c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci if (f2fs_bio_post_read_required(bio)) { 3288c2ecf20Sopenharmony_ci struct bio_post_read_ctx *ctx = bio->bi_private; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci bio_post_read_processing(ctx); 3318c2ecf20Sopenharmony_ci return; 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci __f2fs_read_end_io(bio, false, false); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic void f2fs_write_end_io(struct bio *bio) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = bio->bi_private; 3408c2ecf20Sopenharmony_ci struct bio_vec *bvec; 3418c2ecf20Sopenharmony_ci struct bvec_iter_all iter_all; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (time_to_inject(sbi, FAULT_WRITE_IO)) { 3448c2ecf20Sopenharmony_ci f2fs_show_injection_info(sbi, FAULT_WRITE_IO); 3458c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 3468c2ecf20Sopenharmony_ci } 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_ci bio_for_each_segment_all(bvec, bio, iter_all) { 3498c2ecf20Sopenharmony_ci struct page *page = bvec->bv_page; 3508c2ecf20Sopenharmony_ci enum count_type type = WB_DATA_TYPE(page); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (IS_DUMMY_WRITTEN_PAGE(page)) { 3538c2ecf20Sopenharmony_ci set_page_private(page, (unsigned long)NULL); 3548c2ecf20Sopenharmony_ci ClearPagePrivate(page); 3558c2ecf20Sopenharmony_ci unlock_page(page); 3568c2ecf20Sopenharmony_ci mempool_free(page, sbi->write_io_dummy); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci if (unlikely(bio->bi_status)) 3598c2ecf20Sopenharmony_ci f2fs_stop_checkpoint(sbi, true); 3608c2ecf20Sopenharmony_ci continue; 3618c2ecf20Sopenharmony_ci } 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci fscrypt_finalize_bounce_page(&page); 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 3668c2ecf20Sopenharmony_ci if (f2fs_is_compressed_page(page)) { 3678c2ecf20Sopenharmony_ci f2fs_compress_write_end_io(bio, page); 3688c2ecf20Sopenharmony_ci continue; 3698c2ecf20Sopenharmony_ci } 3708c2ecf20Sopenharmony_ci#endif 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (unlikely(bio->bi_status)) { 3738c2ecf20Sopenharmony_ci mapping_set_error(page->mapping, -EIO); 3748c2ecf20Sopenharmony_ci if (type == F2FS_WB_CP_DATA) 3758c2ecf20Sopenharmony_ci f2fs_stop_checkpoint(sbi, true); 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, page->mapping == NODE_MAPPING(sbi) && 3798c2ecf20Sopenharmony_ci page->index != nid_of_node(page)); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci dec_page_count(sbi, type); 3828c2ecf20Sopenharmony_ci if (f2fs_in_warm_node_list(sbi, page)) 3838c2ecf20Sopenharmony_ci f2fs_del_fsync_node_entry(sbi, page); 3848c2ecf20Sopenharmony_ci clear_cold_data(page); 3858c2ecf20Sopenharmony_ci end_page_writeback(page); 3868c2ecf20Sopenharmony_ci } 3878c2ecf20Sopenharmony_ci if (!get_pages(sbi, F2FS_WB_CP_DATA) && 3888c2ecf20Sopenharmony_ci wq_has_sleeper(&sbi->cp_wait)) 3898c2ecf20Sopenharmony_ci wake_up(&sbi->cp_wait); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci bio_put(bio); 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistruct block_device *f2fs_target_device(struct f2fs_sb_info *sbi, 3958c2ecf20Sopenharmony_ci block_t blk_addr, struct bio *bio) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci struct block_device *bdev = sbi->sb->s_bdev; 3988c2ecf20Sopenharmony_ci int i; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci if (f2fs_is_multi_device(sbi)) { 4018c2ecf20Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) { 4028c2ecf20Sopenharmony_ci if (FDEV(i).start_blk <= blk_addr && 4038c2ecf20Sopenharmony_ci FDEV(i).end_blk >= blk_addr) { 4048c2ecf20Sopenharmony_ci blk_addr -= FDEV(i).start_blk; 4058c2ecf20Sopenharmony_ci bdev = FDEV(i).bdev; 4068c2ecf20Sopenharmony_ci break; 4078c2ecf20Sopenharmony_ci } 4088c2ecf20Sopenharmony_ci } 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci if (bio) { 4118c2ecf20Sopenharmony_ci bio_set_dev(bio, bdev); 4128c2ecf20Sopenharmony_ci bio->bi_iter.bi_sector = SECTOR_FROM_BLOCK(blk_addr); 4138c2ecf20Sopenharmony_ci } 4148c2ecf20Sopenharmony_ci return bdev; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ciint f2fs_target_device_index(struct f2fs_sb_info *sbi, block_t blkaddr) 4188c2ecf20Sopenharmony_ci{ 4198c2ecf20Sopenharmony_ci int i; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci if (!f2fs_is_multi_device(sbi)) 4228c2ecf20Sopenharmony_ci return 0; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci for (i = 0; i < sbi->s_ndevs; i++) 4258c2ecf20Sopenharmony_ci if (FDEV(i).start_blk <= blkaddr && FDEV(i).end_blk >= blkaddr) 4268c2ecf20Sopenharmony_ci return i; 4278c2ecf20Sopenharmony_ci return 0; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci/* 4318c2ecf20Sopenharmony_ci * Return true, if pre_bio's bdev is same as its target device. 4328c2ecf20Sopenharmony_ci */ 4338c2ecf20Sopenharmony_cistatic bool __same_bdev(struct f2fs_sb_info *sbi, 4348c2ecf20Sopenharmony_ci block_t blk_addr, struct bio *bio) 4358c2ecf20Sopenharmony_ci{ 4368c2ecf20Sopenharmony_ci struct block_device *b = f2fs_target_device(sbi, blk_addr, NULL); 4378c2ecf20Sopenharmony_ci return bio->bi_disk == b->bd_disk && bio->bi_partno == b->bd_partno; 4388c2ecf20Sopenharmony_ci} 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic struct bio *__bio_alloc(struct f2fs_io_info *fio, int npages) 4418c2ecf20Sopenharmony_ci{ 4428c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 4438c2ecf20Sopenharmony_ci struct bio *bio; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci bio = f2fs_bio_alloc(sbi, npages, true); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci f2fs_target_device(sbi, fio->new_blkaddr, bio); 4488c2ecf20Sopenharmony_ci if (is_read_io(fio->op)) { 4498c2ecf20Sopenharmony_ci bio->bi_end_io = f2fs_read_end_io; 4508c2ecf20Sopenharmony_ci bio->bi_private = NULL; 4518c2ecf20Sopenharmony_ci } else { 4528c2ecf20Sopenharmony_ci bio->bi_end_io = f2fs_write_end_io; 4538c2ecf20Sopenharmony_ci bio->bi_private = sbi; 4548c2ecf20Sopenharmony_ci bio->bi_write_hint = f2fs_io_type_to_rw_hint(sbi, 4558c2ecf20Sopenharmony_ci fio->type, fio->temp); 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci if (fio->io_wbc) 4588c2ecf20Sopenharmony_ci wbc_init_bio(fio->io_wbc, bio); 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return bio; 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic void f2fs_set_bio_crypt_ctx(struct bio *bio, const struct inode *inode, 4648c2ecf20Sopenharmony_ci pgoff_t first_idx, 4658c2ecf20Sopenharmony_ci const struct f2fs_io_info *fio, 4668c2ecf20Sopenharmony_ci gfp_t gfp_mask) 4678c2ecf20Sopenharmony_ci{ 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * The f2fs garbage collector sets ->encrypted_page when it wants to 4708c2ecf20Sopenharmony_ci * read/write raw data without encryption. 4718c2ecf20Sopenharmony_ci */ 4728c2ecf20Sopenharmony_ci if (!fio || !fio->encrypted_page) 4738c2ecf20Sopenharmony_ci fscrypt_set_bio_crypt_ctx(bio, inode, first_idx, gfp_mask); 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_cistatic bool f2fs_crypt_mergeable_bio(struct bio *bio, const struct inode *inode, 4778c2ecf20Sopenharmony_ci pgoff_t next_idx, 4788c2ecf20Sopenharmony_ci const struct f2fs_io_info *fio) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci /* 4818c2ecf20Sopenharmony_ci * The f2fs garbage collector sets ->encrypted_page when it wants to 4828c2ecf20Sopenharmony_ci * read/write raw data without encryption. 4838c2ecf20Sopenharmony_ci */ 4848c2ecf20Sopenharmony_ci if (fio && fio->encrypted_page) 4858c2ecf20Sopenharmony_ci return !bio_has_crypt_ctx(bio); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci return fscrypt_mergeable_bio(bio, inode, next_idx); 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_cistatic inline void __submit_bio(struct f2fs_sb_info *sbi, 4918c2ecf20Sopenharmony_ci struct bio *bio, enum page_type type) 4928c2ecf20Sopenharmony_ci{ 4938c2ecf20Sopenharmony_ci if (!is_read_io(bio_op(bio))) { 4948c2ecf20Sopenharmony_ci unsigned int start; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci if (type != DATA && type != NODE) 4978c2ecf20Sopenharmony_ci goto submit_io; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_ci if (f2fs_lfs_mode(sbi) && current->plug) 5008c2ecf20Sopenharmony_ci blk_finish_plug(current->plug); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci if (!F2FS_IO_ALIGNED(sbi)) 5038c2ecf20Sopenharmony_ci goto submit_io; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci start = bio->bi_iter.bi_size >> F2FS_BLKSIZE_BITS; 5068c2ecf20Sopenharmony_ci start %= F2FS_IO_SIZE(sbi); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (start == 0) 5098c2ecf20Sopenharmony_ci goto submit_io; 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* fill dummy pages */ 5128c2ecf20Sopenharmony_ci for (; start < F2FS_IO_SIZE(sbi); start++) { 5138c2ecf20Sopenharmony_ci struct page *page = 5148c2ecf20Sopenharmony_ci mempool_alloc(sbi->write_io_dummy, 5158c2ecf20Sopenharmony_ci GFP_NOIO | __GFP_NOFAIL); 5168c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !page); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 5198c2ecf20Sopenharmony_ci SetPagePrivate(page); 5208c2ecf20Sopenharmony_ci set_page_private(page, DUMMY_WRITTEN_PAGE); 5218c2ecf20Sopenharmony_ci lock_page(page); 5228c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) 5238c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, 1); 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci /* 5268c2ecf20Sopenharmony_ci * In the NODE case, we lose next block address chain. So, we 5278c2ecf20Sopenharmony_ci * need to do checkpoint in f2fs_sync_file. 5288c2ecf20Sopenharmony_ci */ 5298c2ecf20Sopenharmony_ci if (type == NODE) 5308c2ecf20Sopenharmony_ci set_sbi_flag(sbi, SBI_NEED_CP); 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_cisubmit_io: 5338c2ecf20Sopenharmony_ci if (is_read_io(bio_op(bio))) 5348c2ecf20Sopenharmony_ci trace_f2fs_submit_read_bio(sbi->sb, type, bio); 5358c2ecf20Sopenharmony_ci else 5368c2ecf20Sopenharmony_ci trace_f2fs_submit_write_bio(sbi->sb, type, bio); 5378c2ecf20Sopenharmony_ci submit_bio(bio); 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_civoid f2fs_submit_bio(struct f2fs_sb_info *sbi, 5418c2ecf20Sopenharmony_ci struct bio *bio, enum page_type type) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci __submit_bio(sbi, bio, type); 5448c2ecf20Sopenharmony_ci} 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic void __attach_io_flag(struct f2fs_io_info *fio) 5478c2ecf20Sopenharmony_ci{ 5488c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 5498c2ecf20Sopenharmony_ci unsigned int temp_mask = (1 << NR_TEMP_TYPE) - 1; 5508c2ecf20Sopenharmony_ci unsigned int io_flag, fua_flag, meta_flag; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (fio->type == DATA) 5538c2ecf20Sopenharmony_ci io_flag = sbi->data_io_flag; 5548c2ecf20Sopenharmony_ci else if (fio->type == NODE) 5558c2ecf20Sopenharmony_ci io_flag = sbi->node_io_flag; 5568c2ecf20Sopenharmony_ci else 5578c2ecf20Sopenharmony_ci return; 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci fua_flag = io_flag & temp_mask; 5608c2ecf20Sopenharmony_ci meta_flag = (io_flag >> NR_TEMP_TYPE) & temp_mask; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci /* 5638c2ecf20Sopenharmony_ci * data/node io flag bits per temp: 5648c2ecf20Sopenharmony_ci * REQ_META | REQ_FUA | 5658c2ecf20Sopenharmony_ci * 5 | 4 | 3 | 2 | 1 | 0 | 5668c2ecf20Sopenharmony_ci * Cold | Warm | Hot | Cold | Warm | Hot | 5678c2ecf20Sopenharmony_ci */ 5688c2ecf20Sopenharmony_ci if ((1 << fio->temp) & meta_flag) 5698c2ecf20Sopenharmony_ci fio->op_flags |= REQ_META; 5708c2ecf20Sopenharmony_ci if ((1 << fio->temp) & fua_flag) 5718c2ecf20Sopenharmony_ci fio->op_flags |= REQ_FUA; 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic void __submit_merged_bio(struct f2fs_bio_info *io) 5758c2ecf20Sopenharmony_ci{ 5768c2ecf20Sopenharmony_ci struct f2fs_io_info *fio = &io->fio; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci if (!io->bio) 5798c2ecf20Sopenharmony_ci return; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci __attach_io_flag(fio); 5828c2ecf20Sopenharmony_ci bio_set_op_attrs(io->bio, fio->op, fio->op_flags); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci if (is_read_io(fio->op)) 5858c2ecf20Sopenharmony_ci trace_f2fs_prepare_read_bio(io->sbi->sb, fio->type, io->bio); 5868c2ecf20Sopenharmony_ci else 5878c2ecf20Sopenharmony_ci trace_f2fs_prepare_write_bio(io->sbi->sb, fio->type, io->bio); 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci __submit_bio(io->sbi, io->bio, fio->type); 5908c2ecf20Sopenharmony_ci io->bio = NULL; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic bool __has_merged_page(struct bio *bio, struct inode *inode, 5948c2ecf20Sopenharmony_ci struct page *page, nid_t ino) 5958c2ecf20Sopenharmony_ci{ 5968c2ecf20Sopenharmony_ci struct bio_vec *bvec; 5978c2ecf20Sopenharmony_ci struct bvec_iter_all iter_all; 5988c2ecf20Sopenharmony_ci 5998c2ecf20Sopenharmony_ci if (!bio) 6008c2ecf20Sopenharmony_ci return false; 6018c2ecf20Sopenharmony_ci 6028c2ecf20Sopenharmony_ci if (!inode && !page && !ino) 6038c2ecf20Sopenharmony_ci return true; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci bio_for_each_segment_all(bvec, bio, iter_all) { 6068c2ecf20Sopenharmony_ci struct page *target = bvec->bv_page; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci if (fscrypt_is_bounce_page(target)) { 6098c2ecf20Sopenharmony_ci target = fscrypt_pagecache_page(target); 6108c2ecf20Sopenharmony_ci if (IS_ERR(target)) 6118c2ecf20Sopenharmony_ci continue; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci if (f2fs_is_compressed_page(target)) { 6148c2ecf20Sopenharmony_ci target = f2fs_compress_control_page(target); 6158c2ecf20Sopenharmony_ci if (IS_ERR(target)) 6168c2ecf20Sopenharmony_ci continue; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci 6198c2ecf20Sopenharmony_ci if (inode && inode == target->mapping->host) 6208c2ecf20Sopenharmony_ci return true; 6218c2ecf20Sopenharmony_ci if (page && page == target) 6228c2ecf20Sopenharmony_ci return true; 6238c2ecf20Sopenharmony_ci if (ino && ino == ino_of_node(target)) 6248c2ecf20Sopenharmony_ci return true; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci return false; 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_cistatic void __f2fs_submit_merged_write(struct f2fs_sb_info *sbi, 6318c2ecf20Sopenharmony_ci enum page_type type, enum temp_type temp) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(type); 6348c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + temp; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci down_write(&io->io_rwsem); 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* change META to META_FLUSH in the checkpoint procedure */ 6398c2ecf20Sopenharmony_ci if (type >= META_FLUSH) { 6408c2ecf20Sopenharmony_ci io->fio.type = META_FLUSH; 6418c2ecf20Sopenharmony_ci io->fio.op = REQ_OP_WRITE; 6428c2ecf20Sopenharmony_ci io->fio.op_flags = REQ_META | REQ_PRIO | REQ_SYNC; 6438c2ecf20Sopenharmony_ci if (!test_opt(sbi, NOBARRIER)) 6448c2ecf20Sopenharmony_ci io->fio.op_flags |= REQ_PREFLUSH | REQ_FUA; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci __submit_merged_bio(io); 6478c2ecf20Sopenharmony_ci up_write(&io->io_rwsem); 6488c2ecf20Sopenharmony_ci} 6498c2ecf20Sopenharmony_ci 6508c2ecf20Sopenharmony_cistatic void __submit_merged_write_cond(struct f2fs_sb_info *sbi, 6518c2ecf20Sopenharmony_ci struct inode *inode, struct page *page, 6528c2ecf20Sopenharmony_ci nid_t ino, enum page_type type, bool force) 6538c2ecf20Sopenharmony_ci{ 6548c2ecf20Sopenharmony_ci enum temp_type temp; 6558c2ecf20Sopenharmony_ci bool ret = true; 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE; temp++) { 6588c2ecf20Sopenharmony_ci if (!force) { 6598c2ecf20Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(type); 6608c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + temp; 6618c2ecf20Sopenharmony_ci 6628c2ecf20Sopenharmony_ci down_read(&io->io_rwsem); 6638c2ecf20Sopenharmony_ci ret = __has_merged_page(io->bio, inode, page, ino); 6648c2ecf20Sopenharmony_ci up_read(&io->io_rwsem); 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci if (ret) 6678c2ecf20Sopenharmony_ci __f2fs_submit_merged_write(sbi, type, temp); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci /* TODO: use HOT temp only for meta pages now. */ 6708c2ecf20Sopenharmony_ci if (type >= META) 6718c2ecf20Sopenharmony_ci break; 6728c2ecf20Sopenharmony_ci } 6738c2ecf20Sopenharmony_ci} 6748c2ecf20Sopenharmony_ci 6758c2ecf20Sopenharmony_civoid f2fs_submit_merged_write(struct f2fs_sb_info *sbi, enum page_type type) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci __submit_merged_write_cond(sbi, NULL, NULL, 0, type, true); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_civoid f2fs_submit_merged_write_cond(struct f2fs_sb_info *sbi, 6818c2ecf20Sopenharmony_ci struct inode *inode, struct page *page, 6828c2ecf20Sopenharmony_ci nid_t ino, enum page_type type) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci __submit_merged_write_cond(sbi, inode, page, ino, type, false); 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ci 6878c2ecf20Sopenharmony_civoid f2fs_flush_merged_writes(struct f2fs_sb_info *sbi) 6888c2ecf20Sopenharmony_ci{ 6898c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 6908c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, NODE); 6918c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, META); 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci/* 6958c2ecf20Sopenharmony_ci * Fill the locked page with data located in the block address. 6968c2ecf20Sopenharmony_ci * A caller needs to unlock the page on failure. 6978c2ecf20Sopenharmony_ci */ 6988c2ecf20Sopenharmony_ciint f2fs_submit_page_bio(struct f2fs_io_info *fio) 6998c2ecf20Sopenharmony_ci{ 7008c2ecf20Sopenharmony_ci struct bio *bio; 7018c2ecf20Sopenharmony_ci struct page *page = fio->encrypted_page ? 7028c2ecf20Sopenharmony_ci fio->encrypted_page : fio->page; 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, 7058c2ecf20Sopenharmony_ci fio->is_por ? META_POR : (__is_meta_io(fio) ? 7068c2ecf20Sopenharmony_ci META_GENERIC : DATA_GENERIC_ENHANCE))) 7078c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci trace_f2fs_submit_page_bio(page, fio); 7108c2ecf20Sopenharmony_ci f2fs_trace_ios(fio, 0); 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci /* Allocate a new bio */ 7138c2ecf20Sopenharmony_ci bio = __bio_alloc(fio, 1); 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, 7168c2ecf20Sopenharmony_ci fio->page->index, fio, GFP_NOIO); 7178c2ecf20Sopenharmony_ci 7188c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { 7198c2ecf20Sopenharmony_ci bio_put(bio); 7208c2ecf20Sopenharmony_ci return -EFAULT; 7218c2ecf20Sopenharmony_ci } 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci if (fio->io_wbc && !is_read_io(fio->op)) 7248c2ecf20Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci __attach_io_flag(fio); 7278c2ecf20Sopenharmony_ci bio_set_op_attrs(bio, fio->op, fio->op_flags); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci inc_page_count(fio->sbi, is_read_io(fio->op) ? 7308c2ecf20Sopenharmony_ci __read_io_type(page): WB_DATA_TYPE(fio->page)); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci __submit_bio(fio->sbi, bio, fio->type); 7338c2ecf20Sopenharmony_ci return 0; 7348c2ecf20Sopenharmony_ci} 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_cistatic bool page_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, 7378c2ecf20Sopenharmony_ci block_t last_blkaddr, block_t cur_blkaddr) 7388c2ecf20Sopenharmony_ci{ 7398c2ecf20Sopenharmony_ci if (last_blkaddr + 1 != cur_blkaddr) 7408c2ecf20Sopenharmony_ci return false; 7418c2ecf20Sopenharmony_ci return __same_bdev(sbi, cur_blkaddr, bio); 7428c2ecf20Sopenharmony_ci} 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic bool io_type_is_mergeable(struct f2fs_bio_info *io, 7458c2ecf20Sopenharmony_ci struct f2fs_io_info *fio) 7468c2ecf20Sopenharmony_ci{ 7478c2ecf20Sopenharmony_ci if (io->fio.op != fio->op) 7488c2ecf20Sopenharmony_ci return false; 7498c2ecf20Sopenharmony_ci return io->fio.op_flags == fio->op_flags; 7508c2ecf20Sopenharmony_ci} 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_cistatic bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio, 7538c2ecf20Sopenharmony_ci struct f2fs_bio_info *io, 7548c2ecf20Sopenharmony_ci struct f2fs_io_info *fio, 7558c2ecf20Sopenharmony_ci block_t last_blkaddr, 7568c2ecf20Sopenharmony_ci block_t cur_blkaddr) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi) && (fio->type == DATA || fio->type == NODE)) { 7598c2ecf20Sopenharmony_ci unsigned int filled_blocks = 7608c2ecf20Sopenharmony_ci F2FS_BYTES_TO_BLK(bio->bi_iter.bi_size); 7618c2ecf20Sopenharmony_ci unsigned int io_size = F2FS_IO_SIZE(sbi); 7628c2ecf20Sopenharmony_ci unsigned int left_vecs = bio->bi_max_vecs - bio->bi_vcnt; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* IOs in bio is aligned and left space of vectors is not enough */ 7658c2ecf20Sopenharmony_ci if (!(filled_blocks % io_size) && left_vecs < io_size) 7668c2ecf20Sopenharmony_ci return false; 7678c2ecf20Sopenharmony_ci } 7688c2ecf20Sopenharmony_ci if (!page_is_mergeable(sbi, bio, last_blkaddr, cur_blkaddr)) 7698c2ecf20Sopenharmony_ci return false; 7708c2ecf20Sopenharmony_ci return io_type_is_mergeable(io, fio); 7718c2ecf20Sopenharmony_ci} 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_cistatic void add_bio_entry(struct f2fs_sb_info *sbi, struct bio *bio, 7748c2ecf20Sopenharmony_ci struct page *page, enum temp_type temp) 7758c2ecf20Sopenharmony_ci{ 7768c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 7778c2ecf20Sopenharmony_ci struct bio_entry *be; 7788c2ecf20Sopenharmony_ci 7798c2ecf20Sopenharmony_ci be = f2fs_kmem_cache_alloc(bio_entry_slab, GFP_NOFS); 7808c2ecf20Sopenharmony_ci be->bio = bio; 7818c2ecf20Sopenharmony_ci bio_get(bio); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) != PAGE_SIZE) 7848c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, 1); 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci down_write(&io->bio_list_lock); 7878c2ecf20Sopenharmony_ci list_add_tail(&be->list, &io->bio_list); 7888c2ecf20Sopenharmony_ci up_write(&io->bio_list_lock); 7898c2ecf20Sopenharmony_ci} 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_cistatic void del_bio_entry(struct bio_entry *be) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci list_del(&be->list); 7948c2ecf20Sopenharmony_ci kmem_cache_free(bio_entry_slab, be); 7958c2ecf20Sopenharmony_ci} 7968c2ecf20Sopenharmony_ci 7978c2ecf20Sopenharmony_cistatic int add_ipu_page(struct f2fs_io_info *fio, struct bio **bio, 7988c2ecf20Sopenharmony_ci struct page *page) 7998c2ecf20Sopenharmony_ci{ 8008c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 8018c2ecf20Sopenharmony_ci enum temp_type temp; 8028c2ecf20Sopenharmony_ci bool found = false; 8038c2ecf20Sopenharmony_ci int ret = -EAGAIN; 8048c2ecf20Sopenharmony_ci 8058c2ecf20Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { 8068c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 8078c2ecf20Sopenharmony_ci struct list_head *head = &io->bio_list; 8088c2ecf20Sopenharmony_ci struct bio_entry *be; 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci down_write(&io->bio_list_lock); 8118c2ecf20Sopenharmony_ci list_for_each_entry(be, head, list) { 8128c2ecf20Sopenharmony_ci if (be->bio != *bio) 8138c2ecf20Sopenharmony_ci continue; 8148c2ecf20Sopenharmony_ci 8158c2ecf20Sopenharmony_ci found = true; 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !page_is_mergeable(sbi, *bio, 8188c2ecf20Sopenharmony_ci *fio->last_block, 8198c2ecf20Sopenharmony_ci fio->new_blkaddr)); 8208c2ecf20Sopenharmony_ci if (f2fs_crypt_mergeable_bio(*bio, 8218c2ecf20Sopenharmony_ci fio->page->mapping->host, 8228c2ecf20Sopenharmony_ci fio->page->index, fio) && 8238c2ecf20Sopenharmony_ci bio_add_page(*bio, page, PAGE_SIZE, 0) == 8248c2ecf20Sopenharmony_ci PAGE_SIZE) { 8258c2ecf20Sopenharmony_ci ret = 0; 8268c2ecf20Sopenharmony_ci break; 8278c2ecf20Sopenharmony_ci } 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci /* page can't be merged into bio; submit the bio */ 8308c2ecf20Sopenharmony_ci del_bio_entry(be); 8318c2ecf20Sopenharmony_ci __submit_bio(sbi, *bio, DATA); 8328c2ecf20Sopenharmony_ci break; 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci up_write(&io->bio_list_lock); 8358c2ecf20Sopenharmony_ci } 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if (ret) { 8388c2ecf20Sopenharmony_ci bio_put(*bio); 8398c2ecf20Sopenharmony_ci *bio = NULL; 8408c2ecf20Sopenharmony_ci } 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci return ret; 8438c2ecf20Sopenharmony_ci} 8448c2ecf20Sopenharmony_ci 8458c2ecf20Sopenharmony_civoid f2fs_submit_merged_ipu_write(struct f2fs_sb_info *sbi, 8468c2ecf20Sopenharmony_ci struct bio **bio, struct page *page) 8478c2ecf20Sopenharmony_ci{ 8488c2ecf20Sopenharmony_ci enum temp_type temp; 8498c2ecf20Sopenharmony_ci bool found = false; 8508c2ecf20Sopenharmony_ci struct bio *target = bio ? *bio : NULL; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, !target && !page); 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_ci for (temp = HOT; temp < NR_TEMP_TYPE && !found; temp++) { 8558c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[DATA] + temp; 8568c2ecf20Sopenharmony_ci struct list_head *head = &io->bio_list; 8578c2ecf20Sopenharmony_ci struct bio_entry *be; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (list_empty(head)) 8608c2ecf20Sopenharmony_ci continue; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci down_read(&io->bio_list_lock); 8638c2ecf20Sopenharmony_ci list_for_each_entry(be, head, list) { 8648c2ecf20Sopenharmony_ci if (target) 8658c2ecf20Sopenharmony_ci found = (target == be->bio); 8668c2ecf20Sopenharmony_ci else 8678c2ecf20Sopenharmony_ci found = __has_merged_page(be->bio, NULL, 8688c2ecf20Sopenharmony_ci page, 0); 8698c2ecf20Sopenharmony_ci if (found) 8708c2ecf20Sopenharmony_ci break; 8718c2ecf20Sopenharmony_ci } 8728c2ecf20Sopenharmony_ci up_read(&io->bio_list_lock); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci if (!found) 8758c2ecf20Sopenharmony_ci continue; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci found = false; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci down_write(&io->bio_list_lock); 8808c2ecf20Sopenharmony_ci list_for_each_entry(be, head, list) { 8818c2ecf20Sopenharmony_ci if (target) 8828c2ecf20Sopenharmony_ci found = (target == be->bio); 8838c2ecf20Sopenharmony_ci else 8848c2ecf20Sopenharmony_ci found = __has_merged_page(be->bio, NULL, 8858c2ecf20Sopenharmony_ci page, 0); 8868c2ecf20Sopenharmony_ci if (found) { 8878c2ecf20Sopenharmony_ci target = be->bio; 8888c2ecf20Sopenharmony_ci del_bio_entry(be); 8898c2ecf20Sopenharmony_ci break; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_ci up_write(&io->bio_list_lock); 8938c2ecf20Sopenharmony_ci } 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci if (found) 8968c2ecf20Sopenharmony_ci __submit_bio(sbi, target, DATA); 8978c2ecf20Sopenharmony_ci if (bio && *bio) { 8988c2ecf20Sopenharmony_ci bio_put(*bio); 8998c2ecf20Sopenharmony_ci *bio = NULL; 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ciint f2fs_merge_page_bio(struct f2fs_io_info *fio) 9048c2ecf20Sopenharmony_ci{ 9058c2ecf20Sopenharmony_ci struct bio *bio = *fio->bio; 9068c2ecf20Sopenharmony_ci struct page *page = fio->encrypted_page ? 9078c2ecf20Sopenharmony_ci fio->encrypted_page : fio->page; 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->new_blkaddr, 9108c2ecf20Sopenharmony_ci __is_meta_io(fio) ? META_GENERIC : DATA_GENERIC)) 9118c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci trace_f2fs_submit_page_bio(page, fio); 9148c2ecf20Sopenharmony_ci f2fs_trace_ios(fio, 0); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci if (bio && !page_is_mergeable(fio->sbi, bio, *fio->last_block, 9178c2ecf20Sopenharmony_ci fio->new_blkaddr)) 9188c2ecf20Sopenharmony_ci f2fs_submit_merged_ipu_write(fio->sbi, &bio, NULL); 9198c2ecf20Sopenharmony_cialloc_new: 9208c2ecf20Sopenharmony_ci if (!bio) { 9218c2ecf20Sopenharmony_ci bio = __bio_alloc(fio, BIO_MAX_PAGES); 9228c2ecf20Sopenharmony_ci __attach_io_flag(fio); 9238c2ecf20Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, fio->page->mapping->host, 9248c2ecf20Sopenharmony_ci fio->page->index, fio, GFP_NOIO); 9258c2ecf20Sopenharmony_ci bio_set_op_attrs(bio, fio->op, fio->op_flags); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci add_bio_entry(fio->sbi, bio, page, fio->temp); 9288c2ecf20Sopenharmony_ci } else { 9298c2ecf20Sopenharmony_ci if (add_ipu_page(fio, &bio, page)) 9308c2ecf20Sopenharmony_ci goto alloc_new; 9318c2ecf20Sopenharmony_ci } 9328c2ecf20Sopenharmony_ci 9338c2ecf20Sopenharmony_ci if (fio->io_wbc) 9348c2ecf20Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci inc_page_count(fio->sbi, WB_DATA_TYPE(page)); 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci *fio->last_block = fio->new_blkaddr; 9398c2ecf20Sopenharmony_ci *fio->bio = bio; 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci return 0; 9428c2ecf20Sopenharmony_ci} 9438c2ecf20Sopenharmony_ci 9448c2ecf20Sopenharmony_civoid f2fs_submit_page_write(struct f2fs_io_info *fio) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = fio->sbi; 9478c2ecf20Sopenharmony_ci enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); 9488c2ecf20Sopenharmony_ci struct f2fs_bio_info *io = sbi->write_io[btype] + fio->temp; 9498c2ecf20Sopenharmony_ci struct page *bio_page; 9508c2ecf20Sopenharmony_ci 9518c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, is_read_io(fio->op)); 9528c2ecf20Sopenharmony_ci 9538c2ecf20Sopenharmony_ci down_write(&io->io_rwsem); 9548c2ecf20Sopenharmony_cinext: 9558c2ecf20Sopenharmony_ci if (fio->in_list) { 9568c2ecf20Sopenharmony_ci spin_lock(&io->io_lock); 9578c2ecf20Sopenharmony_ci if (list_empty(&io->io_list)) { 9588c2ecf20Sopenharmony_ci spin_unlock(&io->io_lock); 9598c2ecf20Sopenharmony_ci goto out; 9608c2ecf20Sopenharmony_ci } 9618c2ecf20Sopenharmony_ci fio = list_first_entry(&io->io_list, 9628c2ecf20Sopenharmony_ci struct f2fs_io_info, list); 9638c2ecf20Sopenharmony_ci list_del(&fio->list); 9648c2ecf20Sopenharmony_ci spin_unlock(&io->io_lock); 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci verify_fio_blkaddr(fio); 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_ci if (fio->encrypted_page) 9708c2ecf20Sopenharmony_ci bio_page = fio->encrypted_page; 9718c2ecf20Sopenharmony_ci else if (fio->compressed_page) 9728c2ecf20Sopenharmony_ci bio_page = fio->compressed_page; 9738c2ecf20Sopenharmony_ci else 9748c2ecf20Sopenharmony_ci bio_page = fio->page; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci /* set submitted = true as a return value */ 9778c2ecf20Sopenharmony_ci fio->submitted = true; 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci inc_page_count(sbi, WB_DATA_TYPE(bio_page)); 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if (io->bio && 9828c2ecf20Sopenharmony_ci (!io_is_mergeable(sbi, io->bio, io, fio, io->last_block_in_bio, 9838c2ecf20Sopenharmony_ci fio->new_blkaddr) || 9848c2ecf20Sopenharmony_ci !f2fs_crypt_mergeable_bio(io->bio, fio->page->mapping->host, 9858c2ecf20Sopenharmony_ci bio_page->index, fio))) 9868c2ecf20Sopenharmony_ci __submit_merged_bio(io); 9878c2ecf20Sopenharmony_cialloc_new: 9888c2ecf20Sopenharmony_ci if (io->bio == NULL) { 9898c2ecf20Sopenharmony_ci if (F2FS_IO_ALIGNED(sbi) && 9908c2ecf20Sopenharmony_ci (fio->type == DATA || fio->type == NODE) && 9918c2ecf20Sopenharmony_ci fio->new_blkaddr & F2FS_IO_SIZE_MASK(sbi)) { 9928c2ecf20Sopenharmony_ci dec_page_count(sbi, WB_DATA_TYPE(bio_page)); 9938c2ecf20Sopenharmony_ci fio->retry = true; 9948c2ecf20Sopenharmony_ci goto skip; 9958c2ecf20Sopenharmony_ci } 9968c2ecf20Sopenharmony_ci io->bio = __bio_alloc(fio, BIO_MAX_PAGES); 9978c2ecf20Sopenharmony_ci f2fs_set_bio_crypt_ctx(io->bio, fio->page->mapping->host, 9988c2ecf20Sopenharmony_ci bio_page->index, fio, GFP_NOIO); 9998c2ecf20Sopenharmony_ci io->fio = *fio; 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci if (bio_add_page(io->bio, bio_page, PAGE_SIZE, 0) < PAGE_SIZE) { 10038c2ecf20Sopenharmony_ci __submit_merged_bio(io); 10048c2ecf20Sopenharmony_ci goto alloc_new; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci if (fio->io_wbc) 10088c2ecf20Sopenharmony_ci wbc_account_cgroup_owner(fio->io_wbc, fio->page, PAGE_SIZE); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci io->last_block_in_bio = fio->new_blkaddr; 10118c2ecf20Sopenharmony_ci f2fs_trace_ios(fio, 0); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci trace_f2fs_submit_page_write(fio->page, fio); 10148c2ecf20Sopenharmony_ciskip: 10158c2ecf20Sopenharmony_ci if (fio->in_list) 10168c2ecf20Sopenharmony_ci goto next; 10178c2ecf20Sopenharmony_ciout: 10188c2ecf20Sopenharmony_ci if (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || 10198c2ecf20Sopenharmony_ci !f2fs_is_checkpoint_ready(sbi)) 10208c2ecf20Sopenharmony_ci __submit_merged_bio(io); 10218c2ecf20Sopenharmony_ci up_write(&io->io_rwsem); 10228c2ecf20Sopenharmony_ci} 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_cistatic inline bool f2fs_need_verity(const struct inode *inode, pgoff_t idx) 10258c2ecf20Sopenharmony_ci{ 10268c2ecf20Sopenharmony_ci return fsverity_active(inode) && (idx < 10278c2ecf20Sopenharmony_ci DIV_ROUND_UP(fsverity_get_verified_data_size(inode), PAGE_SIZE)); 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistatic struct bio *f2fs_grab_read_bio(struct inode *inode, block_t blkaddr, 10318c2ecf20Sopenharmony_ci unsigned nr_pages, unsigned op_flag, 10328c2ecf20Sopenharmony_ci pgoff_t first_idx, bool for_write, 10338c2ecf20Sopenharmony_ci bool for_verity) 10348c2ecf20Sopenharmony_ci{ 10358c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 10368c2ecf20Sopenharmony_ci struct bio *bio; 10378c2ecf20Sopenharmony_ci struct bio_post_read_ctx *ctx; 10388c2ecf20Sopenharmony_ci unsigned int post_read_steps = 0; 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_ci bio = f2fs_bio_alloc(sbi, min_t(int, nr_pages, BIO_MAX_PAGES), 10418c2ecf20Sopenharmony_ci for_write); 10428c2ecf20Sopenharmony_ci if (!bio) 10438c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci f2fs_set_bio_crypt_ctx(bio, inode, first_idx, NULL, GFP_NOFS); 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci f2fs_target_device(sbi, blkaddr, bio); 10488c2ecf20Sopenharmony_ci bio->bi_end_io = f2fs_read_end_io; 10498c2ecf20Sopenharmony_ci bio_set_op_attrs(bio, REQ_OP_READ, op_flag); 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci if (fscrypt_inode_uses_fs_layer_crypto(inode)) 10528c2ecf20Sopenharmony_ci post_read_steps |= 1 << STEP_DECRYPT; 10538c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) 10548c2ecf20Sopenharmony_ci post_read_steps |= 1 << STEP_DECOMPRESS_NOWQ; 10558c2ecf20Sopenharmony_ci if (for_verity && f2fs_need_verity(inode, first_idx)) 10568c2ecf20Sopenharmony_ci post_read_steps |= 1 << STEP_VERITY; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci if (post_read_steps) { 10598c2ecf20Sopenharmony_ci /* Due to the mempool, this never fails. */ 10608c2ecf20Sopenharmony_ci ctx = mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); 10618c2ecf20Sopenharmony_ci ctx->bio = bio; 10628c2ecf20Sopenharmony_ci ctx->sbi = sbi; 10638c2ecf20Sopenharmony_ci ctx->enabled_steps = post_read_steps; 10648c2ecf20Sopenharmony_ci bio->bi_private = ctx; 10658c2ecf20Sopenharmony_ci } 10668c2ecf20Sopenharmony_ci 10678c2ecf20Sopenharmony_ci return bio; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic void f2fs_release_read_bio(struct bio *bio) 10718c2ecf20Sopenharmony_ci{ 10728c2ecf20Sopenharmony_ci if (bio->bi_private) 10738c2ecf20Sopenharmony_ci mempool_free(bio->bi_private, bio_post_read_ctx_pool); 10748c2ecf20Sopenharmony_ci bio_put(bio); 10758c2ecf20Sopenharmony_ci} 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci/* This can handle encryption stuffs */ 10788c2ecf20Sopenharmony_cistatic int f2fs_submit_page_read(struct inode *inode, struct page *page, 10798c2ecf20Sopenharmony_ci block_t blkaddr, int op_flags, bool for_write) 10808c2ecf20Sopenharmony_ci{ 10818c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 10828c2ecf20Sopenharmony_ci struct bio *bio; 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci bio = f2fs_grab_read_bio(inode, blkaddr, 1, op_flags, 10858c2ecf20Sopenharmony_ci page->index, for_write, true); 10868c2ecf20Sopenharmony_ci if (IS_ERR(bio)) 10878c2ecf20Sopenharmony_ci return PTR_ERR(bio); 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci /* wait for GCed page writeback via META_MAPPING */ 10908c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback(inode, blkaddr); 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, PAGE_SIZE, 0) < PAGE_SIZE) { 10938c2ecf20Sopenharmony_ci bio_put(bio); 10948c2ecf20Sopenharmony_ci return -EFAULT; 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci ClearPageError(page); 10978c2ecf20Sopenharmony_ci inc_page_count(sbi, F2FS_RD_DATA); 10988c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE); 10998c2ecf20Sopenharmony_ci __submit_bio(sbi, bio, DATA); 11008c2ecf20Sopenharmony_ci return 0; 11018c2ecf20Sopenharmony_ci} 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_cistatic void __set_data_blkaddr(struct dnode_of_data *dn) 11048c2ecf20Sopenharmony_ci{ 11058c2ecf20Sopenharmony_ci struct f2fs_node *rn = F2FS_NODE(dn->node_page); 11068c2ecf20Sopenharmony_ci __le32 *addr_array; 11078c2ecf20Sopenharmony_ci int base = 0; 11088c2ecf20Sopenharmony_ci 11098c2ecf20Sopenharmony_ci if (IS_INODE(dn->node_page) && f2fs_has_extra_attr(dn->inode)) 11108c2ecf20Sopenharmony_ci base = get_extra_isize(dn->inode); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci /* Get physical address of data block */ 11138c2ecf20Sopenharmony_ci addr_array = blkaddr_in_node(rn); 11148c2ecf20Sopenharmony_ci addr_array[base + dn->ofs_in_node] = cpu_to_le32(dn->data_blkaddr); 11158c2ecf20Sopenharmony_ci} 11168c2ecf20Sopenharmony_ci 11178c2ecf20Sopenharmony_ci/* 11188c2ecf20Sopenharmony_ci * Lock ordering for the change of data block address: 11198c2ecf20Sopenharmony_ci * ->data_page 11208c2ecf20Sopenharmony_ci * ->node_page 11218c2ecf20Sopenharmony_ci * update block addresses in the node page 11228c2ecf20Sopenharmony_ci */ 11238c2ecf20Sopenharmony_civoid f2fs_set_data_blkaddr(struct dnode_of_data *dn) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); 11268c2ecf20Sopenharmony_ci __set_data_blkaddr(dn); 11278c2ecf20Sopenharmony_ci if (set_page_dirty(dn->node_page)) 11288c2ecf20Sopenharmony_ci dn->node_changed = true; 11298c2ecf20Sopenharmony_ci} 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_civoid f2fs_update_data_blkaddr(struct dnode_of_data *dn, block_t blkaddr) 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci dn->data_blkaddr = blkaddr; 11348c2ecf20Sopenharmony_ci f2fs_set_data_blkaddr(dn); 11358c2ecf20Sopenharmony_ci f2fs_update_extent_cache(dn); 11368c2ecf20Sopenharmony_ci} 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci/* dn->ofs_in_node will be returned with up-to-date last block pointer */ 11398c2ecf20Sopenharmony_ciint f2fs_reserve_new_blocks(struct dnode_of_data *dn, blkcnt_t count) 11408c2ecf20Sopenharmony_ci{ 11418c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 11428c2ecf20Sopenharmony_ci int err; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci if (!count) 11458c2ecf20Sopenharmony_ci return 0; 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 11488c2ecf20Sopenharmony_ci return -EPERM; 11498c2ecf20Sopenharmony_ci if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) 11508c2ecf20Sopenharmony_ci return err; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci trace_f2fs_reserve_new_blocks(dn->inode, dn->nid, 11538c2ecf20Sopenharmony_ci dn->ofs_in_node, count); 11548c2ecf20Sopenharmony_ci 11558c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(dn->node_page, NODE, true, true); 11568c2ecf20Sopenharmony_ci 11578c2ecf20Sopenharmony_ci for (; count > 0; dn->ofs_in_node++) { 11588c2ecf20Sopenharmony_ci block_t blkaddr = f2fs_data_blkaddr(dn); 11598c2ecf20Sopenharmony_ci if (blkaddr == NULL_ADDR) { 11608c2ecf20Sopenharmony_ci dn->data_blkaddr = NEW_ADDR; 11618c2ecf20Sopenharmony_ci __set_data_blkaddr(dn); 11628c2ecf20Sopenharmony_ci count--; 11638c2ecf20Sopenharmony_ci } 11648c2ecf20Sopenharmony_ci } 11658c2ecf20Sopenharmony_ci 11668c2ecf20Sopenharmony_ci if (set_page_dirty(dn->node_page)) 11678c2ecf20Sopenharmony_ci dn->node_changed = true; 11688c2ecf20Sopenharmony_ci return 0; 11698c2ecf20Sopenharmony_ci} 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci/* Should keep dn->ofs_in_node unchanged */ 11728c2ecf20Sopenharmony_ciint f2fs_reserve_new_block(struct dnode_of_data *dn) 11738c2ecf20Sopenharmony_ci{ 11748c2ecf20Sopenharmony_ci unsigned int ofs_in_node = dn->ofs_in_node; 11758c2ecf20Sopenharmony_ci int ret; 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci ret = f2fs_reserve_new_blocks(dn, 1); 11788c2ecf20Sopenharmony_ci dn->ofs_in_node = ofs_in_node; 11798c2ecf20Sopenharmony_ci return ret; 11808c2ecf20Sopenharmony_ci} 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ciint f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index) 11838c2ecf20Sopenharmony_ci{ 11848c2ecf20Sopenharmony_ci bool need_put = dn->inode_page ? false : true; 11858c2ecf20Sopenharmony_ci int err; 11868c2ecf20Sopenharmony_ci 11878c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(dn, index, ALLOC_NODE); 11888c2ecf20Sopenharmony_ci if (err) 11898c2ecf20Sopenharmony_ci return err; 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci if (dn->data_blkaddr == NULL_ADDR) 11928c2ecf20Sopenharmony_ci err = f2fs_reserve_new_block(dn); 11938c2ecf20Sopenharmony_ci if (err || need_put) 11948c2ecf20Sopenharmony_ci f2fs_put_dnode(dn); 11958c2ecf20Sopenharmony_ci return err; 11968c2ecf20Sopenharmony_ci} 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ciint f2fs_get_block(struct dnode_of_data *dn, pgoff_t index) 11998c2ecf20Sopenharmony_ci{ 12008c2ecf20Sopenharmony_ci struct extent_info ei = {0, 0, 0}; 12018c2ecf20Sopenharmony_ci struct inode *inode = dn->inode; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci if (f2fs_lookup_extent_cache(inode, index, &ei)) { 12048c2ecf20Sopenharmony_ci dn->data_blkaddr = ei.blk + index - ei.fofs; 12058c2ecf20Sopenharmony_ci return 0; 12068c2ecf20Sopenharmony_ci } 12078c2ecf20Sopenharmony_ci 12088c2ecf20Sopenharmony_ci return f2fs_reserve_block(dn, index); 12098c2ecf20Sopenharmony_ci} 12108c2ecf20Sopenharmony_ci 12118c2ecf20Sopenharmony_cistruct page *f2fs_get_read_data_page(struct inode *inode, pgoff_t index, 12128c2ecf20Sopenharmony_ci int op_flags, bool for_write) 12138c2ecf20Sopenharmony_ci{ 12148c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 12158c2ecf20Sopenharmony_ci struct dnode_of_data dn; 12168c2ecf20Sopenharmony_ci struct page *page; 12178c2ecf20Sopenharmony_ci struct extent_info ei = {0,0,0}; 12188c2ecf20Sopenharmony_ci int err; 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, for_write); 12218c2ecf20Sopenharmony_ci if (!page) 12228c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 12238c2ecf20Sopenharmony_ci 12248c2ecf20Sopenharmony_ci if (f2fs_lookup_extent_cache(inode, index, &ei)) { 12258c2ecf20Sopenharmony_ci dn.data_blkaddr = ei.blk + index - ei.fofs; 12268c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), dn.data_blkaddr, 12278c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 12288c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 12298c2ecf20Sopenharmony_ci goto put_err; 12308c2ecf20Sopenharmony_ci } 12318c2ecf20Sopenharmony_ci goto got_it; 12328c2ecf20Sopenharmony_ci } 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 12358c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); 12368c2ecf20Sopenharmony_ci if (err) 12378c2ecf20Sopenharmony_ci goto put_err; 12388c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci if (unlikely(dn.data_blkaddr == NULL_ADDR)) { 12418c2ecf20Sopenharmony_ci err = -ENOENT; 12428c2ecf20Sopenharmony_ci goto put_err; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci if (dn.data_blkaddr != NEW_ADDR && 12458c2ecf20Sopenharmony_ci !f2fs_is_valid_blkaddr(F2FS_I_SB(inode), 12468c2ecf20Sopenharmony_ci dn.data_blkaddr, 12478c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 12488c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 12498c2ecf20Sopenharmony_ci goto put_err; 12508c2ecf20Sopenharmony_ci } 12518c2ecf20Sopenharmony_cigot_it: 12528c2ecf20Sopenharmony_ci if (PageUptodate(page)) { 12538c2ecf20Sopenharmony_ci unlock_page(page); 12548c2ecf20Sopenharmony_ci return page; 12558c2ecf20Sopenharmony_ci } 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci /* 12588c2ecf20Sopenharmony_ci * A new dentry page is allocated but not able to be written, since its 12598c2ecf20Sopenharmony_ci * new inode page couldn't be allocated due to -ENOSPC. 12608c2ecf20Sopenharmony_ci * In such the case, its blkaddr can be remained as NEW_ADDR. 12618c2ecf20Sopenharmony_ci * see, f2fs_add_link -> f2fs_get_new_data_page -> 12628c2ecf20Sopenharmony_ci * f2fs_init_inode_metadata. 12638c2ecf20Sopenharmony_ci */ 12648c2ecf20Sopenharmony_ci if (dn.data_blkaddr == NEW_ADDR) { 12658c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 12668c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 12678c2ecf20Sopenharmony_ci SetPageUptodate(page); 12688c2ecf20Sopenharmony_ci unlock_page(page); 12698c2ecf20Sopenharmony_ci return page; 12708c2ecf20Sopenharmony_ci } 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci err = f2fs_submit_page_read(inode, page, dn.data_blkaddr, 12738c2ecf20Sopenharmony_ci op_flags, for_write); 12748c2ecf20Sopenharmony_ci if (err) 12758c2ecf20Sopenharmony_ci goto put_err; 12768c2ecf20Sopenharmony_ci return page; 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ciput_err: 12798c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 12808c2ecf20Sopenharmony_ci return ERR_PTR(err); 12818c2ecf20Sopenharmony_ci} 12828c2ecf20Sopenharmony_ci 12838c2ecf20Sopenharmony_cistruct page *f2fs_find_data_page(struct inode *inode, pgoff_t index) 12848c2ecf20Sopenharmony_ci{ 12858c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 12868c2ecf20Sopenharmony_ci struct page *page; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci page = find_get_page(mapping, index); 12898c2ecf20Sopenharmony_ci if (page && PageUptodate(page)) 12908c2ecf20Sopenharmony_ci return page; 12918c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci page = f2fs_get_read_data_page(inode, index, 0, false); 12948c2ecf20Sopenharmony_ci if (IS_ERR(page)) 12958c2ecf20Sopenharmony_ci return page; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci if (PageUptodate(page)) 12988c2ecf20Sopenharmony_ci return page; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_ci wait_on_page_locked(page); 13018c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 13028c2ecf20Sopenharmony_ci f2fs_put_page(page, 0); 13038c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 13048c2ecf20Sopenharmony_ci } 13058c2ecf20Sopenharmony_ci return page; 13068c2ecf20Sopenharmony_ci} 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci/* 13098c2ecf20Sopenharmony_ci * If it tries to access a hole, return an error. 13108c2ecf20Sopenharmony_ci * Because, the callers, functions in dir.c and GC, should be able to know 13118c2ecf20Sopenharmony_ci * whether this page exists or not. 13128c2ecf20Sopenharmony_ci */ 13138c2ecf20Sopenharmony_cistruct page *f2fs_get_lock_data_page(struct inode *inode, pgoff_t index, 13148c2ecf20Sopenharmony_ci bool for_write) 13158c2ecf20Sopenharmony_ci{ 13168c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 13178c2ecf20Sopenharmony_ci struct page *page; 13188c2ecf20Sopenharmony_cirepeat: 13198c2ecf20Sopenharmony_ci page = f2fs_get_read_data_page(inode, index, 0, for_write); 13208c2ecf20Sopenharmony_ci if (IS_ERR(page)) 13218c2ecf20Sopenharmony_ci return page; 13228c2ecf20Sopenharmony_ci 13238c2ecf20Sopenharmony_ci /* wait for read completion */ 13248c2ecf20Sopenharmony_ci lock_page(page); 13258c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 13268c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13278c2ecf20Sopenharmony_ci goto repeat; 13288c2ecf20Sopenharmony_ci } 13298c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 13308c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13318c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 13328c2ecf20Sopenharmony_ci } 13338c2ecf20Sopenharmony_ci return page; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci/* 13378c2ecf20Sopenharmony_ci * Caller ensures that this data page is never allocated. 13388c2ecf20Sopenharmony_ci * A new zero-filled data page is allocated in the page cache. 13398c2ecf20Sopenharmony_ci * 13408c2ecf20Sopenharmony_ci * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and 13418c2ecf20Sopenharmony_ci * f2fs_unlock_op(). 13428c2ecf20Sopenharmony_ci * Note that, ipage is set only by make_empty_dir, and if any error occur, 13438c2ecf20Sopenharmony_ci * ipage should be released by this function. 13448c2ecf20Sopenharmony_ci */ 13458c2ecf20Sopenharmony_cistruct page *f2fs_get_new_data_page(struct inode *inode, 13468c2ecf20Sopenharmony_ci struct page *ipage, pgoff_t index, bool new_i_size) 13478c2ecf20Sopenharmony_ci{ 13488c2ecf20Sopenharmony_ci struct address_space *mapping = inode->i_mapping; 13498c2ecf20Sopenharmony_ci struct page *page; 13508c2ecf20Sopenharmony_ci struct dnode_of_data dn; 13518c2ecf20Sopenharmony_ci int err; 13528c2ecf20Sopenharmony_ci 13538c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(mapping, index, true); 13548c2ecf20Sopenharmony_ci if (!page) { 13558c2ecf20Sopenharmony_ci /* 13568c2ecf20Sopenharmony_ci * before exiting, we should make sure ipage will be released 13578c2ecf20Sopenharmony_ci * if any error occur. 13588c2ecf20Sopenharmony_ci */ 13598c2ecf20Sopenharmony_ci f2fs_put_page(ipage, 1); 13608c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 13618c2ecf20Sopenharmony_ci } 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, ipage, NULL, 0); 13648c2ecf20Sopenharmony_ci err = f2fs_reserve_block(&dn, index); 13658c2ecf20Sopenharmony_ci if (err) { 13668c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13678c2ecf20Sopenharmony_ci return ERR_PTR(err); 13688c2ecf20Sopenharmony_ci } 13698c2ecf20Sopenharmony_ci if (!ipage) 13708c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci if (PageUptodate(page)) 13738c2ecf20Sopenharmony_ci goto got_it; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci if (dn.data_blkaddr == NEW_ADDR) { 13768c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 13778c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 13788c2ecf20Sopenharmony_ci SetPageUptodate(page); 13798c2ecf20Sopenharmony_ci } else { 13808c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 13818c2ecf20Sopenharmony_ci 13828c2ecf20Sopenharmony_ci /* if ipage exists, blkaddr should be NEW_ADDR */ 13838c2ecf20Sopenharmony_ci f2fs_bug_on(F2FS_I_SB(inode), ipage); 13848c2ecf20Sopenharmony_ci page = f2fs_get_lock_data_page(inode, index, true); 13858c2ecf20Sopenharmony_ci if (IS_ERR(page)) 13868c2ecf20Sopenharmony_ci return page; 13878c2ecf20Sopenharmony_ci } 13888c2ecf20Sopenharmony_cigot_it: 13898c2ecf20Sopenharmony_ci if (new_i_size && i_size_read(inode) < 13908c2ecf20Sopenharmony_ci ((loff_t)(index + 1) << PAGE_SHIFT)) 13918c2ecf20Sopenharmony_ci f2fs_i_size_write(inode, ((loff_t)(index + 1) << PAGE_SHIFT)); 13928c2ecf20Sopenharmony_ci return page; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_cistatic int __allocate_data_block(struct dnode_of_data *dn, int seg_type, int contig_level) 13968c2ecf20Sopenharmony_ci{ 13978c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); 13988c2ecf20Sopenharmony_ci struct f2fs_summary sum; 13998c2ecf20Sopenharmony_ci struct node_info ni; 14008c2ecf20Sopenharmony_ci block_t old_blkaddr; 14018c2ecf20Sopenharmony_ci blkcnt_t count = 1; 14028c2ecf20Sopenharmony_ci int err; 14038c2ecf20Sopenharmony_ci 14048c2ecf20Sopenharmony_ci if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) 14058c2ecf20Sopenharmony_ci return -EPERM; 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, dn->nid, &ni); 14088c2ecf20Sopenharmony_ci if (err) 14098c2ecf20Sopenharmony_ci return err; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci dn->data_blkaddr = f2fs_data_blkaddr(dn); 14128c2ecf20Sopenharmony_ci if (dn->data_blkaddr != NULL_ADDR) 14138c2ecf20Sopenharmony_ci goto alloc; 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci if (unlikely((err = inc_valid_block_count(sbi, dn->inode, &count)))) 14168c2ecf20Sopenharmony_ci return err; 14178c2ecf20Sopenharmony_ci 14188c2ecf20Sopenharmony_cialloc: 14198c2ecf20Sopenharmony_ci set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); 14208c2ecf20Sopenharmony_ci old_blkaddr = dn->data_blkaddr; 14218c2ecf20Sopenharmony_ci f2fs_allocate_data_block(sbi, NULL, old_blkaddr, &dn->data_blkaddr, 14228c2ecf20Sopenharmony_ci &sum, seg_type, NULL, contig_level); 14238c2ecf20Sopenharmony_ci if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) 14248c2ecf20Sopenharmony_ci invalidate_mapping_pages(META_MAPPING(sbi), 14258c2ecf20Sopenharmony_ci old_blkaddr, old_blkaddr); 14268c2ecf20Sopenharmony_ci f2fs_update_data_blkaddr(dn, dn->data_blkaddr); 14278c2ecf20Sopenharmony_ci 14288c2ecf20Sopenharmony_ci /* 14298c2ecf20Sopenharmony_ci * i_size will be updated by direct_IO. Otherwise, we'll get stale 14308c2ecf20Sopenharmony_ci * data from unwritten block via dio_read. 14318c2ecf20Sopenharmony_ci */ 14328c2ecf20Sopenharmony_ci return 0; 14338c2ecf20Sopenharmony_ci} 14348c2ecf20Sopenharmony_ci 14358c2ecf20Sopenharmony_ciint f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from) 14368c2ecf20Sopenharmony_ci{ 14378c2ecf20Sopenharmony_ci struct inode *inode = file_inode(iocb->ki_filp); 14388c2ecf20Sopenharmony_ci struct f2fs_map_blocks map; 14398c2ecf20Sopenharmony_ci int flag; 14408c2ecf20Sopenharmony_ci int err = 0; 14418c2ecf20Sopenharmony_ci bool direct_io = iocb->ki_flags & IOCB_DIRECT; 14428c2ecf20Sopenharmony_ci 14438c2ecf20Sopenharmony_ci map.m_lblk = F2FS_BLK_ALIGN(iocb->ki_pos); 14448c2ecf20Sopenharmony_ci map.m_len = F2FS_BYTES_TO_BLK(iocb->ki_pos + iov_iter_count(from)); 14458c2ecf20Sopenharmony_ci if (map.m_len > map.m_lblk) 14468c2ecf20Sopenharmony_ci map.m_len -= map.m_lblk; 14478c2ecf20Sopenharmony_ci else 14488c2ecf20Sopenharmony_ci map.m_len = 0; 14498c2ecf20Sopenharmony_ci 14508c2ecf20Sopenharmony_ci map.m_next_pgofs = NULL; 14518c2ecf20Sopenharmony_ci map.m_next_extent = NULL; 14528c2ecf20Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 14538c2ecf20Sopenharmony_ci map.m_may_create = true; 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_ci if (direct_io) { 14568c2ecf20Sopenharmony_ci map.m_seg_type = f2fs_rw_hint_to_seg_type(iocb->ki_hint); 14578c2ecf20Sopenharmony_ci flag = f2fs_force_buffered_io(inode, iocb, from) ? 14588c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_PRE_AIO : 14598c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_PRE_DIO; 14608c2ecf20Sopenharmony_ci goto map_blocks; 14618c2ecf20Sopenharmony_ci } 14628c2ecf20Sopenharmony_ci if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) { 14638c2ecf20Sopenharmony_ci err = f2fs_convert_inline_inode(inode); 14648c2ecf20Sopenharmony_ci if (err) 14658c2ecf20Sopenharmony_ci return err; 14668c2ecf20Sopenharmony_ci } 14678c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) 14688c2ecf20Sopenharmony_ci return err; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci flag = F2FS_GET_BLOCK_PRE_AIO; 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_cimap_blocks: 14738c2ecf20Sopenharmony_ci err = f2fs_map_blocks(inode, &map, 1, flag); 14748c2ecf20Sopenharmony_ci if (map.m_len > 0 && err == -ENOSPC) { 14758c2ecf20Sopenharmony_ci if (!direct_io) 14768c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_NO_PREALLOC); 14778c2ecf20Sopenharmony_ci err = 0; 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci return err; 14808c2ecf20Sopenharmony_ci} 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_civoid f2fs_do_map_lock(struct f2fs_sb_info *sbi, int flag, bool lock) 14838c2ecf20Sopenharmony_ci{ 14848c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) { 14858c2ecf20Sopenharmony_ci if (lock) 14868c2ecf20Sopenharmony_ci down_read(&sbi->node_change); 14878c2ecf20Sopenharmony_ci else 14888c2ecf20Sopenharmony_ci up_read(&sbi->node_change); 14898c2ecf20Sopenharmony_ci } else { 14908c2ecf20Sopenharmony_ci if (lock) 14918c2ecf20Sopenharmony_ci f2fs_lock_op(sbi); 14928c2ecf20Sopenharmony_ci else 14938c2ecf20Sopenharmony_ci f2fs_unlock_op(sbi); 14948c2ecf20Sopenharmony_ci } 14958c2ecf20Sopenharmony_ci} 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci/* 14988c2ecf20Sopenharmony_ci * f2fs_map_blocks() tries to find or build mapping relationship which 14998c2ecf20Sopenharmony_ci * maps continuous logical blocks to physical blocks, and return such 15008c2ecf20Sopenharmony_ci * info via f2fs_map_blocks structure. 15018c2ecf20Sopenharmony_ci */ 15028c2ecf20Sopenharmony_ciint f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, 15038c2ecf20Sopenharmony_ci int create, int flag) 15048c2ecf20Sopenharmony_ci{ 15058c2ecf20Sopenharmony_ci unsigned int maxblocks = map->m_len; 15068c2ecf20Sopenharmony_ci struct dnode_of_data dn; 15078c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 15088c2ecf20Sopenharmony_ci int mode = map->m_may_create ? ALLOC_NODE : LOOKUP_NODE; 15098c2ecf20Sopenharmony_ci pgoff_t pgofs, end_offset, end; 15108c2ecf20Sopenharmony_ci int err = 0, ofs = 1; 15118c2ecf20Sopenharmony_ci unsigned int ofs_in_node, last_ofs_in_node; 15128c2ecf20Sopenharmony_ci blkcnt_t prealloc; 15138c2ecf20Sopenharmony_ci struct extent_info ei = {0,0,0}; 15148c2ecf20Sopenharmony_ci block_t blkaddr; 15158c2ecf20Sopenharmony_ci unsigned int start_pgofs; 15168c2ecf20Sopenharmony_ci int contig_level = SEQ_NONE; 15178c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_GRADING_SSR 15188c2ecf20Sopenharmony_ci contig_level = check_io_seq(maxblocks); 15198c2ecf20Sopenharmony_ci#endif 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_ci if (!maxblocks) 15228c2ecf20Sopenharmony_ci return 0; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci map->m_len = 0; 15258c2ecf20Sopenharmony_ci map->m_flags = 0; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci /* it only supports block size == page size */ 15288c2ecf20Sopenharmony_ci pgofs = (pgoff_t)map->m_lblk; 15298c2ecf20Sopenharmony_ci end = pgofs + maxblocks; 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci if (!create && f2fs_lookup_extent_cache(inode, pgofs, &ei)) { 15328c2ecf20Sopenharmony_ci if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO && 15338c2ecf20Sopenharmony_ci map->m_may_create) 15348c2ecf20Sopenharmony_ci goto next_dnode; 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_ci map->m_pblk = ei.blk + pgofs - ei.fofs; 15378c2ecf20Sopenharmony_ci map->m_len = min((pgoff_t)maxblocks, ei.fofs + ei.len - pgofs); 15388c2ecf20Sopenharmony_ci map->m_flags = F2FS_MAP_MAPPED; 15398c2ecf20Sopenharmony_ci if (map->m_next_extent) 15408c2ecf20Sopenharmony_ci *map->m_next_extent = pgofs + map->m_len; 15418c2ecf20Sopenharmony_ci 15428c2ecf20Sopenharmony_ci /* for hardware encryption, but to avoid potential issue in future */ 15438c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_DIO) 15448c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback_range(inode, 15458c2ecf20Sopenharmony_ci map->m_pblk, map->m_len); 15468c2ecf20Sopenharmony_ci goto out; 15478c2ecf20Sopenharmony_ci } 15488c2ecf20Sopenharmony_ci 15498c2ecf20Sopenharmony_cinext_dnode: 15508c2ecf20Sopenharmony_ci if (map->m_may_create) 15518c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, flag, true); 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci /* When reading holes, we need its node page */ 15548c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 15558c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, pgofs, mode); 15568c2ecf20Sopenharmony_ci if (err) { 15578c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_BMAP) 15588c2ecf20Sopenharmony_ci map->m_pblk = 0; 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci if (err == -ENOENT) { 15618c2ecf20Sopenharmony_ci /* 15628c2ecf20Sopenharmony_ci * There is one exceptional case that read_node_page() 15638c2ecf20Sopenharmony_ci * may return -ENOENT due to filesystem has been 15648c2ecf20Sopenharmony_ci * shutdown or cp_error, so force to convert error 15658c2ecf20Sopenharmony_ci * number to EIO for such case. 15668c2ecf20Sopenharmony_ci */ 15678c2ecf20Sopenharmony_ci if (map->m_may_create && 15688c2ecf20Sopenharmony_ci (is_sbi_flag_set(sbi, SBI_IS_SHUTDOWN) || 15698c2ecf20Sopenharmony_ci f2fs_cp_error(sbi))) { 15708c2ecf20Sopenharmony_ci err = -EIO; 15718c2ecf20Sopenharmony_ci goto unlock_out; 15728c2ecf20Sopenharmony_ci } 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci err = 0; 15758c2ecf20Sopenharmony_ci if (map->m_next_pgofs) 15768c2ecf20Sopenharmony_ci *map->m_next_pgofs = 15778c2ecf20Sopenharmony_ci f2fs_get_next_page_offset(&dn, pgofs); 15788c2ecf20Sopenharmony_ci if (map->m_next_extent) 15798c2ecf20Sopenharmony_ci *map->m_next_extent = 15808c2ecf20Sopenharmony_ci f2fs_get_next_page_offset(&dn, pgofs); 15818c2ecf20Sopenharmony_ci } 15828c2ecf20Sopenharmony_ci goto unlock_out; 15838c2ecf20Sopenharmony_ci } 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci start_pgofs = pgofs; 15868c2ecf20Sopenharmony_ci prealloc = 0; 15878c2ecf20Sopenharmony_ci last_ofs_in_node = ofs_in_node = dn.ofs_in_node; 15888c2ecf20Sopenharmony_ci end_offset = ADDRS_PER_PAGE(dn.node_page, inode); 15898c2ecf20Sopenharmony_ci 15908c2ecf20Sopenharmony_cinext_block: 15918c2ecf20Sopenharmony_ci blkaddr = f2fs_data_blkaddr(&dn); 15928c2ecf20Sopenharmony_ci 15938c2ecf20Sopenharmony_ci if (__is_valid_data_blkaddr(blkaddr) && 15948c2ecf20Sopenharmony_ci !f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC_ENHANCE)) { 15958c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 15968c2ecf20Sopenharmony_ci goto sync_out; 15978c2ecf20Sopenharmony_ci } 15988c2ecf20Sopenharmony_ci 15998c2ecf20Sopenharmony_ci if (__is_valid_data_blkaddr(blkaddr)) { 16008c2ecf20Sopenharmony_ci /* use out-place-update for driect IO under LFS mode */ 16018c2ecf20Sopenharmony_ci if (f2fs_lfs_mode(sbi) && flag == F2FS_GET_BLOCK_DIO && 16028c2ecf20Sopenharmony_ci map->m_may_create) { 16038c2ecf20Sopenharmony_ci err = __allocate_data_block(&dn, map->m_seg_type, contig_level); 16048c2ecf20Sopenharmony_ci if (err) 16058c2ecf20Sopenharmony_ci goto sync_out; 16068c2ecf20Sopenharmony_ci blkaddr = dn.data_blkaddr; 16078c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 16088c2ecf20Sopenharmony_ci } 16098c2ecf20Sopenharmony_ci } else { 16108c2ecf20Sopenharmony_ci if (create) { 16118c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 16128c2ecf20Sopenharmony_ci err = -EIO; 16138c2ecf20Sopenharmony_ci goto sync_out; 16148c2ecf20Sopenharmony_ci } 16158c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) { 16168c2ecf20Sopenharmony_ci if (blkaddr == NULL_ADDR) { 16178c2ecf20Sopenharmony_ci prealloc++; 16188c2ecf20Sopenharmony_ci last_ofs_in_node = dn.ofs_in_node; 16198c2ecf20Sopenharmony_ci } 16208c2ecf20Sopenharmony_ci } else { 16218c2ecf20Sopenharmony_ci WARN_ON(flag != F2FS_GET_BLOCK_PRE_DIO && 16228c2ecf20Sopenharmony_ci flag != F2FS_GET_BLOCK_DIO); 16238c2ecf20Sopenharmony_ci err = __allocate_data_block(&dn, 16248c2ecf20Sopenharmony_ci map->m_seg_type, contig_level); 16258c2ecf20Sopenharmony_ci if (!err) 16268c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 16278c2ecf20Sopenharmony_ci } 16288c2ecf20Sopenharmony_ci if (err) 16298c2ecf20Sopenharmony_ci goto sync_out; 16308c2ecf20Sopenharmony_ci map->m_flags |= F2FS_MAP_NEW; 16318c2ecf20Sopenharmony_ci blkaddr = dn.data_blkaddr; 16328c2ecf20Sopenharmony_ci } else { 16338c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_BMAP) { 16348c2ecf20Sopenharmony_ci map->m_pblk = 0; 16358c2ecf20Sopenharmony_ci goto sync_out; 16368c2ecf20Sopenharmony_ci } 16378c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRECACHE) 16388c2ecf20Sopenharmony_ci goto sync_out; 16398c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_FIEMAP && 16408c2ecf20Sopenharmony_ci blkaddr == NULL_ADDR) { 16418c2ecf20Sopenharmony_ci if (map->m_next_pgofs) 16428c2ecf20Sopenharmony_ci *map->m_next_pgofs = pgofs + 1; 16438c2ecf20Sopenharmony_ci goto sync_out; 16448c2ecf20Sopenharmony_ci } 16458c2ecf20Sopenharmony_ci if (flag != F2FS_GET_BLOCK_FIEMAP) { 16468c2ecf20Sopenharmony_ci /* for defragment case */ 16478c2ecf20Sopenharmony_ci if (map->m_next_pgofs) 16488c2ecf20Sopenharmony_ci *map->m_next_pgofs = pgofs + 1; 16498c2ecf20Sopenharmony_ci goto sync_out; 16508c2ecf20Sopenharmony_ci } 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci } 16538c2ecf20Sopenharmony_ci 16548c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO) 16558c2ecf20Sopenharmony_ci goto skip; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci if (map->m_len == 0) { 16588c2ecf20Sopenharmony_ci /* preallocated unwritten block should be mapped for fiemap. */ 16598c2ecf20Sopenharmony_ci if (blkaddr == NEW_ADDR) 16608c2ecf20Sopenharmony_ci map->m_flags |= F2FS_MAP_UNWRITTEN; 16618c2ecf20Sopenharmony_ci map->m_flags |= F2FS_MAP_MAPPED; 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci map->m_pblk = blkaddr; 16648c2ecf20Sopenharmony_ci map->m_len = 1; 16658c2ecf20Sopenharmony_ci } else if ((map->m_pblk != NEW_ADDR && 16668c2ecf20Sopenharmony_ci blkaddr == (map->m_pblk + ofs)) || 16678c2ecf20Sopenharmony_ci (map->m_pblk == NEW_ADDR && blkaddr == NEW_ADDR) || 16688c2ecf20Sopenharmony_ci flag == F2FS_GET_BLOCK_PRE_DIO) { 16698c2ecf20Sopenharmony_ci ofs++; 16708c2ecf20Sopenharmony_ci map->m_len++; 16718c2ecf20Sopenharmony_ci } else { 16728c2ecf20Sopenharmony_ci goto sync_out; 16738c2ecf20Sopenharmony_ci } 16748c2ecf20Sopenharmony_ci 16758c2ecf20Sopenharmony_ciskip: 16768c2ecf20Sopenharmony_ci dn.ofs_in_node++; 16778c2ecf20Sopenharmony_ci pgofs++; 16788c2ecf20Sopenharmony_ci 16798c2ecf20Sopenharmony_ci /* preallocate blocks in batch for one dnode page */ 16808c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRE_AIO && 16818c2ecf20Sopenharmony_ci (pgofs == end || dn.ofs_in_node == end_offset)) { 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci dn.ofs_in_node = ofs_in_node; 16848c2ecf20Sopenharmony_ci err = f2fs_reserve_new_blocks(&dn, prealloc); 16858c2ecf20Sopenharmony_ci if (err) 16868c2ecf20Sopenharmony_ci goto sync_out; 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci map->m_len += dn.ofs_in_node - ofs_in_node; 16898c2ecf20Sopenharmony_ci if (prealloc && dn.ofs_in_node != last_ofs_in_node + 1) { 16908c2ecf20Sopenharmony_ci err = -ENOSPC; 16918c2ecf20Sopenharmony_ci goto sync_out; 16928c2ecf20Sopenharmony_ci } 16938c2ecf20Sopenharmony_ci dn.ofs_in_node = end_offset; 16948c2ecf20Sopenharmony_ci } 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci if (pgofs >= end) 16978c2ecf20Sopenharmony_ci goto sync_out; 16988c2ecf20Sopenharmony_ci else if (dn.ofs_in_node < end_offset) 16998c2ecf20Sopenharmony_ci goto next_block; 17008c2ecf20Sopenharmony_ci 17018c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRECACHE) { 17028c2ecf20Sopenharmony_ci if (map->m_flags & F2FS_MAP_MAPPED) { 17038c2ecf20Sopenharmony_ci unsigned int ofs = start_pgofs - map->m_lblk; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci f2fs_update_extent_cache_range(&dn, 17068c2ecf20Sopenharmony_ci start_pgofs, map->m_pblk + ofs, 17078c2ecf20Sopenharmony_ci map->m_len - ofs); 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci } 17108c2ecf20Sopenharmony_ci 17118c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci if (map->m_may_create) { 17148c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, flag, false); 17158c2ecf20Sopenharmony_ci f2fs_balance_fs(sbi, dn.node_changed); 17168c2ecf20Sopenharmony_ci } 17178c2ecf20Sopenharmony_ci goto next_dnode; 17188c2ecf20Sopenharmony_ci 17198c2ecf20Sopenharmony_cisync_out: 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_ci /* for hardware encryption, but to avoid potential issue in future */ 17228c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_DIO && map->m_flags & F2FS_MAP_MAPPED) 17238c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback_range(inode, 17248c2ecf20Sopenharmony_ci map->m_pblk, map->m_len); 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_ci if (flag == F2FS_GET_BLOCK_PRECACHE) { 17278c2ecf20Sopenharmony_ci if (map->m_flags & F2FS_MAP_MAPPED) { 17288c2ecf20Sopenharmony_ci unsigned int ofs = start_pgofs - map->m_lblk; 17298c2ecf20Sopenharmony_ci 17308c2ecf20Sopenharmony_ci f2fs_update_extent_cache_range(&dn, 17318c2ecf20Sopenharmony_ci start_pgofs, map->m_pblk + ofs, 17328c2ecf20Sopenharmony_ci map->m_len - ofs); 17338c2ecf20Sopenharmony_ci } 17348c2ecf20Sopenharmony_ci if (map->m_next_extent) 17358c2ecf20Sopenharmony_ci *map->m_next_extent = pgofs + 1; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 17388c2ecf20Sopenharmony_ciunlock_out: 17398c2ecf20Sopenharmony_ci if (map->m_may_create) { 17408c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, flag, false); 17418c2ecf20Sopenharmony_ci f2fs_balance_fs(sbi, dn.node_changed); 17428c2ecf20Sopenharmony_ci } 17438c2ecf20Sopenharmony_ciout: 17448c2ecf20Sopenharmony_ci trace_f2fs_map_blocks(inode, map, err); 17458c2ecf20Sopenharmony_ci return err; 17468c2ecf20Sopenharmony_ci} 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_cibool f2fs_overwrite_io(struct inode *inode, loff_t pos, size_t len) 17498c2ecf20Sopenharmony_ci{ 17508c2ecf20Sopenharmony_ci struct f2fs_map_blocks map; 17518c2ecf20Sopenharmony_ci block_t last_lblk; 17528c2ecf20Sopenharmony_ci int err; 17538c2ecf20Sopenharmony_ci 17548c2ecf20Sopenharmony_ci if (pos + len > i_size_read(inode)) 17558c2ecf20Sopenharmony_ci return false; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci map.m_lblk = F2FS_BYTES_TO_BLK(pos); 17588c2ecf20Sopenharmony_ci map.m_next_pgofs = NULL; 17598c2ecf20Sopenharmony_ci map.m_next_extent = NULL; 17608c2ecf20Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 17618c2ecf20Sopenharmony_ci map.m_may_create = false; 17628c2ecf20Sopenharmony_ci last_lblk = F2FS_BLK_ALIGN(pos + len); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci while (map.m_lblk < last_lblk) { 17658c2ecf20Sopenharmony_ci map.m_len = last_lblk - map.m_lblk; 17668c2ecf20Sopenharmony_ci err = f2fs_map_blocks(inode, &map, 0, F2FS_GET_BLOCK_DEFAULT); 17678c2ecf20Sopenharmony_ci if (err || map.m_len == 0) 17688c2ecf20Sopenharmony_ci return false; 17698c2ecf20Sopenharmony_ci map.m_lblk += map.m_len; 17708c2ecf20Sopenharmony_ci } 17718c2ecf20Sopenharmony_ci return true; 17728c2ecf20Sopenharmony_ci} 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_cistatic int __get_data_block(struct inode *inode, sector_t iblock, 17758c2ecf20Sopenharmony_ci struct buffer_head *bh, int create, int flag, 17768c2ecf20Sopenharmony_ci pgoff_t *next_pgofs, int seg_type, bool may_write) 17778c2ecf20Sopenharmony_ci{ 17788c2ecf20Sopenharmony_ci struct f2fs_map_blocks map; 17798c2ecf20Sopenharmony_ci int err; 17808c2ecf20Sopenharmony_ci 17818c2ecf20Sopenharmony_ci map.m_lblk = iblock; 17828c2ecf20Sopenharmony_ci map.m_len = bh->b_size >> inode->i_blkbits; 17838c2ecf20Sopenharmony_ci map.m_next_pgofs = next_pgofs; 17848c2ecf20Sopenharmony_ci map.m_next_extent = NULL; 17858c2ecf20Sopenharmony_ci map.m_seg_type = seg_type; 17868c2ecf20Sopenharmony_ci map.m_may_create = may_write; 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci err = f2fs_map_blocks(inode, &map, create, flag); 17898c2ecf20Sopenharmony_ci if (!err) { 17908c2ecf20Sopenharmony_ci map_bh(bh, inode->i_sb, map.m_pblk); 17918c2ecf20Sopenharmony_ci bh->b_state = (bh->b_state & ~F2FS_MAP_FLAGS) | map.m_flags; 17928c2ecf20Sopenharmony_ci bh->b_size = (u64)map.m_len << inode->i_blkbits; 17938c2ecf20Sopenharmony_ci } 17948c2ecf20Sopenharmony_ci return err; 17958c2ecf20Sopenharmony_ci} 17968c2ecf20Sopenharmony_ci 17978c2ecf20Sopenharmony_cistatic int get_data_block(struct inode *inode, sector_t iblock, 17988c2ecf20Sopenharmony_ci struct buffer_head *bh_result, int create, int flag, 17998c2ecf20Sopenharmony_ci pgoff_t *next_pgofs) 18008c2ecf20Sopenharmony_ci{ 18018c2ecf20Sopenharmony_ci return __get_data_block(inode, iblock, bh_result, create, 18028c2ecf20Sopenharmony_ci flag, next_pgofs, 18038c2ecf20Sopenharmony_ci NO_CHECK_TYPE, create); 18048c2ecf20Sopenharmony_ci} 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_cistatic int get_data_block_dio_write(struct inode *inode, sector_t iblock, 18078c2ecf20Sopenharmony_ci struct buffer_head *bh_result, int create) 18088c2ecf20Sopenharmony_ci{ 18098c2ecf20Sopenharmony_ci return __get_data_block(inode, iblock, bh_result, create, 18108c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_DIO, NULL, 18118c2ecf20Sopenharmony_ci f2fs_rw_hint_to_seg_type(inode->i_write_hint), 18128c2ecf20Sopenharmony_ci IS_SWAPFILE(inode) ? false : true); 18138c2ecf20Sopenharmony_ci} 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_cistatic int get_data_block_dio(struct inode *inode, sector_t iblock, 18168c2ecf20Sopenharmony_ci struct buffer_head *bh_result, int create) 18178c2ecf20Sopenharmony_ci{ 18188c2ecf20Sopenharmony_ci return __get_data_block(inode, iblock, bh_result, create, 18198c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_DIO, NULL, 18208c2ecf20Sopenharmony_ci f2fs_rw_hint_to_seg_type(inode->i_write_hint), 18218c2ecf20Sopenharmony_ci false); 18228c2ecf20Sopenharmony_ci} 18238c2ecf20Sopenharmony_ci 18248c2ecf20Sopenharmony_cistatic int get_data_block_bmap(struct inode *inode, sector_t iblock, 18258c2ecf20Sopenharmony_ci struct buffer_head *bh_result, int create) 18268c2ecf20Sopenharmony_ci{ 18278c2ecf20Sopenharmony_ci return __get_data_block(inode, iblock, bh_result, create, 18288c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_BMAP, NULL, 18298c2ecf20Sopenharmony_ci NO_CHECK_TYPE, create); 18308c2ecf20Sopenharmony_ci} 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_cistatic inline sector_t logical_to_blk(struct inode *inode, loff_t offset) 18338c2ecf20Sopenharmony_ci{ 18348c2ecf20Sopenharmony_ci return (offset >> inode->i_blkbits); 18358c2ecf20Sopenharmony_ci} 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_cistatic inline loff_t blk_to_logical(struct inode *inode, sector_t blk) 18388c2ecf20Sopenharmony_ci{ 18398c2ecf20Sopenharmony_ci return (blk << inode->i_blkbits); 18408c2ecf20Sopenharmony_ci} 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_cistatic int f2fs_xattr_fiemap(struct inode *inode, 18438c2ecf20Sopenharmony_ci struct fiemap_extent_info *fieinfo) 18448c2ecf20Sopenharmony_ci{ 18458c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 18468c2ecf20Sopenharmony_ci struct page *page; 18478c2ecf20Sopenharmony_ci struct node_info ni; 18488c2ecf20Sopenharmony_ci __u64 phys = 0, len; 18498c2ecf20Sopenharmony_ci __u32 flags; 18508c2ecf20Sopenharmony_ci nid_t xnid = F2FS_I(inode)->i_xattr_nid; 18518c2ecf20Sopenharmony_ci int err = 0; 18528c2ecf20Sopenharmony_ci 18538c2ecf20Sopenharmony_ci if (f2fs_has_inline_xattr(inode)) { 18548c2ecf20Sopenharmony_ci int offset; 18558c2ecf20Sopenharmony_ci 18568c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), 18578c2ecf20Sopenharmony_ci inode->i_ino, false); 18588c2ecf20Sopenharmony_ci if (!page) 18598c2ecf20Sopenharmony_ci return -ENOMEM; 18608c2ecf20Sopenharmony_ci 18618c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, inode->i_ino, &ni); 18628c2ecf20Sopenharmony_ci if (err) { 18638c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 18648c2ecf20Sopenharmony_ci return err; 18658c2ecf20Sopenharmony_ci } 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci phys = (__u64)blk_to_logical(inode, ni.blk_addr); 18688c2ecf20Sopenharmony_ci offset = offsetof(struct f2fs_inode, i_addr) + 18698c2ecf20Sopenharmony_ci sizeof(__le32) * (DEF_ADDRS_PER_INODE - 18708c2ecf20Sopenharmony_ci get_inline_xattr_addrs(inode)); 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci phys += offset; 18738c2ecf20Sopenharmony_ci len = inline_xattr_size(inode); 18748c2ecf20Sopenharmony_ci 18758c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 18768c2ecf20Sopenharmony_ci 18778c2ecf20Sopenharmony_ci flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED; 18788c2ecf20Sopenharmony_ci 18798c2ecf20Sopenharmony_ci if (!xnid) 18808c2ecf20Sopenharmony_ci flags |= FIEMAP_EXTENT_LAST; 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); 18838c2ecf20Sopenharmony_ci trace_f2fs_fiemap(inode, 0, phys, len, flags, err); 18848c2ecf20Sopenharmony_ci if (err || err == 1) 18858c2ecf20Sopenharmony_ci return err; 18868c2ecf20Sopenharmony_ci } 18878c2ecf20Sopenharmony_ci 18888c2ecf20Sopenharmony_ci if (xnid) { 18898c2ecf20Sopenharmony_ci page = f2fs_grab_cache_page(NODE_MAPPING(sbi), xnid, false); 18908c2ecf20Sopenharmony_ci if (!page) 18918c2ecf20Sopenharmony_ci return -ENOMEM; 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_ci err = f2fs_get_node_info(sbi, xnid, &ni); 18948c2ecf20Sopenharmony_ci if (err) { 18958c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 18968c2ecf20Sopenharmony_ci return err; 18978c2ecf20Sopenharmony_ci } 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci phys = (__u64)blk_to_logical(inode, ni.blk_addr); 19008c2ecf20Sopenharmony_ci len = inode->i_sb->s_blocksize; 19018c2ecf20Sopenharmony_ci 19028c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci flags = FIEMAP_EXTENT_LAST; 19058c2ecf20Sopenharmony_ci } 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci if (phys) { 19088c2ecf20Sopenharmony_ci err = fiemap_fill_next_extent(fieinfo, 0, phys, len, flags); 19098c2ecf20Sopenharmony_ci trace_f2fs_fiemap(inode, 0, phys, len, flags, err); 19108c2ecf20Sopenharmony_ci } 19118c2ecf20Sopenharmony_ci 19128c2ecf20Sopenharmony_ci return (err < 0 ? err : 0); 19138c2ecf20Sopenharmony_ci} 19148c2ecf20Sopenharmony_ci 19158c2ecf20Sopenharmony_cistatic loff_t max_inode_blocks(struct inode *inode) 19168c2ecf20Sopenharmony_ci{ 19178c2ecf20Sopenharmony_ci loff_t result = ADDRS_PER_INODE(inode); 19188c2ecf20Sopenharmony_ci loff_t leaf_count = ADDRS_PER_BLOCK(inode); 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_ci /* two direct node blocks */ 19218c2ecf20Sopenharmony_ci result += (leaf_count * 2); 19228c2ecf20Sopenharmony_ci 19238c2ecf20Sopenharmony_ci /* two indirect node blocks */ 19248c2ecf20Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 19258c2ecf20Sopenharmony_ci result += (leaf_count * 2); 19268c2ecf20Sopenharmony_ci 19278c2ecf20Sopenharmony_ci /* one double indirect node block */ 19288c2ecf20Sopenharmony_ci leaf_count *= NIDS_PER_BLOCK; 19298c2ecf20Sopenharmony_ci result += leaf_count; 19308c2ecf20Sopenharmony_ci 19318c2ecf20Sopenharmony_ci return result; 19328c2ecf20Sopenharmony_ci} 19338c2ecf20Sopenharmony_ci 19348c2ecf20Sopenharmony_ciint f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 19358c2ecf20Sopenharmony_ci u64 start, u64 len) 19368c2ecf20Sopenharmony_ci{ 19378c2ecf20Sopenharmony_ci struct buffer_head map_bh; 19388c2ecf20Sopenharmony_ci sector_t start_blk, last_blk; 19398c2ecf20Sopenharmony_ci pgoff_t next_pgofs; 19408c2ecf20Sopenharmony_ci u64 logical = 0, phys = 0, size = 0; 19418c2ecf20Sopenharmony_ci u32 flags = 0; 19428c2ecf20Sopenharmony_ci int ret = 0; 19438c2ecf20Sopenharmony_ci bool compr_cluster = false; 19448c2ecf20Sopenharmony_ci unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; 19458c2ecf20Sopenharmony_ci 19468c2ecf20Sopenharmony_ci if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { 19478c2ecf20Sopenharmony_ci ret = f2fs_precache_extents(inode); 19488c2ecf20Sopenharmony_ci if (ret) 19498c2ecf20Sopenharmony_ci return ret; 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci 19528c2ecf20Sopenharmony_ci ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_XATTR); 19538c2ecf20Sopenharmony_ci if (ret) 19548c2ecf20Sopenharmony_ci return ret; 19558c2ecf20Sopenharmony_ci 19568c2ecf20Sopenharmony_ci inode_lock(inode); 19578c2ecf20Sopenharmony_ci 19588c2ecf20Sopenharmony_ci if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) { 19598c2ecf20Sopenharmony_ci ret = f2fs_xattr_fiemap(inode, fieinfo); 19608c2ecf20Sopenharmony_ci goto out; 19618c2ecf20Sopenharmony_ci } 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) { 19648c2ecf20Sopenharmony_ci ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); 19658c2ecf20Sopenharmony_ci if (ret != -EAGAIN) 19668c2ecf20Sopenharmony_ci goto out; 19678c2ecf20Sopenharmony_ci } 19688c2ecf20Sopenharmony_ci 19698c2ecf20Sopenharmony_ci if (logical_to_blk(inode, len) == 0) 19708c2ecf20Sopenharmony_ci len = blk_to_logical(inode, 1); 19718c2ecf20Sopenharmony_ci 19728c2ecf20Sopenharmony_ci start_blk = logical_to_blk(inode, start); 19738c2ecf20Sopenharmony_ci last_blk = logical_to_blk(inode, start + len - 1); 19748c2ecf20Sopenharmony_ci 19758c2ecf20Sopenharmony_cinext: 19768c2ecf20Sopenharmony_ci memset(&map_bh, 0, sizeof(struct buffer_head)); 19778c2ecf20Sopenharmony_ci map_bh.b_size = len; 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_ci if (compr_cluster) 19808c2ecf20Sopenharmony_ci map_bh.b_size = blk_to_logical(inode, cluster_size - 1); 19818c2ecf20Sopenharmony_ci 19828c2ecf20Sopenharmony_ci ret = get_data_block(inode, start_blk, &map_bh, 0, 19838c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_FIEMAP, &next_pgofs); 19848c2ecf20Sopenharmony_ci if (ret) 19858c2ecf20Sopenharmony_ci goto out; 19868c2ecf20Sopenharmony_ci 19878c2ecf20Sopenharmony_ci /* HOLE */ 19888c2ecf20Sopenharmony_ci if (!buffer_mapped(&map_bh)) { 19898c2ecf20Sopenharmony_ci start_blk = next_pgofs; 19908c2ecf20Sopenharmony_ci 19918c2ecf20Sopenharmony_ci if (blk_to_logical(inode, start_blk) < blk_to_logical(inode, 19928c2ecf20Sopenharmony_ci max_inode_blocks(inode))) 19938c2ecf20Sopenharmony_ci goto prep_next; 19948c2ecf20Sopenharmony_ci 19958c2ecf20Sopenharmony_ci flags |= FIEMAP_EXTENT_LAST; 19968c2ecf20Sopenharmony_ci } 19978c2ecf20Sopenharmony_ci 19988c2ecf20Sopenharmony_ci if (size) { 19998c2ecf20Sopenharmony_ci if (IS_ENCRYPTED(inode)) 20008c2ecf20Sopenharmony_ci flags |= FIEMAP_EXTENT_DATA_ENCRYPTED; 20018c2ecf20Sopenharmony_ci 20028c2ecf20Sopenharmony_ci ret = fiemap_fill_next_extent(fieinfo, logical, 20038c2ecf20Sopenharmony_ci phys, size, flags); 20048c2ecf20Sopenharmony_ci trace_f2fs_fiemap(inode, logical, phys, size, flags, ret); 20058c2ecf20Sopenharmony_ci if (ret) 20068c2ecf20Sopenharmony_ci goto out; 20078c2ecf20Sopenharmony_ci size = 0; 20088c2ecf20Sopenharmony_ci } 20098c2ecf20Sopenharmony_ci 20108c2ecf20Sopenharmony_ci if (start_blk > last_blk) 20118c2ecf20Sopenharmony_ci goto out; 20128c2ecf20Sopenharmony_ci 20138c2ecf20Sopenharmony_ci if (compr_cluster) { 20148c2ecf20Sopenharmony_ci compr_cluster = false; 20158c2ecf20Sopenharmony_ci 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci logical = blk_to_logical(inode, start_blk - 1); 20188c2ecf20Sopenharmony_ci phys = blk_to_logical(inode, map_bh.b_blocknr); 20198c2ecf20Sopenharmony_ci size = blk_to_logical(inode, cluster_size); 20208c2ecf20Sopenharmony_ci 20218c2ecf20Sopenharmony_ci flags |= FIEMAP_EXTENT_ENCODED; 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci start_blk += cluster_size - 1; 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci if (start_blk > last_blk) 20268c2ecf20Sopenharmony_ci goto out; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci goto prep_next; 20298c2ecf20Sopenharmony_ci } 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci if (map_bh.b_blocknr == COMPRESS_ADDR) { 20328c2ecf20Sopenharmony_ci compr_cluster = true; 20338c2ecf20Sopenharmony_ci start_blk++; 20348c2ecf20Sopenharmony_ci goto prep_next; 20358c2ecf20Sopenharmony_ci } 20368c2ecf20Sopenharmony_ci 20378c2ecf20Sopenharmony_ci logical = blk_to_logical(inode, start_blk); 20388c2ecf20Sopenharmony_ci phys = blk_to_logical(inode, map_bh.b_blocknr); 20398c2ecf20Sopenharmony_ci size = map_bh.b_size; 20408c2ecf20Sopenharmony_ci flags = 0; 20418c2ecf20Sopenharmony_ci if (buffer_unwritten(&map_bh)) 20428c2ecf20Sopenharmony_ci flags = FIEMAP_EXTENT_UNWRITTEN; 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ci start_blk += logical_to_blk(inode, size); 20458c2ecf20Sopenharmony_ci 20468c2ecf20Sopenharmony_ciprep_next: 20478c2ecf20Sopenharmony_ci cond_resched(); 20488c2ecf20Sopenharmony_ci if (fatal_signal_pending(current)) 20498c2ecf20Sopenharmony_ci ret = -EINTR; 20508c2ecf20Sopenharmony_ci else 20518c2ecf20Sopenharmony_ci goto next; 20528c2ecf20Sopenharmony_ciout: 20538c2ecf20Sopenharmony_ci if (ret == 1) 20548c2ecf20Sopenharmony_ci ret = 0; 20558c2ecf20Sopenharmony_ci 20568c2ecf20Sopenharmony_ci inode_unlock(inode); 20578c2ecf20Sopenharmony_ci return ret; 20588c2ecf20Sopenharmony_ci} 20598c2ecf20Sopenharmony_ci 20608c2ecf20Sopenharmony_cistatic inline loff_t f2fs_readpage_limit(struct inode *inode) 20618c2ecf20Sopenharmony_ci{ 20628c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_FS_VERITY) && 20638c2ecf20Sopenharmony_ci (IS_VERITY(inode) || f2fs_verity_in_progress(inode))) 20648c2ecf20Sopenharmony_ci return inode->i_sb->s_maxbytes; 20658c2ecf20Sopenharmony_ci 20668c2ecf20Sopenharmony_ci return i_size_read(inode); 20678c2ecf20Sopenharmony_ci} 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_cistatic int f2fs_read_single_page(struct inode *inode, struct page *page, 20708c2ecf20Sopenharmony_ci unsigned nr_pages, 20718c2ecf20Sopenharmony_ci struct f2fs_map_blocks *map, 20728c2ecf20Sopenharmony_ci struct bio **bio_ret, 20738c2ecf20Sopenharmony_ci sector_t *last_block_in_bio, 20748c2ecf20Sopenharmony_ci bool is_readahead) 20758c2ecf20Sopenharmony_ci{ 20768c2ecf20Sopenharmony_ci struct bio *bio = *bio_ret; 20778c2ecf20Sopenharmony_ci const unsigned blkbits = inode->i_blkbits; 20788c2ecf20Sopenharmony_ci const unsigned blocksize = 1 << blkbits; 20798c2ecf20Sopenharmony_ci sector_t block_in_file; 20808c2ecf20Sopenharmony_ci sector_t last_block; 20818c2ecf20Sopenharmony_ci sector_t last_block_in_file; 20828c2ecf20Sopenharmony_ci sector_t block_nr; 20838c2ecf20Sopenharmony_ci int ret = 0; 20848c2ecf20Sopenharmony_ci 20858c2ecf20Sopenharmony_ci block_in_file = (sector_t)page_index(page); 20868c2ecf20Sopenharmony_ci last_block = block_in_file + nr_pages; 20878c2ecf20Sopenharmony_ci last_block_in_file = (f2fs_readpage_limit(inode) + blocksize - 1) >> 20888c2ecf20Sopenharmony_ci blkbits; 20898c2ecf20Sopenharmony_ci if (last_block > last_block_in_file) 20908c2ecf20Sopenharmony_ci last_block = last_block_in_file; 20918c2ecf20Sopenharmony_ci 20928c2ecf20Sopenharmony_ci /* just zeroing out page which is beyond EOF */ 20938c2ecf20Sopenharmony_ci if (block_in_file >= last_block) 20948c2ecf20Sopenharmony_ci goto zero_out; 20958c2ecf20Sopenharmony_ci /* 20968c2ecf20Sopenharmony_ci * Map blocks using the previous result first. 20978c2ecf20Sopenharmony_ci */ 20988c2ecf20Sopenharmony_ci if ((map->m_flags & F2FS_MAP_MAPPED) && 20998c2ecf20Sopenharmony_ci block_in_file > map->m_lblk && 21008c2ecf20Sopenharmony_ci block_in_file < (map->m_lblk + map->m_len)) 21018c2ecf20Sopenharmony_ci goto got_it; 21028c2ecf20Sopenharmony_ci 21038c2ecf20Sopenharmony_ci /* 21048c2ecf20Sopenharmony_ci * Then do more f2fs_map_blocks() calls until we are 21058c2ecf20Sopenharmony_ci * done with this page. 21068c2ecf20Sopenharmony_ci */ 21078c2ecf20Sopenharmony_ci map->m_lblk = block_in_file; 21088c2ecf20Sopenharmony_ci map->m_len = last_block - block_in_file; 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci ret = f2fs_map_blocks(inode, map, 0, F2FS_GET_BLOCK_DEFAULT); 21118c2ecf20Sopenharmony_ci if (ret) 21128c2ecf20Sopenharmony_ci goto out; 21138c2ecf20Sopenharmony_cigot_it: 21148c2ecf20Sopenharmony_ci if ((map->m_flags & F2FS_MAP_MAPPED)) { 21158c2ecf20Sopenharmony_ci block_nr = map->m_pblk + block_in_file - map->m_lblk; 21168c2ecf20Sopenharmony_ci SetPageMappedToDisk(page); 21178c2ecf20Sopenharmony_ci 21188c2ecf20Sopenharmony_ci if (!PageUptodate(page) && (!PageSwapCache(page) && 21198c2ecf20Sopenharmony_ci !cleancache_get_page(page))) { 21208c2ecf20Sopenharmony_ci SetPageUptodate(page); 21218c2ecf20Sopenharmony_ci goto confused; 21228c2ecf20Sopenharmony_ci } 21238c2ecf20Sopenharmony_ci 21248c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(F2FS_I_SB(inode), block_nr, 21258c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 21268c2ecf20Sopenharmony_ci ret = -EFSCORRUPTED; 21278c2ecf20Sopenharmony_ci goto out; 21288c2ecf20Sopenharmony_ci } 21298c2ecf20Sopenharmony_ci } else { 21308c2ecf20Sopenharmony_cizero_out: 21318c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 21328c2ecf20Sopenharmony_ci if (f2fs_need_verity(inode, page->index) && 21338c2ecf20Sopenharmony_ci !fsverity_verify_page(page)) { 21348c2ecf20Sopenharmony_ci ret = -EIO; 21358c2ecf20Sopenharmony_ci goto out; 21368c2ecf20Sopenharmony_ci } 21378c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 21388c2ecf20Sopenharmony_ci SetPageUptodate(page); 21398c2ecf20Sopenharmony_ci unlock_page(page); 21408c2ecf20Sopenharmony_ci goto out; 21418c2ecf20Sopenharmony_ci } 21428c2ecf20Sopenharmony_ci 21438c2ecf20Sopenharmony_ci /* 21448c2ecf20Sopenharmony_ci * This page will go to BIO. Do we need to send this 21458c2ecf20Sopenharmony_ci * BIO off first? 21468c2ecf20Sopenharmony_ci */ 21478c2ecf20Sopenharmony_ci if (bio && (!page_is_mergeable(F2FS_I_SB(inode), bio, 21488c2ecf20Sopenharmony_ci *last_block_in_bio, block_nr) || 21498c2ecf20Sopenharmony_ci !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { 21508c2ecf20Sopenharmony_cisubmit_and_realloc: 21518c2ecf20Sopenharmony_ci __submit_bio(F2FS_I_SB(inode), bio, DATA); 21528c2ecf20Sopenharmony_ci bio = NULL; 21538c2ecf20Sopenharmony_ci } 21548c2ecf20Sopenharmony_ci if (bio == NULL) { 21558c2ecf20Sopenharmony_ci bio = f2fs_grab_read_bio(inode, block_nr, nr_pages, 21568c2ecf20Sopenharmony_ci is_readahead ? REQ_RAHEAD : 0, page->index, 21578c2ecf20Sopenharmony_ci false, true); 21588c2ecf20Sopenharmony_ci if (IS_ERR(bio)) { 21598c2ecf20Sopenharmony_ci ret = PTR_ERR(bio); 21608c2ecf20Sopenharmony_ci bio = NULL; 21618c2ecf20Sopenharmony_ci goto out; 21628c2ecf20Sopenharmony_ci } 21638c2ecf20Sopenharmony_ci } 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci /* 21668c2ecf20Sopenharmony_ci * If the page is under writeback, we need to wait for 21678c2ecf20Sopenharmony_ci * its completion to see the correct decrypted data. 21688c2ecf20Sopenharmony_ci */ 21698c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback(inode, block_nr); 21708c2ecf20Sopenharmony_ci 21718c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, blocksize, 0) < blocksize) 21728c2ecf20Sopenharmony_ci goto submit_and_realloc; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci inc_page_count(F2FS_I_SB(inode), F2FS_RD_DATA); 21758c2ecf20Sopenharmony_ci f2fs_update_iostat(F2FS_I_SB(inode), FS_DATA_READ_IO, F2FS_BLKSIZE); 21768c2ecf20Sopenharmony_ci ClearPageError(page); 21778c2ecf20Sopenharmony_ci *last_block_in_bio = block_nr; 21788c2ecf20Sopenharmony_ci goto out; 21798c2ecf20Sopenharmony_ciconfused: 21808c2ecf20Sopenharmony_ci if (bio) { 21818c2ecf20Sopenharmony_ci __submit_bio(F2FS_I_SB(inode), bio, DATA); 21828c2ecf20Sopenharmony_ci bio = NULL; 21838c2ecf20Sopenharmony_ci } 21848c2ecf20Sopenharmony_ci unlock_page(page); 21858c2ecf20Sopenharmony_ciout: 21868c2ecf20Sopenharmony_ci *bio_ret = bio; 21878c2ecf20Sopenharmony_ci return ret; 21888c2ecf20Sopenharmony_ci} 21898c2ecf20Sopenharmony_ci 21908c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 21918c2ecf20Sopenharmony_ciint f2fs_read_multi_pages(struct compress_ctx *cc, struct bio **bio_ret, 21928c2ecf20Sopenharmony_ci unsigned nr_pages, sector_t *last_block_in_bio, 21938c2ecf20Sopenharmony_ci bool is_readahead, bool for_write) 21948c2ecf20Sopenharmony_ci{ 21958c2ecf20Sopenharmony_ci struct dnode_of_data dn; 21968c2ecf20Sopenharmony_ci struct inode *inode = cc->inode; 21978c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 21988c2ecf20Sopenharmony_ci struct bio *bio = *bio_ret; 21998c2ecf20Sopenharmony_ci unsigned int start_idx = cc->cluster_idx << cc->log_cluster_size; 22008c2ecf20Sopenharmony_ci sector_t last_block_in_file; 22018c2ecf20Sopenharmony_ci const unsigned blkbits = inode->i_blkbits; 22028c2ecf20Sopenharmony_ci const unsigned blocksize = 1 << blkbits; 22038c2ecf20Sopenharmony_ci struct decompress_io_ctx *dic = NULL; 22048c2ecf20Sopenharmony_ci struct bio_post_read_ctx *ctx; 22058c2ecf20Sopenharmony_ci bool for_verity = false; 22068c2ecf20Sopenharmony_ci int i; 22078c2ecf20Sopenharmony_ci int ret = 0; 22088c2ecf20Sopenharmony_ci 22098c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, f2fs_cluster_is_empty(cc)); 22108c2ecf20Sopenharmony_ci 22118c2ecf20Sopenharmony_ci last_block_in_file = (f2fs_readpage_limit(inode) + 22128c2ecf20Sopenharmony_ci blocksize - 1) >> blkbits; 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci /* get rid of pages beyond EOF */ 22158c2ecf20Sopenharmony_ci for (i = 0; i < cc->cluster_size; i++) { 22168c2ecf20Sopenharmony_ci struct page *page = cc->rpages[i]; 22178c2ecf20Sopenharmony_ci 22188c2ecf20Sopenharmony_ci if (!page) 22198c2ecf20Sopenharmony_ci continue; 22208c2ecf20Sopenharmony_ci if ((sector_t)page->index >= last_block_in_file) { 22218c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 22228c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 22238c2ecf20Sopenharmony_ci SetPageUptodate(page); 22248c2ecf20Sopenharmony_ci } else if (!PageUptodate(page)) { 22258c2ecf20Sopenharmony_ci continue; 22268c2ecf20Sopenharmony_ci } 22278c2ecf20Sopenharmony_ci unlock_page(page); 22288c2ecf20Sopenharmony_ci if (for_write) 22298c2ecf20Sopenharmony_ci put_page(page); 22308c2ecf20Sopenharmony_ci cc->rpages[i] = NULL; 22318c2ecf20Sopenharmony_ci cc->nr_rpages--; 22328c2ecf20Sopenharmony_ci } 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci /* we are done since all pages are beyond EOF */ 22358c2ecf20Sopenharmony_ci if (f2fs_cluster_is_empty(cc)) 22368c2ecf20Sopenharmony_ci goto out; 22378c2ecf20Sopenharmony_ci 22388c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 22398c2ecf20Sopenharmony_ci ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); 22408c2ecf20Sopenharmony_ci if (ret) 22418c2ecf20Sopenharmony_ci goto out; 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci f2fs_bug_on(sbi, dn.data_blkaddr != COMPRESS_ADDR); 22448c2ecf20Sopenharmony_ci 22458c2ecf20Sopenharmony_ci for (i = 1; i < cc->cluster_size; i++) { 22468c2ecf20Sopenharmony_ci block_t blkaddr; 22478c2ecf20Sopenharmony_ci 22488c2ecf20Sopenharmony_ci blkaddr = data_blkaddr(dn.inode, dn.node_page, 22498c2ecf20Sopenharmony_ci dn.ofs_in_node + i); 22508c2ecf20Sopenharmony_ci 22518c2ecf20Sopenharmony_ci if (!__is_valid_data_blkaddr(blkaddr)) 22528c2ecf20Sopenharmony_ci break; 22538c2ecf20Sopenharmony_ci 22548c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, DATA_GENERIC)) { 22558c2ecf20Sopenharmony_ci ret = -EFAULT; 22568c2ecf20Sopenharmony_ci goto out_put_dnode; 22578c2ecf20Sopenharmony_ci } 22588c2ecf20Sopenharmony_ci cc->nr_cpages++; 22598c2ecf20Sopenharmony_ci } 22608c2ecf20Sopenharmony_ci 22618c2ecf20Sopenharmony_ci /* nothing to decompress */ 22628c2ecf20Sopenharmony_ci if (cc->nr_cpages == 0) { 22638c2ecf20Sopenharmony_ci ret = 0; 22648c2ecf20Sopenharmony_ci goto out_put_dnode; 22658c2ecf20Sopenharmony_ci } 22668c2ecf20Sopenharmony_ci 22678c2ecf20Sopenharmony_ci dic = f2fs_alloc_dic(cc); 22688c2ecf20Sopenharmony_ci if (IS_ERR(dic)) { 22698c2ecf20Sopenharmony_ci ret = PTR_ERR(dic); 22708c2ecf20Sopenharmony_ci goto out_put_dnode; 22718c2ecf20Sopenharmony_ci } 22728c2ecf20Sopenharmony_ci 22738c2ecf20Sopenharmony_ci /* 22748c2ecf20Sopenharmony_ci * It's possible to enable fsverity on the fly when handling a cluster, 22758c2ecf20Sopenharmony_ci * which requires complicated error handling. Instead of adding more 22768c2ecf20Sopenharmony_ci * complexity, let's give a rule where end_io post-processes fsverity 22778c2ecf20Sopenharmony_ci * per cluster. In order to do that, we need to submit bio, if previous 22788c2ecf20Sopenharmony_ci * bio sets a different post-process policy. 22798c2ecf20Sopenharmony_ci */ 22808c2ecf20Sopenharmony_ci if (fsverity_active(cc->inode)) { 22818c2ecf20Sopenharmony_ci atomic_set(&dic->verity_pages, cc->nr_cpages); 22828c2ecf20Sopenharmony_ci for_verity = true; 22838c2ecf20Sopenharmony_ci 22848c2ecf20Sopenharmony_ci if (bio) { 22858c2ecf20Sopenharmony_ci ctx = bio->bi_private; 22868c2ecf20Sopenharmony_ci if (!(ctx->enabled_steps & (1 << STEP_VERITY))) { 22878c2ecf20Sopenharmony_ci __submit_bio(sbi, bio, DATA); 22888c2ecf20Sopenharmony_ci bio = NULL; 22898c2ecf20Sopenharmony_ci } 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci } 22928c2ecf20Sopenharmony_ci 22938c2ecf20Sopenharmony_ci for (i = 0; i < dic->nr_cpages; i++) { 22948c2ecf20Sopenharmony_ci struct page *page = dic->cpages[i]; 22958c2ecf20Sopenharmony_ci block_t blkaddr; 22968c2ecf20Sopenharmony_ci 22978c2ecf20Sopenharmony_ci blkaddr = data_blkaddr(dn.inode, dn.node_page, 22988c2ecf20Sopenharmony_ci dn.ofs_in_node + i + 1); 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ci if (bio && (!page_is_mergeable(sbi, bio, 23018c2ecf20Sopenharmony_ci *last_block_in_bio, blkaddr) || 23028c2ecf20Sopenharmony_ci !f2fs_crypt_mergeable_bio(bio, inode, page->index, NULL))) { 23038c2ecf20Sopenharmony_cisubmit_and_realloc: 23048c2ecf20Sopenharmony_ci __submit_bio(sbi, bio, DATA); 23058c2ecf20Sopenharmony_ci bio = NULL; 23068c2ecf20Sopenharmony_ci } 23078c2ecf20Sopenharmony_ci 23088c2ecf20Sopenharmony_ci if (!bio) { 23098c2ecf20Sopenharmony_ci bio = f2fs_grab_read_bio(inode, blkaddr, nr_pages, 23108c2ecf20Sopenharmony_ci is_readahead ? REQ_RAHEAD : 0, 23118c2ecf20Sopenharmony_ci page->index, for_write, for_verity); 23128c2ecf20Sopenharmony_ci if (IS_ERR(bio)) { 23138c2ecf20Sopenharmony_ci unsigned int remained = dic->nr_cpages - i; 23148c2ecf20Sopenharmony_ci bool release = false; 23158c2ecf20Sopenharmony_ci 23168c2ecf20Sopenharmony_ci ret = PTR_ERR(bio); 23178c2ecf20Sopenharmony_ci dic->failed = true; 23188c2ecf20Sopenharmony_ci 23198c2ecf20Sopenharmony_ci if (for_verity) { 23208c2ecf20Sopenharmony_ci if (!atomic_sub_return(remained, 23218c2ecf20Sopenharmony_ci &dic->verity_pages)) 23228c2ecf20Sopenharmony_ci release = true; 23238c2ecf20Sopenharmony_ci } else { 23248c2ecf20Sopenharmony_ci if (!atomic_sub_return(remained, 23258c2ecf20Sopenharmony_ci &dic->pending_pages)) 23268c2ecf20Sopenharmony_ci release = true; 23278c2ecf20Sopenharmony_ci } 23288c2ecf20Sopenharmony_ci 23298c2ecf20Sopenharmony_ci if (release) { 23308c2ecf20Sopenharmony_ci f2fs_decompress_end_io(dic->rpages, 23318c2ecf20Sopenharmony_ci cc->cluster_size, true, 23328c2ecf20Sopenharmony_ci false); 23338c2ecf20Sopenharmony_ci f2fs_free_dic(dic); 23348c2ecf20Sopenharmony_ci } 23358c2ecf20Sopenharmony_ci 23368c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 23378c2ecf20Sopenharmony_ci *bio_ret = NULL; 23388c2ecf20Sopenharmony_ci return ret; 23398c2ecf20Sopenharmony_ci } 23408c2ecf20Sopenharmony_ci } 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback(inode, blkaddr); 23438c2ecf20Sopenharmony_ci 23448c2ecf20Sopenharmony_ci if (bio_add_page(bio, page, blocksize, 0) < blocksize) 23458c2ecf20Sopenharmony_ci goto submit_and_realloc; 23468c2ecf20Sopenharmony_ci 23478c2ecf20Sopenharmony_ci /* tag STEP_DECOMPRESS to handle IO in wq */ 23488c2ecf20Sopenharmony_ci ctx = bio->bi_private; 23498c2ecf20Sopenharmony_ci if (!(ctx->enabled_steps & (1 << STEP_DECOMPRESS))) 23508c2ecf20Sopenharmony_ci ctx->enabled_steps |= 1 << STEP_DECOMPRESS; 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci inc_page_count(sbi, F2FS_RD_DATA); 23538c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_DATA_READ_IO, F2FS_BLKSIZE); 23548c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, FS_CDATA_READ_IO, F2FS_BLKSIZE); 23558c2ecf20Sopenharmony_ci ClearPageError(page); 23568c2ecf20Sopenharmony_ci *last_block_in_bio = blkaddr; 23578c2ecf20Sopenharmony_ci } 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 23608c2ecf20Sopenharmony_ci 23618c2ecf20Sopenharmony_ci *bio_ret = bio; 23628c2ecf20Sopenharmony_ci return 0; 23638c2ecf20Sopenharmony_ci 23648c2ecf20Sopenharmony_ciout_put_dnode: 23658c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 23668c2ecf20Sopenharmony_ciout: 23678c2ecf20Sopenharmony_ci f2fs_decompress_end_io(cc->rpages, cc->cluster_size, true, false); 23688c2ecf20Sopenharmony_ci *bio_ret = bio; 23698c2ecf20Sopenharmony_ci return ret; 23708c2ecf20Sopenharmony_ci} 23718c2ecf20Sopenharmony_ci#endif 23728c2ecf20Sopenharmony_ci 23738c2ecf20Sopenharmony_ci/* 23748c2ecf20Sopenharmony_ci * This function was originally taken from fs/mpage.c, and customized for f2fs. 23758c2ecf20Sopenharmony_ci * Major change was from block_size == page_size in f2fs by default. 23768c2ecf20Sopenharmony_ci * 23778c2ecf20Sopenharmony_ci * Note that the aops->readpages() function is ONLY used for read-ahead. If 23788c2ecf20Sopenharmony_ci * this function ever deviates from doing just read-ahead, it should either 23798c2ecf20Sopenharmony_ci * use ->readpage() or do the necessary surgery to decouple ->readpages() 23808c2ecf20Sopenharmony_ci * from read-ahead. 23818c2ecf20Sopenharmony_ci */ 23828c2ecf20Sopenharmony_cistatic int f2fs_mpage_readpages(struct inode *inode, 23838c2ecf20Sopenharmony_ci struct readahead_control *rac, struct page *page) 23848c2ecf20Sopenharmony_ci{ 23858c2ecf20Sopenharmony_ci struct bio *bio = NULL; 23868c2ecf20Sopenharmony_ci sector_t last_block_in_bio = 0; 23878c2ecf20Sopenharmony_ci struct f2fs_map_blocks map; 23888c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 23898c2ecf20Sopenharmony_ci struct compress_ctx cc = { 23908c2ecf20Sopenharmony_ci .inode = inode, 23918c2ecf20Sopenharmony_ci .log_cluster_size = F2FS_I(inode)->i_log_cluster_size, 23928c2ecf20Sopenharmony_ci .cluster_size = F2FS_I(inode)->i_cluster_size, 23938c2ecf20Sopenharmony_ci .cluster_idx = NULL_CLUSTER, 23948c2ecf20Sopenharmony_ci .rpages = NULL, 23958c2ecf20Sopenharmony_ci .cpages = NULL, 23968c2ecf20Sopenharmony_ci .nr_rpages = 0, 23978c2ecf20Sopenharmony_ci .nr_cpages = 0, 23988c2ecf20Sopenharmony_ci }; 23998c2ecf20Sopenharmony_ci#endif 24008c2ecf20Sopenharmony_ci unsigned nr_pages = rac ? readahead_count(rac) : 1; 24018c2ecf20Sopenharmony_ci unsigned max_nr_pages = nr_pages; 24028c2ecf20Sopenharmony_ci int ret = 0; 24038c2ecf20Sopenharmony_ci bool drop_ra = false; 24048c2ecf20Sopenharmony_ci 24058c2ecf20Sopenharmony_ci map.m_pblk = 0; 24068c2ecf20Sopenharmony_ci map.m_lblk = 0; 24078c2ecf20Sopenharmony_ci map.m_len = 0; 24088c2ecf20Sopenharmony_ci map.m_flags = 0; 24098c2ecf20Sopenharmony_ci map.m_next_pgofs = NULL; 24108c2ecf20Sopenharmony_ci map.m_next_extent = NULL; 24118c2ecf20Sopenharmony_ci map.m_seg_type = NO_CHECK_TYPE; 24128c2ecf20Sopenharmony_ci map.m_may_create = false; 24138c2ecf20Sopenharmony_ci 24148c2ecf20Sopenharmony_ci /* 24158c2ecf20Sopenharmony_ci * Two readahead threads for same address range can cause race condition 24168c2ecf20Sopenharmony_ci * which fragments sequential read IOs. So let's avoid each other. 24178c2ecf20Sopenharmony_ci */ 24188c2ecf20Sopenharmony_ci if (rac && readahead_count(rac)) { 24198c2ecf20Sopenharmony_ci if (READ_ONCE(F2FS_I(inode)->ra_offset) == readahead_index(rac)) 24208c2ecf20Sopenharmony_ci drop_ra = true; 24218c2ecf20Sopenharmony_ci else 24228c2ecf20Sopenharmony_ci WRITE_ONCE(F2FS_I(inode)->ra_offset, 24238c2ecf20Sopenharmony_ci readahead_index(rac)); 24248c2ecf20Sopenharmony_ci } 24258c2ecf20Sopenharmony_ci 24268c2ecf20Sopenharmony_ci for (; nr_pages; nr_pages--) { 24278c2ecf20Sopenharmony_ci if (rac) { 24288c2ecf20Sopenharmony_ci page = readahead_page(rac); 24298c2ecf20Sopenharmony_ci prefetchw(&page->flags); 24308c2ecf20Sopenharmony_ci if (drop_ra) { 24318c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 24328c2ecf20Sopenharmony_ci continue; 24338c2ecf20Sopenharmony_ci } 24348c2ecf20Sopenharmony_ci } 24358c2ecf20Sopenharmony_ci 24368c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 24378c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 24388c2ecf20Sopenharmony_ci /* there are remained comressed pages, submit them */ 24398c2ecf20Sopenharmony_ci if (!f2fs_cluster_can_merge_page(&cc, page->index)) { 24408c2ecf20Sopenharmony_ci ret = f2fs_read_multi_pages(&cc, &bio, 24418c2ecf20Sopenharmony_ci max_nr_pages, 24428c2ecf20Sopenharmony_ci &last_block_in_bio, 24438c2ecf20Sopenharmony_ci rac != NULL, false); 24448c2ecf20Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 24458c2ecf20Sopenharmony_ci if (ret) 24468c2ecf20Sopenharmony_ci goto set_error_page; 24478c2ecf20Sopenharmony_ci } 24488c2ecf20Sopenharmony_ci ret = f2fs_is_compressed_cluster(inode, page->index); 24498c2ecf20Sopenharmony_ci if (ret < 0) 24508c2ecf20Sopenharmony_ci goto set_error_page; 24518c2ecf20Sopenharmony_ci else if (!ret) 24528c2ecf20Sopenharmony_ci goto read_single_page; 24538c2ecf20Sopenharmony_ci 24548c2ecf20Sopenharmony_ci ret = f2fs_init_compress_ctx(&cc); 24558c2ecf20Sopenharmony_ci if (ret) 24568c2ecf20Sopenharmony_ci goto set_error_page; 24578c2ecf20Sopenharmony_ci 24588c2ecf20Sopenharmony_ci f2fs_compress_ctx_add_page(&cc, page); 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci goto next_page; 24618c2ecf20Sopenharmony_ci } 24628c2ecf20Sopenharmony_ciread_single_page: 24638c2ecf20Sopenharmony_ci#endif 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci ret = f2fs_read_single_page(inode, page, max_nr_pages, &map, 24668c2ecf20Sopenharmony_ci &bio, &last_block_in_bio, rac); 24678c2ecf20Sopenharmony_ci if (ret) { 24688c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 24698c2ecf20Sopenharmony_ciset_error_page: 24708c2ecf20Sopenharmony_ci#endif 24718c2ecf20Sopenharmony_ci SetPageError(page); 24728c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 24738c2ecf20Sopenharmony_ci unlock_page(page); 24748c2ecf20Sopenharmony_ci } 24758c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 24768c2ecf20Sopenharmony_cinext_page: 24778c2ecf20Sopenharmony_ci#endif 24788c2ecf20Sopenharmony_ci if (rac) 24798c2ecf20Sopenharmony_ci put_page(page); 24808c2ecf20Sopenharmony_ci 24818c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 24828c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 24838c2ecf20Sopenharmony_ci /* last page */ 24848c2ecf20Sopenharmony_ci if (nr_pages == 1 && !f2fs_cluster_is_empty(&cc)) { 24858c2ecf20Sopenharmony_ci ret = f2fs_read_multi_pages(&cc, &bio, 24868c2ecf20Sopenharmony_ci max_nr_pages, 24878c2ecf20Sopenharmony_ci &last_block_in_bio, 24888c2ecf20Sopenharmony_ci rac != NULL, false); 24898c2ecf20Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 24908c2ecf20Sopenharmony_ci } 24918c2ecf20Sopenharmony_ci } 24928c2ecf20Sopenharmony_ci#endif 24938c2ecf20Sopenharmony_ci } 24948c2ecf20Sopenharmony_ci if (bio) 24958c2ecf20Sopenharmony_ci __submit_bio(F2FS_I_SB(inode), bio, DATA); 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci if (rac && readahead_count(rac) && !drop_ra) 24988c2ecf20Sopenharmony_ci WRITE_ONCE(F2FS_I(inode)->ra_offset, -1); 24998c2ecf20Sopenharmony_ci return ret; 25008c2ecf20Sopenharmony_ci} 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_cistatic int f2fs_read_data_page(struct file *file, struct page *page) 25038c2ecf20Sopenharmony_ci{ 25048c2ecf20Sopenharmony_ci struct inode *inode = page_file_mapping(page)->host; 25058c2ecf20Sopenharmony_ci int ret = -EAGAIN; 25068c2ecf20Sopenharmony_ci 25078c2ecf20Sopenharmony_ci trace_f2fs_readpage(page, DATA); 25088c2ecf20Sopenharmony_ci 25098c2ecf20Sopenharmony_ci if (!f2fs_is_compress_backend_ready(inode)) { 25108c2ecf20Sopenharmony_ci unlock_page(page); 25118c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci 25148c2ecf20Sopenharmony_ci /* If the file has inline data, try to read it directly */ 25158c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) 25168c2ecf20Sopenharmony_ci ret = f2fs_read_inline_data(inode, page); 25178c2ecf20Sopenharmony_ci if (ret == -EAGAIN) 25188c2ecf20Sopenharmony_ci ret = f2fs_mpage_readpages(inode, NULL, page); 25198c2ecf20Sopenharmony_ci return ret; 25208c2ecf20Sopenharmony_ci} 25218c2ecf20Sopenharmony_ci 25228c2ecf20Sopenharmony_cistatic void f2fs_readahead(struct readahead_control *rac) 25238c2ecf20Sopenharmony_ci{ 25248c2ecf20Sopenharmony_ci struct inode *inode = rac->mapping->host; 25258c2ecf20Sopenharmony_ci 25268c2ecf20Sopenharmony_ci trace_f2fs_readpages(inode, readahead_index(rac), readahead_count(rac)); 25278c2ecf20Sopenharmony_ci 25288c2ecf20Sopenharmony_ci if (!f2fs_is_compress_backend_ready(inode)) 25298c2ecf20Sopenharmony_ci return; 25308c2ecf20Sopenharmony_ci 25318c2ecf20Sopenharmony_ci /* If the file has inline data, skip readpages */ 25328c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) 25338c2ecf20Sopenharmony_ci return; 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci f2fs_mpage_readpages(inode, rac, NULL); 25368c2ecf20Sopenharmony_ci} 25378c2ecf20Sopenharmony_ci 25388c2ecf20Sopenharmony_ciint f2fs_encrypt_one_page(struct f2fs_io_info *fio) 25398c2ecf20Sopenharmony_ci{ 25408c2ecf20Sopenharmony_ci struct inode *inode = fio->page->mapping->host; 25418c2ecf20Sopenharmony_ci struct page *mpage, *page; 25428c2ecf20Sopenharmony_ci gfp_t gfp_flags = GFP_NOFS; 25438c2ecf20Sopenharmony_ci 25448c2ecf20Sopenharmony_ci if (!f2fs_encrypted_file(inode)) 25458c2ecf20Sopenharmony_ci return 0; 25468c2ecf20Sopenharmony_ci 25478c2ecf20Sopenharmony_ci page = fio->compressed_page ? fio->compressed_page : fio->page; 25488c2ecf20Sopenharmony_ci 25498c2ecf20Sopenharmony_ci /* wait for GCed page writeback via META_MAPPING */ 25508c2ecf20Sopenharmony_ci f2fs_wait_on_block_writeback(inode, fio->old_blkaddr); 25518c2ecf20Sopenharmony_ci 25528c2ecf20Sopenharmony_ci if (fscrypt_inode_uses_inline_crypto(inode)) 25538c2ecf20Sopenharmony_ci return 0; 25548c2ecf20Sopenharmony_ci 25558c2ecf20Sopenharmony_ciretry_encrypt: 25568c2ecf20Sopenharmony_ci fio->encrypted_page = fscrypt_encrypt_pagecache_blocks(page, 25578c2ecf20Sopenharmony_ci PAGE_SIZE, 0, gfp_flags); 25588c2ecf20Sopenharmony_ci if (IS_ERR(fio->encrypted_page)) { 25598c2ecf20Sopenharmony_ci /* flush pending IOs and wait for a while in the ENOMEM case */ 25608c2ecf20Sopenharmony_ci if (PTR_ERR(fio->encrypted_page) == -ENOMEM) { 25618c2ecf20Sopenharmony_ci f2fs_flush_merged_writes(fio->sbi); 25628c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, DEFAULT_IO_TIMEOUT); 25638c2ecf20Sopenharmony_ci gfp_flags |= __GFP_NOFAIL; 25648c2ecf20Sopenharmony_ci goto retry_encrypt; 25658c2ecf20Sopenharmony_ci } 25668c2ecf20Sopenharmony_ci return PTR_ERR(fio->encrypted_page); 25678c2ecf20Sopenharmony_ci } 25688c2ecf20Sopenharmony_ci 25698c2ecf20Sopenharmony_ci mpage = find_lock_page(META_MAPPING(fio->sbi), fio->old_blkaddr); 25708c2ecf20Sopenharmony_ci if (mpage) { 25718c2ecf20Sopenharmony_ci if (PageUptodate(mpage)) 25728c2ecf20Sopenharmony_ci memcpy(page_address(mpage), 25738c2ecf20Sopenharmony_ci page_address(fio->encrypted_page), PAGE_SIZE); 25748c2ecf20Sopenharmony_ci f2fs_put_page(mpage, 1); 25758c2ecf20Sopenharmony_ci } 25768c2ecf20Sopenharmony_ci return 0; 25778c2ecf20Sopenharmony_ci} 25788c2ecf20Sopenharmony_ci 25798c2ecf20Sopenharmony_cistatic inline bool check_inplace_update_policy(struct inode *inode, 25808c2ecf20Sopenharmony_ci struct f2fs_io_info *fio) 25818c2ecf20Sopenharmony_ci{ 25828c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 25838c2ecf20Sopenharmony_ci unsigned int policy = SM_I(sbi)->ipu_policy; 25848c2ecf20Sopenharmony_ci 25858c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_FORCE)) 25868c2ecf20Sopenharmony_ci return true; 25878c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_SSR) && f2fs_need_SSR(sbi)) 25888c2ecf20Sopenharmony_ci return true; 25898c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_UTIL) && 25908c2ecf20Sopenharmony_ci utilization(sbi) > SM_I(sbi)->min_ipu_util) 25918c2ecf20Sopenharmony_ci return true; 25928c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_SSR_UTIL) && f2fs_need_SSR(sbi) && 25938c2ecf20Sopenharmony_ci utilization(sbi) > SM_I(sbi)->min_ipu_util) 25948c2ecf20Sopenharmony_ci return true; 25958c2ecf20Sopenharmony_ci 25968c2ecf20Sopenharmony_ci /* 25978c2ecf20Sopenharmony_ci * IPU for rewrite async pages 25988c2ecf20Sopenharmony_ci */ 25998c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_ASYNC) && 26008c2ecf20Sopenharmony_ci fio && fio->op == REQ_OP_WRITE && 26018c2ecf20Sopenharmony_ci !(fio->op_flags & REQ_SYNC) && 26028c2ecf20Sopenharmony_ci !IS_ENCRYPTED(inode)) 26038c2ecf20Sopenharmony_ci return true; 26048c2ecf20Sopenharmony_ci 26058c2ecf20Sopenharmony_ci /* this is only set during fdatasync */ 26068c2ecf20Sopenharmony_ci if (policy & (0x1 << F2FS_IPU_FSYNC) && 26078c2ecf20Sopenharmony_ci is_inode_flag_set(inode, FI_NEED_IPU)) 26088c2ecf20Sopenharmony_ci return true; 26098c2ecf20Sopenharmony_ci 26108c2ecf20Sopenharmony_ci if (unlikely(fio && is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 26118c2ecf20Sopenharmony_ci !f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) 26128c2ecf20Sopenharmony_ci return true; 26138c2ecf20Sopenharmony_ci 26148c2ecf20Sopenharmony_ci return false; 26158c2ecf20Sopenharmony_ci} 26168c2ecf20Sopenharmony_ci 26178c2ecf20Sopenharmony_cibool f2fs_should_update_inplace(struct inode *inode, struct f2fs_io_info *fio) 26188c2ecf20Sopenharmony_ci{ 26198c2ecf20Sopenharmony_ci if (f2fs_is_pinned_file(inode)) 26208c2ecf20Sopenharmony_ci return true; 26218c2ecf20Sopenharmony_ci 26228c2ecf20Sopenharmony_ci /* if this is cold file, we should overwrite to avoid fragmentation */ 26238c2ecf20Sopenharmony_ci if (file_is_cold(inode)) 26248c2ecf20Sopenharmony_ci return true; 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ci return check_inplace_update_policy(inode, fio); 26278c2ecf20Sopenharmony_ci} 26288c2ecf20Sopenharmony_ci 26298c2ecf20Sopenharmony_cibool f2fs_should_update_outplace(struct inode *inode, struct f2fs_io_info *fio) 26308c2ecf20Sopenharmony_ci{ 26318c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 26328c2ecf20Sopenharmony_ci 26338c2ecf20Sopenharmony_ci if (f2fs_lfs_mode(sbi)) 26348c2ecf20Sopenharmony_ci return true; 26358c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode)) 26368c2ecf20Sopenharmony_ci return true; 26378c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) 26388c2ecf20Sopenharmony_ci return true; 26398c2ecf20Sopenharmony_ci if (f2fs_is_atomic_file(inode)) 26408c2ecf20Sopenharmony_ci return true; 26418c2ecf20Sopenharmony_ci if (fio) { 26428c2ecf20Sopenharmony_ci if (is_cold_data(fio->page)) 26438c2ecf20Sopenharmony_ci return true; 26448c2ecf20Sopenharmony_ci if (IS_ATOMIC_WRITTEN_PAGE(fio->page)) 26458c2ecf20Sopenharmony_ci return true; 26468c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_CP_DISABLED) && 26478c2ecf20Sopenharmony_ci f2fs_is_checkpointed_data(sbi, fio->old_blkaddr))) 26488c2ecf20Sopenharmony_ci return true; 26498c2ecf20Sopenharmony_ci } 26508c2ecf20Sopenharmony_ci return false; 26518c2ecf20Sopenharmony_ci} 26528c2ecf20Sopenharmony_ci 26538c2ecf20Sopenharmony_cistatic inline bool need_inplace_update(struct f2fs_io_info *fio) 26548c2ecf20Sopenharmony_ci{ 26558c2ecf20Sopenharmony_ci struct inode *inode = fio->page->mapping->host; 26568c2ecf20Sopenharmony_ci 26578c2ecf20Sopenharmony_ci if (f2fs_should_update_outplace(inode, fio)) 26588c2ecf20Sopenharmony_ci return false; 26598c2ecf20Sopenharmony_ci 26608c2ecf20Sopenharmony_ci return f2fs_should_update_inplace(inode, fio); 26618c2ecf20Sopenharmony_ci} 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ciint f2fs_do_write_data_page(struct f2fs_io_info *fio) 26648c2ecf20Sopenharmony_ci{ 26658c2ecf20Sopenharmony_ci struct page *page = fio->page; 26668c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 26678c2ecf20Sopenharmony_ci struct dnode_of_data dn; 26688c2ecf20Sopenharmony_ci struct extent_info ei = {0,0,0}; 26698c2ecf20Sopenharmony_ci struct node_info ni; 26708c2ecf20Sopenharmony_ci bool ipu_force = false; 26718c2ecf20Sopenharmony_ci int err = 0; 26728c2ecf20Sopenharmony_ci 26738c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 26748c2ecf20Sopenharmony_ci if (need_inplace_update(fio) && 26758c2ecf20Sopenharmony_ci f2fs_lookup_extent_cache(inode, page->index, &ei)) { 26768c2ecf20Sopenharmony_ci fio->old_blkaddr = ei.blk + page->index - ei.fofs; 26778c2ecf20Sopenharmony_ci 26788c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 26798c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE)) 26808c2ecf20Sopenharmony_ci return -EFSCORRUPTED; 26818c2ecf20Sopenharmony_ci 26828c2ecf20Sopenharmony_ci ipu_force = true; 26838c2ecf20Sopenharmony_ci fio->need_lock = LOCK_DONE; 26848c2ecf20Sopenharmony_ci goto got_it; 26858c2ecf20Sopenharmony_ci } 26868c2ecf20Sopenharmony_ci 26878c2ecf20Sopenharmony_ci /* Deadlock due to between page->lock and f2fs_lock_op */ 26888c2ecf20Sopenharmony_ci if (fio->need_lock == LOCK_REQ && !f2fs_trylock_op(fio->sbi)) 26898c2ecf20Sopenharmony_ci return -EAGAIN; 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, page->index, LOOKUP_NODE); 26928c2ecf20Sopenharmony_ci if (err) 26938c2ecf20Sopenharmony_ci goto out; 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci fio->old_blkaddr = dn.data_blkaddr; 26968c2ecf20Sopenharmony_ci 26978c2ecf20Sopenharmony_ci /* This page is already truncated */ 26988c2ecf20Sopenharmony_ci if (fio->old_blkaddr == NULL_ADDR) { 26998c2ecf20Sopenharmony_ci ClearPageUptodate(page); 27008c2ecf20Sopenharmony_ci clear_cold_data(page); 27018c2ecf20Sopenharmony_ci goto out_writepage; 27028c2ecf20Sopenharmony_ci } 27038c2ecf20Sopenharmony_cigot_it: 27048c2ecf20Sopenharmony_ci if (__is_valid_data_blkaddr(fio->old_blkaddr) && 27058c2ecf20Sopenharmony_ci !f2fs_is_valid_blkaddr(fio->sbi, fio->old_blkaddr, 27068c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE)) { 27078c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 27088c2ecf20Sopenharmony_ci goto out_writepage; 27098c2ecf20Sopenharmony_ci } 27108c2ecf20Sopenharmony_ci /* 27118c2ecf20Sopenharmony_ci * If current allocation needs SSR, 27128c2ecf20Sopenharmony_ci * it had better in-place writes for updated data. 27138c2ecf20Sopenharmony_ci */ 27148c2ecf20Sopenharmony_ci if (ipu_force || 27158c2ecf20Sopenharmony_ci (__is_valid_data_blkaddr(fio->old_blkaddr) && 27168c2ecf20Sopenharmony_ci need_inplace_update(fio))) { 27178c2ecf20Sopenharmony_ci err = f2fs_encrypt_one_page(fio); 27188c2ecf20Sopenharmony_ci if (err) 27198c2ecf20Sopenharmony_ci goto out_writepage; 27208c2ecf20Sopenharmony_ci 27218c2ecf20Sopenharmony_ci set_page_writeback(page); 27228c2ecf20Sopenharmony_ci ClearPageError(page); 27238c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 27248c2ecf20Sopenharmony_ci if (fio->need_lock == LOCK_REQ) 27258c2ecf20Sopenharmony_ci f2fs_unlock_op(fio->sbi); 27268c2ecf20Sopenharmony_ci err = f2fs_inplace_write_data(fio); 27278c2ecf20Sopenharmony_ci if (err) { 27288c2ecf20Sopenharmony_ci if (fscrypt_inode_uses_fs_layer_crypto(inode)) 27298c2ecf20Sopenharmony_ci fscrypt_finalize_bounce_page(&fio->encrypted_page); 27308c2ecf20Sopenharmony_ci if (PageWriteback(page)) 27318c2ecf20Sopenharmony_ci end_page_writeback(page); 27328c2ecf20Sopenharmony_ci } else { 27338c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_UPDATE_WRITE); 27348c2ecf20Sopenharmony_ci } 27358c2ecf20Sopenharmony_ci trace_f2fs_do_write_data_page(fio->page, IPU); 27368c2ecf20Sopenharmony_ci return err; 27378c2ecf20Sopenharmony_ci } 27388c2ecf20Sopenharmony_ci 27398c2ecf20Sopenharmony_ci if (fio->need_lock == LOCK_RETRY) { 27408c2ecf20Sopenharmony_ci if (!f2fs_trylock_op(fio->sbi)) { 27418c2ecf20Sopenharmony_ci err = -EAGAIN; 27428c2ecf20Sopenharmony_ci goto out_writepage; 27438c2ecf20Sopenharmony_ci } 27448c2ecf20Sopenharmony_ci fio->need_lock = LOCK_REQ; 27458c2ecf20Sopenharmony_ci } 27468c2ecf20Sopenharmony_ci 27478c2ecf20Sopenharmony_ci err = f2fs_get_node_info(fio->sbi, dn.nid, &ni); 27488c2ecf20Sopenharmony_ci if (err) 27498c2ecf20Sopenharmony_ci goto out_writepage; 27508c2ecf20Sopenharmony_ci 27518c2ecf20Sopenharmony_ci fio->version = ni.version; 27528c2ecf20Sopenharmony_ci 27538c2ecf20Sopenharmony_ci err = f2fs_encrypt_one_page(fio); 27548c2ecf20Sopenharmony_ci if (err) 27558c2ecf20Sopenharmony_ci goto out_writepage; 27568c2ecf20Sopenharmony_ci 27578c2ecf20Sopenharmony_ci set_page_writeback(page); 27588c2ecf20Sopenharmony_ci ClearPageError(page); 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ci if (fio->compr_blocks && fio->old_blkaddr == COMPRESS_ADDR) 27618c2ecf20Sopenharmony_ci f2fs_i_compr_blocks_update(inode, fio->compr_blocks - 1, false); 27628c2ecf20Sopenharmony_ci 27638c2ecf20Sopenharmony_ci /* LFS mode write path */ 27648c2ecf20Sopenharmony_ci f2fs_outplace_write_data(&dn, fio); 27658c2ecf20Sopenharmony_ci trace_f2fs_do_write_data_page(page, OPU); 27668c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_APPEND_WRITE); 27678c2ecf20Sopenharmony_ci if (page->index == 0) 27688c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_FIRST_BLOCK_WRITTEN); 27698c2ecf20Sopenharmony_ciout_writepage: 27708c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 27718c2ecf20Sopenharmony_ciout: 27728c2ecf20Sopenharmony_ci if (fio->need_lock == LOCK_REQ) 27738c2ecf20Sopenharmony_ci f2fs_unlock_op(fio->sbi); 27748c2ecf20Sopenharmony_ci return err; 27758c2ecf20Sopenharmony_ci} 27768c2ecf20Sopenharmony_ci 27778c2ecf20Sopenharmony_ciint f2fs_write_single_data_page(struct page *page, int *submitted, 27788c2ecf20Sopenharmony_ci struct bio **bio, 27798c2ecf20Sopenharmony_ci sector_t *last_block, 27808c2ecf20Sopenharmony_ci struct writeback_control *wbc, 27818c2ecf20Sopenharmony_ci enum iostat_type io_type, 27828c2ecf20Sopenharmony_ci int compr_blocks, 27838c2ecf20Sopenharmony_ci bool allow_balance) 27848c2ecf20Sopenharmony_ci{ 27858c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 27868c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 27878c2ecf20Sopenharmony_ci loff_t i_size = i_size_read(inode); 27888c2ecf20Sopenharmony_ci const pgoff_t end_index = ((unsigned long long)i_size) 27898c2ecf20Sopenharmony_ci >> PAGE_SHIFT; 27908c2ecf20Sopenharmony_ci loff_t psize = (loff_t)(page->index + 1) << PAGE_SHIFT; 27918c2ecf20Sopenharmony_ci unsigned offset = 0; 27928c2ecf20Sopenharmony_ci bool need_balance_fs = false; 27938c2ecf20Sopenharmony_ci int err = 0; 27948c2ecf20Sopenharmony_ci struct f2fs_io_info fio = { 27958c2ecf20Sopenharmony_ci .sbi = sbi, 27968c2ecf20Sopenharmony_ci .ino = inode->i_ino, 27978c2ecf20Sopenharmony_ci .type = DATA, 27988c2ecf20Sopenharmony_ci .op = REQ_OP_WRITE, 27998c2ecf20Sopenharmony_ci .op_flags = wbc_to_write_flags(wbc), 28008c2ecf20Sopenharmony_ci .old_blkaddr = NULL_ADDR, 28018c2ecf20Sopenharmony_ci .page = page, 28028c2ecf20Sopenharmony_ci .encrypted_page = NULL, 28038c2ecf20Sopenharmony_ci .submitted = false, 28048c2ecf20Sopenharmony_ci .compr_blocks = compr_blocks, 28058c2ecf20Sopenharmony_ci .need_lock = LOCK_RETRY, 28068c2ecf20Sopenharmony_ci .io_type = io_type, 28078c2ecf20Sopenharmony_ci .io_wbc = wbc, 28088c2ecf20Sopenharmony_ci .bio = bio, 28098c2ecf20Sopenharmony_ci .last_block = last_block, 28108c2ecf20Sopenharmony_ci }; 28118c2ecf20Sopenharmony_ci 28128c2ecf20Sopenharmony_ci trace_f2fs_writepage(page, DATA); 28138c2ecf20Sopenharmony_ci 28148c2ecf20Sopenharmony_ci /* we should bypass data pages to proceed the kworkder jobs */ 28158c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 28168c2ecf20Sopenharmony_ci mapping_set_error(page->mapping, -EIO); 28178c2ecf20Sopenharmony_ci /* 28188c2ecf20Sopenharmony_ci * don't drop any dirty dentry pages for keeping lastest 28198c2ecf20Sopenharmony_ci * directory structure. 28208c2ecf20Sopenharmony_ci */ 28218c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode) && 28228c2ecf20Sopenharmony_ci !is_sbi_flag_set(sbi, SBI_IS_CLOSE)) 28238c2ecf20Sopenharmony_ci goto redirty_out; 28248c2ecf20Sopenharmony_ci goto out; 28258c2ecf20Sopenharmony_ci } 28268c2ecf20Sopenharmony_ci 28278c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 28288c2ecf20Sopenharmony_ci goto redirty_out; 28298c2ecf20Sopenharmony_ci 28308c2ecf20Sopenharmony_ci if (page->index < end_index || 28318c2ecf20Sopenharmony_ci f2fs_verity_in_progress(inode) || 28328c2ecf20Sopenharmony_ci compr_blocks) 28338c2ecf20Sopenharmony_ci goto write; 28348c2ecf20Sopenharmony_ci 28358c2ecf20Sopenharmony_ci /* 28368c2ecf20Sopenharmony_ci * If the offset is out-of-range of file size, 28378c2ecf20Sopenharmony_ci * this page does not have to be written to disk. 28388c2ecf20Sopenharmony_ci */ 28398c2ecf20Sopenharmony_ci offset = i_size & (PAGE_SIZE - 1); 28408c2ecf20Sopenharmony_ci if ((page->index >= end_index + 1) || !offset) 28418c2ecf20Sopenharmony_ci goto out; 28428c2ecf20Sopenharmony_ci 28438c2ecf20Sopenharmony_ci zero_user_segment(page, offset, PAGE_SIZE); 28448c2ecf20Sopenharmony_ciwrite: 28458c2ecf20Sopenharmony_ci if (f2fs_is_drop_cache(inode)) 28468c2ecf20Sopenharmony_ci goto out; 28478c2ecf20Sopenharmony_ci /* we should not write 0'th page having journal header */ 28488c2ecf20Sopenharmony_ci if (f2fs_is_volatile_file(inode) && (!page->index || 28498c2ecf20Sopenharmony_ci (!wbc->for_reclaim && 28508c2ecf20Sopenharmony_ci f2fs_available_free_memory(sbi, BASE_CHECK)))) 28518c2ecf20Sopenharmony_ci goto redirty_out; 28528c2ecf20Sopenharmony_ci 28538c2ecf20Sopenharmony_ci /* Dentry/quota blocks are controlled by checkpoint */ 28548c2ecf20Sopenharmony_ci if (S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) { 28558c2ecf20Sopenharmony_ci /* 28568c2ecf20Sopenharmony_ci * We need to wait for node_write to avoid block allocation during 28578c2ecf20Sopenharmony_ci * checkpoint. This can only happen to quota writes which can cause 28588c2ecf20Sopenharmony_ci * the below discard race condition. 28598c2ecf20Sopenharmony_ci */ 28608c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) 28618c2ecf20Sopenharmony_ci down_read(&sbi->node_write); 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci fio.need_lock = LOCK_DONE; 28648c2ecf20Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) 28678c2ecf20Sopenharmony_ci up_read(&sbi->node_write); 28688c2ecf20Sopenharmony_ci 28698c2ecf20Sopenharmony_ci goto done; 28708c2ecf20Sopenharmony_ci } 28718c2ecf20Sopenharmony_ci 28728c2ecf20Sopenharmony_ci if (!wbc->for_reclaim) 28738c2ecf20Sopenharmony_ci need_balance_fs = true; 28748c2ecf20Sopenharmony_ci else if (has_not_enough_free_secs(sbi, 0, 0)) 28758c2ecf20Sopenharmony_ci goto redirty_out; 28768c2ecf20Sopenharmony_ci else 28778c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_HOT_DATA); 28788c2ecf20Sopenharmony_ci 28798c2ecf20Sopenharmony_ci err = -EAGAIN; 28808c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 28818c2ecf20Sopenharmony_ci err = f2fs_write_inline_data(inode, page); 28828c2ecf20Sopenharmony_ci if (!err) 28838c2ecf20Sopenharmony_ci goto out; 28848c2ecf20Sopenharmony_ci } 28858c2ecf20Sopenharmony_ci 28868c2ecf20Sopenharmony_ci if (err == -EAGAIN) { 28878c2ecf20Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 28888c2ecf20Sopenharmony_ci if (err == -EAGAIN) { 28898c2ecf20Sopenharmony_ci fio.need_lock = LOCK_REQ; 28908c2ecf20Sopenharmony_ci err = f2fs_do_write_data_page(&fio); 28918c2ecf20Sopenharmony_ci } 28928c2ecf20Sopenharmony_ci } 28938c2ecf20Sopenharmony_ci 28948c2ecf20Sopenharmony_ci if (err) { 28958c2ecf20Sopenharmony_ci file_set_keep_isize(inode); 28968c2ecf20Sopenharmony_ci } else { 28978c2ecf20Sopenharmony_ci spin_lock(&F2FS_I(inode)->i_size_lock); 28988c2ecf20Sopenharmony_ci if (F2FS_I(inode)->last_disk_size < psize) 28998c2ecf20Sopenharmony_ci F2FS_I(inode)->last_disk_size = psize; 29008c2ecf20Sopenharmony_ci spin_unlock(&F2FS_I(inode)->i_size_lock); 29018c2ecf20Sopenharmony_ci } 29028c2ecf20Sopenharmony_ci 29038c2ecf20Sopenharmony_cidone: 29048c2ecf20Sopenharmony_ci if (err && err != -ENOENT) 29058c2ecf20Sopenharmony_ci goto redirty_out; 29068c2ecf20Sopenharmony_ci 29078c2ecf20Sopenharmony_ciout: 29088c2ecf20Sopenharmony_ci inode_dec_dirty_pages(inode); 29098c2ecf20Sopenharmony_ci if (err) { 29108c2ecf20Sopenharmony_ci ClearPageUptodate(page); 29118c2ecf20Sopenharmony_ci clear_cold_data(page); 29128c2ecf20Sopenharmony_ci } 29138c2ecf20Sopenharmony_ci 29148c2ecf20Sopenharmony_ci if (wbc->for_reclaim) { 29158c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(sbi, NULL, page, 0, DATA); 29168c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_HOT_DATA); 29178c2ecf20Sopenharmony_ci f2fs_remove_dirty_inode(inode); 29188c2ecf20Sopenharmony_ci submitted = NULL; 29198c2ecf20Sopenharmony_ci } 29208c2ecf20Sopenharmony_ci unlock_page(page); 29218c2ecf20Sopenharmony_ci if (!S_ISDIR(inode->i_mode) && !IS_NOQUOTA(inode) && 29228c2ecf20Sopenharmony_ci !F2FS_I(inode)->wb_task && allow_balance) 29238c2ecf20Sopenharmony_ci f2fs_balance_fs(sbi, need_balance_fs); 29248c2ecf20Sopenharmony_ci 29258c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) { 29268c2ecf20Sopenharmony_ci f2fs_submit_merged_write(sbi, DATA); 29278c2ecf20Sopenharmony_ci if (bio && *bio) 29288c2ecf20Sopenharmony_ci f2fs_submit_merged_ipu_write(sbi, bio, NULL); 29298c2ecf20Sopenharmony_ci submitted = NULL; 29308c2ecf20Sopenharmony_ci } 29318c2ecf20Sopenharmony_ci 29328c2ecf20Sopenharmony_ci if (submitted) 29338c2ecf20Sopenharmony_ci *submitted = fio.submitted ? 1 : 0; 29348c2ecf20Sopenharmony_ci 29358c2ecf20Sopenharmony_ci return 0; 29368c2ecf20Sopenharmony_ci 29378c2ecf20Sopenharmony_ciredirty_out: 29388c2ecf20Sopenharmony_ci redirty_page_for_writepage(wbc, page); 29398c2ecf20Sopenharmony_ci /* 29408c2ecf20Sopenharmony_ci * pageout() in MM traslates EAGAIN, so calls handle_write_error() 29418c2ecf20Sopenharmony_ci * -> mapping_set_error() -> set_bit(AS_EIO, ...). 29428c2ecf20Sopenharmony_ci * file_write_and_wait_range() will see EIO error, which is critical 29438c2ecf20Sopenharmony_ci * to return value of fsync() followed by atomic_write failure to user. 29448c2ecf20Sopenharmony_ci */ 29458c2ecf20Sopenharmony_ci if (!err || wbc->for_reclaim) 29468c2ecf20Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 29478c2ecf20Sopenharmony_ci unlock_page(page); 29488c2ecf20Sopenharmony_ci return err; 29498c2ecf20Sopenharmony_ci} 29508c2ecf20Sopenharmony_ci 29518c2ecf20Sopenharmony_cistatic int f2fs_write_data_page(struct page *page, 29528c2ecf20Sopenharmony_ci struct writeback_control *wbc) 29538c2ecf20Sopenharmony_ci{ 29548c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 29558c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 29568c2ecf20Sopenharmony_ci 29578c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) 29588c2ecf20Sopenharmony_ci goto out; 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 29618c2ecf20Sopenharmony_ci if (f2fs_is_compressed_cluster(inode, page->index)) { 29628c2ecf20Sopenharmony_ci redirty_page_for_writepage(wbc, page); 29638c2ecf20Sopenharmony_ci return AOP_WRITEPAGE_ACTIVATE; 29648c2ecf20Sopenharmony_ci } 29658c2ecf20Sopenharmony_ci } 29668c2ecf20Sopenharmony_ciout: 29678c2ecf20Sopenharmony_ci#endif 29688c2ecf20Sopenharmony_ci 29698c2ecf20Sopenharmony_ci return f2fs_write_single_data_page(page, NULL, NULL, NULL, 29708c2ecf20Sopenharmony_ci wbc, FS_DATA_IO, 0, true); 29718c2ecf20Sopenharmony_ci} 29728c2ecf20Sopenharmony_ci 29738c2ecf20Sopenharmony_ci/* 29748c2ecf20Sopenharmony_ci * This function was copied from write_cche_pages from mm/page-writeback.c. 29758c2ecf20Sopenharmony_ci * The major change is making write step of cold data page separately from 29768c2ecf20Sopenharmony_ci * warm/hot data page. 29778c2ecf20Sopenharmony_ci */ 29788c2ecf20Sopenharmony_cistatic int f2fs_write_cache_pages(struct address_space *mapping, 29798c2ecf20Sopenharmony_ci struct writeback_control *wbc, 29808c2ecf20Sopenharmony_ci enum iostat_type io_type) 29818c2ecf20Sopenharmony_ci{ 29828c2ecf20Sopenharmony_ci int ret = 0; 29838c2ecf20Sopenharmony_ci int done = 0, retry = 0; 29848c2ecf20Sopenharmony_ci struct pagevec pvec; 29858c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); 29868c2ecf20Sopenharmony_ci struct bio *bio = NULL; 29878c2ecf20Sopenharmony_ci sector_t last_block; 29888c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 29898c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 29908c2ecf20Sopenharmony_ci struct compress_ctx cc = { 29918c2ecf20Sopenharmony_ci .inode = inode, 29928c2ecf20Sopenharmony_ci .log_cluster_size = F2FS_I(inode)->i_log_cluster_size, 29938c2ecf20Sopenharmony_ci .cluster_size = F2FS_I(inode)->i_cluster_size, 29948c2ecf20Sopenharmony_ci .cluster_idx = NULL_CLUSTER, 29958c2ecf20Sopenharmony_ci .rpages = NULL, 29968c2ecf20Sopenharmony_ci .nr_rpages = 0, 29978c2ecf20Sopenharmony_ci .cpages = NULL, 29988c2ecf20Sopenharmony_ci .rbuf = NULL, 29998c2ecf20Sopenharmony_ci .cbuf = NULL, 30008c2ecf20Sopenharmony_ci .rlen = PAGE_SIZE * F2FS_I(inode)->i_cluster_size, 30018c2ecf20Sopenharmony_ci .private = NULL, 30028c2ecf20Sopenharmony_ci }; 30038c2ecf20Sopenharmony_ci#endif 30048c2ecf20Sopenharmony_ci int nr_pages; 30058c2ecf20Sopenharmony_ci pgoff_t index; 30068c2ecf20Sopenharmony_ci pgoff_t end; /* Inclusive */ 30078c2ecf20Sopenharmony_ci pgoff_t done_index; 30088c2ecf20Sopenharmony_ci int range_whole = 0; 30098c2ecf20Sopenharmony_ci xa_mark_t tag; 30108c2ecf20Sopenharmony_ci int nwritten = 0; 30118c2ecf20Sopenharmony_ci int submitted = 0; 30128c2ecf20Sopenharmony_ci int i; 30138c2ecf20Sopenharmony_ci 30148c2ecf20Sopenharmony_ci pagevec_init(&pvec); 30158c2ecf20Sopenharmony_ci 30168c2ecf20Sopenharmony_ci if (get_dirty_pages(mapping->host) <= 30178c2ecf20Sopenharmony_ci SM_I(F2FS_M_SB(mapping))->min_hot_blocks) 30188c2ecf20Sopenharmony_ci set_inode_flag(mapping->host, FI_HOT_DATA); 30198c2ecf20Sopenharmony_ci else 30208c2ecf20Sopenharmony_ci clear_inode_flag(mapping->host, FI_HOT_DATA); 30218c2ecf20Sopenharmony_ci 30228c2ecf20Sopenharmony_ci if (wbc->range_cyclic) { 30238c2ecf20Sopenharmony_ci index = mapping->writeback_index; /* prev offset */ 30248c2ecf20Sopenharmony_ci end = -1; 30258c2ecf20Sopenharmony_ci } else { 30268c2ecf20Sopenharmony_ci index = wbc->range_start >> PAGE_SHIFT; 30278c2ecf20Sopenharmony_ci end = wbc->range_end >> PAGE_SHIFT; 30288c2ecf20Sopenharmony_ci if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) 30298c2ecf20Sopenharmony_ci range_whole = 1; 30308c2ecf20Sopenharmony_ci } 30318c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) 30328c2ecf20Sopenharmony_ci tag = PAGECACHE_TAG_TOWRITE; 30338c2ecf20Sopenharmony_ci else 30348c2ecf20Sopenharmony_ci tag = PAGECACHE_TAG_DIRTY; 30358c2ecf20Sopenharmony_ciretry: 30368c2ecf20Sopenharmony_ci retry = 0; 30378c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL || wbc->tagged_writepages) 30388c2ecf20Sopenharmony_ci tag_pages_for_writeback(mapping, index, end); 30398c2ecf20Sopenharmony_ci done_index = index; 30408c2ecf20Sopenharmony_ci while (!done && !retry && (index <= end)) { 30418c2ecf20Sopenharmony_ci nr_pages = pagevec_lookup_range_tag(&pvec, mapping, &index, end, 30428c2ecf20Sopenharmony_ci tag); 30438c2ecf20Sopenharmony_ci if (nr_pages == 0) 30448c2ecf20Sopenharmony_ci break; 30458c2ecf20Sopenharmony_ci 30468c2ecf20Sopenharmony_ci for (i = 0; i < nr_pages; i++) { 30478c2ecf20Sopenharmony_ci struct page *page = pvec.pages[i]; 30488c2ecf20Sopenharmony_ci bool need_readd; 30498c2ecf20Sopenharmony_cireadd: 30508c2ecf20Sopenharmony_ci need_readd = false; 30518c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 30528c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 30538c2ecf20Sopenharmony_ci ret = f2fs_init_compress_ctx(&cc); 30548c2ecf20Sopenharmony_ci if (ret) { 30558c2ecf20Sopenharmony_ci done = 1; 30568c2ecf20Sopenharmony_ci break; 30578c2ecf20Sopenharmony_ci } 30588c2ecf20Sopenharmony_ci 30598c2ecf20Sopenharmony_ci if (!f2fs_cluster_can_merge_page(&cc, 30608c2ecf20Sopenharmony_ci page->index)) { 30618c2ecf20Sopenharmony_ci ret = f2fs_write_multi_pages(&cc, 30628c2ecf20Sopenharmony_ci &submitted, wbc, io_type); 30638c2ecf20Sopenharmony_ci if (!ret) 30648c2ecf20Sopenharmony_ci need_readd = true; 30658c2ecf20Sopenharmony_ci goto result; 30668c2ecf20Sopenharmony_ci } 30678c2ecf20Sopenharmony_ci 30688c2ecf20Sopenharmony_ci if (unlikely(f2fs_cp_error(sbi))) 30698c2ecf20Sopenharmony_ci goto lock_page; 30708c2ecf20Sopenharmony_ci 30718c2ecf20Sopenharmony_ci if (f2fs_cluster_is_empty(&cc)) { 30728c2ecf20Sopenharmony_ci void *fsdata = NULL; 30738c2ecf20Sopenharmony_ci struct page *pagep; 30748c2ecf20Sopenharmony_ci int ret2; 30758c2ecf20Sopenharmony_ci 30768c2ecf20Sopenharmony_ci ret2 = f2fs_prepare_compress_overwrite( 30778c2ecf20Sopenharmony_ci inode, &pagep, 30788c2ecf20Sopenharmony_ci page->index, &fsdata); 30798c2ecf20Sopenharmony_ci if (ret2 < 0) { 30808c2ecf20Sopenharmony_ci ret = ret2; 30818c2ecf20Sopenharmony_ci done = 1; 30828c2ecf20Sopenharmony_ci break; 30838c2ecf20Sopenharmony_ci } else if (ret2 && 30848c2ecf20Sopenharmony_ci !f2fs_compress_write_end(inode, 30858c2ecf20Sopenharmony_ci fsdata, page->index, 30868c2ecf20Sopenharmony_ci 1)) { 30878c2ecf20Sopenharmony_ci retry = 1; 30888c2ecf20Sopenharmony_ci break; 30898c2ecf20Sopenharmony_ci } 30908c2ecf20Sopenharmony_ci } else { 30918c2ecf20Sopenharmony_ci goto lock_page; 30928c2ecf20Sopenharmony_ci } 30938c2ecf20Sopenharmony_ci } 30948c2ecf20Sopenharmony_ci#endif 30958c2ecf20Sopenharmony_ci /* give a priority to WB_SYNC threads */ 30968c2ecf20Sopenharmony_ci if (atomic_read(&sbi->wb_sync_req[DATA]) && 30978c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 30988c2ecf20Sopenharmony_ci done = 1; 30998c2ecf20Sopenharmony_ci break; 31008c2ecf20Sopenharmony_ci } 31018c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 31028c2ecf20Sopenharmony_cilock_page: 31038c2ecf20Sopenharmony_ci#endif 31048c2ecf20Sopenharmony_ci done_index = page->index; 31058c2ecf20Sopenharmony_ciretry_write: 31068c2ecf20Sopenharmony_ci lock_page(page); 31078c2ecf20Sopenharmony_ci 31088c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 31098c2ecf20Sopenharmony_cicontinue_unlock: 31108c2ecf20Sopenharmony_ci unlock_page(page); 31118c2ecf20Sopenharmony_ci continue; 31128c2ecf20Sopenharmony_ci } 31138c2ecf20Sopenharmony_ci 31148c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 31158c2ecf20Sopenharmony_ci /* someone wrote it for us */ 31168c2ecf20Sopenharmony_ci goto continue_unlock; 31178c2ecf20Sopenharmony_ci } 31188c2ecf20Sopenharmony_ci 31198c2ecf20Sopenharmony_ci if (PageWriteback(page)) { 31208c2ecf20Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_NONE) 31218c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, 31228c2ecf20Sopenharmony_ci DATA, true, true); 31238c2ecf20Sopenharmony_ci else 31248c2ecf20Sopenharmony_ci goto continue_unlock; 31258c2ecf20Sopenharmony_ci } 31268c2ecf20Sopenharmony_ci 31278c2ecf20Sopenharmony_ci if (!clear_page_dirty_for_io(page)) 31288c2ecf20Sopenharmony_ci goto continue_unlock; 31298c2ecf20Sopenharmony_ci 31308c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 31318c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 31328c2ecf20Sopenharmony_ci get_page(page); 31338c2ecf20Sopenharmony_ci f2fs_compress_ctx_add_page(&cc, page); 31348c2ecf20Sopenharmony_ci continue; 31358c2ecf20Sopenharmony_ci } 31368c2ecf20Sopenharmony_ci#endif 31378c2ecf20Sopenharmony_ci ret = f2fs_write_single_data_page(page, &submitted, 31388c2ecf20Sopenharmony_ci &bio, &last_block, wbc, io_type, 31398c2ecf20Sopenharmony_ci 0, true); 31408c2ecf20Sopenharmony_ci if (ret == AOP_WRITEPAGE_ACTIVATE) 31418c2ecf20Sopenharmony_ci unlock_page(page); 31428c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 31438c2ecf20Sopenharmony_ciresult: 31448c2ecf20Sopenharmony_ci#endif 31458c2ecf20Sopenharmony_ci nwritten += submitted; 31468c2ecf20Sopenharmony_ci wbc->nr_to_write -= submitted; 31478c2ecf20Sopenharmony_ci 31488c2ecf20Sopenharmony_ci if (unlikely(ret)) { 31498c2ecf20Sopenharmony_ci /* 31508c2ecf20Sopenharmony_ci * keep nr_to_write, since vfs uses this to 31518c2ecf20Sopenharmony_ci * get # of written pages. 31528c2ecf20Sopenharmony_ci */ 31538c2ecf20Sopenharmony_ci if (ret == AOP_WRITEPAGE_ACTIVATE) { 31548c2ecf20Sopenharmony_ci ret = 0; 31558c2ecf20Sopenharmony_ci goto next; 31568c2ecf20Sopenharmony_ci } else if (ret == -EAGAIN) { 31578c2ecf20Sopenharmony_ci ret = 0; 31588c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) { 31598c2ecf20Sopenharmony_ci cond_resched(); 31608c2ecf20Sopenharmony_ci congestion_wait(BLK_RW_ASYNC, 31618c2ecf20Sopenharmony_ci DEFAULT_IO_TIMEOUT); 31628c2ecf20Sopenharmony_ci goto retry_write; 31638c2ecf20Sopenharmony_ci } 31648c2ecf20Sopenharmony_ci goto next; 31658c2ecf20Sopenharmony_ci } 31668c2ecf20Sopenharmony_ci done_index = page->index + 1; 31678c2ecf20Sopenharmony_ci done = 1; 31688c2ecf20Sopenharmony_ci break; 31698c2ecf20Sopenharmony_ci } 31708c2ecf20Sopenharmony_ci 31718c2ecf20Sopenharmony_ci if (wbc->nr_to_write <= 0 && 31728c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE) { 31738c2ecf20Sopenharmony_ci done = 1; 31748c2ecf20Sopenharmony_ci break; 31758c2ecf20Sopenharmony_ci } 31768c2ecf20Sopenharmony_cinext: 31778c2ecf20Sopenharmony_ci if (need_readd) 31788c2ecf20Sopenharmony_ci goto readd; 31798c2ecf20Sopenharmony_ci } 31808c2ecf20Sopenharmony_ci pagevec_release(&pvec); 31818c2ecf20Sopenharmony_ci cond_resched(); 31828c2ecf20Sopenharmony_ci } 31838c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 31848c2ecf20Sopenharmony_ci /* flush remained pages in compress cluster */ 31858c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode) && !f2fs_cluster_is_empty(&cc)) { 31868c2ecf20Sopenharmony_ci ret = f2fs_write_multi_pages(&cc, &submitted, wbc, io_type); 31878c2ecf20Sopenharmony_ci nwritten += submitted; 31888c2ecf20Sopenharmony_ci wbc->nr_to_write -= submitted; 31898c2ecf20Sopenharmony_ci if (ret) { 31908c2ecf20Sopenharmony_ci done = 1; 31918c2ecf20Sopenharmony_ci retry = 0; 31928c2ecf20Sopenharmony_ci } 31938c2ecf20Sopenharmony_ci } 31948c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) 31958c2ecf20Sopenharmony_ci f2fs_destroy_compress_ctx(&cc, false); 31968c2ecf20Sopenharmony_ci#endif 31978c2ecf20Sopenharmony_ci if (retry) { 31988c2ecf20Sopenharmony_ci index = 0; 31998c2ecf20Sopenharmony_ci end = -1; 32008c2ecf20Sopenharmony_ci goto retry; 32018c2ecf20Sopenharmony_ci } 32028c2ecf20Sopenharmony_ci if (wbc->range_cyclic && !done) 32038c2ecf20Sopenharmony_ci done_index = 0; 32048c2ecf20Sopenharmony_ci if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) 32058c2ecf20Sopenharmony_ci mapping->writeback_index = done_index; 32068c2ecf20Sopenharmony_ci 32078c2ecf20Sopenharmony_ci if (nwritten) 32088c2ecf20Sopenharmony_ci f2fs_submit_merged_write_cond(F2FS_M_SB(mapping), mapping->host, 32098c2ecf20Sopenharmony_ci NULL, 0, DATA); 32108c2ecf20Sopenharmony_ci /* submit cached bio of IPU write */ 32118c2ecf20Sopenharmony_ci if (bio) 32128c2ecf20Sopenharmony_ci f2fs_submit_merged_ipu_write(sbi, &bio, NULL); 32138c2ecf20Sopenharmony_ci 32148c2ecf20Sopenharmony_ci return ret; 32158c2ecf20Sopenharmony_ci} 32168c2ecf20Sopenharmony_ci 32178c2ecf20Sopenharmony_cistatic inline bool __should_serialize_io(struct inode *inode, 32188c2ecf20Sopenharmony_ci struct writeback_control *wbc) 32198c2ecf20Sopenharmony_ci{ 32208c2ecf20Sopenharmony_ci /* to avoid deadlock in path of data flush */ 32218c2ecf20Sopenharmony_ci if (F2FS_I(inode)->wb_task) 32228c2ecf20Sopenharmony_ci return false; 32238c2ecf20Sopenharmony_ci 32248c2ecf20Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 32258c2ecf20Sopenharmony_ci return false; 32268c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) 32278c2ecf20Sopenharmony_ci return false; 32288c2ecf20Sopenharmony_ci 32298c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) 32308c2ecf20Sopenharmony_ci return true; 32318c2ecf20Sopenharmony_ci if (wbc->sync_mode != WB_SYNC_ALL) 32328c2ecf20Sopenharmony_ci return true; 32338c2ecf20Sopenharmony_ci if (get_dirty_pages(inode) >= SM_I(F2FS_I_SB(inode))->min_seq_blocks) 32348c2ecf20Sopenharmony_ci return true; 32358c2ecf20Sopenharmony_ci return false; 32368c2ecf20Sopenharmony_ci} 32378c2ecf20Sopenharmony_ci 32388c2ecf20Sopenharmony_cistatic int __f2fs_write_data_pages(struct address_space *mapping, 32398c2ecf20Sopenharmony_ci struct writeback_control *wbc, 32408c2ecf20Sopenharmony_ci enum iostat_type io_type) 32418c2ecf20Sopenharmony_ci{ 32428c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 32438c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 32448c2ecf20Sopenharmony_ci struct blk_plug plug; 32458c2ecf20Sopenharmony_ci int ret; 32468c2ecf20Sopenharmony_ci bool locked = false; 32478c2ecf20Sopenharmony_ci 32488c2ecf20Sopenharmony_ci /* deal with chardevs and other special file */ 32498c2ecf20Sopenharmony_ci if (!mapping->a_ops->writepage) 32508c2ecf20Sopenharmony_ci return 0; 32518c2ecf20Sopenharmony_ci 32528c2ecf20Sopenharmony_ci /* skip writing if there is no dirty page in this inode */ 32538c2ecf20Sopenharmony_ci if (!get_dirty_pages(inode) && wbc->sync_mode == WB_SYNC_NONE) 32548c2ecf20Sopenharmony_ci return 0; 32558c2ecf20Sopenharmony_ci 32568c2ecf20Sopenharmony_ci /* during POR, we don't need to trigger writepage at all. */ 32578c2ecf20Sopenharmony_ci if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) 32588c2ecf20Sopenharmony_ci goto skip_write; 32598c2ecf20Sopenharmony_ci 32608c2ecf20Sopenharmony_ci if ((S_ISDIR(inode->i_mode) || IS_NOQUOTA(inode)) && 32618c2ecf20Sopenharmony_ci wbc->sync_mode == WB_SYNC_NONE && 32628c2ecf20Sopenharmony_ci get_dirty_pages(inode) < nr_pages_to_skip(sbi, DATA) && 32638c2ecf20Sopenharmony_ci f2fs_available_free_memory(sbi, DIRTY_DENTS)) 32648c2ecf20Sopenharmony_ci goto skip_write; 32658c2ecf20Sopenharmony_ci 32668c2ecf20Sopenharmony_ci /* skip writing during file defragment */ 32678c2ecf20Sopenharmony_ci if (is_inode_flag_set(inode, FI_DO_DEFRAG)) 32688c2ecf20Sopenharmony_ci goto skip_write; 32698c2ecf20Sopenharmony_ci 32708c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, DATA); 32718c2ecf20Sopenharmony_ci 32728c2ecf20Sopenharmony_ci /* to avoid spliting IOs due to mixed WB_SYNC_ALL and WB_SYNC_NONE */ 32738c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 32748c2ecf20Sopenharmony_ci atomic_inc(&sbi->wb_sync_req[DATA]); 32758c2ecf20Sopenharmony_ci else if (atomic_read(&sbi->wb_sync_req[DATA])) { 32768c2ecf20Sopenharmony_ci /* to avoid potential deadlock */ 32778c2ecf20Sopenharmony_ci if (current->plug) 32788c2ecf20Sopenharmony_ci blk_finish_plug(current->plug); 32798c2ecf20Sopenharmony_ci goto skip_write; 32808c2ecf20Sopenharmony_ci } 32818c2ecf20Sopenharmony_ci 32828c2ecf20Sopenharmony_ci if (__should_serialize_io(inode, wbc)) { 32838c2ecf20Sopenharmony_ci mutex_lock(&sbi->writepages); 32848c2ecf20Sopenharmony_ci locked = true; 32858c2ecf20Sopenharmony_ci } 32868c2ecf20Sopenharmony_ci 32878c2ecf20Sopenharmony_ci blk_start_plug(&plug); 32888c2ecf20Sopenharmony_ci ret = f2fs_write_cache_pages(mapping, wbc, io_type); 32898c2ecf20Sopenharmony_ci blk_finish_plug(&plug); 32908c2ecf20Sopenharmony_ci 32918c2ecf20Sopenharmony_ci if (locked) 32928c2ecf20Sopenharmony_ci mutex_unlock(&sbi->writepages); 32938c2ecf20Sopenharmony_ci 32948c2ecf20Sopenharmony_ci if (wbc->sync_mode == WB_SYNC_ALL) 32958c2ecf20Sopenharmony_ci atomic_dec(&sbi->wb_sync_req[DATA]); 32968c2ecf20Sopenharmony_ci /* 32978c2ecf20Sopenharmony_ci * if some pages were truncated, we cannot guarantee its mapping->host 32988c2ecf20Sopenharmony_ci * to detect pending bios. 32998c2ecf20Sopenharmony_ci */ 33008c2ecf20Sopenharmony_ci 33018c2ecf20Sopenharmony_ci f2fs_remove_dirty_inode(inode); 33028c2ecf20Sopenharmony_ci return ret; 33038c2ecf20Sopenharmony_ci 33048c2ecf20Sopenharmony_ciskip_write: 33058c2ecf20Sopenharmony_ci wbc->pages_skipped += get_dirty_pages(inode); 33068c2ecf20Sopenharmony_ci trace_f2fs_writepages(mapping->host, wbc, DATA); 33078c2ecf20Sopenharmony_ci return 0; 33088c2ecf20Sopenharmony_ci} 33098c2ecf20Sopenharmony_ci 33108c2ecf20Sopenharmony_cistatic int f2fs_write_data_pages(struct address_space *mapping, 33118c2ecf20Sopenharmony_ci struct writeback_control *wbc) 33128c2ecf20Sopenharmony_ci{ 33138c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 33148c2ecf20Sopenharmony_ci 33158c2ecf20Sopenharmony_ci return __f2fs_write_data_pages(mapping, wbc, 33168c2ecf20Sopenharmony_ci F2FS_I(inode)->cp_task == current ? 33178c2ecf20Sopenharmony_ci FS_CP_DATA_IO : FS_DATA_IO); 33188c2ecf20Sopenharmony_ci} 33198c2ecf20Sopenharmony_ci 33208c2ecf20Sopenharmony_cistatic void f2fs_write_failed(struct address_space *mapping, loff_t to) 33218c2ecf20Sopenharmony_ci{ 33228c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 33238c2ecf20Sopenharmony_ci loff_t i_size = i_size_read(inode); 33248c2ecf20Sopenharmony_ci 33258c2ecf20Sopenharmony_ci if (IS_NOQUOTA(inode)) 33268c2ecf20Sopenharmony_ci return; 33278c2ecf20Sopenharmony_ci 33288c2ecf20Sopenharmony_ci /* In the fs-verity case, f2fs_end_enable_verity() does the truncate */ 33298c2ecf20Sopenharmony_ci if (to > i_size && !f2fs_verity_in_progress(inode)) { 33308c2ecf20Sopenharmony_ci down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 33318c2ecf20Sopenharmony_ci down_write(&F2FS_I(inode)->i_mmap_sem); 33328c2ecf20Sopenharmony_ci 33338c2ecf20Sopenharmony_ci truncate_pagecache(inode, i_size); 33348c2ecf20Sopenharmony_ci f2fs_truncate_blocks(inode, i_size, true); 33358c2ecf20Sopenharmony_ci 33368c2ecf20Sopenharmony_ci up_write(&F2FS_I(inode)->i_mmap_sem); 33378c2ecf20Sopenharmony_ci up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); 33388c2ecf20Sopenharmony_ci } 33398c2ecf20Sopenharmony_ci} 33408c2ecf20Sopenharmony_ci 33418c2ecf20Sopenharmony_cistatic int prepare_write_begin(struct f2fs_sb_info *sbi, 33428c2ecf20Sopenharmony_ci struct page *page, loff_t pos, unsigned len, 33438c2ecf20Sopenharmony_ci block_t *blk_addr, bool *node_changed) 33448c2ecf20Sopenharmony_ci{ 33458c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 33468c2ecf20Sopenharmony_ci pgoff_t index = page->index; 33478c2ecf20Sopenharmony_ci struct dnode_of_data dn; 33488c2ecf20Sopenharmony_ci struct page *ipage; 33498c2ecf20Sopenharmony_ci bool locked = false; 33508c2ecf20Sopenharmony_ci struct extent_info ei = {0,0,0}; 33518c2ecf20Sopenharmony_ci int err = 0; 33528c2ecf20Sopenharmony_ci int flag; 33538c2ecf20Sopenharmony_ci 33548c2ecf20Sopenharmony_ci /* 33558c2ecf20Sopenharmony_ci * we already allocated all the blocks, so we don't need to get 33568c2ecf20Sopenharmony_ci * the block addresses when there is no need to fill the page. 33578c2ecf20Sopenharmony_ci */ 33588c2ecf20Sopenharmony_ci if (!f2fs_has_inline_data(inode) && len == PAGE_SIZE && 33598c2ecf20Sopenharmony_ci !is_inode_flag_set(inode, FI_NO_PREALLOC) && 33608c2ecf20Sopenharmony_ci !f2fs_verity_in_progress(inode)) 33618c2ecf20Sopenharmony_ci return 0; 33628c2ecf20Sopenharmony_ci 33638c2ecf20Sopenharmony_ci /* f2fs_lock_op avoids race between write CP and convert_inline_page */ 33648c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode) && pos + len > MAX_INLINE_DATA(inode)) 33658c2ecf20Sopenharmony_ci flag = F2FS_GET_BLOCK_DEFAULT; 33668c2ecf20Sopenharmony_ci else 33678c2ecf20Sopenharmony_ci flag = F2FS_GET_BLOCK_PRE_AIO; 33688c2ecf20Sopenharmony_ci 33698c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode) || 33708c2ecf20Sopenharmony_ci (pos & PAGE_MASK) >= i_size_read(inode)) { 33718c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, flag, true); 33728c2ecf20Sopenharmony_ci locked = true; 33738c2ecf20Sopenharmony_ci } 33748c2ecf20Sopenharmony_ci 33758c2ecf20Sopenharmony_cirestart: 33768c2ecf20Sopenharmony_ci /* check inline_data */ 33778c2ecf20Sopenharmony_ci ipage = f2fs_get_node_page(sbi, inode->i_ino); 33788c2ecf20Sopenharmony_ci if (IS_ERR(ipage)) { 33798c2ecf20Sopenharmony_ci err = PTR_ERR(ipage); 33808c2ecf20Sopenharmony_ci goto unlock_out; 33818c2ecf20Sopenharmony_ci } 33828c2ecf20Sopenharmony_ci 33838c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, ipage, ipage, 0); 33848c2ecf20Sopenharmony_ci 33858c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) { 33868c2ecf20Sopenharmony_ci if (pos + len <= MAX_INLINE_DATA(inode)) { 33878c2ecf20Sopenharmony_ci f2fs_do_read_inline_data(page, ipage); 33888c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_DATA_EXIST); 33898c2ecf20Sopenharmony_ci if (inode->i_nlink) 33908c2ecf20Sopenharmony_ci set_inline_node(ipage); 33918c2ecf20Sopenharmony_ci } else { 33928c2ecf20Sopenharmony_ci err = f2fs_convert_inline_page(&dn, page); 33938c2ecf20Sopenharmony_ci if (err) 33948c2ecf20Sopenharmony_ci goto out; 33958c2ecf20Sopenharmony_ci if (dn.data_blkaddr == NULL_ADDR) 33968c2ecf20Sopenharmony_ci err = f2fs_get_block(&dn, index); 33978c2ecf20Sopenharmony_ci } 33988c2ecf20Sopenharmony_ci } else if (locked) { 33998c2ecf20Sopenharmony_ci err = f2fs_get_block(&dn, index); 34008c2ecf20Sopenharmony_ci } else { 34018c2ecf20Sopenharmony_ci if (f2fs_lookup_extent_cache(inode, index, &ei)) { 34028c2ecf20Sopenharmony_ci dn.data_blkaddr = ei.blk + index - ei.fofs; 34038c2ecf20Sopenharmony_ci } else { 34048c2ecf20Sopenharmony_ci /* hole case */ 34058c2ecf20Sopenharmony_ci err = f2fs_get_dnode_of_data(&dn, index, LOOKUP_NODE); 34068c2ecf20Sopenharmony_ci if (err || dn.data_blkaddr == NULL_ADDR) { 34078c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 34088c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, F2FS_GET_BLOCK_PRE_AIO, 34098c2ecf20Sopenharmony_ci true); 34108c2ecf20Sopenharmony_ci WARN_ON(flag != F2FS_GET_BLOCK_PRE_AIO); 34118c2ecf20Sopenharmony_ci locked = true; 34128c2ecf20Sopenharmony_ci goto restart; 34138c2ecf20Sopenharmony_ci } 34148c2ecf20Sopenharmony_ci } 34158c2ecf20Sopenharmony_ci } 34168c2ecf20Sopenharmony_ci 34178c2ecf20Sopenharmony_ci /* convert_inline_page can make node_changed */ 34188c2ecf20Sopenharmony_ci *blk_addr = dn.data_blkaddr; 34198c2ecf20Sopenharmony_ci *node_changed = dn.node_changed; 34208c2ecf20Sopenharmony_ciout: 34218c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 34228c2ecf20Sopenharmony_ciunlock_out: 34238c2ecf20Sopenharmony_ci if (locked) 34248c2ecf20Sopenharmony_ci f2fs_do_map_lock(sbi, flag, false); 34258c2ecf20Sopenharmony_ci return err; 34268c2ecf20Sopenharmony_ci} 34278c2ecf20Sopenharmony_ci 34288c2ecf20Sopenharmony_cistatic int f2fs_write_begin(struct file *file, struct address_space *mapping, 34298c2ecf20Sopenharmony_ci loff_t pos, unsigned len, unsigned flags, 34308c2ecf20Sopenharmony_ci struct page **pagep, void **fsdata) 34318c2ecf20Sopenharmony_ci{ 34328c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 34338c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 34348c2ecf20Sopenharmony_ci struct page *page = NULL; 34358c2ecf20Sopenharmony_ci pgoff_t index = ((unsigned long long) pos) >> PAGE_SHIFT; 34368c2ecf20Sopenharmony_ci bool need_balance = false, drop_atomic = false; 34378c2ecf20Sopenharmony_ci block_t blkaddr = NULL_ADDR; 34388c2ecf20Sopenharmony_ci int err = 0; 34398c2ecf20Sopenharmony_ci 34408c2ecf20Sopenharmony_ci trace_f2fs_write_begin(inode, pos, len, flags); 34418c2ecf20Sopenharmony_ci 34428c2ecf20Sopenharmony_ci if (!f2fs_is_checkpoint_ready(sbi)) { 34438c2ecf20Sopenharmony_ci err = -ENOSPC; 34448c2ecf20Sopenharmony_ci goto fail; 34458c2ecf20Sopenharmony_ci } 34468c2ecf20Sopenharmony_ci 34478c2ecf20Sopenharmony_ci if ((f2fs_is_atomic_file(inode) && 34488c2ecf20Sopenharmony_ci !f2fs_available_free_memory(sbi, INMEM_PAGES)) || 34498c2ecf20Sopenharmony_ci is_inode_flag_set(inode, FI_ATOMIC_REVOKE_REQUEST)) { 34508c2ecf20Sopenharmony_ci err = -ENOMEM; 34518c2ecf20Sopenharmony_ci drop_atomic = true; 34528c2ecf20Sopenharmony_ci goto fail; 34538c2ecf20Sopenharmony_ci } 34548c2ecf20Sopenharmony_ci 34558c2ecf20Sopenharmony_ci /* 34568c2ecf20Sopenharmony_ci * We should check this at this moment to avoid deadlock on inode page 34578c2ecf20Sopenharmony_ci * and #0 page. The locking rule for inline_data conversion should be: 34588c2ecf20Sopenharmony_ci * lock_page(page #0) -> lock_page(inode_page) 34598c2ecf20Sopenharmony_ci */ 34608c2ecf20Sopenharmony_ci if (index != 0) { 34618c2ecf20Sopenharmony_ci err = f2fs_convert_inline_inode(inode); 34628c2ecf20Sopenharmony_ci if (err) 34638c2ecf20Sopenharmony_ci goto fail; 34648c2ecf20Sopenharmony_ci } 34658c2ecf20Sopenharmony_ci 34668c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 34678c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 34688c2ecf20Sopenharmony_ci int ret; 34698c2ecf20Sopenharmony_ci 34708c2ecf20Sopenharmony_ci *fsdata = NULL; 34718c2ecf20Sopenharmony_ci 34728c2ecf20Sopenharmony_ci if (len == PAGE_SIZE && !(f2fs_is_atomic_file(inode))) 34738c2ecf20Sopenharmony_ci goto repeat; 34748c2ecf20Sopenharmony_ci 34758c2ecf20Sopenharmony_ci ret = f2fs_prepare_compress_overwrite(inode, pagep, 34768c2ecf20Sopenharmony_ci index, fsdata); 34778c2ecf20Sopenharmony_ci if (ret < 0) { 34788c2ecf20Sopenharmony_ci err = ret; 34798c2ecf20Sopenharmony_ci goto fail; 34808c2ecf20Sopenharmony_ci } else if (ret) { 34818c2ecf20Sopenharmony_ci return 0; 34828c2ecf20Sopenharmony_ci } 34838c2ecf20Sopenharmony_ci } 34848c2ecf20Sopenharmony_ci#endif 34858c2ecf20Sopenharmony_ci 34868c2ecf20Sopenharmony_cirepeat: 34878c2ecf20Sopenharmony_ci /* 34888c2ecf20Sopenharmony_ci * Do not use grab_cache_page_write_begin() to avoid deadlock due to 34898c2ecf20Sopenharmony_ci * wait_for_stable_page. Will wait that below with our IO control. 34908c2ecf20Sopenharmony_ci */ 34918c2ecf20Sopenharmony_ci page = f2fs_pagecache_get_page(mapping, index, 34928c2ecf20Sopenharmony_ci FGP_LOCK | FGP_WRITE | FGP_CREAT, GFP_NOFS); 34938c2ecf20Sopenharmony_ci if (!page) { 34948c2ecf20Sopenharmony_ci err = -ENOMEM; 34958c2ecf20Sopenharmony_ci goto fail; 34968c2ecf20Sopenharmony_ci } 34978c2ecf20Sopenharmony_ci 34988c2ecf20Sopenharmony_ci /* TODO: cluster can be compressed due to race with .writepage */ 34998c2ecf20Sopenharmony_ci 35008c2ecf20Sopenharmony_ci *pagep = page; 35018c2ecf20Sopenharmony_ci 35028c2ecf20Sopenharmony_ci err = prepare_write_begin(sbi, page, pos, len, 35038c2ecf20Sopenharmony_ci &blkaddr, &need_balance); 35048c2ecf20Sopenharmony_ci if (err) 35058c2ecf20Sopenharmony_ci goto fail; 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci if (need_balance && !IS_NOQUOTA(inode) && 35088c2ecf20Sopenharmony_ci has_not_enough_free_secs(sbi, 0, 0)) { 35098c2ecf20Sopenharmony_ci unlock_page(page); 35108c2ecf20Sopenharmony_ci f2fs_balance_fs(sbi, true); 35118c2ecf20Sopenharmony_ci lock_page(page); 35128c2ecf20Sopenharmony_ci if (page->mapping != mapping) { 35138c2ecf20Sopenharmony_ci /* The page got truncated from under us */ 35148c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 35158c2ecf20Sopenharmony_ci goto repeat; 35168c2ecf20Sopenharmony_ci } 35178c2ecf20Sopenharmony_ci } 35188c2ecf20Sopenharmony_ci 35198c2ecf20Sopenharmony_ci f2fs_wait_on_page_writeback(page, DATA, false, true); 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ci if (len == PAGE_SIZE || PageUptodate(page)) 35228c2ecf20Sopenharmony_ci return 0; 35238c2ecf20Sopenharmony_ci 35248c2ecf20Sopenharmony_ci if (!(pos & (PAGE_SIZE - 1)) && (pos + len) >= i_size_read(inode) && 35258c2ecf20Sopenharmony_ci !f2fs_verity_in_progress(inode)) { 35268c2ecf20Sopenharmony_ci zero_user_segment(page, len, PAGE_SIZE); 35278c2ecf20Sopenharmony_ci return 0; 35288c2ecf20Sopenharmony_ci } 35298c2ecf20Sopenharmony_ci 35308c2ecf20Sopenharmony_ci if (blkaddr == NEW_ADDR) { 35318c2ecf20Sopenharmony_ci zero_user_segment(page, 0, PAGE_SIZE); 35328c2ecf20Sopenharmony_ci SetPageUptodate(page); 35338c2ecf20Sopenharmony_ci } else { 35348c2ecf20Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, 35358c2ecf20Sopenharmony_ci DATA_GENERIC_ENHANCE_READ)) { 35368c2ecf20Sopenharmony_ci err = -EFSCORRUPTED; 35378c2ecf20Sopenharmony_ci goto fail; 35388c2ecf20Sopenharmony_ci } 35398c2ecf20Sopenharmony_ci err = f2fs_submit_page_read(inode, page, blkaddr, 0, true); 35408c2ecf20Sopenharmony_ci if (err) 35418c2ecf20Sopenharmony_ci goto fail; 35428c2ecf20Sopenharmony_ci 35438c2ecf20Sopenharmony_ci lock_page(page); 35448c2ecf20Sopenharmony_ci if (unlikely(page->mapping != mapping)) { 35458c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 35468c2ecf20Sopenharmony_ci goto repeat; 35478c2ecf20Sopenharmony_ci } 35488c2ecf20Sopenharmony_ci if (unlikely(!PageUptodate(page))) { 35498c2ecf20Sopenharmony_ci err = -EIO; 35508c2ecf20Sopenharmony_ci goto fail; 35518c2ecf20Sopenharmony_ci } 35528c2ecf20Sopenharmony_ci } 35538c2ecf20Sopenharmony_ci return 0; 35548c2ecf20Sopenharmony_ci 35558c2ecf20Sopenharmony_cifail: 35568c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 35578c2ecf20Sopenharmony_ci f2fs_write_failed(mapping, pos + len); 35588c2ecf20Sopenharmony_ci if (drop_atomic) 35598c2ecf20Sopenharmony_ci f2fs_drop_inmem_pages_all(sbi, false); 35608c2ecf20Sopenharmony_ci return err; 35618c2ecf20Sopenharmony_ci} 35628c2ecf20Sopenharmony_ci 35638c2ecf20Sopenharmony_cistatic int f2fs_write_end(struct file *file, 35648c2ecf20Sopenharmony_ci struct address_space *mapping, 35658c2ecf20Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, 35668c2ecf20Sopenharmony_ci struct page *page, void *fsdata) 35678c2ecf20Sopenharmony_ci{ 35688c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 35698c2ecf20Sopenharmony_ci 35708c2ecf20Sopenharmony_ci trace_f2fs_write_end(inode, pos, len, copied); 35718c2ecf20Sopenharmony_ci 35728c2ecf20Sopenharmony_ci /* 35738c2ecf20Sopenharmony_ci * This should be come from len == PAGE_SIZE, and we expect copied 35748c2ecf20Sopenharmony_ci * should be PAGE_SIZE. Otherwise, we treat it with zero copied and 35758c2ecf20Sopenharmony_ci * let generic_perform_write() try to copy data again through copied=0. 35768c2ecf20Sopenharmony_ci */ 35778c2ecf20Sopenharmony_ci if (!PageUptodate(page)) { 35788c2ecf20Sopenharmony_ci if (unlikely(copied != len)) 35798c2ecf20Sopenharmony_ci copied = 0; 35808c2ecf20Sopenharmony_ci else 35818c2ecf20Sopenharmony_ci SetPageUptodate(page); 35828c2ecf20Sopenharmony_ci } 35838c2ecf20Sopenharmony_ci 35848c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 35858c2ecf20Sopenharmony_ci /* overwrite compressed file */ 35868c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode) && fsdata) { 35878c2ecf20Sopenharmony_ci f2fs_compress_write_end(inode, fsdata, page->index, copied); 35888c2ecf20Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 35898c2ecf20Sopenharmony_ci 35908c2ecf20Sopenharmony_ci if (pos + copied > i_size_read(inode) && 35918c2ecf20Sopenharmony_ci !f2fs_verity_in_progress(inode)) 35928c2ecf20Sopenharmony_ci f2fs_i_size_write(inode, pos + copied); 35938c2ecf20Sopenharmony_ci return copied; 35948c2ecf20Sopenharmony_ci } 35958c2ecf20Sopenharmony_ci#endif 35968c2ecf20Sopenharmony_ci 35978c2ecf20Sopenharmony_ci if (!copied) 35988c2ecf20Sopenharmony_ci goto unlock_out; 35998c2ecf20Sopenharmony_ci 36008c2ecf20Sopenharmony_ci set_page_dirty(page); 36018c2ecf20Sopenharmony_ci 36028c2ecf20Sopenharmony_ci if (pos + copied > i_size_read(inode) && 36038c2ecf20Sopenharmony_ci !f2fs_verity_in_progress(inode)) 36048c2ecf20Sopenharmony_ci f2fs_i_size_write(inode, pos + copied); 36058c2ecf20Sopenharmony_ciunlock_out: 36068c2ecf20Sopenharmony_ci f2fs_put_page(page, 1); 36078c2ecf20Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 36088c2ecf20Sopenharmony_ci return copied; 36098c2ecf20Sopenharmony_ci} 36108c2ecf20Sopenharmony_ci 36118c2ecf20Sopenharmony_cistatic int check_direct_IO(struct inode *inode, struct iov_iter *iter, 36128c2ecf20Sopenharmony_ci loff_t offset) 36138c2ecf20Sopenharmony_ci{ 36148c2ecf20Sopenharmony_ci unsigned i_blkbits = READ_ONCE(inode->i_blkbits); 36158c2ecf20Sopenharmony_ci unsigned blkbits = i_blkbits; 36168c2ecf20Sopenharmony_ci unsigned blocksize_mask = (1 << blkbits) - 1; 36178c2ecf20Sopenharmony_ci unsigned long align = offset | iov_iter_alignment(iter); 36188c2ecf20Sopenharmony_ci struct block_device *bdev = inode->i_sb->s_bdev; 36198c2ecf20Sopenharmony_ci 36208c2ecf20Sopenharmony_ci if (iov_iter_rw(iter) == READ && offset >= i_size_read(inode)) 36218c2ecf20Sopenharmony_ci return 1; 36228c2ecf20Sopenharmony_ci 36238c2ecf20Sopenharmony_ci if (align & blocksize_mask) { 36248c2ecf20Sopenharmony_ci if (bdev) 36258c2ecf20Sopenharmony_ci blkbits = blksize_bits(bdev_logical_block_size(bdev)); 36268c2ecf20Sopenharmony_ci blocksize_mask = (1 << blkbits) - 1; 36278c2ecf20Sopenharmony_ci if (align & blocksize_mask) 36288c2ecf20Sopenharmony_ci return -EINVAL; 36298c2ecf20Sopenharmony_ci return 1; 36308c2ecf20Sopenharmony_ci } 36318c2ecf20Sopenharmony_ci return 0; 36328c2ecf20Sopenharmony_ci} 36338c2ecf20Sopenharmony_ci 36348c2ecf20Sopenharmony_cistatic void f2fs_dio_end_io(struct bio *bio) 36358c2ecf20Sopenharmony_ci{ 36368c2ecf20Sopenharmony_ci struct f2fs_private_dio *dio = bio->bi_private; 36378c2ecf20Sopenharmony_ci 36388c2ecf20Sopenharmony_ci dec_page_count(F2FS_I_SB(dio->inode), 36398c2ecf20Sopenharmony_ci dio->write ? F2FS_DIO_WRITE : F2FS_DIO_READ); 36408c2ecf20Sopenharmony_ci 36418c2ecf20Sopenharmony_ci bio->bi_private = dio->orig_private; 36428c2ecf20Sopenharmony_ci bio->bi_end_io = dio->orig_end_io; 36438c2ecf20Sopenharmony_ci 36448c2ecf20Sopenharmony_ci kfree(dio); 36458c2ecf20Sopenharmony_ci 36468c2ecf20Sopenharmony_ci bio_endio(bio); 36478c2ecf20Sopenharmony_ci} 36488c2ecf20Sopenharmony_ci 36498c2ecf20Sopenharmony_cistatic void f2fs_dio_submit_bio(struct bio *bio, struct inode *inode, 36508c2ecf20Sopenharmony_ci loff_t file_offset) 36518c2ecf20Sopenharmony_ci{ 36528c2ecf20Sopenharmony_ci struct f2fs_private_dio *dio; 36538c2ecf20Sopenharmony_ci bool write = (bio_op(bio) == REQ_OP_WRITE); 36548c2ecf20Sopenharmony_ci 36558c2ecf20Sopenharmony_ci dio = f2fs_kzalloc(F2FS_I_SB(inode), 36568c2ecf20Sopenharmony_ci sizeof(struct f2fs_private_dio), GFP_NOFS); 36578c2ecf20Sopenharmony_ci if (!dio) 36588c2ecf20Sopenharmony_ci goto out; 36598c2ecf20Sopenharmony_ci 36608c2ecf20Sopenharmony_ci dio->inode = inode; 36618c2ecf20Sopenharmony_ci dio->orig_end_io = bio->bi_end_io; 36628c2ecf20Sopenharmony_ci dio->orig_private = bio->bi_private; 36638c2ecf20Sopenharmony_ci dio->write = write; 36648c2ecf20Sopenharmony_ci 36658c2ecf20Sopenharmony_ci bio->bi_end_io = f2fs_dio_end_io; 36668c2ecf20Sopenharmony_ci bio->bi_private = dio; 36678c2ecf20Sopenharmony_ci 36688c2ecf20Sopenharmony_ci inc_page_count(F2FS_I_SB(inode), 36698c2ecf20Sopenharmony_ci write ? F2FS_DIO_WRITE : F2FS_DIO_READ); 36708c2ecf20Sopenharmony_ci 36718c2ecf20Sopenharmony_ci submit_bio(bio); 36728c2ecf20Sopenharmony_ci return; 36738c2ecf20Sopenharmony_ciout: 36748c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 36758c2ecf20Sopenharmony_ci bio_endio(bio); 36768c2ecf20Sopenharmony_ci} 36778c2ecf20Sopenharmony_ci 36788c2ecf20Sopenharmony_cistatic ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) 36798c2ecf20Sopenharmony_ci{ 36808c2ecf20Sopenharmony_ci struct address_space *mapping = iocb->ki_filp->f_mapping; 36818c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 36828c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 36838c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi = F2FS_I(inode); 36848c2ecf20Sopenharmony_ci size_t count = iov_iter_count(iter); 36858c2ecf20Sopenharmony_ci loff_t offset = iocb->ki_pos; 36868c2ecf20Sopenharmony_ci int rw = iov_iter_rw(iter); 36878c2ecf20Sopenharmony_ci int err; 36888c2ecf20Sopenharmony_ci enum rw_hint hint = iocb->ki_hint; 36898c2ecf20Sopenharmony_ci int whint_mode = F2FS_OPTION(sbi).whint_mode; 36908c2ecf20Sopenharmony_ci bool do_opu; 36918c2ecf20Sopenharmony_ci 36928c2ecf20Sopenharmony_ci err = check_direct_IO(inode, iter, offset); 36938c2ecf20Sopenharmony_ci if (err) 36948c2ecf20Sopenharmony_ci return err < 0 ? err : 0; 36958c2ecf20Sopenharmony_ci 36968c2ecf20Sopenharmony_ci if (f2fs_force_buffered_io(inode, iocb, iter)) 36978c2ecf20Sopenharmony_ci return 0; 36988c2ecf20Sopenharmony_ci 36998c2ecf20Sopenharmony_ci do_opu = allow_outplace_dio(inode, iocb, iter); 37008c2ecf20Sopenharmony_ci 37018c2ecf20Sopenharmony_ci trace_f2fs_direct_IO_enter(inode, offset, count, rw); 37028c2ecf20Sopenharmony_ci 37038c2ecf20Sopenharmony_ci if (rw == WRITE && whint_mode == WHINT_MODE_OFF) 37048c2ecf20Sopenharmony_ci iocb->ki_hint = WRITE_LIFE_NOT_SET; 37058c2ecf20Sopenharmony_ci 37068c2ecf20Sopenharmony_ci if (iocb->ki_flags & IOCB_NOWAIT) { 37078c2ecf20Sopenharmony_ci if (!down_read_trylock(&fi->i_gc_rwsem[rw])) { 37088c2ecf20Sopenharmony_ci iocb->ki_hint = hint; 37098c2ecf20Sopenharmony_ci err = -EAGAIN; 37108c2ecf20Sopenharmony_ci goto out; 37118c2ecf20Sopenharmony_ci } 37128c2ecf20Sopenharmony_ci if (do_opu && !down_read_trylock(&fi->i_gc_rwsem[READ])) { 37138c2ecf20Sopenharmony_ci up_read(&fi->i_gc_rwsem[rw]); 37148c2ecf20Sopenharmony_ci iocb->ki_hint = hint; 37158c2ecf20Sopenharmony_ci err = -EAGAIN; 37168c2ecf20Sopenharmony_ci goto out; 37178c2ecf20Sopenharmony_ci } 37188c2ecf20Sopenharmony_ci } else { 37198c2ecf20Sopenharmony_ci down_read(&fi->i_gc_rwsem[rw]); 37208c2ecf20Sopenharmony_ci if (do_opu) 37218c2ecf20Sopenharmony_ci down_read(&fi->i_gc_rwsem[READ]); 37228c2ecf20Sopenharmony_ci } 37238c2ecf20Sopenharmony_ci 37248c2ecf20Sopenharmony_ci err = __blockdev_direct_IO(iocb, inode, inode->i_sb->s_bdev, 37258c2ecf20Sopenharmony_ci iter, rw == WRITE ? get_data_block_dio_write : 37268c2ecf20Sopenharmony_ci get_data_block_dio, NULL, f2fs_dio_submit_bio, 37278c2ecf20Sopenharmony_ci rw == WRITE ? DIO_LOCKING | DIO_SKIP_HOLES : 37288c2ecf20Sopenharmony_ci DIO_SKIP_HOLES); 37298c2ecf20Sopenharmony_ci 37308c2ecf20Sopenharmony_ci if (do_opu) 37318c2ecf20Sopenharmony_ci up_read(&fi->i_gc_rwsem[READ]); 37328c2ecf20Sopenharmony_ci 37338c2ecf20Sopenharmony_ci up_read(&fi->i_gc_rwsem[rw]); 37348c2ecf20Sopenharmony_ci 37358c2ecf20Sopenharmony_ci if (rw == WRITE) { 37368c2ecf20Sopenharmony_ci if (whint_mode == WHINT_MODE_OFF) 37378c2ecf20Sopenharmony_ci iocb->ki_hint = hint; 37388c2ecf20Sopenharmony_ci if (err > 0) { 37398c2ecf20Sopenharmony_ci f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, 37408c2ecf20Sopenharmony_ci err); 37418c2ecf20Sopenharmony_ci if (!do_opu) 37428c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_UPDATE_WRITE); 37438c2ecf20Sopenharmony_ci } else if (err == -EIOCBQUEUED) { 37448c2ecf20Sopenharmony_ci f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_IO, 37458c2ecf20Sopenharmony_ci count - iov_iter_count(iter)); 37468c2ecf20Sopenharmony_ci } else if (err < 0) { 37478c2ecf20Sopenharmony_ci f2fs_write_failed(mapping, offset + count); 37488c2ecf20Sopenharmony_ci } 37498c2ecf20Sopenharmony_ci } else { 37508c2ecf20Sopenharmony_ci if (err > 0) 37518c2ecf20Sopenharmony_ci f2fs_update_iostat(sbi, APP_DIRECT_READ_IO, err); 37528c2ecf20Sopenharmony_ci else if (err == -EIOCBQUEUED) 37538c2ecf20Sopenharmony_ci f2fs_update_iostat(F2FS_I_SB(inode), APP_DIRECT_READ_IO, 37548c2ecf20Sopenharmony_ci count - iov_iter_count(iter)); 37558c2ecf20Sopenharmony_ci } 37568c2ecf20Sopenharmony_ci 37578c2ecf20Sopenharmony_ciout: 37588c2ecf20Sopenharmony_ci trace_f2fs_direct_IO_exit(inode, offset, count, rw, err); 37598c2ecf20Sopenharmony_ci 37608c2ecf20Sopenharmony_ci return err; 37618c2ecf20Sopenharmony_ci} 37628c2ecf20Sopenharmony_ci 37638c2ecf20Sopenharmony_civoid f2fs_invalidate_page(struct page *page, unsigned int offset, 37648c2ecf20Sopenharmony_ci unsigned int length) 37658c2ecf20Sopenharmony_ci{ 37668c2ecf20Sopenharmony_ci struct inode *inode = page->mapping->host; 37678c2ecf20Sopenharmony_ci struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 37688c2ecf20Sopenharmony_ci 37698c2ecf20Sopenharmony_ci if (inode->i_ino >= F2FS_ROOT_INO(sbi) && 37708c2ecf20Sopenharmony_ci (offset % PAGE_SIZE || length != PAGE_SIZE)) 37718c2ecf20Sopenharmony_ci return; 37728c2ecf20Sopenharmony_ci 37738c2ecf20Sopenharmony_ci if (PageDirty(page)) { 37748c2ecf20Sopenharmony_ci if (inode->i_ino == F2FS_META_INO(sbi)) { 37758c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_META); 37768c2ecf20Sopenharmony_ci } else if (inode->i_ino == F2FS_NODE_INO(sbi)) { 37778c2ecf20Sopenharmony_ci dec_page_count(sbi, F2FS_DIRTY_NODES); 37788c2ecf20Sopenharmony_ci } else { 37798c2ecf20Sopenharmony_ci inode_dec_dirty_pages(inode); 37808c2ecf20Sopenharmony_ci f2fs_remove_dirty_inode(inode); 37818c2ecf20Sopenharmony_ci } 37828c2ecf20Sopenharmony_ci } 37838c2ecf20Sopenharmony_ci 37848c2ecf20Sopenharmony_ci clear_cold_data(page); 37858c2ecf20Sopenharmony_ci 37868c2ecf20Sopenharmony_ci if (IS_ATOMIC_WRITTEN_PAGE(page)) 37878c2ecf20Sopenharmony_ci return f2fs_drop_inmem_page(inode, page); 37888c2ecf20Sopenharmony_ci 37898c2ecf20Sopenharmony_ci f2fs_clear_page_private(page); 37908c2ecf20Sopenharmony_ci} 37918c2ecf20Sopenharmony_ci 37928c2ecf20Sopenharmony_ciint f2fs_release_page(struct page *page, gfp_t wait) 37938c2ecf20Sopenharmony_ci{ 37948c2ecf20Sopenharmony_ci /* If this is dirty page, keep PagePrivate */ 37958c2ecf20Sopenharmony_ci if (PageDirty(page)) 37968c2ecf20Sopenharmony_ci return 0; 37978c2ecf20Sopenharmony_ci 37988c2ecf20Sopenharmony_ci /* This is atomic written page, keep Private */ 37998c2ecf20Sopenharmony_ci if (IS_ATOMIC_WRITTEN_PAGE(page)) 38008c2ecf20Sopenharmony_ci return 0; 38018c2ecf20Sopenharmony_ci 38028c2ecf20Sopenharmony_ci clear_cold_data(page); 38038c2ecf20Sopenharmony_ci f2fs_clear_page_private(page); 38048c2ecf20Sopenharmony_ci return 1; 38058c2ecf20Sopenharmony_ci} 38068c2ecf20Sopenharmony_ci 38078c2ecf20Sopenharmony_cistatic int f2fs_set_data_page_dirty(struct page *page) 38088c2ecf20Sopenharmony_ci{ 38098c2ecf20Sopenharmony_ci struct inode *inode = page_file_mapping(page)->host; 38108c2ecf20Sopenharmony_ci 38118c2ecf20Sopenharmony_ci trace_f2fs_set_page_dirty(page, DATA); 38128c2ecf20Sopenharmony_ci 38138c2ecf20Sopenharmony_ci if (!PageUptodate(page)) 38148c2ecf20Sopenharmony_ci SetPageUptodate(page); 38158c2ecf20Sopenharmony_ci if (PageSwapCache(page)) 38168c2ecf20Sopenharmony_ci return __set_page_dirty_nobuffers(page); 38178c2ecf20Sopenharmony_ci 38188c2ecf20Sopenharmony_ci if (f2fs_is_atomic_file(inode) && !f2fs_is_commit_atomic_write(inode)) { 38198c2ecf20Sopenharmony_ci if (!IS_ATOMIC_WRITTEN_PAGE(page)) { 38208c2ecf20Sopenharmony_ci f2fs_register_inmem_page(inode, page); 38218c2ecf20Sopenharmony_ci return 1; 38228c2ecf20Sopenharmony_ci } 38238c2ecf20Sopenharmony_ci /* 38248c2ecf20Sopenharmony_ci * Previously, this page has been registered, we just 38258c2ecf20Sopenharmony_ci * return here. 38268c2ecf20Sopenharmony_ci */ 38278c2ecf20Sopenharmony_ci return 0; 38288c2ecf20Sopenharmony_ci } 38298c2ecf20Sopenharmony_ci 38308c2ecf20Sopenharmony_ci if (!PageDirty(page)) { 38318c2ecf20Sopenharmony_ci __set_page_dirty_nobuffers(page); 38328c2ecf20Sopenharmony_ci f2fs_update_dirty_page(inode, page); 38338c2ecf20Sopenharmony_ci return 1; 38348c2ecf20Sopenharmony_ci } 38358c2ecf20Sopenharmony_ci return 0; 38368c2ecf20Sopenharmony_ci} 38378c2ecf20Sopenharmony_ci 38388c2ecf20Sopenharmony_ci 38398c2ecf20Sopenharmony_cistatic sector_t f2fs_bmap_compress(struct inode *inode, sector_t block) 38408c2ecf20Sopenharmony_ci{ 38418c2ecf20Sopenharmony_ci#ifdef CONFIG_F2FS_FS_COMPRESSION 38428c2ecf20Sopenharmony_ci struct dnode_of_data dn; 38438c2ecf20Sopenharmony_ci sector_t start_idx, blknr = 0; 38448c2ecf20Sopenharmony_ci int ret; 38458c2ecf20Sopenharmony_ci 38468c2ecf20Sopenharmony_ci start_idx = round_down(block, F2FS_I(inode)->i_cluster_size); 38478c2ecf20Sopenharmony_ci 38488c2ecf20Sopenharmony_ci set_new_dnode(&dn, inode, NULL, NULL, 0); 38498c2ecf20Sopenharmony_ci ret = f2fs_get_dnode_of_data(&dn, start_idx, LOOKUP_NODE); 38508c2ecf20Sopenharmony_ci if (ret) 38518c2ecf20Sopenharmony_ci return 0; 38528c2ecf20Sopenharmony_ci 38538c2ecf20Sopenharmony_ci if (dn.data_blkaddr != COMPRESS_ADDR) { 38548c2ecf20Sopenharmony_ci dn.ofs_in_node += block - start_idx; 38558c2ecf20Sopenharmony_ci blknr = f2fs_data_blkaddr(&dn); 38568c2ecf20Sopenharmony_ci if (!__is_valid_data_blkaddr(blknr)) 38578c2ecf20Sopenharmony_ci blknr = 0; 38588c2ecf20Sopenharmony_ci } 38598c2ecf20Sopenharmony_ci 38608c2ecf20Sopenharmony_ci f2fs_put_dnode(&dn); 38618c2ecf20Sopenharmony_ci return blknr; 38628c2ecf20Sopenharmony_ci#else 38638c2ecf20Sopenharmony_ci return 0; 38648c2ecf20Sopenharmony_ci#endif 38658c2ecf20Sopenharmony_ci} 38668c2ecf20Sopenharmony_ci 38678c2ecf20Sopenharmony_ci 38688c2ecf20Sopenharmony_cistatic sector_t f2fs_bmap(struct address_space *mapping, sector_t block) 38698c2ecf20Sopenharmony_ci{ 38708c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 38718c2ecf20Sopenharmony_ci struct buffer_head tmp = { 38728c2ecf20Sopenharmony_ci .b_size = i_blocksize(inode), 38738c2ecf20Sopenharmony_ci }; 38748c2ecf20Sopenharmony_ci sector_t blknr = 0; 38758c2ecf20Sopenharmony_ci 38768c2ecf20Sopenharmony_ci if (f2fs_has_inline_data(inode)) 38778c2ecf20Sopenharmony_ci goto out; 38788c2ecf20Sopenharmony_ci 38798c2ecf20Sopenharmony_ci /* make sure allocating whole blocks */ 38808c2ecf20Sopenharmony_ci if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY)) 38818c2ecf20Sopenharmony_ci filemap_write_and_wait(mapping); 38828c2ecf20Sopenharmony_ci 38838c2ecf20Sopenharmony_ci /* Block number less than F2FS MAX BLOCKS */ 38848c2ecf20Sopenharmony_ci if (unlikely(block >= F2FS_I_SB(inode)->max_file_blocks)) 38858c2ecf20Sopenharmony_ci goto out; 38868c2ecf20Sopenharmony_ci 38878c2ecf20Sopenharmony_ci if (f2fs_compressed_file(inode)) { 38888c2ecf20Sopenharmony_ci blknr = f2fs_bmap_compress(inode, block); 38898c2ecf20Sopenharmony_ci } else { 38908c2ecf20Sopenharmony_ci if (!get_data_block_bmap(inode, block, &tmp, 0)) 38918c2ecf20Sopenharmony_ci blknr = tmp.b_blocknr; 38928c2ecf20Sopenharmony_ci } 38938c2ecf20Sopenharmony_ciout: 38948c2ecf20Sopenharmony_ci trace_f2fs_bmap(inode, block, blknr); 38958c2ecf20Sopenharmony_ci return blknr; 38968c2ecf20Sopenharmony_ci} 38978c2ecf20Sopenharmony_ci 38988c2ecf20Sopenharmony_ci#ifdef CONFIG_MIGRATION 38998c2ecf20Sopenharmony_ci#include <linux/migrate.h> 39008c2ecf20Sopenharmony_ci 39018c2ecf20Sopenharmony_ciint f2fs_migrate_page(struct address_space *mapping, 39028c2ecf20Sopenharmony_ci struct page *newpage, struct page *page, enum migrate_mode mode) 39038c2ecf20Sopenharmony_ci{ 39048c2ecf20Sopenharmony_ci int rc, extra_count; 39058c2ecf20Sopenharmony_ci struct f2fs_inode_info *fi = F2FS_I(mapping->host); 39068c2ecf20Sopenharmony_ci bool atomic_written = IS_ATOMIC_WRITTEN_PAGE(page); 39078c2ecf20Sopenharmony_ci 39088c2ecf20Sopenharmony_ci BUG_ON(PageWriteback(page)); 39098c2ecf20Sopenharmony_ci 39108c2ecf20Sopenharmony_ci /* migrating an atomic written page is safe with the inmem_lock hold */ 39118c2ecf20Sopenharmony_ci if (atomic_written) { 39128c2ecf20Sopenharmony_ci if (mode != MIGRATE_SYNC) 39138c2ecf20Sopenharmony_ci return -EBUSY; 39148c2ecf20Sopenharmony_ci if (!mutex_trylock(&fi->inmem_lock)) 39158c2ecf20Sopenharmony_ci return -EAGAIN; 39168c2ecf20Sopenharmony_ci } 39178c2ecf20Sopenharmony_ci 39188c2ecf20Sopenharmony_ci /* one extra reference was held for atomic_write page */ 39198c2ecf20Sopenharmony_ci extra_count = atomic_written ? 1 : 0; 39208c2ecf20Sopenharmony_ci rc = migrate_page_move_mapping(mapping, newpage, 39218c2ecf20Sopenharmony_ci page, extra_count); 39228c2ecf20Sopenharmony_ci if (rc != MIGRATEPAGE_SUCCESS) { 39238c2ecf20Sopenharmony_ci if (atomic_written) 39248c2ecf20Sopenharmony_ci mutex_unlock(&fi->inmem_lock); 39258c2ecf20Sopenharmony_ci return rc; 39268c2ecf20Sopenharmony_ci } 39278c2ecf20Sopenharmony_ci 39288c2ecf20Sopenharmony_ci if (atomic_written) { 39298c2ecf20Sopenharmony_ci struct inmem_pages *cur; 39308c2ecf20Sopenharmony_ci list_for_each_entry(cur, &fi->inmem_pages, list) 39318c2ecf20Sopenharmony_ci if (cur->page == page) { 39328c2ecf20Sopenharmony_ci cur->page = newpage; 39338c2ecf20Sopenharmony_ci break; 39348c2ecf20Sopenharmony_ci } 39358c2ecf20Sopenharmony_ci mutex_unlock(&fi->inmem_lock); 39368c2ecf20Sopenharmony_ci put_page(page); 39378c2ecf20Sopenharmony_ci get_page(newpage); 39388c2ecf20Sopenharmony_ci } 39398c2ecf20Sopenharmony_ci 39408c2ecf20Sopenharmony_ci if (PagePrivate(page)) { 39418c2ecf20Sopenharmony_ci f2fs_set_page_private(newpage, page_private(page)); 39428c2ecf20Sopenharmony_ci f2fs_clear_page_private(page); 39438c2ecf20Sopenharmony_ci } 39448c2ecf20Sopenharmony_ci 39458c2ecf20Sopenharmony_ci if (mode != MIGRATE_SYNC_NO_COPY) 39468c2ecf20Sopenharmony_ci migrate_page_copy(newpage, page); 39478c2ecf20Sopenharmony_ci else 39488c2ecf20Sopenharmony_ci migrate_page_states(newpage, page); 39498c2ecf20Sopenharmony_ci 39508c2ecf20Sopenharmony_ci return MIGRATEPAGE_SUCCESS; 39518c2ecf20Sopenharmony_ci} 39528c2ecf20Sopenharmony_ci#endif 39538c2ecf20Sopenharmony_ci 39548c2ecf20Sopenharmony_ci#ifdef CONFIG_SWAP 39558c2ecf20Sopenharmony_cistatic int check_swap_activate_fast(struct swap_info_struct *sis, 39568c2ecf20Sopenharmony_ci struct file *swap_file, sector_t *span) 39578c2ecf20Sopenharmony_ci{ 39588c2ecf20Sopenharmony_ci struct address_space *mapping = swap_file->f_mapping; 39598c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 39608c2ecf20Sopenharmony_ci sector_t cur_lblock; 39618c2ecf20Sopenharmony_ci sector_t last_lblock; 39628c2ecf20Sopenharmony_ci sector_t pblock; 39638c2ecf20Sopenharmony_ci sector_t lowest_pblock = -1; 39648c2ecf20Sopenharmony_ci sector_t highest_pblock = 0; 39658c2ecf20Sopenharmony_ci int nr_extents = 0; 39668c2ecf20Sopenharmony_ci unsigned long nr_pblocks; 39678c2ecf20Sopenharmony_ci unsigned long len; 39688c2ecf20Sopenharmony_ci int ret; 39698c2ecf20Sopenharmony_ci 39708c2ecf20Sopenharmony_ci /* 39718c2ecf20Sopenharmony_ci * Map all the blocks into the extent list. This code doesn't try 39728c2ecf20Sopenharmony_ci * to be very smart. 39738c2ecf20Sopenharmony_ci */ 39748c2ecf20Sopenharmony_ci cur_lblock = 0; 39758c2ecf20Sopenharmony_ci last_lblock = logical_to_blk(inode, i_size_read(inode)); 39768c2ecf20Sopenharmony_ci len = i_size_read(inode); 39778c2ecf20Sopenharmony_ci 39788c2ecf20Sopenharmony_ci while (cur_lblock <= last_lblock && cur_lblock < sis->max) { 39798c2ecf20Sopenharmony_ci struct buffer_head map_bh; 39808c2ecf20Sopenharmony_ci pgoff_t next_pgofs; 39818c2ecf20Sopenharmony_ci 39828c2ecf20Sopenharmony_ci cond_resched(); 39838c2ecf20Sopenharmony_ci 39848c2ecf20Sopenharmony_ci memset(&map_bh, 0, sizeof(struct buffer_head)); 39858c2ecf20Sopenharmony_ci map_bh.b_size = len - cur_lblock; 39868c2ecf20Sopenharmony_ci 39878c2ecf20Sopenharmony_ci ret = get_data_block(inode, cur_lblock, &map_bh, 0, 39888c2ecf20Sopenharmony_ci F2FS_GET_BLOCK_FIEMAP, &next_pgofs); 39898c2ecf20Sopenharmony_ci if (ret) 39908c2ecf20Sopenharmony_ci goto err_out; 39918c2ecf20Sopenharmony_ci 39928c2ecf20Sopenharmony_ci /* hole */ 39938c2ecf20Sopenharmony_ci if (!buffer_mapped(&map_bh)) 39948c2ecf20Sopenharmony_ci goto err_out; 39958c2ecf20Sopenharmony_ci 39968c2ecf20Sopenharmony_ci pblock = map_bh.b_blocknr; 39978c2ecf20Sopenharmony_ci nr_pblocks = logical_to_blk(inode, map_bh.b_size); 39988c2ecf20Sopenharmony_ci 39998c2ecf20Sopenharmony_ci if (cur_lblock + nr_pblocks >= sis->max) 40008c2ecf20Sopenharmony_ci nr_pblocks = sis->max - cur_lblock; 40018c2ecf20Sopenharmony_ci 40028c2ecf20Sopenharmony_ci if (cur_lblock) { /* exclude the header page */ 40038c2ecf20Sopenharmony_ci if (pblock < lowest_pblock) 40048c2ecf20Sopenharmony_ci lowest_pblock = pblock; 40058c2ecf20Sopenharmony_ci if (pblock + nr_pblocks - 1 > highest_pblock) 40068c2ecf20Sopenharmony_ci highest_pblock = pblock + nr_pblocks - 1; 40078c2ecf20Sopenharmony_ci } 40088c2ecf20Sopenharmony_ci 40098c2ecf20Sopenharmony_ci /* 40108c2ecf20Sopenharmony_ci * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks 40118c2ecf20Sopenharmony_ci */ 40128c2ecf20Sopenharmony_ci ret = add_swap_extent(sis, cur_lblock, nr_pblocks, pblock); 40138c2ecf20Sopenharmony_ci if (ret < 0) 40148c2ecf20Sopenharmony_ci goto out; 40158c2ecf20Sopenharmony_ci nr_extents += ret; 40168c2ecf20Sopenharmony_ci cur_lblock += nr_pblocks; 40178c2ecf20Sopenharmony_ci } 40188c2ecf20Sopenharmony_ci ret = nr_extents; 40198c2ecf20Sopenharmony_ci *span = 1 + highest_pblock - lowest_pblock; 40208c2ecf20Sopenharmony_ci if (cur_lblock == 0) 40218c2ecf20Sopenharmony_ci cur_lblock = 1; /* force Empty message */ 40228c2ecf20Sopenharmony_ci sis->max = cur_lblock; 40238c2ecf20Sopenharmony_ci sis->pages = cur_lblock - 1; 40248c2ecf20Sopenharmony_ci sis->highest_bit = cur_lblock - 1; 40258c2ecf20Sopenharmony_ciout: 40268c2ecf20Sopenharmony_ci return ret; 40278c2ecf20Sopenharmony_cierr_out: 40288c2ecf20Sopenharmony_ci pr_err("swapon: swapfile has holes\n"); 40298c2ecf20Sopenharmony_ci return -EINVAL; 40308c2ecf20Sopenharmony_ci} 40318c2ecf20Sopenharmony_ci 40328c2ecf20Sopenharmony_ci/* Copied from generic_swapfile_activate() to check any holes */ 40338c2ecf20Sopenharmony_cistatic int check_swap_activate(struct swap_info_struct *sis, 40348c2ecf20Sopenharmony_ci struct file *swap_file, sector_t *span) 40358c2ecf20Sopenharmony_ci{ 40368c2ecf20Sopenharmony_ci struct address_space *mapping = swap_file->f_mapping; 40378c2ecf20Sopenharmony_ci struct inode *inode = mapping->host; 40388c2ecf20Sopenharmony_ci unsigned blocks_per_page; 40398c2ecf20Sopenharmony_ci unsigned long page_no; 40408c2ecf20Sopenharmony_ci unsigned blkbits; 40418c2ecf20Sopenharmony_ci sector_t probe_block; 40428c2ecf20Sopenharmony_ci sector_t last_block; 40438c2ecf20Sopenharmony_ci sector_t lowest_block = -1; 40448c2ecf20Sopenharmony_ci sector_t highest_block = 0; 40458c2ecf20Sopenharmony_ci int nr_extents = 0; 40468c2ecf20Sopenharmony_ci int ret; 40478c2ecf20Sopenharmony_ci 40488c2ecf20Sopenharmony_ci if (PAGE_SIZE == F2FS_BLKSIZE) 40498c2ecf20Sopenharmony_ci return check_swap_activate_fast(sis, swap_file, span); 40508c2ecf20Sopenharmony_ci 40518c2ecf20Sopenharmony_ci blkbits = inode->i_blkbits; 40528c2ecf20Sopenharmony_ci blocks_per_page = PAGE_SIZE >> blkbits; 40538c2ecf20Sopenharmony_ci 40548c2ecf20Sopenharmony_ci /* 40558c2ecf20Sopenharmony_ci * Map all the blocks into the extent list. This code doesn't try 40568c2ecf20Sopenharmony_ci * to be very smart. 40578c2ecf20Sopenharmony_ci */ 40588c2ecf20Sopenharmony_ci probe_block = 0; 40598c2ecf20Sopenharmony_ci page_no = 0; 40608c2ecf20Sopenharmony_ci last_block = i_size_read(inode) >> blkbits; 40618c2ecf20Sopenharmony_ci while ((probe_block + blocks_per_page) <= last_block && 40628c2ecf20Sopenharmony_ci page_no < sis->max) { 40638c2ecf20Sopenharmony_ci unsigned block_in_page; 40648c2ecf20Sopenharmony_ci sector_t first_block; 40658c2ecf20Sopenharmony_ci sector_t block = 0; 40668c2ecf20Sopenharmony_ci int err = 0; 40678c2ecf20Sopenharmony_ci 40688c2ecf20Sopenharmony_ci cond_resched(); 40698c2ecf20Sopenharmony_ci 40708c2ecf20Sopenharmony_ci block = probe_block; 40718c2ecf20Sopenharmony_ci err = bmap(inode, &block); 40728c2ecf20Sopenharmony_ci if (err || !block) 40738c2ecf20Sopenharmony_ci goto bad_bmap; 40748c2ecf20Sopenharmony_ci first_block = block; 40758c2ecf20Sopenharmony_ci 40768c2ecf20Sopenharmony_ci /* 40778c2ecf20Sopenharmony_ci * It must be PAGE_SIZE aligned on-disk 40788c2ecf20Sopenharmony_ci */ 40798c2ecf20Sopenharmony_ci if (first_block & (blocks_per_page - 1)) { 40808c2ecf20Sopenharmony_ci probe_block++; 40818c2ecf20Sopenharmony_ci goto reprobe; 40828c2ecf20Sopenharmony_ci } 40838c2ecf20Sopenharmony_ci 40848c2ecf20Sopenharmony_ci for (block_in_page = 1; block_in_page < blocks_per_page; 40858c2ecf20Sopenharmony_ci block_in_page++) { 40868c2ecf20Sopenharmony_ci 40878c2ecf20Sopenharmony_ci block = probe_block + block_in_page; 40888c2ecf20Sopenharmony_ci err = bmap(inode, &block); 40898c2ecf20Sopenharmony_ci 40908c2ecf20Sopenharmony_ci if (err || !block) 40918c2ecf20Sopenharmony_ci goto bad_bmap; 40928c2ecf20Sopenharmony_ci 40938c2ecf20Sopenharmony_ci if (block != first_block + block_in_page) { 40948c2ecf20Sopenharmony_ci /* Discontiguity */ 40958c2ecf20Sopenharmony_ci probe_block++; 40968c2ecf20Sopenharmony_ci goto reprobe; 40978c2ecf20Sopenharmony_ci } 40988c2ecf20Sopenharmony_ci } 40998c2ecf20Sopenharmony_ci 41008c2ecf20Sopenharmony_ci first_block >>= (PAGE_SHIFT - blkbits); 41018c2ecf20Sopenharmony_ci if (page_no) { /* exclude the header page */ 41028c2ecf20Sopenharmony_ci if (first_block < lowest_block) 41038c2ecf20Sopenharmony_ci lowest_block = first_block; 41048c2ecf20Sopenharmony_ci if (first_block > highest_block) 41058c2ecf20Sopenharmony_ci highest_block = first_block; 41068c2ecf20Sopenharmony_ci } 41078c2ecf20Sopenharmony_ci 41088c2ecf20Sopenharmony_ci /* 41098c2ecf20Sopenharmony_ci * We found a PAGE_SIZE-length, PAGE_SIZE-aligned run of blocks 41108c2ecf20Sopenharmony_ci */ 41118c2ecf20Sopenharmony_ci ret = add_swap_extent(sis, page_no, 1, first_block); 41128c2ecf20Sopenharmony_ci if (ret < 0) 41138c2ecf20Sopenharmony_ci goto out; 41148c2ecf20Sopenharmony_ci nr_extents += ret; 41158c2ecf20Sopenharmony_ci page_no++; 41168c2ecf20Sopenharmony_ci probe_block += blocks_per_page; 41178c2ecf20Sopenharmony_cireprobe: 41188c2ecf20Sopenharmony_ci continue; 41198c2ecf20Sopenharmony_ci } 41208c2ecf20Sopenharmony_ci ret = nr_extents; 41218c2ecf20Sopenharmony_ci *span = 1 + highest_block - lowest_block; 41228c2ecf20Sopenharmony_ci if (page_no == 0) 41238c2ecf20Sopenharmony_ci page_no = 1; /* force Empty message */ 41248c2ecf20Sopenharmony_ci sis->max = page_no; 41258c2ecf20Sopenharmony_ci sis->pages = page_no - 1; 41268c2ecf20Sopenharmony_ci sis->highest_bit = page_no - 1; 41278c2ecf20Sopenharmony_ciout: 41288c2ecf20Sopenharmony_ci return ret; 41298c2ecf20Sopenharmony_cibad_bmap: 41308c2ecf20Sopenharmony_ci pr_err("swapon: swapfile has holes\n"); 41318c2ecf20Sopenharmony_ci return -EINVAL; 41328c2ecf20Sopenharmony_ci} 41338c2ecf20Sopenharmony_ci 41348c2ecf20Sopenharmony_cistatic int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, 41358c2ecf20Sopenharmony_ci sector_t *span) 41368c2ecf20Sopenharmony_ci{ 41378c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 41388c2ecf20Sopenharmony_ci int ret; 41398c2ecf20Sopenharmony_ci 41408c2ecf20Sopenharmony_ci if (!S_ISREG(inode->i_mode)) 41418c2ecf20Sopenharmony_ci return -EINVAL; 41428c2ecf20Sopenharmony_ci 41438c2ecf20Sopenharmony_ci if (f2fs_readonly(F2FS_I_SB(inode)->sb)) 41448c2ecf20Sopenharmony_ci return -EROFS; 41458c2ecf20Sopenharmony_ci 41468c2ecf20Sopenharmony_ci if (f2fs_lfs_mode(F2FS_I_SB(inode))) { 41478c2ecf20Sopenharmony_ci f2fs_err(F2FS_I_SB(inode), 41488c2ecf20Sopenharmony_ci "Swapfile not supported in LFS mode"); 41498c2ecf20Sopenharmony_ci return -EINVAL; 41508c2ecf20Sopenharmony_ci } 41518c2ecf20Sopenharmony_ci 41528c2ecf20Sopenharmony_ci ret = f2fs_convert_inline_inode(inode); 41538c2ecf20Sopenharmony_ci if (ret) 41548c2ecf20Sopenharmony_ci return ret; 41558c2ecf20Sopenharmony_ci 41568c2ecf20Sopenharmony_ci if (!f2fs_disable_compressed_file(inode)) 41578c2ecf20Sopenharmony_ci return -EINVAL; 41588c2ecf20Sopenharmony_ci 41598c2ecf20Sopenharmony_ci ret = check_swap_activate(sis, file, span); 41608c2ecf20Sopenharmony_ci if (ret < 0) 41618c2ecf20Sopenharmony_ci return ret; 41628c2ecf20Sopenharmony_ci 41638c2ecf20Sopenharmony_ci set_inode_flag(inode, FI_PIN_FILE); 41648c2ecf20Sopenharmony_ci f2fs_precache_extents(inode); 41658c2ecf20Sopenharmony_ci f2fs_update_time(F2FS_I_SB(inode), REQ_TIME); 41668c2ecf20Sopenharmony_ci return ret; 41678c2ecf20Sopenharmony_ci} 41688c2ecf20Sopenharmony_ci 41698c2ecf20Sopenharmony_cistatic void f2fs_swap_deactivate(struct file *file) 41708c2ecf20Sopenharmony_ci{ 41718c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 41728c2ecf20Sopenharmony_ci 41738c2ecf20Sopenharmony_ci clear_inode_flag(inode, FI_PIN_FILE); 41748c2ecf20Sopenharmony_ci} 41758c2ecf20Sopenharmony_ci#else 41768c2ecf20Sopenharmony_cistatic int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, 41778c2ecf20Sopenharmony_ci sector_t *span) 41788c2ecf20Sopenharmony_ci{ 41798c2ecf20Sopenharmony_ci return -EOPNOTSUPP; 41808c2ecf20Sopenharmony_ci} 41818c2ecf20Sopenharmony_ci 41828c2ecf20Sopenharmony_cistatic void f2fs_swap_deactivate(struct file *file) 41838c2ecf20Sopenharmony_ci{ 41848c2ecf20Sopenharmony_ci} 41858c2ecf20Sopenharmony_ci#endif 41868c2ecf20Sopenharmony_ci 41878c2ecf20Sopenharmony_ciconst struct address_space_operations f2fs_dblock_aops = { 41888c2ecf20Sopenharmony_ci .readpage = f2fs_read_data_page, 41898c2ecf20Sopenharmony_ci .readahead = f2fs_readahead, 41908c2ecf20Sopenharmony_ci .writepage = f2fs_write_data_page, 41918c2ecf20Sopenharmony_ci .writepages = f2fs_write_data_pages, 41928c2ecf20Sopenharmony_ci .write_begin = f2fs_write_begin, 41938c2ecf20Sopenharmony_ci .write_end = f2fs_write_end, 41948c2ecf20Sopenharmony_ci .set_page_dirty = f2fs_set_data_page_dirty, 41958c2ecf20Sopenharmony_ci .invalidatepage = f2fs_invalidate_page, 41968c2ecf20Sopenharmony_ci .releasepage = f2fs_release_page, 41978c2ecf20Sopenharmony_ci .direct_IO = f2fs_direct_IO, 41988c2ecf20Sopenharmony_ci .bmap = f2fs_bmap, 41998c2ecf20Sopenharmony_ci .swap_activate = f2fs_swap_activate, 42008c2ecf20Sopenharmony_ci .swap_deactivate = f2fs_swap_deactivate, 42018c2ecf20Sopenharmony_ci#ifdef CONFIG_MIGRATION 42028c2ecf20Sopenharmony_ci .migratepage = f2fs_migrate_page, 42038c2ecf20Sopenharmony_ci#endif 42048c2ecf20Sopenharmony_ci}; 42058c2ecf20Sopenharmony_ci 42068c2ecf20Sopenharmony_civoid f2fs_clear_page_cache_dirty_tag(struct page *page) 42078c2ecf20Sopenharmony_ci{ 42088c2ecf20Sopenharmony_ci struct address_space *mapping = page_mapping(page); 42098c2ecf20Sopenharmony_ci unsigned long flags; 42108c2ecf20Sopenharmony_ci 42118c2ecf20Sopenharmony_ci xa_lock_irqsave(&mapping->i_pages, flags); 42128c2ecf20Sopenharmony_ci __xa_clear_mark(&mapping->i_pages, page_index(page), 42138c2ecf20Sopenharmony_ci PAGECACHE_TAG_DIRTY); 42148c2ecf20Sopenharmony_ci xa_unlock_irqrestore(&mapping->i_pages, flags); 42158c2ecf20Sopenharmony_ci} 42168c2ecf20Sopenharmony_ci 42178c2ecf20Sopenharmony_ciint __init f2fs_init_post_read_processing(void) 42188c2ecf20Sopenharmony_ci{ 42198c2ecf20Sopenharmony_ci bio_post_read_ctx_cache = 42208c2ecf20Sopenharmony_ci kmem_cache_create("f2fs_bio_post_read_ctx", 42218c2ecf20Sopenharmony_ci sizeof(struct bio_post_read_ctx), 0, 0, NULL); 42228c2ecf20Sopenharmony_ci if (!bio_post_read_ctx_cache) 42238c2ecf20Sopenharmony_ci goto fail; 42248c2ecf20Sopenharmony_ci bio_post_read_ctx_pool = 42258c2ecf20Sopenharmony_ci mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, 42268c2ecf20Sopenharmony_ci bio_post_read_ctx_cache); 42278c2ecf20Sopenharmony_ci if (!bio_post_read_ctx_pool) 42288c2ecf20Sopenharmony_ci goto fail_free_cache; 42298c2ecf20Sopenharmony_ci return 0; 42308c2ecf20Sopenharmony_ci 42318c2ecf20Sopenharmony_cifail_free_cache: 42328c2ecf20Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 42338c2ecf20Sopenharmony_cifail: 42348c2ecf20Sopenharmony_ci return -ENOMEM; 42358c2ecf20Sopenharmony_ci} 42368c2ecf20Sopenharmony_ci 42378c2ecf20Sopenharmony_civoid f2fs_destroy_post_read_processing(void) 42388c2ecf20Sopenharmony_ci{ 42398c2ecf20Sopenharmony_ci mempool_destroy(bio_post_read_ctx_pool); 42408c2ecf20Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 42418c2ecf20Sopenharmony_ci} 42428c2ecf20Sopenharmony_ci 42438c2ecf20Sopenharmony_ciint f2fs_init_post_read_wq(struct f2fs_sb_info *sbi) 42448c2ecf20Sopenharmony_ci{ 42458c2ecf20Sopenharmony_ci if (!f2fs_sb_has_encrypt(sbi) && 42468c2ecf20Sopenharmony_ci !f2fs_sb_has_verity(sbi) && 42478c2ecf20Sopenharmony_ci !f2fs_sb_has_compression(sbi)) 42488c2ecf20Sopenharmony_ci return 0; 42498c2ecf20Sopenharmony_ci 42508c2ecf20Sopenharmony_ci sbi->post_read_wq = alloc_workqueue("f2fs_post_read_wq", 42518c2ecf20Sopenharmony_ci WQ_UNBOUND | WQ_HIGHPRI, 42528c2ecf20Sopenharmony_ci num_online_cpus()); 42538c2ecf20Sopenharmony_ci if (!sbi->post_read_wq) 42548c2ecf20Sopenharmony_ci return -ENOMEM; 42558c2ecf20Sopenharmony_ci return 0; 42568c2ecf20Sopenharmony_ci} 42578c2ecf20Sopenharmony_ci 42588c2ecf20Sopenharmony_civoid f2fs_destroy_post_read_wq(struct f2fs_sb_info *sbi) 42598c2ecf20Sopenharmony_ci{ 42608c2ecf20Sopenharmony_ci if (sbi->post_read_wq) 42618c2ecf20Sopenharmony_ci destroy_workqueue(sbi->post_read_wq); 42628c2ecf20Sopenharmony_ci} 42638c2ecf20Sopenharmony_ci 42648c2ecf20Sopenharmony_ciint __init f2fs_init_bio_entry_cache(void) 42658c2ecf20Sopenharmony_ci{ 42668c2ecf20Sopenharmony_ci bio_entry_slab = f2fs_kmem_cache_create("f2fs_bio_entry_slab", 42678c2ecf20Sopenharmony_ci sizeof(struct bio_entry)); 42688c2ecf20Sopenharmony_ci if (!bio_entry_slab) 42698c2ecf20Sopenharmony_ci return -ENOMEM; 42708c2ecf20Sopenharmony_ci return 0; 42718c2ecf20Sopenharmony_ci} 42728c2ecf20Sopenharmony_ci 42738c2ecf20Sopenharmony_civoid f2fs_destroy_bio_entry_cache(void) 42748c2ecf20Sopenharmony_ci{ 42758c2ecf20Sopenharmony_ci kmem_cache_destroy(bio_entry_slab); 42768c2ecf20Sopenharmony_ci} 4277