diff options
Diffstat (limited to 'fs/partitions/check.c')
-rw-r--r-- | fs/partitions/check.c | 52 |
1 files changed, 42 insertions, 10 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 99e33ef40be4..1a9c7878f864 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -219,6 +219,13 @@ ssize_t part_size_show(struct device *dev, | |||
219 | return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); | 219 | return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects); |
220 | } | 220 | } |
221 | 221 | ||
222 | ssize_t part_alignment_offset_show(struct device *dev, | ||
223 | struct device_attribute *attr, char *buf) | ||
224 | { | ||
225 | struct hd_struct *p = dev_to_part(dev); | ||
226 | return sprintf(buf, "%llu\n", (unsigned long long)p->alignment_offset); | ||
227 | } | ||
228 | |||
222 | ssize_t part_stat_show(struct device *dev, | 229 | ssize_t part_stat_show(struct device *dev, |
223 | struct device_attribute *attr, char *buf) | 230 | struct device_attribute *attr, char *buf) |
224 | { | 231 | { |
@@ -272,6 +279,7 @@ ssize_t part_fail_store(struct device *dev, | |||
272 | static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL); | 279 | static DEVICE_ATTR(partition, S_IRUGO, part_partition_show, NULL); |
273 | static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL); | 280 | static DEVICE_ATTR(start, S_IRUGO, part_start_show, NULL); |
274 | static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); | 281 | static DEVICE_ATTR(size, S_IRUGO, part_size_show, NULL); |
282 | static DEVICE_ATTR(alignment_offset, S_IRUGO, part_alignment_offset_show, NULL); | ||
275 | static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); | 283 | static DEVICE_ATTR(stat, S_IRUGO, part_stat_show, NULL); |
276 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 284 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
277 | static struct device_attribute dev_attr_fail = | 285 | static struct device_attribute dev_attr_fail = |
@@ -282,6 +290,7 @@ static struct attribute *part_attrs[] = { | |||
282 | &dev_attr_partition.attr, | 290 | &dev_attr_partition.attr, |
283 | &dev_attr_start.attr, | 291 | &dev_attr_start.attr, |
284 | &dev_attr_size.attr, | 292 | &dev_attr_size.attr, |
293 | &dev_attr_alignment_offset.attr, | ||
285 | &dev_attr_stat.attr, | 294 | &dev_attr_stat.attr, |
286 | #ifdef CONFIG_FAIL_MAKE_REQUEST | 295 | #ifdef CONFIG_FAIL_MAKE_REQUEST |
287 | &dev_attr_fail.attr, | 296 | &dev_attr_fail.attr, |
@@ -383,6 +392,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, | |||
383 | pdev = part_to_dev(p); | 392 | pdev = part_to_dev(p); |
384 | 393 | ||
385 | p->start_sect = start; | 394 | p->start_sect = start; |
395 | p->alignment_offset = queue_sector_alignment_offset(disk->queue, start); | ||
386 | p->nr_sects = len; | 396 | p->nr_sects = len; |
387 | p->partno = partno; | 397 | p->partno = partno; |
388 | p->policy = get_disk_ro(disk); | 398 | p->policy = get_disk_ro(disk); |
@@ -546,27 +556,49 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
546 | 556 | ||
547 | /* add partitions */ | 557 | /* add partitions */ |
548 | for (p = 1; p < state->limit; p++) { | 558 | for (p = 1; p < state->limit; p++) { |
549 | sector_t size = state->parts[p].size; | 559 | sector_t size, from; |
550 | sector_t from = state->parts[p].from; | 560 | try_scan: |
561 | size = state->parts[p].size; | ||
551 | if (!size) | 562 | if (!size) |
552 | continue; | 563 | continue; |
564 | |||
565 | from = state->parts[p].from; | ||
553 | if (from >= get_capacity(disk)) { | 566 | if (from >= get_capacity(disk)) { |
554 | printk(KERN_WARNING | 567 | printk(KERN_WARNING |
555 | "%s: p%d ignored, start %llu is behind the end of the disk\n", | 568 | "%s: p%d ignored, start %llu is behind the end of the disk\n", |
556 | disk->disk_name, p, (unsigned long long) from); | 569 | disk->disk_name, p, (unsigned long long) from); |
557 | continue; | 570 | continue; |
558 | } | 571 | } |
572 | |||
559 | if (from + size > get_capacity(disk)) { | 573 | if (from + size > get_capacity(disk)) { |
560 | /* | 574 | struct block_device_operations *bdops = disk->fops; |
561 | * we can not ignore partitions of broken tables | 575 | unsigned long long capacity; |
562 | * created by for example camera firmware, but we | 576 | |
563 | * limit them to the end of the disk to avoid | ||
564 | * creating invalid block devices | ||
565 | */ | ||
566 | printk(KERN_WARNING | 577 | printk(KERN_WARNING |
567 | "%s: p%d size %llu limited to end of disk\n", | 578 | "%s: p%d size %llu exceeds device capacity, ", |
568 | disk->disk_name, p, (unsigned long long) size); | 579 | disk->disk_name, p, (unsigned long long) size); |
569 | size = get_capacity(disk) - from; | 580 | |
581 | if (bdops->set_capacity && | ||
582 | (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) { | ||
583 | printk(KERN_CONT "enabling native capacity\n"); | ||
584 | capacity = bdops->set_capacity(disk, ~0ULL); | ||
585 | disk->flags |= GENHD_FL_NATIVE_CAPACITY; | ||
586 | if (capacity > get_capacity(disk)) { | ||
587 | set_capacity(disk, capacity); | ||
588 | check_disk_size_change(disk, bdev); | ||
589 | bdev->bd_invalidated = 0; | ||
590 | } | ||
591 | goto try_scan; | ||
592 | } else { | ||
593 | /* | ||
594 | * we can not ignore partitions of broken tables | ||
595 | * created by for example camera firmware, but | ||
596 | * we limit them to the end of the disk to avoid | ||
597 | * creating invalid block devices | ||
598 | */ | ||
599 | printk(KERN_CONT "limited to end of disk\n"); | ||
600 | size = get_capacity(disk) - from; | ||
601 | } | ||
570 | } | 602 | } |
571 | part = add_partition(disk, p, from, size, | 603 | part = add_partition(disk, p, from, size, |
572 | state->parts[p].flags); | 604 | state->parts[p].flags); |