rbd: rework rbd_img_obj_exists_submit() error paths
authorIlya Dryomov <idryomov@gmail.com>
Thu, 15 Sep 2016 15:53:32 +0000 (17:53 +0200)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 3 Oct 2016 14:13:48 +0000 (16:13 +0200)
- don't put obj_request before rbd_obj_request_get() if
  rbd_obj_request_create() fails
- don't leak pages if rbd_obj_request_create() fails
- don't leak stat_request if rbd_osd_req_create() fails

Reported-by: David Disseldorp <ddiss@suse.de>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
Reviewed-by: Alex Elder <elder@linaro.org>
Reviewed-by: David Disseldorp <ddiss@suse.de>
drivers/block/rbd.c

index 77675ac..3218ac4 100644 (file)
@@ -2894,11 +2894,23 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
 {
        struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
        struct rbd_obj_request *stat_request;
 {
        struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
        struct rbd_obj_request *stat_request;
-       struct page **pages = NULL;
+       struct page **pages;
        u32 page_count;
        size_t size;
        int ret;
 
        u32 page_count;
        size_t size;
        int ret;
 
+       stat_request = rbd_obj_request_create(obj_request->object_name, 0, 0,
+                                             OBJ_REQUEST_PAGES);
+       if (!stat_request)
+               return -ENOMEM;
+
+       stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1,
+                                                  stat_request);
+       if (!stat_request->osd_req) {
+               ret = -ENOMEM;
+               goto fail_stat_request;
+       }
+
        /*
         * The response data for a STAT call consists of:
         *     le64 length;
        /*
         * The response data for a STAT call consists of:
         *     le64 length;
@@ -2910,38 +2922,28 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
        size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32);
        page_count = (u32)calc_pages_for(0, size);
        pages = ceph_alloc_page_vector(page_count, GFP_KERNEL);
        size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32);
        page_count = (u32)calc_pages_for(0, size);
        pages = ceph_alloc_page_vector(page_count, GFP_KERNEL);
-       if (IS_ERR(pages))
-               return PTR_ERR(pages);
+       if (IS_ERR(pages)) {
+               ret = PTR_ERR(pages);
+               goto fail_stat_request;
+       }
 
 
-       ret = -ENOMEM;
-       stat_request = rbd_obj_request_create(obj_request->object_name, 0, 0,
-                                                       OBJ_REQUEST_PAGES);
-       if (!stat_request)
-               goto out;
+       osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0);
+       osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages, size, 0,
+                                    false, false);
 
        rbd_obj_request_get(obj_request);
        stat_request->obj_request = obj_request;
        stat_request->pages = pages;
        stat_request->page_count = page_count;
 
        rbd_obj_request_get(obj_request);
        stat_request->obj_request = obj_request;
        stat_request->pages = pages;
        stat_request->page_count = page_count;
-
-       stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1,
-                                                  stat_request);
-       if (!stat_request->osd_req)
-               goto out;
        stat_request->callback = rbd_img_obj_exists_callback;
 
        stat_request->callback = rbd_img_obj_exists_callback;
 
-       osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0);
-       osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages, size, 0,
-                                       false, false);
        rbd_osd_req_format_read(stat_request);
 
        rbd_obj_request_submit(stat_request);
        return 0;
 
        rbd_osd_req_format_read(stat_request);
 
        rbd_obj_request_submit(stat_request);
        return 0;
 
-out:
-       if (ret)
-               rbd_obj_request_put(obj_request);
-
+fail_stat_request:
+       rbd_obj_request_put(stat_request);
        return ret;
 }
 
        return ret;
 }