rbd: don't leak parent_spec in rbd_dev_probe_parent()
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / block / rbd.c
index 8b01b45d2662fe763f0dd74de6b6c82ce3830c3c..64f2f184e674edbd425e1a35fca2023a1e4d4b6d 100644 (file)
@@ -4834,41 +4834,36 @@ out_err:
 static int rbd_dev_probe_parent(struct rbd_device *rbd_dev)
 {
        struct rbd_device *parent = 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)
+       parent = rbd_dev_create(rbd_dev->rbd_client, rbd_dev->parent_spec);
+       if (!parent) {
+               ret = -ENOMEM;
                goto out_err;
+       }
+
+       /*
+        * Images related by parent/child relationships always share
+        * rbd_client and spec/parent_spec, so bump their refcounts.
+        */
+       __rbd_get_client(rbd_dev->rbd_client);
+       rbd_spec_get(rbd_dev->parent_spec);
 
        ret = rbd_dev_image_probe(parent, false);
        if (ret < 0)
                goto out_err;
+
        rbd_dev->parent = parent;
        atomic_set(&rbd_dev->parent_ref, 1);
-
        return 0;
+
 out_err:
-       if (parent) {
-               rbd_dev_unparent(rbd_dev);
+       rbd_dev_unparent(rbd_dev);
+       if (parent)
                rbd_dev_destroy(parent);
-       } else {
-               rbd_put_client(rbdc);
-               rbd_spec_put(parent_spec);
-       }
-
        return ret;
 }