162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * linux/fs/ext4/readpage.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2002, Linus Torvalds. 662306a36Sopenharmony_ci * Copyright (C) 2015, Google, Inc. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * This was originally taken from fs/mpage.c 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * The ext4_mpage_readpages() function here is intended to 1162306a36Sopenharmony_ci * replace mpage_readahead() in the general case, not just for 1262306a36Sopenharmony_ci * encrypted files. It has some limitations (see below), where it 1362306a36Sopenharmony_ci * will fall back to read_block_full_page(), but these limitations 1462306a36Sopenharmony_ci * should only be hit when page_size != block_size. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * This will allow us to attach a callback function to support ext4 1762306a36Sopenharmony_ci * encryption. 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * If anything unusual happens, such as: 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * - encountering a page which has buffers 2262306a36Sopenharmony_ci * - encountering a page which has a non-hole after a hole 2362306a36Sopenharmony_ci * - encountering a page with non-contiguous blocks 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * then this code just gives up and calls the buffer_head-based read function. 2662306a36Sopenharmony_ci * It does handle a page which has holes at the end - that is a common case: 2762306a36Sopenharmony_ci * the end-of-file on blocksize < PAGE_SIZE setups. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci */ 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#include <linux/kernel.h> 3262306a36Sopenharmony_ci#include <linux/export.h> 3362306a36Sopenharmony_ci#include <linux/mm.h> 3462306a36Sopenharmony_ci#include <linux/kdev_t.h> 3562306a36Sopenharmony_ci#include <linux/gfp.h> 3662306a36Sopenharmony_ci#include <linux/bio.h> 3762306a36Sopenharmony_ci#include <linux/fs.h> 3862306a36Sopenharmony_ci#include <linux/buffer_head.h> 3962306a36Sopenharmony_ci#include <linux/blkdev.h> 4062306a36Sopenharmony_ci#include <linux/highmem.h> 4162306a36Sopenharmony_ci#include <linux/prefetch.h> 4262306a36Sopenharmony_ci#include <linux/mpage.h> 4362306a36Sopenharmony_ci#include <linux/writeback.h> 4462306a36Sopenharmony_ci#include <linux/backing-dev.h> 4562306a36Sopenharmony_ci#include <linux/pagevec.h> 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#include "ext4.h" 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci#define NUM_PREALLOC_POST_READ_CTXS 128 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic struct kmem_cache *bio_post_read_ctx_cache; 5262306a36Sopenharmony_cistatic mempool_t *bio_post_read_ctx_pool; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* postprocessing steps for read bios */ 5562306a36Sopenharmony_cienum bio_post_read_step { 5662306a36Sopenharmony_ci STEP_INITIAL = 0, 5762306a36Sopenharmony_ci STEP_DECRYPT, 5862306a36Sopenharmony_ci STEP_VERITY, 5962306a36Sopenharmony_ci STEP_MAX, 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistruct bio_post_read_ctx { 6362306a36Sopenharmony_ci struct bio *bio; 6462306a36Sopenharmony_ci struct work_struct work; 6562306a36Sopenharmony_ci unsigned int cur_step; 6662306a36Sopenharmony_ci unsigned int enabled_steps; 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic void __read_end_io(struct bio *bio) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci struct folio_iter fi; 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci bio_for_each_folio_all(fi, bio) { 7462306a36Sopenharmony_ci struct folio *folio = fi.folio; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (bio->bi_status) 7762306a36Sopenharmony_ci folio_clear_uptodate(folio); 7862306a36Sopenharmony_ci else 7962306a36Sopenharmony_ci folio_mark_uptodate(folio); 8062306a36Sopenharmony_ci folio_unlock(folio); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci if (bio->bi_private) 8362306a36Sopenharmony_ci mempool_free(bio->bi_private, bio_post_read_ctx_pool); 8462306a36Sopenharmony_ci bio_put(bio); 8562306a36Sopenharmony_ci} 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_cistatic void bio_post_read_processing(struct bio_post_read_ctx *ctx); 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic void decrypt_work(struct work_struct *work) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = 9262306a36Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 9362306a36Sopenharmony_ci struct bio *bio = ctx->bio; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci if (fscrypt_decrypt_bio(bio)) 9662306a36Sopenharmony_ci bio_post_read_processing(ctx); 9762306a36Sopenharmony_ci else 9862306a36Sopenharmony_ci __read_end_io(bio); 9962306a36Sopenharmony_ci} 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_cistatic void verity_work(struct work_struct *work) 10262306a36Sopenharmony_ci{ 10362306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = 10462306a36Sopenharmony_ci container_of(work, struct bio_post_read_ctx, work); 10562306a36Sopenharmony_ci struct bio *bio = ctx->bio; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci /* 10862306a36Sopenharmony_ci * fsverity_verify_bio() may call readahead() again, and although verity 10962306a36Sopenharmony_ci * will be disabled for that, decryption may still be needed, causing 11062306a36Sopenharmony_ci * another bio_post_read_ctx to be allocated. So to guarantee that 11162306a36Sopenharmony_ci * mempool_alloc() never deadlocks we must free the current ctx first. 11262306a36Sopenharmony_ci * This is safe because verity is the last post-read step. 11362306a36Sopenharmony_ci */ 11462306a36Sopenharmony_ci BUILD_BUG_ON(STEP_VERITY + 1 != STEP_MAX); 11562306a36Sopenharmony_ci mempool_free(ctx, bio_post_read_ctx_pool); 11662306a36Sopenharmony_ci bio->bi_private = NULL; 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci fsverity_verify_bio(bio); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci __read_end_io(bio); 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic void bio_post_read_processing(struct bio_post_read_ctx *ctx) 12462306a36Sopenharmony_ci{ 12562306a36Sopenharmony_ci /* 12662306a36Sopenharmony_ci * We use different work queues for decryption and for verity because 12762306a36Sopenharmony_ci * verity may require reading metadata pages that need decryption, and 12862306a36Sopenharmony_ci * we shouldn't recurse to the same workqueue. 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_ci switch (++ctx->cur_step) { 13162306a36Sopenharmony_ci case STEP_DECRYPT: 13262306a36Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_DECRYPT)) { 13362306a36Sopenharmony_ci INIT_WORK(&ctx->work, decrypt_work); 13462306a36Sopenharmony_ci fscrypt_enqueue_decrypt_work(&ctx->work); 13562306a36Sopenharmony_ci return; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci ctx->cur_step++; 13862306a36Sopenharmony_ci fallthrough; 13962306a36Sopenharmony_ci case STEP_VERITY: 14062306a36Sopenharmony_ci if (ctx->enabled_steps & (1 << STEP_VERITY)) { 14162306a36Sopenharmony_ci INIT_WORK(&ctx->work, verity_work); 14262306a36Sopenharmony_ci fsverity_enqueue_verify_work(&ctx->work); 14362306a36Sopenharmony_ci return; 14462306a36Sopenharmony_ci } 14562306a36Sopenharmony_ci ctx->cur_step++; 14662306a36Sopenharmony_ci fallthrough; 14762306a36Sopenharmony_ci default: 14862306a36Sopenharmony_ci __read_end_io(ctx->bio); 14962306a36Sopenharmony_ci } 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic bool bio_post_read_required(struct bio *bio) 15362306a36Sopenharmony_ci{ 15462306a36Sopenharmony_ci return bio->bi_private && !bio->bi_status; 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* 15862306a36Sopenharmony_ci * I/O completion handler for multipage BIOs. 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * The mpage code never puts partial pages into a BIO (except for end-of-file). 16162306a36Sopenharmony_ci * If a page does not map to a contiguous run of blocks then it simply falls 16262306a36Sopenharmony_ci * back to block_read_full_folio(). 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * Why is this? If a page's completion depends on a number of different BIOs 16562306a36Sopenharmony_ci * which can complete in any order (or at the same time) then determining the 16662306a36Sopenharmony_ci * status of that page is hard. See end_buffer_async_read() for the details. 16762306a36Sopenharmony_ci * There is no point in duplicating all that complexity. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_cistatic void mpage_end_io(struct bio *bio) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci if (bio_post_read_required(bio)) { 17262306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = bio->bi_private; 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci ctx->cur_step = STEP_INITIAL; 17562306a36Sopenharmony_ci bio_post_read_processing(ctx); 17662306a36Sopenharmony_ci return; 17762306a36Sopenharmony_ci } 17862306a36Sopenharmony_ci __read_end_io(bio); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic inline bool ext4_need_verity(const struct inode *inode, pgoff_t idx) 18262306a36Sopenharmony_ci{ 18362306a36Sopenharmony_ci return fsverity_active(inode) && 18462306a36Sopenharmony_ci idx < DIV_ROUND_UP(inode->i_size, PAGE_SIZE); 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic void ext4_set_bio_post_read_ctx(struct bio *bio, 18862306a36Sopenharmony_ci const struct inode *inode, 18962306a36Sopenharmony_ci pgoff_t first_idx) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci unsigned int post_read_steps = 0; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (fscrypt_inode_uses_fs_layer_crypto(inode)) 19462306a36Sopenharmony_ci post_read_steps |= 1 << STEP_DECRYPT; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci if (ext4_need_verity(inode, first_idx)) 19762306a36Sopenharmony_ci post_read_steps |= 1 << STEP_VERITY; 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci if (post_read_steps) { 20062306a36Sopenharmony_ci /* Due to the mempool, this never fails. */ 20162306a36Sopenharmony_ci struct bio_post_read_ctx *ctx = 20262306a36Sopenharmony_ci mempool_alloc(bio_post_read_ctx_pool, GFP_NOFS); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci ctx->bio = bio; 20562306a36Sopenharmony_ci ctx->enabled_steps = post_read_steps; 20662306a36Sopenharmony_ci bio->bi_private = ctx; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic inline loff_t ext4_readpage_limit(struct inode *inode) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_FS_VERITY) && IS_VERITY(inode)) 21362306a36Sopenharmony_ci return inode->i_sb->s_maxbytes; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci return i_size_read(inode); 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ciint ext4_mpage_readpages(struct inode *inode, 21962306a36Sopenharmony_ci struct readahead_control *rac, struct folio *folio) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci struct bio *bio = NULL; 22262306a36Sopenharmony_ci sector_t last_block_in_bio = 0; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci const unsigned blkbits = inode->i_blkbits; 22562306a36Sopenharmony_ci const unsigned blocks_per_page = PAGE_SIZE >> blkbits; 22662306a36Sopenharmony_ci const unsigned blocksize = 1 << blkbits; 22762306a36Sopenharmony_ci sector_t next_block; 22862306a36Sopenharmony_ci sector_t block_in_file; 22962306a36Sopenharmony_ci sector_t last_block; 23062306a36Sopenharmony_ci sector_t last_block_in_file; 23162306a36Sopenharmony_ci sector_t blocks[MAX_BUF_PER_PAGE]; 23262306a36Sopenharmony_ci unsigned page_block; 23362306a36Sopenharmony_ci struct block_device *bdev = inode->i_sb->s_bdev; 23462306a36Sopenharmony_ci int length; 23562306a36Sopenharmony_ci unsigned relative_block = 0; 23662306a36Sopenharmony_ci struct ext4_map_blocks map; 23762306a36Sopenharmony_ci unsigned int nr_pages = rac ? readahead_count(rac) : 1; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci map.m_pblk = 0; 24062306a36Sopenharmony_ci map.m_lblk = 0; 24162306a36Sopenharmony_ci map.m_len = 0; 24262306a36Sopenharmony_ci map.m_flags = 0; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci for (; nr_pages; nr_pages--) { 24562306a36Sopenharmony_ci int fully_mapped = 1; 24662306a36Sopenharmony_ci unsigned first_hole = blocks_per_page; 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci if (rac) 24962306a36Sopenharmony_ci folio = readahead_folio(rac); 25062306a36Sopenharmony_ci prefetchw(&folio->flags); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (folio_buffers(folio)) 25362306a36Sopenharmony_ci goto confused; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci block_in_file = next_block = 25662306a36Sopenharmony_ci (sector_t)folio->index << (PAGE_SHIFT - blkbits); 25762306a36Sopenharmony_ci last_block = block_in_file + nr_pages * blocks_per_page; 25862306a36Sopenharmony_ci last_block_in_file = (ext4_readpage_limit(inode) + 25962306a36Sopenharmony_ci blocksize - 1) >> blkbits; 26062306a36Sopenharmony_ci if (last_block > last_block_in_file) 26162306a36Sopenharmony_ci last_block = last_block_in_file; 26262306a36Sopenharmony_ci page_block = 0; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci /* 26562306a36Sopenharmony_ci * Map blocks using the previous result first. 26662306a36Sopenharmony_ci */ 26762306a36Sopenharmony_ci if ((map.m_flags & EXT4_MAP_MAPPED) && 26862306a36Sopenharmony_ci block_in_file > map.m_lblk && 26962306a36Sopenharmony_ci block_in_file < (map.m_lblk + map.m_len)) { 27062306a36Sopenharmony_ci unsigned map_offset = block_in_file - map.m_lblk; 27162306a36Sopenharmony_ci unsigned last = map.m_len - map_offset; 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci for (relative_block = 0; ; relative_block++) { 27462306a36Sopenharmony_ci if (relative_block == last) { 27562306a36Sopenharmony_ci /* needed? */ 27662306a36Sopenharmony_ci map.m_flags &= ~EXT4_MAP_MAPPED; 27762306a36Sopenharmony_ci break; 27862306a36Sopenharmony_ci } 27962306a36Sopenharmony_ci if (page_block == blocks_per_page) 28062306a36Sopenharmony_ci break; 28162306a36Sopenharmony_ci blocks[page_block] = map.m_pblk + map_offset + 28262306a36Sopenharmony_ci relative_block; 28362306a36Sopenharmony_ci page_block++; 28462306a36Sopenharmony_ci block_in_file++; 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci /* 28962306a36Sopenharmony_ci * Then do more ext4_map_blocks() calls until we are 29062306a36Sopenharmony_ci * done with this folio. 29162306a36Sopenharmony_ci */ 29262306a36Sopenharmony_ci while (page_block < blocks_per_page) { 29362306a36Sopenharmony_ci if (block_in_file < last_block) { 29462306a36Sopenharmony_ci map.m_lblk = block_in_file; 29562306a36Sopenharmony_ci map.m_len = last_block - block_in_file; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (ext4_map_blocks(NULL, inode, &map, 0) < 0) { 29862306a36Sopenharmony_ci set_error_page: 29962306a36Sopenharmony_ci folio_set_error(folio); 30062306a36Sopenharmony_ci folio_zero_segment(folio, 0, 30162306a36Sopenharmony_ci folio_size(folio)); 30262306a36Sopenharmony_ci folio_unlock(folio); 30362306a36Sopenharmony_ci goto next_page; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci if ((map.m_flags & EXT4_MAP_MAPPED) == 0) { 30762306a36Sopenharmony_ci fully_mapped = 0; 30862306a36Sopenharmony_ci if (first_hole == blocks_per_page) 30962306a36Sopenharmony_ci first_hole = page_block; 31062306a36Sopenharmony_ci page_block++; 31162306a36Sopenharmony_ci block_in_file++; 31262306a36Sopenharmony_ci continue; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci if (first_hole != blocks_per_page) 31562306a36Sopenharmony_ci goto confused; /* hole -> non-hole */ 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* Contiguous blocks? */ 31862306a36Sopenharmony_ci if (page_block && blocks[page_block-1] != map.m_pblk-1) 31962306a36Sopenharmony_ci goto confused; 32062306a36Sopenharmony_ci for (relative_block = 0; ; relative_block++) { 32162306a36Sopenharmony_ci if (relative_block == map.m_len) { 32262306a36Sopenharmony_ci /* needed? */ 32362306a36Sopenharmony_ci map.m_flags &= ~EXT4_MAP_MAPPED; 32462306a36Sopenharmony_ci break; 32562306a36Sopenharmony_ci } else if (page_block == blocks_per_page) 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci blocks[page_block] = map.m_pblk+relative_block; 32862306a36Sopenharmony_ci page_block++; 32962306a36Sopenharmony_ci block_in_file++; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci if (first_hole != blocks_per_page) { 33362306a36Sopenharmony_ci folio_zero_segment(folio, first_hole << blkbits, 33462306a36Sopenharmony_ci folio_size(folio)); 33562306a36Sopenharmony_ci if (first_hole == 0) { 33662306a36Sopenharmony_ci if (ext4_need_verity(inode, folio->index) && 33762306a36Sopenharmony_ci !fsverity_verify_folio(folio)) 33862306a36Sopenharmony_ci goto set_error_page; 33962306a36Sopenharmony_ci folio_mark_uptodate(folio); 34062306a36Sopenharmony_ci folio_unlock(folio); 34162306a36Sopenharmony_ci continue; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci } else if (fully_mapped) { 34462306a36Sopenharmony_ci folio_set_mappedtodisk(folio); 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* 34862306a36Sopenharmony_ci * This folio will go to BIO. Do we need to send this 34962306a36Sopenharmony_ci * BIO off first? 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci if (bio && (last_block_in_bio != blocks[0] - 1 || 35262306a36Sopenharmony_ci !fscrypt_mergeable_bio(bio, inode, next_block))) { 35362306a36Sopenharmony_ci submit_and_realloc: 35462306a36Sopenharmony_ci submit_bio(bio); 35562306a36Sopenharmony_ci bio = NULL; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci if (bio == NULL) { 35862306a36Sopenharmony_ci /* 35962306a36Sopenharmony_ci * bio_alloc will _always_ be able to allocate a bio if 36062306a36Sopenharmony_ci * __GFP_DIRECT_RECLAIM is set, see bio_alloc_bioset(). 36162306a36Sopenharmony_ci */ 36262306a36Sopenharmony_ci bio = bio_alloc(bdev, bio_max_segs(nr_pages), 36362306a36Sopenharmony_ci REQ_OP_READ, GFP_KERNEL); 36462306a36Sopenharmony_ci fscrypt_set_bio_crypt_ctx(bio, inode, next_block, 36562306a36Sopenharmony_ci GFP_KERNEL); 36662306a36Sopenharmony_ci ext4_set_bio_post_read_ctx(bio, inode, folio->index); 36762306a36Sopenharmony_ci bio->bi_iter.bi_sector = blocks[0] << (blkbits - 9); 36862306a36Sopenharmony_ci bio->bi_end_io = mpage_end_io; 36962306a36Sopenharmony_ci if (rac) 37062306a36Sopenharmony_ci bio->bi_opf |= REQ_RAHEAD; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci length = first_hole << blkbits; 37462306a36Sopenharmony_ci if (!bio_add_folio(bio, folio, length, 0)) 37562306a36Sopenharmony_ci goto submit_and_realloc; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (((map.m_flags & EXT4_MAP_BOUNDARY) && 37862306a36Sopenharmony_ci (relative_block == map.m_len)) || 37962306a36Sopenharmony_ci (first_hole != blocks_per_page)) { 38062306a36Sopenharmony_ci submit_bio(bio); 38162306a36Sopenharmony_ci bio = NULL; 38262306a36Sopenharmony_ci } else 38362306a36Sopenharmony_ci last_block_in_bio = blocks[blocks_per_page - 1]; 38462306a36Sopenharmony_ci continue; 38562306a36Sopenharmony_ci confused: 38662306a36Sopenharmony_ci if (bio) { 38762306a36Sopenharmony_ci submit_bio(bio); 38862306a36Sopenharmony_ci bio = NULL; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci if (!folio_test_uptodate(folio)) 39162306a36Sopenharmony_ci block_read_full_folio(folio, ext4_get_block); 39262306a36Sopenharmony_ci else 39362306a36Sopenharmony_ci folio_unlock(folio); 39462306a36Sopenharmony_cinext_page: 39562306a36Sopenharmony_ci ; /* A label shall be followed by a statement until C23 */ 39662306a36Sopenharmony_ci } 39762306a36Sopenharmony_ci if (bio) 39862306a36Sopenharmony_ci submit_bio(bio); 39962306a36Sopenharmony_ci return 0; 40062306a36Sopenharmony_ci} 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ciint __init ext4_init_post_read_processing(void) 40362306a36Sopenharmony_ci{ 40462306a36Sopenharmony_ci bio_post_read_ctx_cache = KMEM_CACHE(bio_post_read_ctx, SLAB_RECLAIM_ACCOUNT); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (!bio_post_read_ctx_cache) 40762306a36Sopenharmony_ci goto fail; 40862306a36Sopenharmony_ci bio_post_read_ctx_pool = 40962306a36Sopenharmony_ci mempool_create_slab_pool(NUM_PREALLOC_POST_READ_CTXS, 41062306a36Sopenharmony_ci bio_post_read_ctx_cache); 41162306a36Sopenharmony_ci if (!bio_post_read_ctx_pool) 41262306a36Sopenharmony_ci goto fail_free_cache; 41362306a36Sopenharmony_ci return 0; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cifail_free_cache: 41662306a36Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 41762306a36Sopenharmony_cifail: 41862306a36Sopenharmony_ci return -ENOMEM; 41962306a36Sopenharmony_ci} 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_civoid ext4_exit_post_read_processing(void) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci mempool_destroy(bio_post_read_ctx_pool); 42462306a36Sopenharmony_ci kmem_cache_destroy(bio_post_read_ctx_cache); 42562306a36Sopenharmony_ci} 426