Message ID | 20250422142628.1553523-3-hch@lst.de |
---|---|
State | New |
Headers | show |
Series | [01/17] block: add a bio_add_virt_nofail helper | expand |
On 4/22/25 16:26, Christoph Hellwig wrote: > Add a helper to perform synchronous I/O on a kernel direct map range. > Currently this is implemented in various places in usually not very > efficient ways, so provide a generic helper instead. > > Signed-off-by: Christoph Hellwig <hch@lst.de> > --- > block/bio.c | 30 ++++++++++++++++++++++++++++++ > include/linux/bio.h | 5 ++++- > 2 files changed, 34 insertions(+), 1 deletion(-) > > diff --git a/block/bio.c b/block/bio.c > index 4e6c85a33d74..a6a867a432cf 100644 > --- a/block/bio.c > +++ b/block/bio.c > @@ -1301,6 +1301,36 @@ int submit_bio_wait(struct bio *bio) > } > EXPORT_SYMBOL(submit_bio_wait); > > +/** > + * bdev_rw_virt - synchronously read into / write from kernel mapping > + * @bdev: block device to access > + * @sector: sector to accasse > + * @data: data to read/write > + * @len: length to read/write > + * @op: operation (e.g. REQ_OP_READ/REQ_OP_WRITE) > + * > + * Performs synchronous I/O to @bdev for @data/@len. @data must be in > + * the kernel direct mapping and not a vmalloc address. > + */ > +int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, > + size_t len, enum req_op op) > +{ > + struct bio_vec bv; > + struct bio bio; > + int error; > + > + if (WARN_ON_ONCE(is_vmalloc_addr(data))) > + return -EIO; > + > + bio_init(&bio, bdev, &bv, 1, op); > + bio.bi_iter.bi_sector = sector; > + bio_add_virt_nofail(&bio, data, len); > + error = submit_bio_wait(&bio); > + bio_uninit(&bio); > + return error; > +} > +EXPORT_SYMBOL_GPL(bdev_rw_virt); > + > static void bio_wait_end_io(struct bio *bio) > { > complete(bio->bi_private); > diff --git a/include/linux/bio.h b/include/linux/bio.h > index 0678b67162ee..17a10220c57d 100644 > --- a/include/linux/bio.h > +++ b/include/linux/bio.h > @@ -402,7 +402,6 @@ static inline int bio_iov_vecs_to_alloc(struct iov_iter *iter, int max_segs) > > struct request_queue; > > -extern int submit_bio_wait(struct bio *bio); > void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table, > unsigned short max_vecs, blk_opf_t opf); > extern void bio_uninit(struct bio *); > @@ -434,6 +433,10 @@ static inline void bio_add_virt_nofail(struct bio *bio, void *vaddr, > __bio_add_page(bio, virt_to_page(vaddr), len, offset_in_page(vaddr)); > } > > +int submit_bio_wait(struct bio *bio); > +int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, > + size_t len, enum req_op op); > + > int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter); > void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter); > void __bio_release_pages(struct bio *bio, bool mark_dirty); Any specific reason why the declaration of 'submit_bio_wait()' is moved? Other than that: Reviewed-by: Hannes Reinecke <hare@suse.de> Cheers, Hannes
On Wed, Apr 23, 2025 at 08:07:19AM +0200, Hannes Reinecke wrote: >> +int submit_bio_wait(struct bio *bio); >> +int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, >> + size_t len, enum req_op op); >> + >> int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter); >> void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter); >> void __bio_release_pages(struct bio *bio, bool mark_dirty); > > Any specific reason why the declaration of 'submit_bio_wait()' is moved? To keep the related declarations together.
With the typo fixes addressed:
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
diff --git a/block/bio.c b/block/bio.c index 4e6c85a33d74..a6a867a432cf 100644 --- a/block/bio.c +++ b/block/bio.c @@ -1301,6 +1301,36 @@ int submit_bio_wait(struct bio *bio) } EXPORT_SYMBOL(submit_bio_wait); +/** + * bdev_rw_virt - synchronously read into / write from kernel mapping + * @bdev: block device to access + * @sector: sector to accasse + * @data: data to read/write + * @len: length to read/write + * @op: operation (e.g. REQ_OP_READ/REQ_OP_WRITE) + * + * Performs synchronous I/O to @bdev for @data/@len. @data must be in + * the kernel direct mapping and not a vmalloc address. + */ +int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, + size_t len, enum req_op op) +{ + struct bio_vec bv; + struct bio bio; + int error; + + if (WARN_ON_ONCE(is_vmalloc_addr(data))) + return -EIO; + + bio_init(&bio, bdev, &bv, 1, op); + bio.bi_iter.bi_sector = sector; + bio_add_virt_nofail(&bio, data, len); + error = submit_bio_wait(&bio); + bio_uninit(&bio); + return error; +} +EXPORT_SYMBOL_GPL(bdev_rw_virt); + static void bio_wait_end_io(struct bio *bio) { complete(bio->bi_private); diff --git a/include/linux/bio.h b/include/linux/bio.h index 0678b67162ee..17a10220c57d 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -402,7 +402,6 @@ static inline int bio_iov_vecs_to_alloc(struct iov_iter *iter, int max_segs) struct request_queue; -extern int submit_bio_wait(struct bio *bio); void bio_init(struct bio *bio, struct block_device *bdev, struct bio_vec *table, unsigned short max_vecs, blk_opf_t opf); extern void bio_uninit(struct bio *); @@ -434,6 +433,10 @@ static inline void bio_add_virt_nofail(struct bio *bio, void *vaddr, __bio_add_page(bio, virt_to_page(vaddr), len, offset_in_page(vaddr)); } +int submit_bio_wait(struct bio *bio); +int bdev_rw_virt(struct block_device *bdev, sector_t sector, void *data, + size_t len, enum req_op op); + int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter); void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter); void __bio_release_pages(struct bio *bio, bool mark_dirty);
Add a helper to perform synchronous I/O on a kernel direct map range. Currently this is implemented in various places in usually not very efficient ways, so provide a generic helper instead. Signed-off-by: Christoph Hellwig <hch@lst.de> --- block/bio.c | 30 ++++++++++++++++++++++++++++++ include/linux/bio.h | 5 ++++- 2 files changed, 34 insertions(+), 1 deletion(-)