History

ublk: add segment parameter

IO split is usually bad in io_uring world, since -EAGAIN is caused and IO handling may have to fallback to io-wq, this way does hurt performance. ublk starts to support zero copy recently, for avoiding unnecessary IO split, ublk driver's segment limit should be aligned with backend device's segment limit. Another reason is that io_buffer_register_bvec() needs to allocate bvecs, which number is aligned with ublk request segment number, so that big memory allocation can be avoided by setting reasonable max_segments limit. So add segment parameter for providing ublk server chance to align segment limit with backend, and keep it reasonable from implementation viewpoint.

Ming Lei committed 1 year ago

Commit ebf695f1 parent b460f322 files · +44 −1Browse files

Unified · Split

2 files
  1. drivers/block/ublk_drv.c +19 −1
  2. include/uapi/linux/ublk_cmd.h +25 −0
drivers/block/ublk_drv.c+19−1
@@ -74,7 +74,7 @@ · 73 unmodified lines
74#define UBLK_PARAM_TYPE_ALL \74#define UBLK_PARAM_TYPE_ALL \
75 (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \75 (UBLK_PARAM_TYPE_BASIC | UBLK_PARAM_TYPE_DISCARD | \
76 UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED | \76 UBLK_PARAM_TYPE_DEVT | UBLK_PARAM_TYPE_ZONED | \
77 UBLK_PARAM_TYPE_DMA_ALIGN)77 UBLK_PARAM_TYPE_DMA_ALIGN | UBLK_PARAM_TYPE_SEGMENT)
78 78
79struct ublk_rq_data {79struct ublk_rq_data {
80 struct kref ref;80 struct kref ref;
@@ -580,6 +580,18 @@ static int ublk_validate_params(const struct ublk_device *ub) · 499 unmodified lines
580 return -EINVAL;580 return -EINVAL;
581 }581 }
582 582
583 if (ub->params.types & UBLK_PARAM_TYPE_SEGMENT) {
584 const struct ublk_param_segment *p = &ub->params.seg;
585
586 if (!is_power_of_2(p->seg_boundary_mask + 1))
587 return -EINVAL;
588
589 if (p->seg_boundary_mask + 1 < UBLK_MIN_SEGMENT_SIZE)
590 return -EINVAL;
591 if (p->max_segment_size < UBLK_MIN_SEGMENT_SIZE)
592 return -EINVAL;
593 }
594
583 return 0;595 return 0;
584}596}
585 597
@@ -2370,6 +2382,12 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd) · 1784 unmodified lines
2370 if (ub->params.types & UBLK_PARAM_TYPE_DMA_ALIGN)2382 if (ub->params.types & UBLK_PARAM_TYPE_DMA_ALIGN)
2371 lim.dma_alignment = ub->params.dma.alignment;2383 lim.dma_alignment = ub->params.dma.alignment;
2372 2384
2385 if (ub->params.types & UBLK_PARAM_TYPE_SEGMENT) {
2386 lim.seg_boundary_mask = ub->params.seg.seg_boundary_mask;
2387 lim.max_segment_size = ub->params.seg.max_segment_size;
2388 lim.max_segments = ub->params.seg.max_segments;
2389 }
2390
2373 if (wait_for_completion_interruptible(&ub->completion) != 0)2391 if (wait_for_completion_interruptible(&ub->completion) != 0)
2374 return -EINTR;2392 return -EINTR;
2375 2393
include/uapi/linux/ublk_cmd.h+25−0
@@ -410,6 +410,29 @@ struct ublk_param_dma_align { · 409 unmodified lines
410 __u8 pad[4];410 __u8 pad[4];
411};411};
412 412
413#define UBLK_MIN_SEGMENT_SIZE 4096
414/*
415 * If any one of the three segment parameter is set as 0, the behavior is
416 * undefined.
417 */
418struct ublk_param_segment {
419 /*
420 * seg_boundary_mask + 1 needs to be power_of_2(), and the sum has
421 * to be >= UBLK_MIN_SEGMENT_SIZE(4096)
422 */
423 __u64 seg_boundary_mask;
424
425 /*
426 * max_segment_size could be override by virt_boundary_mask, so be
427 * careful when setting both.
428 *
429 * max_segment_size has to be >= UBLK_MIN_SEGMENT_SIZE(4096)
430 */
431 __u32 max_segment_size;
432 __u16 max_segments;
433 __u8 pad[2];
434};
435
413struct ublk_params {436struct ublk_params {
414 /*437 /*
415 * Total length of parameters, userspace has to set 'len' for both438 * Total length of parameters, userspace has to set 'len' for both
@@ -423,6 +446,7 @@ struct ublk_params { · 7 unmodified lines
423#define UBLK_PARAM_TYPE_DEVT (1 << 2)446#define UBLK_PARAM_TYPE_DEVT (1 << 2)
424#define UBLK_PARAM_TYPE_ZONED (1 << 3)447#define UBLK_PARAM_TYPE_ZONED (1 << 3)
425#define UBLK_PARAM_TYPE_DMA_ALIGN (1 << 4)448#define UBLK_PARAM_TYPE_DMA_ALIGN (1 << 4)
449#define UBLK_PARAM_TYPE_SEGMENT (1 << 5)
426 __u32 types; /* types of parameter included */450 __u32 types; /* types of parameter included */
427 451
428 struct ublk_param_basic basic;452 struct ublk_param_basic basic;
@@ -430,6 +454,7 @@ struct ublk_params { · 1 unmodified line
430 struct ublk_param_devt devt;454 struct ublk_param_devt devt;
431 struct ublk_param_zoned zoned;455 struct ublk_param_zoned zoned;
432 struct ublk_param_dma_align dma;456 struct ublk_param_dma_align dma;
457 struct ublk_param_segment seg;
433};458};
434 459
435#endif460#endif