Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Ken Raeburn <raeburn@redhat.com>
Signed-off-by: Matthew Sakai <msakai@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>

authored by

Ken Raeburn and committed by
Mikulas Patocka
f979da51 979a0fd3

+46 -19
+4 -2
drivers/md/dm-vdo/io-submitter.c
··· 327 327 * @error_handler: the handler for submission or I/O errors (may be NULL) 328 328 * @operation: the type of I/O to perform 329 329 * @data: the buffer to read or write (may be NULL) 330 + * @size: the I/O amount in bytes 330 331 * 331 332 * The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block 332 333 * other vdo threads. ··· 339 338 */ 340 339 void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, 341 340 bio_end_io_t callback, vdo_action_fn error_handler, 342 - blk_opf_t operation, char *data) 341 + blk_opf_t operation, char *data, int size) 343 342 { 344 343 int result; 345 344 struct vdo_completion *completion = &vio->completion; ··· 350 349 351 350 vdo_reset_completion(completion); 352 351 completion->error_handler = error_handler; 353 - result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical); 352 + result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META, 353 + physical); 354 354 if (result != VDO_SUCCESS) { 355 355 continue_vio(vio, result); 356 356 return;
+15 -3
drivers/md/dm-vdo/io-submitter.h
··· 8 8 9 9 #include <linux/bio.h> 10 10 11 + #include "constants.h" 11 12 #include "types.h" 12 13 13 14 struct io_submitter; ··· 27 26 28 27 void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical, 29 28 bio_end_io_t callback, vdo_action_fn error_handler, 30 - blk_opf_t operation, char *data); 29 + blk_opf_t operation, char *data, int size); 31 30 32 31 static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical, 33 32 bio_end_io_t callback, vdo_action_fn error_handler, 34 33 blk_opf_t operation) 35 34 { 36 35 __submit_metadata_vio(vio, physical, callback, error_handler, 37 - operation, vio->data); 36 + operation, vio->data, vio->block_count * VDO_BLOCK_SIZE); 37 + } 38 + 39 + static inline void vdo_submit_metadata_vio_with_size(struct vio *vio, 40 + physical_block_number_t physical, 41 + bio_end_io_t callback, 42 + vdo_action_fn error_handler, 43 + blk_opf_t operation, 44 + int size) 45 + { 46 + __submit_metadata_vio(vio, physical, callback, error_handler, 47 + operation, vio->data, size); 38 48 } 39 49 40 50 static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback, ··· 53 41 { 54 42 /* FIXME: Can we just use REQ_OP_FLUSH? */ 55 43 __submit_metadata_vio(vio, 0, callback, error_handler, 56 - REQ_OP_WRITE | REQ_PREFLUSH, NULL); 44 + REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0); 57 45 } 58 46 59 47 #endif /* VDO_IO_SUBMITTER_H */
+3
drivers/md/dm-vdo/types.h
··· 376 376 /* The size of this vio in blocks */ 377 377 unsigned int block_count; 378 378 379 + /* The amount of data to be read or written, in bytes */ 380 + unsigned int io_size; 381 + 379 382 /* The data being read or written. */ 380 383 char *data; 381 384
+22 -14
drivers/md/dm-vdo/vio.c
··· 188 188 189 189 /* 190 190 * Prepares the bio to perform IO with the specified buffer. May only be used on a VDO-allocated 191 - * bio, as it assumes the bio wraps a 4k buffer that is 4k aligned, but there does not have to be a 192 - * vio associated with the bio. 191 + * bio, as it assumes the bio wraps a 4k-multiple buffer that is 4k aligned, but there does not 192 + * have to be a vio associated with the bio. 193 193 */ 194 194 int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, 195 195 blk_opf_t bi_opf, physical_block_number_t pbn) 196 196 { 197 - int bvec_count, offset, len, i; 197 + return vio_reset_bio_with_size(vio, data, vio->block_count * VDO_BLOCK_SIZE, 198 + callback, bi_opf, pbn); 199 + } 200 + 201 + int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, 202 + blk_opf_t bi_opf, physical_block_number_t pbn) 203 + { 204 + int bvec_count, offset, i; 198 205 struct bio *bio = vio->bio; 206 + int vio_size = vio->block_count * VDO_BLOCK_SIZE; 207 + int remaining; 199 208 200 209 bio_reset(bio, bio->bi_bdev, bi_opf); 201 210 vdo_set_bio_properties(bio, vio, callback, bi_opf, pbn); ··· 214 205 bio->bi_ioprio = 0; 215 206 bio->bi_io_vec = bio->bi_inline_vecs; 216 207 bio->bi_max_vecs = vio->block_count + 1; 217 - len = VDO_BLOCK_SIZE * vio->block_count; 208 + if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d", 209 + size, vio_size) != VDO_SUCCESS) 210 + size = vio_size; 211 + vio->io_size = size; 218 212 offset = offset_in_page(data); 219 - bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE); 213 + bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE); 214 + remaining = size; 220 215 221 - /* 222 - * If we knew that data was always on one page, or contiguous pages, we wouldn't need the 223 - * loop. But if we're using vmalloc, it's not impossible that the data is in different 224 - * pages that can't be merged in bio_add_page... 225 - */ 226 - for (i = 0; (i < bvec_count) && (len > 0); i++) { 216 + for (i = 0; (i < bvec_count) && (remaining > 0); i++) { 227 217 struct page *page; 228 218 int bytes_added; 229 219 int bytes = PAGE_SIZE - offset; 230 220 231 - if (bytes > len) 232 - bytes = len; 221 + if (bytes > remaining) 222 + bytes = remaining; 233 223 234 224 page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data); 235 225 bytes_added = bio_add_page(bio, page, bytes, offset); ··· 240 232 } 241 233 242 234 data += bytes; 243 - len -= bytes; 235 + remaining -= bytes; 244 236 offset = 0; 245 237 } 246 238
+2
drivers/md/dm-vdo/vio.h
··· 125 125 126 126 int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback, 127 127 blk_opf_t bi_opf, physical_block_number_t pbn); 128 + int vio_reset_bio_with_size(struct vio *vio, char *data, int size, bio_end_io_t callback, 129 + blk_opf_t bi_opf, physical_block_number_t pbn); 128 130 129 131 void update_vio_error_stats(struct vio *vio, const char *format, ...) 130 132 __printf(2, 3);