Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 124afba2 authored by Alex Elder's avatar Alex Elder Committed by Sage Weil
Browse files

rbd: encapsulate probing for parent devices



Encapsulate the code that probes for an rbd device's parent images
into a new function, rbd_dev_probe_parent().

Signed-off-by: default avatarAlex Elder <elder@inktank.com>
Reviewed-by: default avatarJosh Durgin <josh.durgin@inktank.com>
parent b5156e76
Loading
Loading
Loading
Loading
+44 −38
Original line number Diff line number Diff line
@@ -4702,11 +4702,49 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
	return ret;
}

static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
{
	struct rbd_device *parent = NULL;
	struct rbd_spec *parent_spec = NULL;
	struct rbd_client *rbdc = NULL;
	struct rbd_spec *parent_spec;
	struct rbd_client *rbdc;
	int ret;

	if (!rbd_dev->parent_spec)
		return 0;
	/*
	 * We need to pass a reference to the client and the parent
	 * spec when creating the parent rbd_dev.  Images related by
	 * parent/child relationships always share both.
	 */
	parent_spec = rbd_spec_get(rbd_dev->parent_spec);
	rbdc = __rbd_get_client(rbd_dev->rbd_client);

	ret = -ENOMEM;
	parent = rbd_dev_create(rbdc, parent_spec);
	if (!parent)
		goto out_err;

	ret = rbd_dev_image_probe(parent);
	if (ret < 0)
		goto out_err;
	rbd_dev->parent = parent;

	return 0;
out_err:
	if (parent) {
		rbd_spec_put(rbd_dev->parent_spec);
		kfree(rbd_dev->header_name);
		rbd_dev_destroy(parent);
	} else {
		rbd_put_client(rbdc);
		rbd_spec_put(parent_spec);
	}

	return ret;
}

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 */
@@ -4747,34 +4785,9 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)
	if (ret)
		goto err_out_disk;

	/*
	 * At this point cleanup in the event of an error is the job
	 * of the sysfs code (initiated by rbd_bus_del_dev()).
	 */
	/* Probe the parent if there is one */

	if (rbd_dev->parent_spec) {
		/*
		 * We need to pass a reference to the client and the
		 * parent spec when creating the parent rbd_dev.
		 * Images related by parent/child relationships
		 * always share both.
		 */
		parent_spec = rbd_spec_get(rbd_dev->parent_spec);
		rbdc = __rbd_get_client(rbd_dev->rbd_client);

		parent = rbd_dev_create(rbdc, parent_spec);
		if (!parent) {
			ret = -ENOMEM;
			goto err_out_spec;
		}
		rbdc = NULL;		/* parent now owns reference */
		parent_spec = NULL;	/* parent now owns reference */
		ret = rbd_dev_image_probe(parent);
		if (ret < 0)
			goto err_out_parent;
		rbd_dev->parent = parent;
	}
	ret = rbd_dev_probe_parent(rbd_dev);
	if (ret)
		goto err_out_bus;

	ret = rbd_dev_header_watch_sync(rbd_dev, 1);
	if (ret)
@@ -4791,13 +4804,6 @@ static int rbd_dev_probe_finish(struct rbd_device *rbd_dev)

	return ret;

err_out_parent:
	rbd_spec_put(rbd_dev->parent_spec);
	kfree(rbd_dev->header_name);
	rbd_dev_destroy(parent);
err_out_spec:
	rbd_spec_put(parent_spec);
	rbd_put_client(rbdc);
err_out_bus:
	/* this will also clean up rest of rbd_dev stuff */