Commit f979da51 authored by Ken Raeburn's avatar Ken Raeburn Committed by Mikulas Patocka
Browse files

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



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: default avatarKen Raeburn <raeburn@redhat.com>
Signed-off-by: default avatarMatthew Sakai <msakai@redhat.com>
Signed-off-by: default avatarMikulas Patocka <mpatocka@redhat.com>
parent 979a0fd3
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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;
+15 −3
Original line number Diff line number Diff line
@@ -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 */
+3 −0
Original line number Diff line number Diff line
@@ -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;

+22 −14
Original line number Diff line number Diff line
@@ -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);
@@ -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;
		remaining -= bytes;
		offset = 0;
	}

+2 −0
Original line number Diff line number Diff line
@@ -125,6 +125,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);