aboutsummaryrefslogtreecommitdiffstats
path: root/block/blk-settings.c
diff options
context:
space:
mode:
Diffstat (limited to 'block/blk-settings.c')
-rw-r--r--block/blk-settings.c140
1 files changed, 103 insertions, 37 deletions
diff --git a/block/blk-settings.c b/block/blk-settings.c
index 6ae118d6e193..5eeb9e0d256e 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -505,21 +505,30 @@ static unsigned int lcm(unsigned int a, unsigned int b)
505 505
506/** 506/**
507 * blk_stack_limits - adjust queue_limits for stacked devices 507 * blk_stack_limits - adjust queue_limits for stacked devices
508 * @t: the stacking driver limits (top) 508 * @t: the stacking driver limits (top device)
509 * @b: the underlying queue limits (bottom) 509 * @b: the underlying queue limits (bottom, component device)
510 * @offset: offset to beginning of data within component device 510 * @offset: offset to beginning of data within component device
511 * 511 *
512 * Description: 512 * Description:
513 * Merges two queue_limit structs. Returns 0 if alignment didn't 513 * This function is used by stacking drivers like MD and DM to ensure
514 * change. Returns -1 if adding the bottom device caused 514 * that all component devices have compatible block sizes and
515 * misalignment. 515 * alignments. The stacking driver must provide a queue_limits
516 * struct (top) and then iteratively call the stacking function for
517 * all component (bottom) devices. The stacking function will
518 * attempt to combine the values and ensure proper alignment.
519 *
520 * Returns 0 if the top and bottom queue_limits are compatible. The
521 * top device's block sizes and alignment offsets may be adjusted to
522 * ensure alignment with the bottom device. If no compatible sizes
523 * and alignments exist, -1 is returned and the resulting top
524 * queue_limits will have the misaligned flag set to indicate that
525 * the alignment_offset is undefined.
516 */ 526 */
517int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, 527int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
518 sector_t offset) 528 sector_t offset)
519{ 529{
520 int ret; 530 sector_t alignment;
521 531 unsigned int top, bottom, ret = 0;
522 ret = 0;
523 532
524 t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors); 533 t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors);
525 t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); 534 t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors);
@@ -537,6 +546,26 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
537 t->max_segment_size = min_not_zero(t->max_segment_size, 546 t->max_segment_size = min_not_zero(t->max_segment_size,
538 b->max_segment_size); 547 b->max_segment_size);
539 548
549 t->misaligned |= b->misaligned;
550
551 alignment = queue_limit_alignment_offset(b, offset);
552
553 /* Bottom device has different alignment. Check that it is
554 * compatible with the current top alignment.
555 */
556 if (t->alignment_offset != alignment) {
557
558 top = max(t->physical_block_size, t->io_min)
559 + t->alignment_offset;
560 bottom = max(b->physical_block_size, b->io_min) + alignment;
561
562 /* Verify that top and bottom intervals line up */
563 if (max(top, bottom) & (min(top, bottom) - 1)) {
564 t->misaligned = 1;
565 ret = -1;
566 }
567 }
568
540 t->logical_block_size = max(t->logical_block_size, 569 t->logical_block_size = max(t->logical_block_size,
541 b->logical_block_size); 570 b->logical_block_size);
542 571
@@ -544,58 +573,95 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
544 b->physical_block_size); 573 b->physical_block_size);
545 574
546 t->io_min = max(t->io_min, b->io_min); 575 t->io_min = max(t->io_min, b->io_min);
576 t->io_opt = lcm(t->io_opt, b->io_opt);
577
547 t->no_cluster |= b->no_cluster; 578 t->no_cluster |= b->no_cluster;
548 t->discard_zeroes_data &= b->discard_zeroes_data; 579 t->discard_zeroes_data &= b->discard_zeroes_data;
549 580
550 /* Bottom device offset aligned? */ 581 /* Physical block size a multiple of the logical block size? */
551 if (offset && 582 if (t->physical_block_size & (t->logical_block_size - 1)) {
552 (offset & (b->physical_block_size - 1)) != b->alignment_offset) { 583 t->physical_block_size = t->logical_block_size;
553 t->misaligned = 1; 584 t->misaligned = 1;
554 ret = -1; 585 ret = -1;
555 } 586 }
556 587
557 /* 588 /* Minimum I/O a multiple of the physical block size? */
558 * Temporarily disable discard granularity. It's currently buggy 589 if (t->io_min & (t->physical_block_size - 1)) {
559 * since we default to 0 for discard_granularity, hence this 590 t->io_min = t->physical_block_size;
560 * "failure" will always trigger for non-zero offsets. 591 t->misaligned = 1;
561 */
562#if 0
563 if (offset &&
564 (offset & (b->discard_granularity - 1)) != b->discard_alignment) {
565 t->discard_misaligned = 1;
566 ret = -1; 592 ret = -1;
567 } 593 }
568#endif
569 594
570 /* If top has no alignment offset, inherit from bottom */ 595 /* Optimal I/O a multiple of the physical block size? */
571 if (!t->alignment_offset) 596 if (t->io_opt & (t->physical_block_size - 1)) {
572 t->alignment_offset = 597 t->io_opt = 0;
573 b->alignment_offset & (b->physical_block_size - 1); 598 t->misaligned = 1;
599 ret = -1;
600 }
574 601
575 if (!t->discard_alignment) 602 /* Find lowest common alignment_offset */
576 t->discard_alignment = 603 t->alignment_offset = lcm(t->alignment_offset, alignment)
577 b->discard_alignment & (b->discard_granularity - 1); 604 & (max(t->physical_block_size, t->io_min) - 1);
578 605
579 /* Top device aligned on logical block boundary? */ 606 /* Verify that new alignment_offset is on a logical block boundary */
580 if (t->alignment_offset & (t->logical_block_size - 1)) { 607 if (t->alignment_offset & (t->logical_block_size - 1)) {
581 t->misaligned = 1; 608 t->misaligned = 1;
582 ret = -1; 609 ret = -1;
583 } 610 }
584 611
585 /* Find lcm() of optimal I/O size and granularity */ 612 /* Discard alignment and granularity */
586 t->io_opt = lcm(t->io_opt, b->io_opt); 613 if (b->discard_granularity) {
587 t->discard_granularity = lcm(t->discard_granularity, 614 unsigned int granularity = b->discard_granularity;
588 b->discard_granularity); 615 offset &= granularity - 1;
589 616
590 /* Verify that optimal I/O size is a multiple of io_min */ 617 alignment = (granularity + b->discard_alignment - offset)
591 if (t->io_min && t->io_opt % t->io_min) 618 & (granularity - 1);
592 ret = -1; 619
620 if (t->discard_granularity != 0 &&
621 t->discard_alignment != alignment) {
622 top = t->discard_granularity + t->discard_alignment;
623 bottom = b->discard_granularity + alignment;
624
625 /* Verify that top and bottom intervals line up */
626 if (max(top, bottom) & (min(top, bottom) - 1))
627 t->discard_misaligned = 1;
628 }
629
630 t->max_discard_sectors = min_not_zero(t->max_discard_sectors,
631 b->max_discard_sectors);
632 t->discard_granularity = max(t->discard_granularity,
633 b->discard_granularity);
634 t->discard_alignment = lcm(t->discard_alignment, alignment) &
635 (t->discard_granularity - 1);
636 }
593 637
594 return ret; 638 return ret;
595} 639}
596EXPORT_SYMBOL(blk_stack_limits); 640EXPORT_SYMBOL(blk_stack_limits);
597 641
598/** 642/**
643 * bdev_stack_limits - adjust queue limits for stacked drivers
644 * @t: the stacking driver limits (top device)
645 * @bdev: the component block_device (bottom)
646 * @start: first data sector within component device
647 *
648 * Description:
649 * Merges queue limits for a top device and a block_device. Returns
650 * 0 if alignment didn't change. Returns -1 if adding the bottom
651 * device caused misalignment.
652 */
653int bdev_stack_limits(struct queue_limits *t, struct block_device *bdev,
654 sector_t start)
655{
656 struct request_queue *bq = bdev_get_queue(bdev);
657
658 start += get_start_sect(bdev);
659
660 return blk_stack_limits(t, &bq->limits, start << 9);
661}
662EXPORT_SYMBOL(bdev_stack_limits);
663
664/**
599 * disk_stack_limits - adjust queue limits for stacked drivers 665 * disk_stack_limits - adjust queue limits for stacked drivers
600 * @disk: MD/DM gendisk (top) 666 * @disk: MD/DM gendisk (top)
601 * @bdev: the underlying block device (bottom) 667 * @bdev: the underlying block device (bottom)