aboutsummaryrefslogtreecommitdiffstats
path: root/fs/partitions
diff options
context:
space:
mode:
authorBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-07 07:52:52 -0400
committerBartlomiej Zolnierkiewicz <bzolnier@gmail.com>2009-06-07 07:52:52 -0400
commitdb429e9ec0f9dee2d8e50c154f04f29f880fc9d6 (patch)
tree363328c6aa85f7a15cc061f7c71f3cc3a8cde970 /fs/partitions
parent02c33b123e59cab5771e52a012aeb810500260a2 (diff)
partitions: add ->set_capacity block device method
* Add ->set_capacity block device method and use it in rescan_partitions() to attempt enabling native capacity of the device upon detecting the partition which exceeds device capacity. * Add GENHD_FL_NATIVE_CAPACITY flag to try limit attempts of enabling native capacity during partition scan. Together with the consecutive patch implementing ->set_capacity method in ide-gd device driver this allows automatic disabling of Host Protected Area (HPA) if any partitions overlapping HPA are detected. Cc: Robert Hancock <hancockrwd@gmail.com> Cc: Frans Pop <elendil@planet.nl> Cc: "Andries E. Brouwer" <Andries.Brouwer@cwi.nl> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Emphatically-Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'fs/partitions')
-rw-r--r--fs/partitions/check.c43
1 files changed, 32 insertions, 11 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c
index 137a708bb215..4bc2c43fa083 100644
--- a/fs/partitions/check.c
+++ b/fs/partitions/check.c
@@ -546,28 +546,49 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
546 546
547 /* add partitions */ 547 /* add partitions */
548 for (p = 1; p < state->limit; p++) { 548 for (p = 1; p < state->limit; p++) {
549 sector_t size = state->parts[p].size; 549 sector_t size, from;
550 sector_t from = state->parts[p].from; 550try_scan:
551 size = state->parts[p].size;
551 if (!size) 552 if (!size)
552 continue; 553 continue;
554
555 from = state->parts[p].from;
553 if (from >= get_capacity(disk)) { 556 if (from >= get_capacity(disk)) {
554 printk(KERN_WARNING 557 printk(KERN_WARNING
555 "%s: p%d ignored, start %llu is behind the end of the disk\n", 558 "%s: p%d ignored, start %llu is behind the end of the disk\n",
556 disk->disk_name, p, (unsigned long long) from); 559 disk->disk_name, p, (unsigned long long) from);
557 continue; 560 continue;
558 } 561 }
562
559 if (from + size > get_capacity(disk)) { 563 if (from + size > get_capacity(disk)) {
560 /* 564 struct block_device_operations *bdops = disk->fops;
561 * we can not ignore partitions of broken tables 565 unsigned long long capacity;
562 * created by for example camera firmware, but we 566
563 * limit them to the end of the disk to avoid
564 * creating invalid block devices
565 */
566 printk(KERN_WARNING 567 printk(KERN_WARNING
567 "%s: p%d size %llu exceeds device capacity, " 568 "%s: p%d size %llu exceeds device capacity, ",
568 "limited to end of disk\n",
569 disk->disk_name, p, (unsigned long long) size); 569 disk->disk_name, p, (unsigned long long) size);
570 size = get_capacity(disk) - from; 570
571 if (bdops->set_capacity &&
572 (disk->flags & GENHD_FL_NATIVE_CAPACITY) == 0) {
573 printk(KERN_CONT "enabling native capacity\n");
574 capacity = bdops->set_capacity(disk, ~0ULL);
575 disk->flags |= GENHD_FL_NATIVE_CAPACITY;
576 if (capacity > get_capacity(disk)) {
577 set_capacity(disk, capacity);
578 check_disk_size_change(disk, bdev);
579 bdev->bd_invalidated = 0;
580 }
581 goto try_scan;
582 } else {
583 /*
584 * we can not ignore partitions of broken tables
585 * created by for example camera firmware, but
586 * we limit them to the end of the disk to avoid
587 * creating invalid block devices
588 */
589 printk(KERN_CONT "limited to end of disk\n");
590 size = get_capacity(disk) - from;
591 }
571 } 592 }
572 part = add_partition(disk, p, from, size, 593 part = add_partition(disk, p, from, size,
573 state->parts[p].flags); 594 state->parts[p].flags);