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: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index b6024a2..c80fc1a 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4702,11 +4702,49 @@
 	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 @@
 	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 @@
 
 	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 */