diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/partitions/check.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 0af36085eb28..1a9c7878f864 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -556,27 +556,49 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
556 | 556 | ||
557 | /* add partitions */ | 557 | /* add partitions */ |
558 | for (p = 1; p < state->limit; p++) { | 558 | for (p = 1; p < state->limit; p++) { |
559 | sector_t size = state->parts[p].size; | 559 | sector_t size, from; |
560 | sector_t from = state->parts[p].from; | 560 | try_scan: |
561 | size = state->parts[p].size; | ||
561 | if (!size) | 562 | if (!size) |
562 | continue; | 563 | continue; |
564 | |||
565 | from = state->parts[p].from; | ||
563 | if (from >= get_capacity(disk)) { | 566 | if (from >= get_capacity(disk)) { |
564 | printk(KERN_WARNING | 567 | printk(KERN_WARNING |
565 | "%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", |
566 | disk->disk_name, p, (unsigned long long) from); | 569 | disk->disk_name, p, (unsigned long long) from); |
567 | continue; | 570 | continue; |
568 | } | 571 | } |
572 | |||
569 | if (from + size > get_capacity(disk)) { | 573 | if (from + size > get_capacity(disk)) { |
570 | /* | 574 | struct block_device_operations *bdops = disk->fops; |
571 | * we can not ignore partitions of broken tables | 575 | unsigned long long capacity; |
572 | * created by for example camera firmware, but we | 576 | |
573 | * limit them to the end of the disk to avoid | ||
574 | * creating invalid block devices | ||
575 | */ | ||
576 | printk(KERN_WARNING | 577 | printk(KERN_WARNING |
577 | "%s: p%d size %llu limited to end of disk\n", | 578 | "%s: p%d size %llu exceeds device capacity, ", |
578 | disk->disk_name, p, (unsigned long long) size); | 579 | disk->disk_name, p, (unsigned long long) size); |
579 | 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 | } | ||
580 | } | 602 | } |
581 | part = add_partition(disk, p, from, size, | 603 | part = add_partition(disk, p, from, size, |
582 | state->parts[p].flags); | 604 | state->parts[p].flags); |