block: update add_partition() error handling
[safe/jmp/linux-2.6] / fs / partitions / check.c
index 68f3e41..16f98d8 100644 (file)
@@ -300,15 +300,6 @@ struct device_type part_type = {
        .release        = part_release,
 };
 
-static inline void partition_sysfs_add_subdir(struct hd_struct *p)
-{
-       struct kobject *k;
-
-       k = kobject_get(&p->dev.kobj);
-       p->holder_dir = kobject_create_and_add("holders", k);
-       kobject_put(k);
-}
-
 static inline void disk_sysfs_add_subdirs(struct gendisk *disk)
 {
        struct kobject *k;
@@ -347,13 +338,16 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
        struct hd_struct *p;
        int err;
 
+       if (disk->part[part - 1])
+               return -EBUSY;
+
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
                return -ENOMEM;
 
        if (!init_part_stats(p)) {
                err = -ENOMEM;
-               goto out0;
+               goto out_free;
        }
        p->start_sect = start;
        p->nr_sects = len;
@@ -372,34 +366,42 @@ int add_partition(struct gendisk *disk, int part, sector_t start, sector_t len,
        p->dev.class = &block_class;
        p->dev.type = &part_type;
        p->dev.parent = &disk->dev;
-       disk->part[part-1] = p;
 
        /* delay uevent until 'holders' subdir is created */
        p->dev.uevent_suppress = 1;
        err = device_add(&p->dev);
        if (err)
-               goto out1;
-       partition_sysfs_add_subdir(p);
+               goto out_put;
+
+       err = -ENOMEM;
+       p->holder_dir = kobject_create_and_add("holders", &p->dev.kobj);
+       if (!p->holder_dir)
+               goto out_del;
+
        p->dev.uevent_suppress = 0;
        if (flags & ADDPART_FLAG_WHOLEDISK) {
                err = device_create_file(&p->dev, &dev_attr_whole_disk);
                if (err)
-                       goto out2;
+                       goto out_del;
        }
 
+       /* everything is up and running, commence */
+       disk->part[part - 1] = p;
+
        /* suppress uevent if the disk supresses it */
        if (!disk->dev.uevent_suppress)
                kobject_uevent(&p->dev.kobj, KOBJ_ADD);
 
        return 0;
 
-out2:
+out_free:
+       kfree(p);
+       return err;
+out_del:
+       kobject_put(p->holder_dir);
        device_del(&p->dev);
-out1:
+out_put:
        put_device(&p->dev);
-       free_part_stats(p);
-out0:
-       kfree(p);
        return err;
 }