Skip to content

Commit f979da5

Browse files
raeburnMikulas Patocka
authored andcommitted
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>
1 parent 979a0fd commit f979da5

File tree

5 files changed

+46
-19
lines changed

5 files changed

+46
-19
lines changed

drivers/md/dm-vdo/io-submitter.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio)
327327
* @error_handler: the handler for submission or I/O errors (may be NULL)
328328
* @operation: the type of I/O to perform
329329
* @data: the buffer to read or write (may be NULL)
330+
* @size: the I/O amount in bytes
330331
*
331332
* The vio is enqueued on a vdo bio queue so that bio submission (which may block) does not block
332333
* other vdo threads.
@@ -338,7 +339,7 @@ void vdo_submit_data_vio(struct data_vio *data_vio)
338339
*/
339340
void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
340341
bio_end_io_t callback, vdo_action_fn error_handler,
341-
blk_opf_t operation, char *data)
342+
blk_opf_t operation, char *data, int size)
342343
{
343344
int result;
344345
struct vdo_completion *completion = &vio->completion;
@@ -349,7 +350,8 @@ void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
349350

350351
vdo_reset_completion(completion);
351352
completion->error_handler = error_handler;
352-
result = vio_reset_bio(vio, data, callback, operation | REQ_META, physical);
353+
result = vio_reset_bio_with_size(vio, data, size, callback, operation | REQ_META,
354+
physical);
353355
if (result != VDO_SUCCESS) {
354356
continue_vio(vio, result);
355357
return;

drivers/md/dm-vdo/io-submitter.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/bio.h>
1010

11+
#include "constants.h"
1112
#include "types.h"
1213

1314
struct io_submitter;
@@ -26,22 +27,33 @@ void vdo_submit_data_vio(struct data_vio *data_vio);
2627

2728
void __submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
2829
bio_end_io_t callback, vdo_action_fn error_handler,
29-
blk_opf_t operation, char *data);
30+
blk_opf_t operation, char *data, int size);
3031

3132
static inline void vdo_submit_metadata_vio(struct vio *vio, physical_block_number_t physical,
3233
bio_end_io_t callback, vdo_action_fn error_handler,
3334
blk_opf_t operation)
3435
{
3536
__submit_metadata_vio(vio, physical, callback, error_handler,
36-
operation, vio->data);
37+
operation, vio->data, vio->block_count * VDO_BLOCK_SIZE);
38+
}
39+
40+
static inline void vdo_submit_metadata_vio_with_size(struct vio *vio,
41+
physical_block_number_t physical,
42+
bio_end_io_t callback,
43+
vdo_action_fn error_handler,
44+
blk_opf_t operation,
45+
int size)
46+
{
47+
__submit_metadata_vio(vio, physical, callback, error_handler,
48+
operation, vio->data, size);
3749
}
3850

3951
static inline void vdo_submit_flush_vio(struct vio *vio, bio_end_io_t callback,
4052
vdo_action_fn error_handler)
4153
{
4254
/* FIXME: Can we just use REQ_OP_FLUSH? */
4355
__submit_metadata_vio(vio, 0, callback, error_handler,
44-
REQ_OP_WRITE | REQ_PREFLUSH, NULL);
56+
REQ_OP_WRITE | REQ_PREFLUSH, NULL, 0);
4557
}
4658

4759
#endif /* VDO_IO_SUBMITTER_H */

drivers/md/dm-vdo/types.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ struct vio {
376376
/* The size of this vio in blocks */
377377
unsigned int block_count;
378378

379+
/* The amount of data to be read or written, in bytes */
380+
unsigned int io_size;
381+
379382
/* The data being read or written. */
380383
char *data;
381384

drivers/md/dm-vdo/vio.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,23 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb
188188

189189
/*
190190
* 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.
193193
*/
194194
int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
195195
blk_opf_t bi_opf, physical_block_number_t pbn)
196196
{
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;
198205
struct bio *bio = vio->bio;
206+
int vio_size = vio->block_count * VDO_BLOCK_SIZE;
207+
int remaining;
199208

200209
bio_reset(bio, bio->bi_bdev, bi_opf);
201210
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,
205214
bio->bi_ioprio = 0;
206215
bio->bi_io_vec = bio->bi_inline_vecs;
207216
bio->bi_max_vecs = vio->block_count + 1;
208-
len = VDO_BLOCK_SIZE * vio->block_count;
217+
if (VDO_ASSERT(size <= vio_size, "specified size %d is not greater than allocated %d",
218+
size, vio_size) != VDO_SUCCESS)
219+
size = vio_size;
220+
vio->io_size = size;
209221
offset = offset_in_page(data);
210-
bvec_count = DIV_ROUND_UP(offset + len, PAGE_SIZE);
222+
bvec_count = DIV_ROUND_UP(offset + size, PAGE_SIZE);
223+
remaining = size;
211224

212-
/*
213-
* If we knew that data was always on one page, or contiguous pages, we wouldn't need the
214-
* loop. But if we're using vmalloc, it's not impossible that the data is in different
215-
* pages that can't be merged in bio_add_page...
216-
*/
217-
for (i = 0; (i < bvec_count) && (len > 0); i++) {
225+
for (i = 0; (i < bvec_count) && (remaining > 0); i++) {
218226
struct page *page;
219227
int bytes_added;
220228
int bytes = PAGE_SIZE - offset;
221229

222-
if (bytes > len)
223-
bytes = len;
230+
if (bytes > remaining)
231+
bytes = remaining;
224232

225233
page = is_vmalloc_addr(data) ? vmalloc_to_page(data) : virt_to_page(data);
226234
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,
232240
}
233241

234242
data += bytes;
235-
len -= bytes;
243+
remaining -= bytes;
236244
offset = 0;
237245
}
238246

drivers/md/dm-vdo/vio.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ void vdo_set_bio_properties(struct bio *bio, struct vio *vio, bio_end_io_t callb
125125

126126
int vio_reset_bio(struct vio *vio, char *data, bio_end_io_t callback,
127127
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);
128130

129131
void update_vio_error_stats(struct vio *vio, const char *format, ...)
130132
__printf(2, 3);

0 commit comments

Comments
 (0)