summaryrefslogtreecommitdiffstats
path: root/fs/partitions/check.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-06-12 09:29:42 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2009-06-12 09:29:42 -0700
commitd614aec4752f8c61b2e7cb77806b6bd59aa50836 (patch)
tree3b0cfb3085c43415931dbf18666d582fb8ae3c75 /fs/partitions/check.c
parentdb8e7f10ed67933ca272f4030eb7057b7f13de07 (diff)
parentad7c52d0988a8965989dc06d630c52a5bde849d5 (diff)
Merge branch 'for-2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6
* 'for-2.6.31' of git://git.kernel.org/pub/scm/linux/kernel/git/bart/ide-2.6: (29 commits) ide: re-implement ide_pci_init_one() on top of ide_pci_init_two() ide: unexport ide_find_dma_mode() ide: fix PowerMac bootup oops ide: skip probe if there are no devices on the port (v2) sl82c105: add printk() logging facility ide-tape: fix proc warning ide: add IDE_DFLAG_NIEN_QUIRK device flag ide: respect quirk_drives[] list on all controllers hpt366: enable all quirks for devices on quirk_drives[] list hpt366: sync quirk_drives[] list with pdc202xx_{new,old}.c ide: remove superfluous SELECT_MASK() call from do_rw_taskfile() ide: remove superfluous SELECT_MASK() call from ide_driveid_update() icside: remove superfluous ->maskproc method ide-tape: fix IDE_AFLAG_* atomic accesses ide-tape: change IDE_AFLAG_IGNORE_DSC non-atomically pdc202xx_old: kill resetproc() method pdc202xx_old: don't call pdc202xx_reset() on IRQ timeout pdc202xx_old: use ide_dma_test_irq() ide: preserve Host Protected Area by default (v2) ide-gd: implement block device ->set_capacity method (v2) ...
Diffstat (limited to 'fs/partitions/check.c')
-rw-r--r--fs/partitions/check.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 0af36085eb2..1a9c7878f86 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)
/* add partitions */
for (p = 1; p < state->limit; p++) {
- sector_t size = state->parts[p].size;
- sector_t from = state->parts[p].from;
+ sector_t size, from;
+try_scan:
+ size = state->parts[p].size;
if (!size)
continue;
+
+ from = state->parts[p].from;
if (from >= get_capacity(disk)) {
printk(KERN_WARNING
"%s: p%d ignored, start %llu is behind the end of the disk\n",
disk->disk_name, p, (unsigned long long) from);
continue;
}
+
if (from + size > get_capacity(disk)) {
- /*
- * we can not ignore partitions of broken tables
- * created by for example camera firmware, but we
- * limit them to the end of the disk to avoid
- * creating invalid block devices
- */
+ struct block_device_operations *bdops = disk->fops;
+ unsigned long long capacity;
+
printk(KERN_WARNING
- "%s: p%d size %llu limited to end of disk\n",
+ "%s: p%d size %llu exceeds device capacity, ",
disk->disk_name, p, (unsigned long long) size);
- size = get_capacity(disk) - from;
+
+ if (bdops->set_capacity &&
+ (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) {
+ printk(KERN_CONT "enabling native capacity\n");
+ capacity = bdops->set_capacity(disk, ~0ULL);
+ disk->flags |= GENHD_FL_NATIVE_CAPACITY;
+ if (capacity > get_capacity(disk)) {
+ set_capacity(disk, capacity);
+ check_disk_size_change(disk, bdev);
+ bdev->bd_invalidated = 0;
+ }
+ goto try_scan;
+ } else {
+ /*
+ * we can not ignore partitions of broken tables
+ * created by for example camera firmware, but
+ * we limit them to the end of the disk to avoid
+ * creating invalid block devices
+ */
+ printk(KERN_CONT "limited to end of disk\n");
+ size = get_capacity(disk) - from;
+ }
}
part = add_partition(disk, p, from, size,
state->parts[p].flags);