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))) {
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);
{
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);
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);
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;
}
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;
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:
/* 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);
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;
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;
}
}
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);