* [PATCH 0/2] use blk_rq_nr_phys_segments() instead of iterating bvecs @ 2025-11-08 23:00 Caleb Sander Mateos 2025-11-08 23:01 ` [PATCH 1/2] loop: " Caleb Sander Mateos 2025-11-08 23:01 ` [PATCH 2/2] zloop: " Caleb Sander Mateos 0 siblings, 2 replies; 10+ messages in thread From: Caleb Sander Mateos @ 2025-11-08 23:00 UTC (permalink / raw) To: Jens Axboe, Damien Le Moal, Christoph Hellwig Cc: linux-block, linux-kernel, Caleb Sander Mateos Minor simplification to loop and zloop to get the number of segments from the request directly instead of iterating over all its bvecs. Caleb Sander Mateos (2): loop: use blk_rq_nr_phys_segments() instead of iterating bvecs zloop: use blk_rq_nr_phys_segments() instead of iterating bvecs drivers/block/loop.c | 5 +---- drivers/block/zloop.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) -- 2.45.2 ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-08 23:00 [PATCH 0/2] use blk_rq_nr_phys_segments() instead of iterating bvecs Caleb Sander Mateos @ 2025-11-08 23:01 ` Caleb Sander Mateos 2025-11-09 12:19 ` Ming Lei 2025-11-08 23:01 ` [PATCH 2/2] zloop: " Caleb Sander Mateos 1 sibling, 1 reply; 10+ messages in thread From: Caleb Sander Mateos @ 2025-11-08 23:01 UTC (permalink / raw) To: Jens Axboe, Damien Le Moal, Christoph Hellwig Cc: linux-block, linux-kernel, Caleb Sander Mateos The number of bvecs can be obtained directly from struct request's nr_phys_segments field via blk_rq_nr_phys_segments(), so use that instead of iterating over the bvecs an extra time. Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> --- drivers/block/loop.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 13ce229d450c..8096478fad45 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, struct request *rq = blk_mq_rq_from_pdu(cmd); struct bio *bio = rq->bio; struct file *file = lo->lo_backing_file; struct bio_vec tmp; unsigned int offset; - int nr_bvec = 0; + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); int ret; - rq_for_each_bvec(tmp, rq, rq_iter) - nr_bvec++; - if (rq->bio != rq->biotail) { bvec = kmalloc_array(nr_bvec, sizeof(struct bio_vec), GFP_NOIO); if (!bvec) -- 2.45.2 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-08 23:01 ` [PATCH 1/2] loop: " Caleb Sander Mateos @ 2025-11-09 12:19 ` Ming Lei 2025-11-09 19:05 ` Chaitanya Kulkarni 2025-11-10 16:47 ` Caleb Sander Mateos 0 siblings, 2 replies; 10+ messages in thread From: Ming Lei @ 2025-11-09 12:19 UTC (permalink / raw) To: Caleb Sander Mateos Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block, linux-kernel On Sat, Nov 08, 2025 at 04:01:00PM -0700, Caleb Sander Mateos wrote: > The number of bvecs can be obtained directly from struct request's > nr_phys_segments field via blk_rq_nr_phys_segments(), so use that > instead of iterating over the bvecs an extra time. > > Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> > --- > drivers/block/loop.c | 5 +---- > 1 file changed, 1 insertion(+), 4 deletions(-) > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > index 13ce229d450c..8096478fad45 100644 > --- a/drivers/block/loop.c > +++ b/drivers/block/loop.c > @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, > struct request *rq = blk_mq_rq_from_pdu(cmd); > struct bio *bio = rq->bio; > struct file *file = lo->lo_backing_file; > struct bio_vec tmp; > unsigned int offset; > - int nr_bvec = 0; > + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); > int ret; > > - rq_for_each_bvec(tmp, rq, rq_iter) > - nr_bvec++; > - The two may not be same, since one bvec can be splitted into multiple segments. Thanks, Ming ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-09 12:19 ` Ming Lei @ 2025-11-09 19:05 ` Chaitanya Kulkarni 2025-11-10 16:47 ` Caleb Sander Mateos 1 sibling, 0 replies; 10+ messages in thread From: Chaitanya Kulkarni @ 2025-11-09 19:05 UTC (permalink / raw) To: Ming Lei, Caleb Sander Mateos Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org On 11/9/25 04:19, Ming Lei wrote: > On Sat, Nov 08, 2025 at 04:01:00PM -0700, Caleb Sander Mateos wrote: >> The number of bvecs can be obtained directly from struct request's >> nr_phys_segments field via blk_rq_nr_phys_segments(), so use that >> instead of iterating over the bvecs an extra time. >> >> Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> >> --- >> drivers/block/loop.c | 5 +---- >> 1 file changed, 1 insertion(+), 4 deletions(-) >> >> diff --git a/drivers/block/loop.c b/drivers/block/loop.c >> index 13ce229d450c..8096478fad45 100644 >> --- a/drivers/block/loop.c >> +++ b/drivers/block/loop.c >> @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, >> struct request *rq = blk_mq_rq_from_pdu(cmd); >> struct bio *bio = rq->bio; >> struct file *file = lo->lo_backing_file; >> struct bio_vec tmp; >> unsigned int offset; >> - int nr_bvec = 0; >> + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); >> int ret; >> >> - rq_for_each_bvec(tmp, rq, rq_iter) >> - nr_bvec++; >> - > The two may not be same, since one bvec can be splitted into multiple segments. > > Thanks, > Ming > > I had this patch only to realize this :- bvec_split_segs():- * When splitting a bio, it can happen that a bvec is encountered that is too * big to fit in a single segment and hence that it has to be split in the * middle. This function verifies whether or not that should happen. The value * %true is returned if and only if appending the entire @bv to a bio with * *@nsegs segments and *@sectors sectors would make that bio unacceptable for * the block driver. if following messup the indentation after I send plz ignore :- submit_bio() -> submit_bio_noacct() -> __submit_bio_noacct() -> __submit_bio() -> blk_mq_submit_bio() -> __bio_split_to_limits() -> bio_split_rw() -> bio_split_rw_at() -> bio_split_io_at() -- bio_for_each_bvec() (iterate all bvecs) -- [Fast path] nsegs++ (1 bvec = 1 segment) bytes += bv.bv_len -- [Slow path] /* one bv is passed from bio bvec list */ -> bvec_split_segs(lim, &bv, &nsegs, &bytes, lim->max_segments, max_bytes) /* working on one bvec and associated segments */ -- while (len && *nsegs < max_segs) { ... get_max_segment_size() -> min(len, seg_boundary_mask - offset, max_segment_size) (*nsegs)++ total_len += seg_size len -= seg_size ... } -- *bytes += total_len -- return (len > 0) -> blk_mq_bio_to_request() rq->nr_phys_segments = nr_segs -ck ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-09 12:19 ` Ming Lei 2025-11-09 19:05 ` Chaitanya Kulkarni @ 2025-11-10 16:47 ` Caleb Sander Mateos 2025-11-10 21:34 ` Chaitanya Kulkarni 2025-11-11 1:22 ` Ming Lei 1 sibling, 2 replies; 10+ messages in thread From: Caleb Sander Mateos @ 2025-11-10 16:47 UTC (permalink / raw) To: Ming Lei Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block, linux-kernel, Keith Busch On Sun, Nov 9, 2025 at 4:20 AM Ming Lei <ming.lei@redhat.com> wrote: > > On Sat, Nov 08, 2025 at 04:01:00PM -0700, Caleb Sander Mateos wrote: > > The number of bvecs can be obtained directly from struct request's > > nr_phys_segments field via blk_rq_nr_phys_segments(), so use that > > instead of iterating over the bvecs an extra time. > > > > Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> > > --- > > drivers/block/loop.c | 5 +---- > > 1 file changed, 1 insertion(+), 4 deletions(-) > > > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > > index 13ce229d450c..8096478fad45 100644 > > --- a/drivers/block/loop.c > > +++ b/drivers/block/loop.c > > @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, > > struct request *rq = blk_mq_rq_from_pdu(cmd); > > struct bio *bio = rq->bio; > > struct file *file = lo->lo_backing_file; > > struct bio_vec tmp; > > unsigned int offset; > > - int nr_bvec = 0; > > + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); > > int ret; > > > > - rq_for_each_bvec(tmp, rq, rq_iter) > > - nr_bvec++; > > - > > The two may not be same, since one bvec can be splitted into multiple segments. Hmm, io_buffer_register_bvec() already assumes blk_rq_nr_phys_segments() returns the number of bvecs iterated by rq_for_each_bvec(). I asked about this on the patch adding it, but Keith assures me they match: https://lore.kernel.org/io-uring/Z7TmrB4_aBnZdFbo@kbusch-mbp/. Best, Caleb ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-10 16:47 ` Caleb Sander Mateos @ 2025-11-10 21:34 ` Chaitanya Kulkarni 2025-11-11 1:22 ` Ming Lei 1 sibling, 0 replies; 10+ messages in thread From: Chaitanya Kulkarni @ 2025-11-10 21:34 UTC (permalink / raw) To: Caleb Sander Mateos Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, Ming Lei, Keith Busch On 11/10/25 08:47, Caleb Sander Mateos wrote: > On Sun, Nov 9, 2025 at 4:20 AM Ming Lei <ming.lei@redhat.com> wrote: >> On Sat, Nov 08, 2025 at 04:01:00PM -0700, Caleb Sander Mateos wrote: >>> The number of bvecs can be obtained directly from struct request's >>> nr_phys_segments field via blk_rq_nr_phys_segments(), so use that >>> instead of iterating over the bvecs an extra time. >>> >>> Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> >>> --- >>> drivers/block/loop.c | 5 +---- >>> 1 file changed, 1 insertion(+), 4 deletions(-) >>> >>> diff --git a/drivers/block/loop.c b/drivers/block/loop.c >>> index 13ce229d450c..8096478fad45 100644 >>> --- a/drivers/block/loop.c >>> +++ b/drivers/block/loop.c >>> @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, >>> struct request *rq = blk_mq_rq_from_pdu(cmd); >>> struct bio *bio = rq->bio; >>> struct file *file = lo->lo_backing_file; >>> struct bio_vec tmp; >>> unsigned int offset; >>> - int nr_bvec = 0; >>> + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); >>> int ret; >>> >>> - rq_for_each_bvec(tmp, rq, rq_iter) >>> - nr_bvec++; >>> - >> The two may not be same, since one bvec can be splitted into multiple segments. > Hmm, io_buffer_register_bvec() already assumes > blk_rq_nr_phys_segments() returns the number of bvecs iterated by > rq_for_each_bvec(). I asked about this on the patch adding it, but > Keith assures me they match: > https://lore.kernel.org/io-uring/Z7TmrB4_aBnZdFbo@kbusch-mbp/. > > Best, > Caleb > Perhaps I don't understand how they will be same ? can share more details. Segment Splitting :- nr_bvec=1, blk_rq_nr_phys_segments=2 (see below) - ONE large bvec split into MULTIPLE physical segments - Patch above allocate array[2], but iterate and fill only array[0] ? *[ 6155.673749] nullb_bio: 128K bio as ONE bvec: sector=0, size=131072, op=WRITE* *[ 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* diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index 1fe3373431ca..74ab0ba53f62 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1364,7 +1364,18 @@ static blk_status_t null_handle_data_transfer(struct nullb_cmd *cmd, unsigned int max_bytes = nr_sectors << SECTOR_SHIFT; unsigned int transferred_bytes = 0; struct req_iterator iter; + struct req_iterator rq_iter; struct bio_vec bvec; + int nr_bvec = 0; + + rq_for_each_bvec(bvec, rq, rq_iter) + nr_bvec++; + + if (req_op(rq) == REQ_OP_WRITE) { + pr_info("#### %s:%d\n", __func__, __LINE__); + pr_info("nr_bvec=%d blk_rq_nr_phys_segments=%u\n", + nr_bvec, blk_rq_nr_phys_segments(rq)); + } spin_lock_irq(&nullb->lock); rq_for_each_segment(bvec, rq, iter) { -ck ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] loop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-10 16:47 ` Caleb Sander Mateos 2025-11-10 21:34 ` Chaitanya Kulkarni @ 2025-11-11 1:22 ` Ming Lei 1 sibling, 0 replies; 10+ messages in thread From: Ming Lei @ 2025-11-11 1:22 UTC (permalink / raw) To: Caleb Sander Mateos Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block, linux-kernel, Keith Busch On Mon, Nov 10, 2025 at 08:47:46AM -0800, Caleb Sander Mateos wrote: > On Sun, Nov 9, 2025 at 4:20 AM Ming Lei <ming.lei@redhat.com> wrote: > > > > On Sat, Nov 08, 2025 at 04:01:00PM -0700, Caleb Sander Mateos wrote: > > > The number of bvecs can be obtained directly from struct request's > > > nr_phys_segments field via blk_rq_nr_phys_segments(), so use that > > > instead of iterating over the bvecs an extra time. > > > > > > Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> > > > --- > > > drivers/block/loop.c | 5 +---- > > > 1 file changed, 1 insertion(+), 4 deletions(-) > > > > > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c > > > index 13ce229d450c..8096478fad45 100644 > > > --- a/drivers/block/loop.c > > > +++ b/drivers/block/loop.c > > > @@ -346,16 +346,13 @@ static int lo_rw_aio(struct loop_device *lo, struct loop_cmd *cmd, > > > struct request *rq = blk_mq_rq_from_pdu(cmd); > > > struct bio *bio = rq->bio; > > > struct file *file = lo->lo_backing_file; > > > struct bio_vec tmp; > > > unsigned int offset; > > > - int nr_bvec = 0; > > > + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); > > > int ret; > > > > > > - rq_for_each_bvec(tmp, rq, rq_iter) > > > - nr_bvec++; > > > - > > > > The two may not be same, since one bvec can be splitted into multiple segments. > > Hmm, io_buffer_register_bvec() already assumes > blk_rq_nr_phys_segments() returns the number of bvecs iterated by > rq_for_each_bvec(). I asked about this on the patch adding it, but > Keith assures me they match: > https://lore.kernel.org/io-uring/Z7TmrB4_aBnZdFbo@kbusch-mbp/. blk_rq_nr_phys_segments() >= nr_bvec, would you like to cook a fix? Thanks, Ming ^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 2/2] zloop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-08 23:00 [PATCH 0/2] use blk_rq_nr_phys_segments() instead of iterating bvecs Caleb Sander Mateos 2025-11-08 23:01 ` [PATCH 1/2] loop: " Caleb Sander Mateos @ 2025-11-08 23:01 ` Caleb Sander Mateos 2025-11-11 9:07 ` Christoph Hellwig 1 sibling, 1 reply; 10+ messages in thread From: Caleb Sander Mateos @ 2025-11-08 23:01 UTC (permalink / raw) To: Jens Axboe, Damien Le Moal, Christoph Hellwig Cc: linux-block, linux-kernel, Caleb Sander Mateos The number of bvecs can be obtained directly from struct request's nr_phys_segments field via blk_rq_nr_phys_segments(), so use that instead of iterating over the bvecs an extra time. Signed-off-by: Caleb Sander Mateos <csander@purestorage.com> --- drivers/block/zloop.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/block/zloop.c b/drivers/block/zloop.c index 92be9f0af00a..7883e56ed12a 100644 --- a/drivers/block/zloop.c +++ b/drivers/block/zloop.c @@ -368,11 +368,11 @@ static void zloop_rw(struct zloop_cmd *cmd) struct req_iterator rq_iter; struct zloop_zone *zone; struct iov_iter iter; struct bio_vec tmp; sector_t zone_end; - int nr_bvec = 0; + unsigned short nr_bvec = blk_rq_nr_phys_segments(rq); int ret; atomic_set(&cmd->ref, 2); cmd->sector = sector; cmd->nr_sectors = nr_sectors; @@ -435,13 +435,10 @@ static void zloop_rw(struct zloop_cmd *cmd) zone->wp += nr_sectors; if (zone->wp == zone_end) zone->cond = BLK_ZONE_COND_FULL; } - rq_for_each_bvec(tmp, rq, rq_iter) - nr_bvec++; - if (rq->bio != rq->biotail) { struct bio_vec *bvec; cmd->bvec = kmalloc_array(nr_bvec, sizeof(*cmd->bvec), GFP_NOIO); if (!cmd->bvec) { -- 2.45.2 ^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] zloop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-08 23:01 ` [PATCH 2/2] zloop: " Caleb Sander Mateos @ 2025-11-11 9:07 ` Christoph Hellwig 2025-11-11 18:19 ` Chaitanya Kulkarni 0 siblings, 1 reply; 10+ messages in thread From: Christoph Hellwig @ 2025-11-11 9:07 UTC (permalink / raw) To: Caleb Sander Mateos Cc: Jens Axboe, Damien Le Moal, Christoph Hellwig, linux-block, linux-kernel On Sat, Nov 08, 2025 at 04:01:01PM -0700, Caleb Sander Mateos wrote: > The number of bvecs can be obtained directly from struct request's > nr_phys_segments field via blk_rq_nr_phys_segments(), so use that > instead of iterating over the bvecs an extra time. Same reason this doesn't work as Ming explained for ublk. Maybe we should lift this code from loop/zloop into a well documented common helper to make it more obvious? ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] zloop: use blk_rq_nr_phys_segments() instead of iterating bvecs 2025-11-11 9:07 ` Christoph Hellwig @ 2025-11-11 18:19 ` Chaitanya Kulkarni 0 siblings, 0 replies; 10+ messages in thread From: Chaitanya Kulkarni @ 2025-11-11 18:19 UTC (permalink / raw) To: Christoph Hellwig Cc: Jens Axboe, Damien Le Moal, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org, Caleb Sander Mateos On 11/11/25 01:07, Christoph Hellwig wrote: > On Sat, Nov 08, 2025 at 04:01:01PM -0700, Caleb Sander Mateos wrote: >> The number of bvecs can be obtained directly from struct request's >> nr_phys_segments field via blk_rq_nr_phys_segments(), so use that >> instead of iterating over the bvecs an extra time. > Same reason this doesn't work as Ming explained for ublk. > > Maybe we should lift this code from loop/zloop into a well documented > common helper to make it more obvious? > > Absolutely, patch sent with added quantitative data from my experiments, to prove why above is wrong, please have a look. -ck ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-11-11 18:19 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-11-08 23:00 [PATCH 0/2] use blk_rq_nr_phys_segments() instead of iterating bvecs Caleb Sander Mateos 2025-11-08 23:01 ` [PATCH 1/2] loop: " Caleb Sander Mateos 2025-11-09 12:19 ` Ming Lei 2025-11-09 19:05 ` Chaitanya Kulkarni 2025-11-10 16:47 ` Caleb Sander Mateos 2025-11-10 21:34 ` Chaitanya Kulkarni 2025-11-11 1:22 ` Ming Lei 2025-11-08 23:01 ` [PATCH 2/2] zloop: " Caleb Sander Mateos 2025-11-11 9:07 ` Christoph Hellwig 2025-11-11 18:19 ` Chaitanya Kulkarni
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).