On 5/27/25 12:26 PM, Greg Kroah-Hartman wrote:
6.14-stable review patch. If anyone has any objections, please let me know.
There's no reason to take this patch for 6.14, it can just be dropped.
This patch adds a new interface, but the subsequent patches that use that interface are not being backported. So it won't hurt anything, but it's also useless in 6.14.
Matt
From: Ken Raeburn raeburn@redhat.com
[ Upstream commit f979da512553a41a657f2c1198277e84d66f8ce3 ]
With larger-sized metadata vio pools, vdo will sometimes need to issue I/O with a smaller size than the allocated size. Since vio_reset_bio is where the bvec array and I/O size are initialized, this reset interface must now specify what I/O size to use.
Signed-off-by: Ken Raeburn raeburn@redhat.com Signed-off-by: Matthew Sakai msakai@redhat.com Signed-off-by: Mikulas Patocka mpatocka@redhat.com Signed-off-by: Sasha Levin sashal@kernel.org
drivers/md/dm-vdo/io-submitter.c | 6 ++++-- drivers/md/dm-vdo/io-submitter.h | 18 +++++++++++++--- drivers/md/dm-vdo/types.h | 3 +++ drivers/md/dm-vdo/vio.c | 36 +++++++++++++++++++------------- drivers/md/dm-vdo/vio.h | 2 ++ 5 files changed, 46 insertions(+), 19 deletions(-)
diff --git a/drivers/md/dm-vdo/io-submitter.c b/drivers/md/dm-vdo/io-submitter.c index 421e5436c32c9..11d47770b54d2 100644 --- a/drivers/md/dm-vdo/io-submitter.c +++ b/drivers/md/dm-vdo/io-submitter.c @@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio)
- @error_handler: the handler for submission or I/O errors (may be NULL)
- @operation: the type of I/O to perform
- @data: the buffer to read or write (may be NULL)
- @size: the I/O amount in bytes
- The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block
- other vdo threads.
@@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio) */ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler,
blk_opf_t operation, char *data)
{ int result; struct vdo_completion *completion = &vio->completion;blk_opf_t operation, char *data, int size)
@@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, vdo_reset_completion(completion); completion->error_handler = error_handler;
- result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical);
- result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META,
if (result != VDO_SUCCESS) { continue_vio(vio, result); return;physical);
diff --git a/drivers/md/dm-vdo/io-submitter.h b/drivers/md/dm-vdo/io-submitter.h index 80748699496f2..3088f11055fdd 100644 --- a/drivers/md/dm-vdo/io-submitter.h +++ b/drivers/md/dm-vdo/io-submitter.h @@ -8,6 +8,7 @@ #include <linux/bio.h> +#include "constants.h" #include "types.h" struct io_submitter; @@ -26,14 +27,25 @@ void vdo_submit_data_vio(struct data_vio *data_vio); void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler,
blk_opf_t operation, char *data);
blk_opf_t operation, char *data, int size);
static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical, bio_end_io_t callback, vdo_action_fn error_handler, blk_opf_t operation) { __submit_metadata_vio(vio, physical, callback, error_handler,
operation, vio->data);
operation, vio->data, vio->block_count * VDO_BLOCK_SIZE);
+}
+static inline void vdo_submit_metadata_vio_with_size(struct vio *vio,
physical_block_number_t physical,
bio_end_io_t callback,
vdo_action_fn error_handler,
blk_opf_t operation,
int size)
+{
- __submit_metadata_vio(vio, physical, callback, error_handler,
}operation, vio->data, size);
static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, @@ -41,7 +53,7 @@ static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, { /* FIXME: Can we just use REQ_OP_FLUSH? */ __submit_metadata_vio(vio, 0, callback, error_handler,
REQ_OP_WRITE | REQ_PREFLUSH, NULL);
}REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0);
#endif /* VDO_IO_SUBMITTER_H */ diff --git a/drivers/md/dm-vdo/types.h b/drivers/md/dm-vdo/types.h index dbe892b10f265..cdf36e7d77021 100644 --- a/drivers/md/dm-vdo/types.h +++ b/drivers/md/dm-vdo/types.h @@ -376,6 +376,9 @@ struct vio { /* The size of this vio in blocks */ unsigned int block_count;
- /* The amount of data to be read or written, in bytes */
- unsigned int io_size;
- /* The data being read or written. */ char *data;
diff --git a/drivers/md/dm-vdo/vio.c b/drivers/md/dm-vdo/vio.c index e710f3c5a972d..725d87ecf2150 100644 --- a/drivers/md/dm-vdo/vio.c +++ b/drivers/md/dm-vdo/vio.c @@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb /*
- Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated
- bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a
- vio associated with the bio.
- bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not
*/ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, blk_opf_t bi_opf, physical_block_number_t pbn) {
- have to be a vio associated with the bio.
- int bvec_count, offset, len, i;
- return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE,
callback, bi_opf, pbn);
+}
+int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback,
blk_opf_t bi_opf, physical_block_number_t pbn)
+{
- int bvec_count, offset, i; struct bio *bio = vio->bio;
- int vio_size = vio->block_count * VDO_BLOCK_SIZE;
- int remaining;
bio_reset(bio, bio->bi_bdev, bi_opf); vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn); @@ -205,22 +214,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, bio->bi_ioprio = 0; bio->bi_io_vec = bio->bi_inline_vecs; bio->bi_max_vecs = vio->block_count + 1;
- len = VDO_BLOCK_SIZE * vio->block_count;
- if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d",
size, vio_size) != VDO_SUCCESS)
size = vio_size;
- vio->io_size = size; offset = offset_in_page(data);
- bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE);
- bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE);
- remaining = size;
- /*
* If we knew that data was always on one page, or contiguous pages, we wouldn't need the
* loop. But if we're using vmalloc, it's not impossible that the data is in different
* pages that can't be merged in bio_add_page...
*/
- for (i = 0; (i < bvec_count) && (len > 0); i++) {
- for (i = 0; (i < bvec_count) && (remaining > 0); i++) { struct page *page; int bytes_added; int bytes = PAGE_SIZE - offset;
if (bytes > len)
bytes = len;
if (bytes > remaining)
bytes = remaining;
page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data); bytes_added = bio_add_page(bio, page, bytes, offset); @@ -232,7 +240,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, } data += bytes;
len -= bytes;
offset = 0; }remaining -= bytes;
diff --git a/drivers/md/dm-vdo/vio.h b/drivers/md/dm-vdo/vio.h index 3490e9f59b04a..74e8fd7c8c029 100644 --- a/drivers/md/dm-vdo/vio.h +++ b/drivers/md/dm-vdo/vio.h @@ -123,6 +123,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, blk_opf_t bi_opf, physical_block_number_t pbn); +int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback,
blk_opf_t bi_opf, physical_block_number_t pbn);
void update_vio_error_stats(struct vio *vio, const char *format, ...) __printf(2, 3);