diff options
Diffstat (limited to 'fs/partitions/check.c')
-rw-r--r-- | fs/partitions/check.c | 31 |
1 files changed, 26 insertions, 5 deletions
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index f517869e8d10..772b2ed8d239 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -312,14 +312,18 @@ static void delete_partition_rcu_cb(struct rcu_head *head) | |||
312 | 312 | ||
313 | void delete_partition(struct gendisk *disk, int partno) | 313 | void delete_partition(struct gendisk *disk, int partno) |
314 | { | 314 | { |
315 | struct disk_part_tbl *ptbl = disk->part_tbl; | ||
315 | struct hd_struct *part; | 316 | struct hd_struct *part; |
316 | 317 | ||
317 | part = disk->__part[partno]; | 318 | if (partno >= ptbl->len) |
319 | return; | ||
320 | |||
321 | part = ptbl->part[partno]; | ||
318 | if (!part) | 322 | if (!part) |
319 | return; | 323 | return; |
320 | 324 | ||
321 | blk_free_devt(part_devt(part)); | 325 | blk_free_devt(part_devt(part)); |
322 | rcu_assign_pointer(disk->__part[partno], NULL); | 326 | rcu_assign_pointer(ptbl->part[partno], NULL); |
323 | kobject_put(part->holder_dir); | 327 | kobject_put(part->holder_dir); |
324 | device_del(part_to_dev(part)); | 328 | device_del(part_to_dev(part)); |
325 | 329 | ||
@@ -341,10 +345,16 @@ int add_partition(struct gendisk *disk, int partno, | |||
341 | dev_t devt = MKDEV(0, 0); | 345 | dev_t devt = MKDEV(0, 0); |
342 | struct device *ddev = disk_to_dev(disk); | 346 | struct device *ddev = disk_to_dev(disk); |
343 | struct device *pdev; | 347 | struct device *pdev; |
348 | struct disk_part_tbl *ptbl; | ||
344 | const char *dname; | 349 | const char *dname; |
345 | int err; | 350 | int err; |
346 | 351 | ||
347 | if (disk->__part[partno]) | 352 | err = disk_expand_part_tbl(disk, partno); |
353 | if (err) | ||
354 | return err; | ||
355 | ptbl = disk->part_tbl; | ||
356 | |||
357 | if (ptbl->part[partno]) | ||
348 | return -EBUSY; | 358 | return -EBUSY; |
349 | 359 | ||
350 | p = kzalloc(sizeof(*p), GFP_KERNEL); | 360 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
@@ -398,7 +408,7 @@ int add_partition(struct gendisk *disk, int partno, | |||
398 | 408 | ||
399 | /* everything is up and running, commence */ | 409 | /* everything is up and running, commence */ |
400 | INIT_RCU_HEAD(&p->rcu_head); | 410 | INIT_RCU_HEAD(&p->rcu_head); |
401 | rcu_assign_pointer(disk->__part[partno], p); | 411 | rcu_assign_pointer(ptbl->part[partno], p); |
402 | 412 | ||
403 | /* suppress uevent if the disk supresses it */ | 413 | /* suppress uevent if the disk supresses it */ |
404 | if (!ddev->uevent_suppress) | 414 | if (!ddev->uevent_suppress) |
@@ -487,7 +497,7 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
487 | struct disk_part_iter piter; | 497 | struct disk_part_iter piter; |
488 | struct hd_struct *part; | 498 | struct hd_struct *part; |
489 | struct parsed_partitions *state; | 499 | struct parsed_partitions *state; |
490 | int p, res; | 500 | int p, highest, res; |
491 | 501 | ||
492 | if (bdev->bd_part_count) | 502 | if (bdev->bd_part_count) |
493 | return -EBUSY; | 503 | return -EBUSY; |
@@ -511,6 +521,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
511 | /* tell userspace that the media / partition table may have changed */ | 521 | /* tell userspace that the media / partition table may have changed */ |
512 | kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); | 522 | kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE); |
513 | 523 | ||
524 | /* Detect the highest partition number and preallocate | ||
525 | * disk->part_tbl. This is an optimization and not strictly | ||
526 | * necessary. | ||
527 | */ | ||
528 | for (p = 1, highest = 0; p < state->limit; p++) | ||
529 | if (state->parts[p].size) | ||
530 | highest = p; | ||
531 | |||
532 | disk_expand_part_tbl(disk, highest); | ||
533 | |||
534 | /* add partitions */ | ||
514 | for (p = 1; p < state->limit; p++) { | 535 | for (p = 1; p < state->limit; p++) { |
515 | sector_t size = state->parts[p].size; | 536 | sector_t size = state->parts[p].size; |
516 | sector_t from = state->parts[p].from; | 537 | sector_t from = state->parts[p].from; |