Merge branch 'stable-3.2' into pandora-3.2
[pandora-kernel.git] / fs / partitions / check.c
index e3c63d1..66897c9 100644 (file)
@@ -361,6 +361,7 @@ static const struct attribute_group *part_attr_groups[] = {
 static void part_release(struct device *dev)
 {
        struct hd_struct *p = dev_to_part(dev);
+       blk_free_devt(dev->devt);
        free_part_stats(p);
        free_part_info(p);
        kfree(p);
@@ -399,7 +400,6 @@ void delete_partition(struct gendisk *disk, int partno)
        if (!part)
                return;
 
-       blk_free_devt(part_devt(part));
        rcu_assign_pointer(ptbl->part[partno], NULL);
        rcu_assign_pointer(ptbl->last_lookup, NULL);
        kobject_put(part->holder_dir);
@@ -457,8 +457,10 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno,
 
        if (info) {
                struct partition_meta_info *pinfo = alloc_part_info(disk);
-               if (!pinfo)
+               if (!pinfo) {
+                       err = -ENOMEM;
                        goto out_free_stats;
+               }
                memcpy(pinfo, info, sizeof(*info));
                p->info = pinfo;
        }
@@ -539,17 +541,11 @@ static bool disk_unlock_native_capacity(struct gendisk *disk)
        }
 }
 
-int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+static int drop_partitions(struct gendisk *disk, struct block_device *bdev)
 {
-       struct parsed_partitions *state = NULL;
        struct disk_part_iter piter;
        struct hd_struct *part;
-       int p, highest, res;
-rescan:
-       if (state && !IS_ERR(state)) {
-               kfree(state);
-               state = NULL;
-       }
+       int res;
 
        if (bdev->bd_part_count)
                return -EBUSY;
@@ -562,6 +558,24 @@ rescan:
                delete_partition(disk, part->partno);
        disk_part_iter_exit(&piter);
 
+       return 0;
+}
+
+int rescan_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+       struct parsed_partitions *state = NULL;
+       struct hd_struct *part;
+       int p, highest, res;
+rescan:
+       if (state && !IS_ERR(state)) {
+               kfree(state);
+               state = NULL;
+       }
+
+       res = drop_partitions(disk, bdev);
+       if (res)
+               return res;
+
        if (disk->fops->revalidate_disk)
                disk->fops->revalidate_disk(disk);
        check_disk_size_change(disk, bdev);
@@ -665,6 +679,26 @@ rescan:
        return 0;
 }
 
+int invalidate_partitions(struct gendisk *disk, struct block_device *bdev)
+{
+       int res;
+
+       if (!bdev->bd_invalidated)
+               return 0;
+
+       res = drop_partitions(disk, bdev);
+       if (res)
+               return res;
+
+       set_capacity(disk, 0);
+       check_disk_size_change(disk, bdev);
+       bdev->bd_invalidated = 0;
+       /* tell userspace that the media / partition table may have changed */
+       kobject_uevent(&disk_to_dev(disk)->kobj, KOBJ_CHANGE);
+
+       return 0;
+}
+
 unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p)
 {
        struct address_space *mapping = bdev->bd_inode->i_mapping;