rbd: move more initialization into rbd_dev_image_probe()
[cascardo/linux.git] / drivers / block / rbd.c
index 87ef011..ebf4d47 100644 (file)
@@ -866,7 +866,7 @@ static struct rbd_snap *snap_by_name(struct rbd_device *rbd_dev,
        return NULL;
 }
 
-static int rbd_dev_set_mapping(struct rbd_device *rbd_dev)
+static int rbd_dev_mapping_set(struct rbd_device *rbd_dev)
 {
        if (!memcmp(rbd_dev->spec->snap_name, RBD_SNAP_HEAD_NAME,
                    sizeof (RBD_SNAP_HEAD_NAME))) {
@@ -886,6 +886,13 @@ static int rbd_dev_set_mapping(struct rbd_device *rbd_dev)
        return 0;
 }
 
+static void rbd_dev_mapping_clear(struct rbd_device *rbd_dev)
+{
+       rbd_dev->mapping.size = 0;
+       rbd_dev->mapping.features = 0;
+       rbd_dev->mapping.read_only = true;
+}
+
 static void rbd_header_free(struct rbd_image_header *header)
 {
        kfree(header->object_prefix);
@@ -4748,18 +4755,13 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
 {
        int ret;
 
-       /* no need to lock here, as rbd_dev is not registered yet */
-       ret = rbd_dev_snaps_update(rbd_dev);
+       ret = rbd_dev_header_watch_sync(rbd_dev, 1);
        if (ret)
                return ret;
 
-       ret = rbd_dev_spec_update(rbd_dev);
-       if (ret)
-               goto err_out_snaps;
-
-       ret = rbd_dev_set_mapping(rbd_dev);
+       ret = rbd_dev_mapping_set(rbd_dev);
        if (ret)
-               goto err_out_snaps;
+               return ret;
 
        /* generate unique id: find highest unique id, add one */
        rbd_dev_id_get(rbd_dev);
@@ -4786,14 +4788,6 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
        if (ret)
                goto err_out_disk;
 
-       ret = rbd_dev_probe_parent(rbd_dev);
-       if (ret)
-               goto err_out_bus;
-
-       ret = rbd_dev_header_watch_sync(rbd_dev, 1);
-       if (ret)
-               goto err_out_bus;
-
        /* Everything's ready.  Announce the disk to the world. */
 
        set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
@@ -4805,20 +4799,13 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
 
        return ret;
 
-err_out_bus:
-       /* this will also clean up rest of rbd_dev stuff */
-
-       rbd_bus_del_dev(rbd_dev);
-
-       return ret;
 err_out_disk:
        rbd_free_disk(rbd_dev);
 err_out_blkdev:
        unregister_blkdev(rbd_dev->major, rbd_dev->name);
 err_out_id:
        rbd_dev_id_put(rbd_dev);
-err_out_snaps:
-       rbd_remove_all_snaps(rbd_dev);
+       rbd_dev_mapping_clear(rbd_dev);
 
        return ret;
 }
@@ -4850,11 +4837,28 @@ static int rbd_dev_image_probe(struct rbd_device *rbd_dev)
        if (ret)
                goto out_err;
 
+       ret = rbd_dev_snaps_update(rbd_dev);
+       if (ret)
+               goto out_err;
+
+       ret = rbd_dev_spec_update(rbd_dev);
+       if (ret)
+               goto err_out_snaps;
+
+       ret = rbd_dev_probe_parent(rbd_dev);
+       if (ret)
+               goto err_out_snaps;
+
        ret = rbd_dev_probe_finish(rbd_dev);
        if (ret)
-               rbd_header_free(&rbd_dev->header);
+               goto err_out_parent;
 
        return ret;
+err_out_parent:
+       rbd_dev_remove_parent(rbd_dev);
+       rbd_header_free(&rbd_dev->header);
+err_out_snaps:
+       rbd_remove_all_snaps(rbd_dev);
 out_err:
        kfree(rbd_dev->spec->image_id);
        rbd_dev->spec->image_id = NULL;
@@ -4923,7 +4927,6 @@ static ssize_t rbd_add(struct bus_type *bus,
 
        return count;
 err_out_rbd_dev:
-       rbd_spec_put(rbd_dev->parent_spec);
        kfree(rbd_dev->header_name);
        rbd_dev_destroy(rbd_dev);
 err_out_client:
@@ -4974,6 +4977,7 @@ static void rbd_dev_release(struct device *dev)
 
        /* done with the id, and with the rbd_dev */
        rbd_dev_id_put(rbd_dev);
+       rbd_dev_mapping_clear(rbd_dev);
        rbd_assert(rbd_dev->rbd_client != NULL);
        rbd_spec_put(rbd_dev->parent_spec);
        kfree(rbd_dev->header_name);
@@ -4983,15 +4987,9 @@ static void rbd_dev_release(struct device *dev)
        module_put(THIS_MODULE);
 }
 
-static void __rbd_remove(struct rbd_device *rbd_dev)
-{
-       rbd_remove_all_snaps(rbd_dev);
-       rbd_bus_del_dev(rbd_dev);
-}
-
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
 {
-       while (rbd_dev->parent_spec) {
+       while (rbd_dev->parent) {
                struct rbd_device *first = rbd_dev;
                struct rbd_device *second = first->parent;
                struct rbd_device *third;
@@ -5004,11 +5002,15 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
                        first = second;
                        second = third;
                }
-               __rbd_remove(second);
+               rbd_assert(second);
+               rbd_remove_all_snaps(second);
+               rbd_bus_del_dev(second);
+               first->parent = NULL;
+               first->parent_overlap = 0;
+
+               rbd_assert(first->parent_spec);
                rbd_spec_put(first->parent_spec);
                first->parent_spec = NULL;
-               first->parent_overlap = 0;
-               first->parent = NULL;
        }
 }
 
@@ -5049,8 +5051,8 @@ static ssize_t rbd_remove(struct bus_type *bus,
 
        rbd_dev_remove_parent(rbd_dev);
 
-       __rbd_remove(rbd_dev);
-
+       rbd_remove_all_snaps(rbd_dev);
+       rbd_bus_del_dev(rbd_dev);
 done:
        mutex_unlock(&ctl_mutex);