summaryrefslogtreecommitdiffstats
path: root/drivers/block
diff options
context:
space:
mode:
authorIlya Dryomov <idryomov@gmail.com>2016-09-15 17:53:32 +0200
committerIlya Dryomov <idryomov@gmail.com>2016-10-03 16:13:48 +0200
commit710214e391476f331abed1b774b5f025d054ab7f (patch)
tree3ca0c6e07acc2a7a07cdf86bb4b8325a5a4266d4 /drivers/block
parentrbd: don't crash or leak on errors in rbd_img_obj_parent_read_full_callback() (diff)
downloadlinux-710214e391476f331abed1b774b5f025d054ab7f.tar.xz
linux-710214e391476f331abed1b774b5f025d054ab7f.zip
rbd: rework rbd_img_obj_exists_submit() error paths
- 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>
Diffstat (limited to 'drivers/block')
-rw-r--r--drivers/block/rbd.c42
1 files changed, 22 insertions, 20 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 77675ac8fc4c..3218ac4f2e09 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -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 page **pages = NULL;
+ struct page **pages;
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;
@@ -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);
- 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;
-
- 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;
- 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;
-out:
- if (ret)
- rbd_obj_request_put(obj_request);
-
+fail_stat_request:
+ rbd_obj_request_put(stat_request);
return ret;
}