Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

block: remove bounce buffering support

The block layer bounce buffering support is unused now, remove it.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: John Garry <john.g.garry@oracle.com>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Link: https://lore.kernel.org/r/20250505081138.3435992-7-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
eeadd68e a9437f6a

+3 -327
-1
arch/mips/configs/gcw0_defconfig
··· 13 13 CONFIG_MODULES=y 14 14 CONFIG_MODULE_UNLOAD=y 15 15 # CONFIG_BLK_DEV_BSG is not set 16 - # CONFIG_BOUNCE is not set 17 16 CONFIG_NET=y 18 17 CONFIG_PACKET=y 19 18 CONFIG_UNIX=y
-1
block/Makefile
··· 11 11 genhd.o ioprio.o badblocks.o partitions/ blk-rq-qos.o \ 12 12 disk-events.o blk-ia-ranges.o early-lookup.o 13 13 14 - obj-$(CONFIG_BOUNCE) += bounce.o 15 14 obj-$(CONFIG_BLK_DEV_BSG_COMMON) += bsg.o 16 15 obj-$(CONFIG_BLK_DEV_BSGLIB) += bsg-lib.o 17 16 obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o
+1 -4
block/blk-map.c
··· 556 556 557 557 if (map_data) 558 558 copy = true; 559 - else if (blk_queue_may_bounce(q)) 560 - copy = true; 561 559 else if (iov_iter_alignment(iter) & align) 562 560 copy = true; 563 561 else if (iov_iter_is_bvec(iter)) ··· 711 713 if (!len || !kbuf) 712 714 return -EINVAL; 713 715 714 - if (!blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf) || 715 - blk_queue_may_bounce(q)) 716 + if (!blk_rq_aligned(q, addr, len) || object_is_on_stack(kbuf)) 716 717 bio = bio_copy_kern(q, kbuf, len, gfp_mask, reading); 717 718 else 718 719 bio = bio_map_kern(q, kbuf, len, gfp_mask);
-2
block/blk-mq.c
··· 3144 3144 goto new_request; 3145 3145 } 3146 3146 3147 - bio = blk_queue_bounce(bio, q); 3148 - 3149 3147 /* 3150 3148 * The cached request already holds a q_usage_counter reference and we 3151 3149 * don't have to acquire a new one if we use it.
-5
block/blk-settings.c
··· 124 124 return 0; 125 125 } 126 126 127 - if (lim->features & BLK_FEAT_BOUNCE_HIGH) { 128 - pr_warn("no bounce buffer support for integrity metadata\n"); 129 - return -EINVAL; 130 - } 131 - 132 127 if (!IS_ENABLED(CONFIG_BLK_DEV_INTEGRITY)) { 133 128 pr_warn("integrity support disabled.\n"); 134 129 return -EINVAL;
-17
block/blk.h
··· 443 443 } 444 444 #endif /* CONFIG_BLK_ICQ */ 445 445 446 - struct bio *__blk_queue_bounce(struct bio *bio, struct request_queue *q); 447 - 448 - static inline bool blk_queue_may_bounce(struct request_queue *q) 449 - { 450 - return IS_ENABLED(CONFIG_BOUNCE) && 451 - (q->limits.features & BLK_FEAT_BOUNCE_HIGH) && 452 - max_low_pfn >= max_pfn; 453 - } 454 - 455 - static inline struct bio *blk_queue_bounce(struct bio *bio, 456 - struct request_queue *q) 457 - { 458 - if (unlikely(blk_queue_may_bounce(q) && bio_has_data(bio))) 459 - return __blk_queue_bounce(bio, q); 460 - return bio; 461 - } 462 - 463 446 #ifdef CONFIG_BLK_DEV_ZONED 464 447 void disk_init_zone_resources(struct gendisk *disk); 465 448 void disk_free_zone_resources(struct gendisk *disk);
-267
block/bounce.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* bounce buffer handling for block devices 3 - * 4 - * - Split from highmem.c 5 - */ 6 - 7 - #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8 - 9 - #include <linux/mm.h> 10 - #include <linux/export.h> 11 - #include <linux/swap.h> 12 - #include <linux/gfp.h> 13 - #include <linux/bio-integrity.h> 14 - #include <linux/pagemap.h> 15 - #include <linux/mempool.h> 16 - #include <linux/blkdev.h> 17 - #include <linux/backing-dev.h> 18 - #include <linux/init.h> 19 - #include <linux/hash.h> 20 - #include <linux/highmem.h> 21 - #include <linux/printk.h> 22 - #include <asm/tlbflush.h> 23 - 24 - #include <trace/events/block.h> 25 - #include "blk.h" 26 - #include "blk-cgroup.h" 27 - 28 - #define POOL_SIZE 64 29 - #define ISA_POOL_SIZE 16 30 - 31 - static struct bio_set bounce_bio_set, bounce_bio_split; 32 - static mempool_t page_pool; 33 - 34 - static void init_bounce_bioset(void) 35 - { 36 - static bool bounce_bs_setup; 37 - int ret; 38 - 39 - if (bounce_bs_setup) 40 - return; 41 - 42 - ret = bioset_init(&bounce_bio_set, BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); 43 - BUG_ON(ret); 44 - 45 - ret = bioset_init(&bounce_bio_split, BIO_POOL_SIZE, 0, 0); 46 - BUG_ON(ret); 47 - bounce_bs_setup = true; 48 - } 49 - 50 - static __init int init_emergency_pool(void) 51 - { 52 - int ret; 53 - 54 - #ifndef CONFIG_MEMORY_HOTPLUG 55 - if (max_pfn <= max_low_pfn) 56 - return 0; 57 - #endif 58 - 59 - ret = mempool_init_page_pool(&page_pool, POOL_SIZE, 0); 60 - BUG_ON(ret); 61 - pr_info("pool size: %d pages\n", POOL_SIZE); 62 - 63 - init_bounce_bioset(); 64 - return 0; 65 - } 66 - 67 - __initcall(init_emergency_pool); 68 - 69 - /* 70 - * Simple bounce buffer support for highmem pages. Depending on the 71 - * queue gfp mask set, *to may or may not be a highmem page. kmap it 72 - * always, it will do the Right Thing 73 - */ 74 - static void copy_to_high_bio_irq(struct bio *to, struct bio *from) 75 - { 76 - struct bio_vec tovec, fromvec; 77 - struct bvec_iter iter; 78 - /* 79 - * The bio of @from is created by bounce, so we can iterate 80 - * its bvec from start to end, but the @from->bi_iter can't be 81 - * trusted because it might be changed by splitting. 82 - */ 83 - struct bvec_iter from_iter = BVEC_ITER_ALL_INIT; 84 - 85 - bio_for_each_segment(tovec, to, iter) { 86 - fromvec = bio_iter_iovec(from, from_iter); 87 - if (tovec.bv_page != fromvec.bv_page) { 88 - /* 89 - * fromvec->bv_offset and fromvec->bv_len might have 90 - * been modified by the block layer, so use the original 91 - * copy, bounce_copy_vec already uses tovec->bv_len 92 - */ 93 - memcpy_to_bvec(&tovec, page_address(fromvec.bv_page) + 94 - tovec.bv_offset); 95 - } 96 - bio_advance_iter(from, &from_iter, tovec.bv_len); 97 - } 98 - } 99 - 100 - static void bounce_end_io(struct bio *bio) 101 - { 102 - struct bio *bio_orig = bio->bi_private; 103 - struct bio_vec *bvec, orig_vec; 104 - struct bvec_iter orig_iter = bio_orig->bi_iter; 105 - struct bvec_iter_all iter_all; 106 - 107 - /* 108 - * free up bounce indirect pages used 109 - */ 110 - bio_for_each_segment_all(bvec, bio, iter_all) { 111 - orig_vec = bio_iter_iovec(bio_orig, orig_iter); 112 - if (bvec->bv_page != orig_vec.bv_page) { 113 - dec_zone_page_state(bvec->bv_page, NR_BOUNCE); 114 - mempool_free(bvec->bv_page, &page_pool); 115 - } 116 - bio_advance_iter(bio_orig, &orig_iter, orig_vec.bv_len); 117 - } 118 - 119 - bio_orig->bi_status = bio->bi_status; 120 - bio_endio(bio_orig); 121 - bio_put(bio); 122 - } 123 - 124 - static void bounce_end_io_write(struct bio *bio) 125 - { 126 - bounce_end_io(bio); 127 - } 128 - 129 - static void bounce_end_io_read(struct bio *bio) 130 - { 131 - struct bio *bio_orig = bio->bi_private; 132 - 133 - if (!bio->bi_status) 134 - copy_to_high_bio_irq(bio_orig, bio); 135 - 136 - bounce_end_io(bio); 137 - } 138 - 139 - static struct bio *bounce_clone_bio(struct bio *bio_src) 140 - { 141 - struct bvec_iter iter; 142 - struct bio_vec bv; 143 - struct bio *bio; 144 - 145 - /* 146 - * Pre immutable biovecs, __bio_clone() used to just do a memcpy from 147 - * bio_src->bi_io_vec to bio->bi_io_vec. 148 - * 149 - * We can't do that anymore, because: 150 - * 151 - * - The point of cloning the biovec is to produce a bio with a biovec 152 - * the caller can modify: bi_idx and bi_bvec_done should be 0. 153 - * 154 - * - The original bio could've had more than BIO_MAX_VECS biovecs; if 155 - * we tried to clone the whole thing bio_alloc_bioset() would fail. 156 - * But the clone should succeed as long as the number of biovecs we 157 - * actually need to allocate is fewer than BIO_MAX_VECS. 158 - * 159 - * - Lastly, bi_vcnt should not be looked at or relied upon by code 160 - * that does not own the bio - reason being drivers don't use it for 161 - * iterating over the biovec anymore, so expecting it to be kept up 162 - * to date (i.e. for clones that share the parent biovec) is just 163 - * asking for trouble and would force extra work. 164 - */ 165 - bio = bio_alloc_bioset(bio_src->bi_bdev, bio_segments(bio_src), 166 - bio_src->bi_opf, GFP_NOIO, &bounce_bio_set); 167 - if (bio_flagged(bio_src, BIO_REMAPPED)) 168 - bio_set_flag(bio, BIO_REMAPPED); 169 - bio->bi_ioprio = bio_src->bi_ioprio; 170 - bio->bi_write_hint = bio_src->bi_write_hint; 171 - bio->bi_iter.bi_sector = bio_src->bi_iter.bi_sector; 172 - bio->bi_iter.bi_size = bio_src->bi_iter.bi_size; 173 - 174 - switch (bio_op(bio)) { 175 - case REQ_OP_DISCARD: 176 - case REQ_OP_SECURE_ERASE: 177 - case REQ_OP_WRITE_ZEROES: 178 - break; 179 - default: 180 - bio_for_each_segment(bv, bio_src, iter) 181 - bio->bi_io_vec[bio->bi_vcnt++] = bv; 182 - break; 183 - } 184 - 185 - if (bio_crypt_clone(bio, bio_src, GFP_NOIO) < 0) 186 - goto err_put; 187 - 188 - if (bio_integrity(bio_src) && 189 - bio_integrity_clone(bio, bio_src, GFP_NOIO) < 0) 190 - goto err_put; 191 - 192 - bio_clone_blkg_association(bio, bio_src); 193 - 194 - return bio; 195 - 196 - err_put: 197 - bio_put(bio); 198 - return NULL; 199 - } 200 - 201 - struct bio *__blk_queue_bounce(struct bio *bio_orig, struct request_queue *q) 202 - { 203 - struct bio *bio; 204 - int rw = bio_data_dir(bio_orig); 205 - struct bio_vec *to, from; 206 - struct bvec_iter iter; 207 - unsigned i = 0, bytes = 0; 208 - bool bounce = false; 209 - int sectors; 210 - 211 - bio_for_each_segment(from, bio_orig, iter) { 212 - if (i++ < BIO_MAX_VECS) 213 - bytes += from.bv_len; 214 - if (PageHighMem(from.bv_page)) 215 - bounce = true; 216 - } 217 - if (!bounce) 218 - return bio_orig; 219 - 220 - /* 221 - * Individual bvecs might not be logical block aligned. Round down 222 - * the split size so that each bio is properly block size aligned, 223 - * even if we do not use the full hardware limits. 224 - */ 225 - sectors = ALIGN_DOWN(bytes, queue_logical_block_size(q)) >> 226 - SECTOR_SHIFT; 227 - if (sectors < bio_sectors(bio_orig)) { 228 - bio = bio_split(bio_orig, sectors, GFP_NOIO, &bounce_bio_split); 229 - bio_chain(bio, bio_orig); 230 - submit_bio_noacct(bio_orig); 231 - bio_orig = bio; 232 - } 233 - bio = bounce_clone_bio(bio_orig); 234 - 235 - /* 236 - * Bvec table can't be updated by bio_for_each_segment_all(), 237 - * so retrieve bvec from the table directly. This way is safe 238 - * because the 'bio' is single-page bvec. 239 - */ 240 - for (i = 0, to = bio->bi_io_vec; i < bio->bi_vcnt; to++, i++) { 241 - struct page *bounce_page; 242 - 243 - if (!PageHighMem(to->bv_page)) 244 - continue; 245 - 246 - bounce_page = mempool_alloc(&page_pool, GFP_NOIO); 247 - inc_zone_page_state(bounce_page, NR_BOUNCE); 248 - 249 - if (rw == WRITE) { 250 - flush_dcache_page(to->bv_page); 251 - memcpy_from_bvec(page_address(bounce_page), to); 252 - } 253 - to->bv_page = bounce_page; 254 - } 255 - 256 - trace_block_bio_bounce(bio_orig); 257 - 258 - bio->bi_flags |= (1 << BIO_BOUNCED); 259 - 260 - if (rw == READ) 261 - bio->bi_end_io = bounce_end_io_read; 262 - else 263 - bio->bi_end_io = bounce_end_io_write; 264 - 265 - bio->bi_private = bio_orig; 266 - return bio; 267 - }
-1
include/linux/blk_types.h
··· 286 286 enum { 287 287 BIO_PAGE_PINNED, /* Unpin pages in bio_release_pages() */ 288 288 BIO_CLONED, /* doesn't own data */ 289 - BIO_BOUNCED, /* bio is a bounce bio */ 290 289 BIO_QUIET, /* Make BIO Quiet */ 291 290 BIO_CHAIN, /* chained bio, ->bi_remaining in effect */ 292 291 BIO_REFFED, /* bio has elevated ->bi_cnt */
+1 -4
include/linux/blkdev.h
··· 331 331 /* skip this queue in blk_mq_(un)quiesce_tagset */ 332 332 #define BLK_FEAT_SKIP_TAGSET_QUIESCE ((__force blk_features_t)(1u << 13)) 333 333 334 - /* bounce all highmem pages */ 335 - #define BLK_FEAT_BOUNCE_HIGH ((__force blk_features_t)(1u << 14)) 336 - 337 334 /* undocumented magic for bcache */ 338 335 #define BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE \ 339 336 ((__force blk_features_t)(1u << 15)) ··· 344 347 */ 345 348 #define BLK_FEAT_INHERIT_MASK \ 346 349 (BLK_FEAT_WRITE_CACHE | BLK_FEAT_FUA | BLK_FEAT_ROTATIONAL | \ 347 - BLK_FEAT_STABLE_WRITES | BLK_FEAT_ZONED | BLK_FEAT_BOUNCE_HIGH | \ 350 + BLK_FEAT_STABLE_WRITES | BLK_FEAT_ZONED | \ 348 351 BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE) 349 352 350 353 /* internal flags in queue_limits.flags */
-15
include/trace/events/block.h
··· 361 361 ); 362 362 363 363 /** 364 - * block_bio_bounce - used bounce buffer when processing block operation 365 - * @bio: block operation 366 - * 367 - * A bounce buffer was used to handle the block operation @bio in @q. 368 - * This occurs when hardware limitations prevent a direct transfer of 369 - * data between the @bio data memory area and the IO device. Use of a 370 - * bounce buffer requires extra copying of data and decreases 371 - * performance. 372 - */ 373 - DEFINE_EVENT(block_bio, block_bio_bounce, 374 - TP_PROTO(struct bio *bio), 375 - TP_ARGS(bio) 376 - ); 377 - 378 - /** 379 364 * block_bio_backmerge - merging block operation to the end of an existing operation 380 365 * @bio: new block operation to merge 381 366 *
+1 -1
include/uapi/linux/blktrace_api.h
··· 49 49 __BLK_TA_UNPLUG_TIMER, /* queue was unplugged by timer */ 50 50 __BLK_TA_INSERT, /* insert request */ 51 51 __BLK_TA_SPLIT, /* bio was split */ 52 - __BLK_TA_BOUNCE, /* bio was bounced */ 52 + __BLK_TA_BOUNCE, /* unused, was: bio was bounced */ 53 53 __BLK_TA_REMAP, /* bio was remapped */ 54 54 __BLK_TA_ABORT, /* request aborted */ 55 55 __BLK_TA_DRV_DATA, /* driver-specific binary data */
-9
kernel/trace/blktrace.c
··· 893 893 rcu_read_unlock(); 894 894 } 895 895 896 - static void blk_add_trace_bio_bounce(void *ignore, struct bio *bio) 897 - { 898 - blk_add_trace_bio(bio->bi_bdev->bd_disk->queue, bio, BLK_TA_BOUNCE, 0); 899 - } 900 - 901 896 static void blk_add_trace_bio_complete(void *ignore, 902 897 struct request_queue *q, struct bio *bio) 903 898 { ··· 1084 1089 WARN_ON(ret); 1085 1090 ret = register_trace_block_rq_complete(blk_add_trace_rq_complete, NULL); 1086 1091 WARN_ON(ret); 1087 - ret = register_trace_block_bio_bounce(blk_add_trace_bio_bounce, NULL); 1088 - WARN_ON(ret); 1089 1092 ret = register_trace_block_bio_complete(blk_add_trace_bio_complete, NULL); 1090 1093 WARN_ON(ret); 1091 1094 ret = register_trace_block_bio_backmerge(blk_add_trace_bio_backmerge, NULL); ··· 1118 1125 unregister_trace_block_bio_frontmerge(blk_add_trace_bio_frontmerge, NULL); 1119 1126 unregister_trace_block_bio_backmerge(blk_add_trace_bio_backmerge, NULL); 1120 1127 unregister_trace_block_bio_complete(blk_add_trace_bio_complete, NULL); 1121 - unregister_trace_block_bio_bounce(blk_add_trace_bio_bounce, NULL); 1122 1128 unregister_trace_block_rq_complete(blk_add_trace_rq_complete, NULL); 1123 1129 unregister_trace_block_rq_requeue(blk_add_trace_rq_requeue, NULL); 1124 1130 unregister_trace_block_rq_merge(blk_add_trace_rq_merge, NULL); ··· 1454 1462 [__BLK_TA_UNPLUG_TIMER] = {{ "UT", "unplug_timer" }, blk_log_unplug }, 1455 1463 [__BLK_TA_INSERT] = {{ "I", "insert" }, blk_log_generic }, 1456 1464 [__BLK_TA_SPLIT] = {{ "X", "split" }, blk_log_split }, 1457 - [__BLK_TA_BOUNCE] = {{ "B", "bounce" }, blk_log_generic }, 1458 1465 [__BLK_TA_REMAP] = {{ "A", "remap" }, blk_log_remap }, 1459 1466 }; 1460 1467