diff options
Diffstat (limited to 'block/blk-settings.c')
-rw-r--r-- | block/blk-settings.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/block/blk-settings.c b/block/blk-settings.c index d52d4adc440b..5eeb9e0d256e 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -528,7 +528,7 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
528 | sector_t offset) | 528 | sector_t offset) |
529 | { | 529 | { |
530 | sector_t alignment; | 530 | sector_t alignment; |
531 | unsigned int top, bottom; | 531 | unsigned int top, bottom, ret = 0; |
532 | 532 | ||
533 | 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); |
534 | 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); |
@@ -546,6 +546,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
546 | t->max_segment_size = min_not_zero(t->max_segment_size, | 546 | t->max_segment_size = min_not_zero(t->max_segment_size, |
547 | b->max_segment_size); | 547 | b->max_segment_size); |
548 | 548 | ||
549 | t->misaligned |= b->misaligned; | ||
550 | |||
549 | alignment = queue_limit_alignment_offset(b, offset); | 551 | alignment = queue_limit_alignment_offset(b, offset); |
550 | 552 | ||
551 | /* Bottom device has different alignment. Check that it is | 553 | /* Bottom device has different alignment. Check that it is |
@@ -558,8 +560,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
558 | bottom = max(b->physical_block_size, b->io_min) + alignment; | 560 | bottom = max(b->physical_block_size, b->io_min) + alignment; |
559 | 561 | ||
560 | /* Verify that top and bottom intervals line up */ | 562 | /* Verify that top and bottom intervals line up */ |
561 | if (max(top, bottom) & (min(top, bottom) - 1)) | 563 | if (max(top, bottom) & (min(top, bottom) - 1)) { |
562 | t->misaligned = 1; | 564 | t->misaligned = 1; |
565 | ret = -1; | ||
566 | } | ||
563 | } | 567 | } |
564 | 568 | ||
565 | t->logical_block_size = max(t->logical_block_size, | 569 | t->logical_block_size = max(t->logical_block_size, |
@@ -578,18 +582,21 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
578 | if (t->physical_block_size & (t->logical_block_size - 1)) { | 582 | if (t->physical_block_size & (t->logical_block_size - 1)) { |
579 | t->physical_block_size = t->logical_block_size; | 583 | t->physical_block_size = t->logical_block_size; |
580 | t->misaligned = 1; | 584 | t->misaligned = 1; |
585 | ret = -1; | ||
581 | } | 586 | } |
582 | 587 | ||
583 | /* Minimum I/O a multiple of the physical block size? */ | 588 | /* Minimum I/O a multiple of the physical block size? */ |
584 | if (t->io_min & (t->physical_block_size - 1)) { | 589 | if (t->io_min & (t->physical_block_size - 1)) { |
585 | t->io_min = t->physical_block_size; | 590 | t->io_min = t->physical_block_size; |
586 | t->misaligned = 1; | 591 | t->misaligned = 1; |
592 | ret = -1; | ||
587 | } | 593 | } |
588 | 594 | ||
589 | /* Optimal I/O a multiple of the physical block size? */ | 595 | /* Optimal I/O a multiple of the physical block size? */ |
590 | if (t->io_opt & (t->physical_block_size - 1)) { | 596 | if (t->io_opt & (t->physical_block_size - 1)) { |
591 | t->io_opt = 0; | 597 | t->io_opt = 0; |
592 | t->misaligned = 1; | 598 | t->misaligned = 1; |
599 | ret = -1; | ||
593 | } | 600 | } |
594 | 601 | ||
595 | /* Find lowest common alignment_offset */ | 602 | /* Find lowest common alignment_offset */ |
@@ -597,8 +604,10 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
597 | & (max(t->physical_block_size, t->io_min) - 1); | 604 | & (max(t->physical_block_size, t->io_min) - 1); |
598 | 605 | ||
599 | /* Verify that new alignment_offset is on a logical block boundary */ | 606 | /* Verify that new alignment_offset is on a logical block boundary */ |
600 | if (t->alignment_offset & (t->logical_block_size - 1)) | 607 | if (t->alignment_offset & (t->logical_block_size - 1)) { |
601 | t->misaligned = 1; | 608 | t->misaligned = 1; |
609 | ret = -1; | ||
610 | } | ||
602 | 611 | ||
603 | /* Discard alignment and granularity */ | 612 | /* Discard alignment and granularity */ |
604 | if (b->discard_granularity) { | 613 | if (b->discard_granularity) { |
@@ -626,11 +635,33 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
626 | (t->discard_granularity - 1); | 635 | (t->discard_granularity - 1); |
627 | } | 636 | } |
628 | 637 | ||
629 | return t->misaligned ? -1 : 0; | 638 | return ret; |
630 | } | 639 | } |
631 | EXPORT_SYMBOL(blk_stack_limits); | 640 | EXPORT_SYMBOL(blk_stack_limits); |
632 | 641 | ||
633 | /** | 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 | */ | ||
653 | int 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 | } | ||
662 | EXPORT_SYMBOL(bdev_stack_limits); | ||
663 | |||
664 | /** | ||
634 | * disk_stack_limits - adjust queue limits for stacked drivers | 665 | * disk_stack_limits - adjust queue limits for stacked drivers |
635 | * @disk: MD/DM gendisk (top) | 666 | * @disk: MD/DM gendisk (top) |
636 | * @bdev: the underlying block device (bottom) | 667 | * @bdev: the underlying block device (bottom) |