diff options
Diffstat (limited to 'block')
-rw-r--r-- | block/blk-settings.c | 46 | ||||
-rw-r--r-- | block/blk-sysfs.c | 22 | ||||
-rw-r--r-- | block/genhd.c | 12 |
3 files changed, 70 insertions, 10 deletions
diff --git a/block/blk-settings.c b/block/blk-settings.c index 66d4aa8799b7..7f986cafacd5 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c | |||
@@ -96,7 +96,10 @@ void blk_set_default_limits(struct queue_limits *lim) | |||
96 | lim->max_segment_size = MAX_SEGMENT_SIZE; | 96 | lim->max_segment_size = MAX_SEGMENT_SIZE; |
97 | lim->max_sectors = BLK_DEF_MAX_SECTORS; | 97 | lim->max_sectors = BLK_DEF_MAX_SECTORS; |
98 | lim->max_hw_sectors = INT_MAX; | 98 | lim->max_hw_sectors = INT_MAX; |
99 | lim->max_discard_sectors = SAFE_MAX_SECTORS; | 99 | lim->max_discard_sectors = 0; |
100 | lim->discard_granularity = 0; | ||
101 | lim->discard_alignment = 0; | ||
102 | lim->discard_misaligned = 0; | ||
100 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; | 103 | lim->logical_block_size = lim->physical_block_size = lim->io_min = 512; |
101 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); | 104 | lim->bounce_pfn = (unsigned long)(BLK_BOUNCE_ANY >> PAGE_SHIFT); |
102 | lim->alignment_offset = 0; | 105 | lim->alignment_offset = 0; |
@@ -488,6 +491,16 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b) | |||
488 | } | 491 | } |
489 | EXPORT_SYMBOL(blk_queue_stack_limits); | 492 | EXPORT_SYMBOL(blk_queue_stack_limits); |
490 | 493 | ||
494 | static unsigned int lcm(unsigned int a, unsigned int b) | ||
495 | { | ||
496 | if (a && b) | ||
497 | return (a * b) / gcd(a, b); | ||
498 | else if (b) | ||
499 | return b; | ||
500 | |||
501 | return a; | ||
502 | } | ||
503 | |||
491 | /** | 504 | /** |
492 | * blk_stack_limits - adjust queue_limits for stacked devices | 505 | * blk_stack_limits - adjust queue_limits for stacked devices |
493 | * @t: the stacking driver limits (top) | 506 | * @t: the stacking driver limits (top) |
@@ -502,6 +515,10 @@ EXPORT_SYMBOL(blk_queue_stack_limits); | |||
502 | int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | 515 | int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, |
503 | sector_t offset) | 516 | sector_t offset) |
504 | { | 517 | { |
518 | int ret; | ||
519 | |||
520 | ret = 0; | ||
521 | |||
505 | t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors); | 522 | t->max_sectors = min_not_zero(t->max_sectors, b->max_sectors); |
506 | t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); | 523 | t->max_hw_sectors = min_not_zero(t->max_hw_sectors, b->max_hw_sectors); |
507 | t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn); | 524 | t->bounce_pfn = min_not_zero(t->bounce_pfn, b->bounce_pfn); |
@@ -531,7 +548,13 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
531 | if (offset && | 548 | if (offset && |
532 | (offset & (b->physical_block_size - 1)) != b->alignment_offset) { | 549 | (offset & (b->physical_block_size - 1)) != b->alignment_offset) { |
533 | t->misaligned = 1; | 550 | t->misaligned = 1; |
534 | return -1; | 551 | ret = -1; |
552 | } | ||
553 | |||
554 | if (offset && | ||
555 | (offset & (b->discard_granularity - 1)) != b->discard_alignment) { | ||
556 | t->discard_misaligned = 1; | ||
557 | ret = -1; | ||
535 | } | 558 | } |
536 | 559 | ||
537 | /* If top has no alignment offset, inherit from bottom */ | 560 | /* If top has no alignment offset, inherit from bottom */ |
@@ -539,23 +562,26 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b, | |||
539 | t->alignment_offset = | 562 | t->alignment_offset = |
540 | b->alignment_offset & (b->physical_block_size - 1); | 563 | b->alignment_offset & (b->physical_block_size - 1); |
541 | 564 | ||
565 | if (!t->discard_alignment) | ||
566 | t->discard_alignment = | ||
567 | b->discard_alignment & (b->discard_granularity - 1); | ||
568 | |||
542 | /* Top device aligned on logical block boundary? */ | 569 | /* Top device aligned on logical block boundary? */ |
543 | if (t->alignment_offset & (t->logical_block_size - 1)) { | 570 | if (t->alignment_offset & (t->logical_block_size - 1)) { |
544 | t->misaligned = 1; | 571 | t->misaligned = 1; |
545 | return -1; | 572 | ret = -1; |
546 | } | 573 | } |
547 | 574 | ||
548 | /* Find lcm() of optimal I/O size */ | 575 | /* Find lcm() of optimal I/O size and granularity */ |
549 | if (t->io_opt && b->io_opt) | 576 | t->io_opt = lcm(t->io_opt, b->io_opt); |
550 | t->io_opt = (t->io_opt * b->io_opt) / gcd(t->io_opt, b->io_opt); | 577 | t->discard_granularity = lcm(t->discard_granularity, |
551 | else if (b->io_opt) | 578 | b->discard_granularity); |
552 | t->io_opt = b->io_opt; | ||
553 | 579 | ||
554 | /* Verify that optimal I/O size is a multiple of io_min */ | 580 | /* Verify that optimal I/O size is a multiple of io_min */ |
555 | if (t->io_min && t->io_opt % t->io_min) | 581 | if (t->io_min && t->io_opt % t->io_min) |
556 | return -1; | 582 | ret = -1; |
557 | 583 | ||
558 | return 0; | 584 | return ret; |
559 | } | 585 | } |
560 | EXPORT_SYMBOL(blk_stack_limits); | 586 | EXPORT_SYMBOL(blk_stack_limits); |
561 | 587 | ||
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c index 8a6d81afb284..3147145edc15 100644 --- a/block/blk-sysfs.c +++ b/block/blk-sysfs.c | |||
@@ -126,6 +126,16 @@ static ssize_t queue_io_opt_show(struct request_queue *q, char *page) | |||
126 | return queue_var_show(queue_io_opt(q), page); | 126 | return queue_var_show(queue_io_opt(q), page); |
127 | } | 127 | } |
128 | 128 | ||
129 | static ssize_t queue_discard_granularity_show(struct request_queue *q, char *page) | ||
130 | { | ||
131 | return queue_var_show(q->limits.discard_granularity, page); | ||
132 | } | ||
133 | |||
134 | static ssize_t queue_discard_max_show(struct request_queue *q, char *page) | ||
135 | { | ||
136 | return queue_var_show(q->limits.max_discard_sectors << 9, page); | ||
137 | } | ||
138 | |||
129 | static ssize_t | 139 | static ssize_t |
130 | queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) | 140 | queue_max_sectors_store(struct request_queue *q, const char *page, size_t count) |
131 | { | 141 | { |
@@ -293,6 +303,16 @@ static struct queue_sysfs_entry queue_io_opt_entry = { | |||
293 | .show = queue_io_opt_show, | 303 | .show = queue_io_opt_show, |
294 | }; | 304 | }; |
295 | 305 | ||
306 | static struct queue_sysfs_entry queue_discard_granularity_entry = { | ||
307 | .attr = {.name = "discard_granularity", .mode = S_IRUGO }, | ||
308 | .show = queue_discard_granularity_show, | ||
309 | }; | ||
310 | |||
311 | static struct queue_sysfs_entry queue_discard_max_entry = { | ||
312 | .attr = {.name = "discard_max_bytes", .mode = S_IRUGO }, | ||
313 | .show = queue_discard_max_show, | ||
314 | }; | ||
315 | |||
296 | static struct queue_sysfs_entry queue_nonrot_entry = { | 316 | static struct queue_sysfs_entry queue_nonrot_entry = { |
297 | .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR }, | 317 | .attr = {.name = "rotational", .mode = S_IRUGO | S_IWUSR }, |
298 | .show = queue_nonrot_show, | 318 | .show = queue_nonrot_show, |
@@ -328,6 +348,8 @@ static struct attribute *default_attrs[] = { | |||
328 | &queue_physical_block_size_entry.attr, | 348 | &queue_physical_block_size_entry.attr, |
329 | &queue_io_min_entry.attr, | 349 | &queue_io_min_entry.attr, |
330 | &queue_io_opt_entry.attr, | 350 | &queue_io_opt_entry.attr, |
351 | &queue_discard_granularity_entry.attr, | ||
352 | &queue_discard_max_entry.attr, | ||
331 | &queue_nonrot_entry.attr, | 353 | &queue_nonrot_entry.attr, |
332 | &queue_nomerges_entry.attr, | 354 | &queue_nomerges_entry.attr, |
333 | &queue_rq_affinity_entry.attr, | 355 | &queue_rq_affinity_entry.attr, |
diff --git a/block/genhd.c b/block/genhd.c index 517e4332cb37..b11a4ad7d571 100644 --- a/block/genhd.c +++ b/block/genhd.c | |||
@@ -861,12 +861,23 @@ static ssize_t disk_alignment_offset_show(struct device *dev, | |||
861 | return sprintf(buf, "%d\n", queue_alignment_offset(disk->queue)); | 861 | return sprintf(buf, "%d\n", queue_alignment_offset(disk->queue)); |
862 | } | 862 | } |
863 | 863 | ||
864 | static ssize_t disk_discard_alignment_show(struct device *dev, | ||
865 | struct device_attribute *attr, | ||
866 | char *buf) | ||
867 | { | ||
868 | struct gendisk *disk = dev_to_disk(dev); | ||
869 | |||
870 | return sprintf(buf, "%u\n", queue_discard_alignment(disk->queue)); | ||
871 | } | ||
872 | |||
864 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); | 873 | static DEVICE_ATTR(range, S_IRUGO, disk_range_show, NULL); |
865 | static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); | 874 | static DEVICE_ATTR(ext_range, S_IRUGO, disk_ext_range_show, NULL); |
866 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); | 875 | static DEVICE_ATTR(removable, S_IRUGO, disk_removable_show, NULL); |
867 | static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); | 876 | static DEVICE_ATTR(ro, S_IRUGO, disk_ro_show, NULL); |
868 | static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); | 877 | static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); |
869 | static DEVICE_ATTR(alignment_offset, S_IRUGO, disk_alignment_offset_show, NULL); | 878 | static DEVICE_ATTR(alignment_offset, S_IRUGO, disk_alignment_offset_show, NULL); |
879 | static DEVICE_ATTR(discard_alignment, S_IRUGO, disk_discard_alignment_show, | ||
880 | NULL); | ||
870 | static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); | 881 | static DEVICE_ATTR(capability, S_IRUGO, disk_capability_show, NULL); |
871 | static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); | 882 | static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); |
872 | static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL); | 883 | static DEVICE_ATTR(inflight, S_IRUGO, part_inflight_show, NULL); |
@@ -887,6 +898,7 @@ static struct attribute *disk_attrs[] = { | |||
887 | &dev_attr_ro.attr, | 898 | &dev_attr_ro.attr, |
888 | &dev_attr_size.attr, | 899 | &dev_attr_size.attr, |
889 | &dev_attr_alignment_offset.attr, | 900 | &dev_attr_alignment_offset.attr, |
901 | &dev_attr_discard_alignment.attr, | ||
890 | &dev_attr_capability.attr, | 902 | &dev_attr_capability.attr, |
891 | &dev_attr_stat.attr, | 903 | &dev_attr_stat.attr, |
892 | &dev_attr_inflight.attr, | 904 | &dev_attr_inflight.attr, |