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

block: add a bio_add_vmalloc helpers

Add a helper to add a vmalloc region to a bio, abstracting away the
vmalloc addresses from the underlying pages and another one wrapping
it for the simple case where all data fits into a single bio.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Link: https://lore.kernel.org/r/20250507120451.4000627-5-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Christoph Hellwig and committed by
Jens Axboe
8dd16f5e 75f88659

+58
+55
block/bio.c
··· 1076 1076 } 1077 1077 EXPORT_SYMBOL(bio_add_folio); 1078 1078 1079 + /** 1080 + * bio_add_vmalloc_chunk - add a vmalloc chunk to a bio 1081 + * @bio: destination bio 1082 + * @vaddr: vmalloc address to add 1083 + * @len: total length in bytes of the data to add 1084 + * 1085 + * Add data starting at @vaddr to @bio and return how many bytes were added. 1086 + * This may be less than the amount originally asked. Returns 0 if no data 1087 + * could be added to @bio. 1088 + * 1089 + * This helper calls flush_kernel_vmap_range() for the range added. For reads 1090 + * the caller still needs to manually call invalidate_kernel_vmap_range() in 1091 + * the completion handler. 1092 + */ 1093 + unsigned int bio_add_vmalloc_chunk(struct bio *bio, void *vaddr, unsigned len) 1094 + { 1095 + unsigned int offset = offset_in_page(vaddr); 1096 + 1097 + len = min(len, PAGE_SIZE - offset); 1098 + if (bio_add_page(bio, vmalloc_to_page(vaddr), len, offset) < len) 1099 + return 0; 1100 + if (op_is_write(bio_op(bio))) 1101 + flush_kernel_vmap_range(vaddr, len); 1102 + return len; 1103 + } 1104 + EXPORT_SYMBOL_GPL(bio_add_vmalloc_chunk); 1105 + 1106 + /** 1107 + * bio_add_vmalloc - add a vmalloc region to a bio 1108 + * @bio: destination bio 1109 + * @vaddr: vmalloc address to add 1110 + * @len: total length in bytes of the data to add 1111 + * 1112 + * Add data starting at @vaddr to @bio. Return %true on success or %false if 1113 + * @bio does not have enough space for the payload. 1114 + * 1115 + * This helper calls flush_kernel_vmap_range() for the range added. For reads 1116 + * the caller still needs to manually call invalidate_kernel_vmap_range() in 1117 + * the completion handler. 1118 + */ 1119 + bool bio_add_vmalloc(struct bio *bio, void *vaddr, unsigned int len) 1120 + { 1121 + do { 1122 + unsigned int added = bio_add_vmalloc_chunk(bio, vaddr, len); 1123 + 1124 + if (!added) 1125 + return false; 1126 + vaddr += added; 1127 + len -= added; 1128 + } while (len); 1129 + 1130 + return true; 1131 + } 1132 + EXPORT_SYMBOL_GPL(bio_add_vmalloc); 1133 + 1079 1134 void __bio_release_pages(struct bio *bio, bool mark_dirty) 1080 1135 { 1081 1136 struct folio_iter fi;
+3
include/linux/bio.h
··· 433 433 return 1; 434 434 } 435 435 436 + unsigned int bio_add_vmalloc_chunk(struct bio *bio, void *vaddr, unsigned len); 437 + bool bio_add_vmalloc(struct bio *bio, void *vaddr, unsigned int len); 438 + 436 439 int submit_bio_wait(struct bio *bio); 437 440 int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, 438 441 size_t len, enum req_op op);