* [PATCH] bvec: make the bvec_iter helpers inline functions
@ 2026-05-26 7:00 Christoph Hellwig
2026-05-26 18:09 ` Caleb Sander Mateos
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Christoph Hellwig @ 2026-05-26 7:00 UTC (permalink / raw)
To: axboe; +Cc: linux-block
The macros are impossible to follow due to the lack of visual type
information and all the braces. Replace them with inline helpers to
improve on that. Because the calling conventions are a bit problematic
with a lot of passing structures by value, all the helpers are marked
as __always_inline so that they are force inlined.
Signed-off-by: Christoph Hellwig <hch@lst.de>
---
include/linux/bvec.h | 101 +++++++++++++++++++++++++++----------------
1 file changed, 64 insertions(+), 37 deletions(-)
diff --git a/include/linux/bvec.h b/include/linux/bvec.h
index d36dd476feda..f4c7ec282ac9 100644
--- a/include/linux/bvec.h
+++ b/include/linux/bvec.h
@@ -104,51 +104,78 @@ struct bvec_iter_all {
unsigned done;
};
-/*
- * various member access, note that bio_data should of course not be used
- * on highmem page vectors
- */
-#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
+static __always_inline const struct bio_vec *
+__bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return bvecs + iter.bi_idx;
+}
/* multi-page (mp_bvec) helpers */
-#define mp_bvec_iter_page(bvec, iter) \
- (__bvec_iter_bvec((bvec), (iter))->bv_page)
+static __always_inline struct page *
+mp_bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return __bvec_iter_bvec(bvecs, iter)->bv_page;
+}
-#define mp_bvec_iter_len(bvec, iter) \
- min((iter).bi_size, \
- __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
+static __always_inline unsigned int
+mp_bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return min(__bvec_iter_bvec(bvecs, iter)->bv_len - iter.bi_bvec_done,
+ iter.bi_size);
+}
-#define mp_bvec_iter_offset(bvec, iter) \
- (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
+static __always_inline unsigned int
+mp_bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return __bvec_iter_bvec(bvecs, iter)->bv_offset + iter.bi_bvec_done;
+}
-#define mp_bvec_iter_page_idx(bvec, iter) \
- (mp_bvec_iter_offset((bvec), (iter)) / PAGE_SIZE)
+static __always_inline unsigned int
+mp_bvec_iter_page_idx(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_offset(bvecs, iter) / PAGE_SIZE;
+}
-#define mp_bvec_iter_bvec(bvec, iter) \
-((struct bio_vec) { \
- .bv_page = mp_bvec_iter_page((bvec), (iter)), \
- .bv_len = mp_bvec_iter_len((bvec), (iter)), \
- .bv_offset = mp_bvec_iter_offset((bvec), (iter)), \
-})
+static __always_inline struct bio_vec
+mp_bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return (struct bio_vec) {
+ .bv_page = mp_bvec_iter_page(bvecs, iter),
+ .bv_len = mp_bvec_iter_len(bvecs, iter),
+ .bv_offset = mp_bvec_iter_offset(bvecs, iter),
+ };
+}
/* For building single-page bvec in flight */
- #define bvec_iter_offset(bvec, iter) \
- (mp_bvec_iter_offset((bvec), (iter)) % PAGE_SIZE)
-
-#define bvec_iter_len(bvec, iter) \
- min_t(unsigned, mp_bvec_iter_len((bvec), (iter)), \
- PAGE_SIZE - bvec_iter_offset((bvec), (iter)))
-
-#define bvec_iter_page(bvec, iter) \
- (mp_bvec_iter_page((bvec), (iter)) + \
- mp_bvec_iter_page_idx((bvec), (iter)))
-
-#define bvec_iter_bvec(bvec, iter) \
-((struct bio_vec) { \
- .bv_page = bvec_iter_page((bvec), (iter)), \
- .bv_len = bvec_iter_len((bvec), (iter)), \
- .bv_offset = bvec_iter_offset((bvec), (iter)), \
-})
+static __always_inline unsigned int
+bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_offset(bvecs, iter) % PAGE_SIZE;
+}
+
+static __always_inline unsigned int
+bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return min(mp_bvec_iter_len(bvecs, iter),
+ PAGE_SIZE - bvec_iter_offset(bvecs, iter));
+}
+
+static __always_inline struct page *
+bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return mp_bvec_iter_page(bvecs, iter) +
+ mp_bvec_iter_page_idx(bvecs, iter);
+}
+
+static __always_inline struct bio_vec
+bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
+{
+ return (struct bio_vec) {
+ .bv_page = bvec_iter_page(bvecs, iter),
+ .bv_len = bvec_iter_len(bvecs, iter),
+ .bv_offset = bvec_iter_offset(bvecs, iter),
+ };
+}
static inline bool bvec_iter_advance(const struct bio_vec *bv,
struct bvec_iter *iter, unsigned bytes)
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] bvec: make the bvec_iter helpers inline functions
2026-05-26 7:00 [PATCH] bvec: make the bvec_iter helpers inline functions Christoph Hellwig
@ 2026-05-26 18:09 ` Caleb Sander Mateos
2026-05-26 19:32 ` Bart Van Assche
2026-05-26 19:51 ` Keith Busch
2 siblings, 0 replies; 5+ messages in thread
From: Caleb Sander Mateos @ 2026-05-26 18:09 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: axboe, linux-block
On Tue, May 26, 2026 at 12:00 AM Christoph Hellwig <hch@lst.de> wrote:
>
> The macros are impossible to follow due to the lack of visual type
> information and all the braces. Replace them with inline helpers to
> improve on that. Because the calling conventions are a bit problematic
> with a lot of passing structures by value, all the helpers are marked
> as __always_inline so that they are force inlined.
>
> Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Caleb Sander Mateos <csander@purestorage.com>
> ---
> include/linux/bvec.h | 101 +++++++++++++++++++++++++++----------------
> 1 file changed, 64 insertions(+), 37 deletions(-)
>
> diff --git a/include/linux/bvec.h b/include/linux/bvec.h
> index d36dd476feda..f4c7ec282ac9 100644
> --- a/include/linux/bvec.h
> +++ b/include/linux/bvec.h
> @@ -104,51 +104,78 @@ struct bvec_iter_all {
> unsigned done;
> };
>
> -/*
> - * various member access, note that bio_data should of course not be used
> - * on highmem page vectors
> - */
> -#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
> +static __always_inline const struct bio_vec *
> +__bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return bvecs + iter.bi_idx;
> +}
>
> /* multi-page (mp_bvec) helpers */
> -#define mp_bvec_iter_page(bvec, iter) \
> - (__bvec_iter_bvec((bvec), (iter))->bv_page)
> +static __always_inline struct page *
> +mp_bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return __bvec_iter_bvec(bvecs, iter)->bv_page;
> +}
>
> -#define mp_bvec_iter_len(bvec, iter) \
> - min((iter).bi_size, \
> - __bvec_iter_bvec((bvec), (iter))->bv_len - (iter).bi_bvec_done)
> +static __always_inline unsigned int
> +mp_bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return min(__bvec_iter_bvec(bvecs, iter)->bv_len - iter.bi_bvec_done,
> + iter.bi_size);
> +}
>
> -#define mp_bvec_iter_offset(bvec, iter) \
> - (__bvec_iter_bvec((bvec), (iter))->bv_offset + (iter).bi_bvec_done)
> +static __always_inline unsigned int
> +mp_bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return __bvec_iter_bvec(bvecs, iter)->bv_offset + iter.bi_bvec_done;
> +}
>
> -#define mp_bvec_iter_page_idx(bvec, iter) \
> - (mp_bvec_iter_offset((bvec), (iter)) / PAGE_SIZE)
> +static __always_inline unsigned int
> +mp_bvec_iter_page_idx(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return mp_bvec_iter_offset(bvecs, iter) / PAGE_SIZE;
> +}
>
> -#define mp_bvec_iter_bvec(bvec, iter) \
> -((struct bio_vec) { \
> - .bv_page = mp_bvec_iter_page((bvec), (iter)), \
> - .bv_len = mp_bvec_iter_len((bvec), (iter)), \
> - .bv_offset = mp_bvec_iter_offset((bvec), (iter)), \
> -})
> +static __always_inline struct bio_vec
> +mp_bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return (struct bio_vec) {
> + .bv_page = mp_bvec_iter_page(bvecs, iter),
> + .bv_len = mp_bvec_iter_len(bvecs, iter),
> + .bv_offset = mp_bvec_iter_offset(bvecs, iter),
> + };
> +}
>
> /* For building single-page bvec in flight */
> - #define bvec_iter_offset(bvec, iter) \
> - (mp_bvec_iter_offset((bvec), (iter)) % PAGE_SIZE)
> -
> -#define bvec_iter_len(bvec, iter) \
> - min_t(unsigned, mp_bvec_iter_len((bvec), (iter)), \
> - PAGE_SIZE - bvec_iter_offset((bvec), (iter)))
> -
> -#define bvec_iter_page(bvec, iter) \
> - (mp_bvec_iter_page((bvec), (iter)) + \
> - mp_bvec_iter_page_idx((bvec), (iter)))
> -
> -#define bvec_iter_bvec(bvec, iter) \
> -((struct bio_vec) { \
> - .bv_page = bvec_iter_page((bvec), (iter)), \
> - .bv_len = bvec_iter_len((bvec), (iter)), \
> - .bv_offset = bvec_iter_offset((bvec), (iter)), \
> -})
> +static __always_inline unsigned int
> +bvec_iter_offset(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return mp_bvec_iter_offset(bvecs, iter) % PAGE_SIZE;
> +}
> +
> +static __always_inline unsigned int
> +bvec_iter_len(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return min(mp_bvec_iter_len(bvecs, iter),
> + PAGE_SIZE - bvec_iter_offset(bvecs, iter));
> +}
> +
> +static __always_inline struct page *
> +bvec_iter_page(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return mp_bvec_iter_page(bvecs, iter) +
> + mp_bvec_iter_page_idx(bvecs, iter);
> +}
> +
> +static __always_inline struct bio_vec
> +bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return (struct bio_vec) {
> + .bv_page = bvec_iter_page(bvecs, iter),
> + .bv_len = bvec_iter_len(bvecs, iter),
> + .bv_offset = bvec_iter_offset(bvecs, iter),
> + };
> +}
>
> static inline bool bvec_iter_advance(const struct bio_vec *bv,
> struct bvec_iter *iter, unsigned bytes)
> --
> 2.53.0
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] bvec: make the bvec_iter helpers inline functions
2026-05-26 7:00 [PATCH] bvec: make the bvec_iter helpers inline functions Christoph Hellwig
2026-05-26 18:09 ` Caleb Sander Mateos
@ 2026-05-26 19:32 ` Bart Van Assche
2026-05-26 19:51 ` Keith Busch
2 siblings, 0 replies; 5+ messages in thread
From: Bart Van Assche @ 2026-05-26 19:32 UTC (permalink / raw)
To: Christoph Hellwig, axboe; +Cc: linux-block
On 5/26/26 12:00 AM, Christoph Hellwig wrote:
> The macros are impossible to follow due to the lack of visual type
> information and all the braces. Replace them with inline helpers to
> improve on that. Because the calling conventions are a bit problematic
> with a lot of passing structures by value, all the helpers are marked
> as __always_inline so that they are force inlined.
Thanks Christoph!
Reviewed-by: Bart Van Assche <bvanassche@acm.org>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] bvec: make the bvec_iter helpers inline functions
2026-05-26 7:00 [PATCH] bvec: make the bvec_iter helpers inline functions Christoph Hellwig
2026-05-26 18:09 ` Caleb Sander Mateos
2026-05-26 19:32 ` Bart Van Assche
@ 2026-05-26 19:51 ` Keith Busch
2026-05-27 6:39 ` Christoph Hellwig
2 siblings, 1 reply; 5+ messages in thread
From: Keith Busch @ 2026-05-26 19:51 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: axboe, linux-block
On Tue, May 26, 2026 at 09:00:27AM +0200, Christoph Hellwig wrote:
> -#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
> +static __always_inline const struct bio_vec *
> +__bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
> +{
> + return bvecs + iter.bi_idx;
> +}
There's a couple drivers, nvme-tcp and loop, that call this without the
const qualifier, so this will produce new warnings. The nvme-tcp one is
simpler to fix by just adding the 'const', where loop looks like it
needs a little more consideration to get there, but still doable.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] bvec: make the bvec_iter helpers inline functions
2026-05-26 19:51 ` Keith Busch
@ 2026-05-27 6:39 ` Christoph Hellwig
0 siblings, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2026-05-27 6:39 UTC (permalink / raw)
To: Keith Busch; +Cc: Christoph Hellwig, axboe, linux-block
On Tue, May 26, 2026 at 01:51:44PM -0600, Keith Busch wrote:
> On Tue, May 26, 2026 at 09:00:27AM +0200, Christoph Hellwig wrote:
> > -#define __bvec_iter_bvec(bvec, iter) (&(bvec)[(iter).bi_idx])
> > +static __always_inline const struct bio_vec *
> > +__bvec_iter_bvec(const struct bio_vec *bvecs, const struct bvec_iter iter)
> > +{
> > + return bvecs + iter.bi_idx;
> > +}
>
> There's a couple drivers, nvme-tcp and loop, that call this without the
> const qualifier, so this will produce new warnings. The nvme-tcp one is
> simpler to fix by just adding the 'const', where loop looks like it
> needs a little more consideration to get there, but still doable.
Yeah. I actually had this fixes but sent out just HEAD^..HEAD instead
of including the cleanups from them, which basically copy the nicer
code pattern from the zloop driver.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-05-27 6:39 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-26 7:00 [PATCH] bvec: make the bvec_iter helpers inline functions Christoph Hellwig
2026-05-26 18:09 ` Caleb Sander Mateos
2026-05-26 19:32 ` Bart Van Assche
2026-05-26 19:51 ` Keith Busch
2026-05-27 6:39 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox