Skip to contentSkip to conversation

Patch "dm vdo vio-pool: allow variable-sized metadata vios" has been added to the 6.12-stable tree

DISCUSSION Matthew Sakai 1 participant 1 message May 22, 2025 1 message not in the archive Stable branch

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw
Quoted 7 lines · Sasha Levin

This is a note to let you know that I've just added the patch titled

dm vdo vio-pool: allow variable-sized metadata vios

to the 6.12-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

Quoted 6 lines

The filename of the patch is:
dm-vdo-vio-pool-allow-variable-sized-metadata-vios.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.

There is no reason to pull this patch into 6.12 since there are no features in 6.12 that would use it.

Matt

Quoted 199 lines

commit ac663217ac4eeab508db348a67511d45ccd9846f

Author: Ken Raeburn <[email protected]>
Date:   Fri Jan 31 21:18:05 2025 -0500

dm vdo vio-pool: allow variable-sized metadata vios

[ 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.

drivers/md/dm-vdo/io-submitter.c +4 -2
index ab62abe18827b..a664be89c15d7 100644
@@ -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)
+			   blk_opf_t operation, char *data, int size)
  {
  	int result;
  	struct vdo_completion *completion = &vio->completion;
@@ -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,
+					 physical);
  	if (result != VDO_SUCCESS) {
  		continue_vio(vio, result);
  		return;
drivers/md/dm-vdo/io-submitter.h +15 -3
index 80748699496f2..3088f11055fdd 100644
@@ -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 */
drivers/md/dm-vdo/types.h +3 -0
index dbe892b10f265..cdf36e7d77021 100644
@@ -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;
 
drivers/md/dm-vdo/vio.c +22 -14
index b291578f726f5..7c417c1af4516 100644
@@ -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
+ * have to be a vio associated with the bio.
   */
  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 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);
@@ -204,22 +213,21 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
 
  	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);
@@ -231,7 +239,7 @@ int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
  		}
 
  		data += bytes;
-		len -= bytes;
+		remaining -= bytes;
  		offset = 0;
  	}
 
drivers/md/dm-vdo/vio.h +2 -0
index 3490e9f59b04a..74e8fd7c8c029 100644
@@ -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);