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>
This commit is contained in:
parent
02c33b123e
commit
db429e9ec0
|
@ -546,28 +546,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 exceeds device capacity, "
|
||||
"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);
|
||||
|
|
|
@ -1106,6 +1106,8 @@ struct block_device_operations {
|
|||
int (*direct_access) (struct block_device *, sector_t,
|
||||
void **, unsigned long *);
|
||||
int (*media_changed) (struct gendisk *);
|
||||
unsigned long long (*set_capacity) (struct gendisk *,
|
||||
unsigned long long);
|
||||
int (*revalidate_disk) (struct gendisk *);
|
||||
int (*getgeo)(struct block_device *, struct hd_geometry *);
|
||||
struct module *owner;
|
||||
|
|
|
@ -113,6 +113,7 @@ struct hd_struct {
|
|||
#define GENHD_FL_UP 16
|
||||
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
|
||||
#define GENHD_FL_EXT_DEVT 64 /* allow extended devt */
|
||||
#define GENHD_FL_NATIVE_CAPACITY 128
|
||||
|
||||
#define BLK_SCSI_MAX_CMDS (256)
|
||||
#define BLK_SCSI_CMD_PER_LONG (BLK_SCSI_MAX_CMDS / (sizeof(long) * 8))
|
||||
|
|
Loading…
Reference in New Issue