aboutsummaryrefslogtreecommitdiffstats
path: root/fs/partitions/check.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/partitions/check.c')
-rw-r--r--fs/partitions/check.c31
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
313void delete_partition(struct gendisk *disk, int partno) 313void 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;