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

Configure Feed

Select the types of activity you want to include in your feed.

blk-mq: add blk_rq_nr_bvec() helper

Add a new helper function blk_rq_nr_bvec() that returns the number of
bvecs in a request. This count represents the number of iterations
rq_for_each_bvec() would perform on a request.

Drivers need to pre-allocate bvec arrays before iterating through
a request's bvecs. Currently, they manually count bvecs using
rq_for_each_bvec() in a loop, which is repetitive. The new helper
centralizes this logic.

This pattern exists in loop and zloop drivers, where multi-bio requests
require copying bvecs into a contiguous array before creating
an iov_iter for file operations.

Update loop and zloop drivers to use the new helper, eliminating
duplicate code.

This patch also provides a clear API to avoid any potential misuse of
blk_nr_phys_segments() for calculating the bvecs since, one bvec can
have more than one segments and use of blk_nr_phys_segments() can
lead to extra memory allocation :-

[ 6155.673749] nullb_bio: 128K bio as ONE bvec: sector=0, size=131072
[ 6155.673846] null_blk: #### null_handle_data_transfer:1375
[ 6155.673850] null_blk: nr_bvec=1 blk_rq_nr_phys_segments=2
[ 6155.674263] null_blk: #### null_handle_data_transfer:1375
[ 6155.674267] null_blk: nr_bvec=1 blk_rq_nr_phys_segments=1

Reviewed-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Chaitanya Kulkarni <ckulkarnilinux@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Chaitanya Kulkarni and committed by
Jens Axboe
71075d25 3e2cb9ee

+22 -6
+2 -3
drivers/block/loop.c
··· 348 348 struct file *file = lo->lo_backing_file; 349 349 struct bio_vec tmp; 350 350 unsigned int offset; 351 - int nr_bvec = 0; 351 + unsigned int nr_bvec; 352 352 int ret; 353 353 354 - rq_for_each_bvec(tmp, rq, rq_iter) 355 - nr_bvec++; 354 + nr_bvec = blk_rq_nr_bvec(rq); 356 355 357 356 if (rq->bio != rq->biotail) { 358 357
+2 -3
drivers/block/zloop.c
··· 394 394 struct bio_vec tmp; 395 395 unsigned long flags; 396 396 sector_t zone_end; 397 - int nr_bvec = 0; 397 + unsigned int nr_bvec; 398 398 int ret; 399 399 400 400 atomic_set(&cmd->ref, 2); ··· 487 487 spin_unlock_irqrestore(&zone->wp_lock, flags); 488 488 } 489 489 490 - rq_for_each_bvec(tmp, rq, rq_iter) 491 - nr_bvec++; 490 + nr_bvec = blk_rq_nr_bvec(rq); 492 491 493 492 if (rq->bio != rq->biotail) { 494 493 struct bio_vec *bvec;
+18
include/linux/blk-mq.h
··· 1213 1213 return max_t(unsigned short, rq->nr_phys_segments, 1); 1214 1214 } 1215 1215 1216 + /** 1217 + * blk_rq_nr_bvec - return number of bvecs in a request 1218 + * @rq: request to calculate bvecs for 1219 + * 1220 + * Returns the number of bvecs. 1221 + */ 1222 + static inline unsigned int blk_rq_nr_bvec(struct request *rq) 1223 + { 1224 + struct req_iterator rq_iter; 1225 + struct bio_vec bv; 1226 + unsigned int nr_bvec = 0; 1227 + 1228 + rq_for_each_bvec(bv, rq, rq_iter) 1229 + nr_bvec++; 1230 + 1231 + return nr_bvec; 1232 + } 1233 + 1216 1234 int __blk_rq_map_sg(struct request *rq, struct scatterlist *sglist, 1217 1235 struct scatterlist **last_sg); 1218 1236 static inline int blk_rq_map_sg(struct request *rq, struct scatterlist *sglist)