]> Pileus Git - ~andy/linux/blobdiff - fs/partitions/check.c
Merge commit 'origin'
[~andy/linux] / fs / partitions / check.c
index f0f604950ff4433032076a9b612a4770f5c5752c..7408227c49c91cefed99f861a90a8bbb85e8b346 100644 (file)
@@ -134,12 +134,7 @@ char *disk_name(struct gendisk *hd, int partno, char *buf)
 
 const char *bdevname(struct block_device *bdev, char *buf)
 {
-       int partno = 0;
-
-       if (bdev->bd_part)
-               partno = bdev->bd_part->partno;
-
-       return disk_name(bdev->bd_disk, partno, buf);
+       return disk_name(bdev->bd_disk, bdev->bd_part->partno, buf);
 }
 
 EXPORT_SYMBOL(bdevname);
@@ -215,15 +210,15 @@ ssize_t part_size_show(struct device *dev,
        return sprintf(buf, "%llu\n",(unsigned long long)p->nr_sects);
 }
 
-static ssize_t part_stat_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+ssize_t part_stat_show(struct device *dev,
+                      struct device_attribute *attr, char *buf)
 {
        struct hd_struct *p = dev_to_part(dev);
        int cpu;
 
-       cpu = disk_stat_lock();
+       cpu = part_stat_lock();
        part_round_stats(cpu, p);
-       disk_stat_unlock();
+       part_stat_unlock();
        return sprintf(buf,
                "%8lu %8lu %8llu %8u "
                "%8lu %8lu %8llu %8u "
@@ -243,17 +238,17 @@ static ssize_t part_stat_show(struct device *dev,
 }
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
-static ssize_t part_fail_show(struct device *dev,
-                             struct device_attribute *attr, char *buf)
+ssize_t part_fail_show(struct device *dev,
+                      struct device_attribute *attr, char *buf)
 {
        struct hd_struct *p = dev_to_part(dev);
 
        return sprintf(buf, "%d\n", p->make_it_fail);
 }
 
-static ssize_t part_fail_store(struct device *dev,
-                              struct device_attribute *attr,
-                              const char *buf, size_t count)
+ssize_t part_fail_store(struct device *dev,
+                       struct device_attribute *attr,
+                       const char *buf, size_t count)
 {
        struct hd_struct *p = dev_to_part(dev);
        int i;
@@ -317,14 +312,18 @@ static void delete_partition_rcu_cb(struct rcu_head *head)
 
 void delete_partition(struct gendisk *disk, int partno)
 {
+       struct disk_part_tbl *ptbl = disk->part_tbl;
        struct hd_struct *part;
 
-       part = disk->__part[partno];
+       if (partno >= ptbl->len)
+               return;
+
+       part = ptbl->part[partno];
        if (!part)
                return;
 
        blk_free_devt(part_devt(part));
-       rcu_assign_pointer(disk->__part[partno], NULL);
+       rcu_assign_pointer(ptbl->part[partno], NULL);
        kobject_put(part->holder_dir);
        device_del(part_to_dev(part));
 
@@ -346,10 +345,16 @@ int add_partition(struct gendisk *disk, int partno,
        dev_t devt = MKDEV(0, 0);
        struct device *ddev = disk_to_dev(disk);
        struct device *pdev;
+       struct disk_part_tbl *ptbl;
        const char *dname;
        int err;
 
-       if (disk->__part[partno])
+       err = disk_expand_part_tbl(disk, partno);
+       if (err)
+               return err;
+       ptbl = disk->part_tbl;
+
+       if (ptbl->part[partno])
                return -EBUSY;
 
        p = kzalloc(sizeof(*p), GFP_KERNEL);
@@ -403,7 +408,7 @@ int add_partition(struct gendisk *disk, int partno,
 
        /* everything is up and running, commence */
        INIT_RCU_HEAD(&p->rcu_head);
-       rcu_assign_pointer(disk->__part[partno], p);
+       rcu_assign_pointer(ptbl->part[partno], p);
 
        /* suppress uevent if the disk supresses it */
        if (!ddev->uevent_suppress)
@@ -492,14 +497,13 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
        struct disk_part_iter piter;
        struct hd_struct *part;
        struct parsed_partitions *state;
-       int p, res;
+       int p, highest, res;
 
        if (bdev->bd_part_count)
                return -EBUSY;
        res = invalidate_partition(disk, 0);
        if (res)
                return res;
-       bdev->bd_invalidated = 0;
 
        disk_part_iter_init(&piter, disk, DISK_PITER_INCL_EMPTY);
        while ((part = disk_part_iter_next(&piter)))
@@ -508,6 +512,8 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
 
        if (disk->fops->revalidate_disk)
                disk->fops->revalidate_disk(disk);
+       check_disk_size_change(disk, bdev);
+       bdev->bd_invalidated = 0;
        if (!get_capacity(disk) || !(state = check_partition(disk, bdev)))
                return 0;
        if (IS_ERR(state))      /* I/O error reading the partition table */
@@ -516,6 +522,17 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
        /* tell userspace that the media / partition table may have changed */
        kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
 
+       /* Detect the highest partition number and preallocate
+        * disk->part_tbl.  This is an optimization and not strictly
+        * necessary.
+        */
+       for (p = 1, highest = 0; p < state->limit; p++)
+               if (state->parts[p].size)
+                       highest = p;
+
+       disk_expand_part_tbl(disk, highest);
+
+       /* add partitions */
        for (p = 1; p < state->limit; p++) {
                sector_t size = state->parts[p].size;
                sector_t from = state->parts[p].from;
@@ -577,11 +594,12 @@ void del_gendisk(struct gendisk *disk)
        disk_part_iter_exit(&piter);
 
        invalidate_partition(disk, 0);
+       blk_free_devt(disk_to_dev(disk)->devt);
        set_capacity(disk, 0);
        disk->flags &= ~GENHD_FL_UP;
        unlink_gendisk(disk);
-       disk_stat_set_all(disk, 0);
-       disk->stamp = 0;
+       part_stat_set_all(&disk->part0, 0);
+       disk->part0.stamp = 0;
 
        kobject_put(disk->part0.holder_dir);
        kobject_put(disk->slave_dir);