diff options
| author | Ilya Dryomov <idryomov@gmail.com> | 2016-09-15 11:53:32 -0400 |
|---|---|---|
| committer | Ilya Dryomov <idryomov@gmail.com> | 2016-10-03 10:13:48 -0400 |
| commit | 710214e391476f331abed1b774b5f025d054ab7f (patch) | |
| tree | 3ca0c6e07acc2a7a07cdf86bb4b8325a5a4266d4 /drivers/block/rbd.c | |
| parent | fa355112c2763d513f1356119684dc8a6150d08a (diff) | |
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/rbd.c')
| -rw-r--r-- | drivers/block/rbd.c | 42 |
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) | |||
| 2894 | { | 2894 | { |
| 2895 | struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev; | 2895 | struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev; |
| 2896 | struct rbd_obj_request *stat_request; | 2896 | struct rbd_obj_request *stat_request; |
| 2897 | struct page **pages = NULL; | 2897 | struct page **pages; |
| 2898 | u32 page_count; | 2898 | u32 page_count; |
| 2899 | size_t size; | 2899 | size_t size; |
| 2900 | int ret; | 2900 | int ret; |
| 2901 | 2901 | ||
| 2902 | stat_request = rbd_obj_request_create(obj_request->object_name, 0, 0, | ||
| 2903 | OBJ_REQUEST_PAGES); | ||
| 2904 | if (!stat_request) | ||
| 2905 | return -ENOMEM; | ||
| 2906 | |||
| 2907 | stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1, | ||
| 2908 | stat_request); | ||
| 2909 | if (!stat_request->osd_req) { | ||
| 2910 | ret = -ENOMEM; | ||
| 2911 | goto fail_stat_request; | ||
| 2912 | } | ||
| 2913 | |||
| 2902 | /* | 2914 | /* |
| 2903 | * The response data for a STAT call consists of: | 2915 | * The response data for a STAT call consists of: |
| 2904 | * le64 length; | 2916 | * le64 length; |
| @@ -2910,38 +2922,28 @@ static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request) | |||
| 2910 | size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32); | 2922 | size = sizeof (__le64) + sizeof (__le32) + sizeof (__le32); |
| 2911 | page_count = (u32)calc_pages_for(0, size); | 2923 | page_count = (u32)calc_pages_for(0, size); |
| 2912 | pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); | 2924 | pages = ceph_alloc_page_vector(page_count, GFP_KERNEL); |
| 2913 | if (IS_ERR(pages)) | 2925 | if (IS_ERR(pages)) { |
| 2914 | return PTR_ERR(pages); | 2926 | ret = PTR_ERR(pages); |
| 2927 | goto fail_stat_request; | ||
| 2928 | } | ||
| 2915 | 2929 | ||
| 2916 | ret = -ENOMEM; | 2930 | osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0); |
| 2917 | stat_request = rbd_obj_request_create(obj_request->object_name, 0, 0, | 2931 | osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages, size, 0, |
| 2918 | OBJ_REQUEST_PAGES); | 2932 | false, false); |
| 2919 | if (!stat_request) | ||
| 2920 | goto out; | ||
| 2921 | 2933 | ||
| 2922 | rbd_obj_request_get(obj_request); | 2934 | rbd_obj_request_get(obj_request); |
| 2923 | stat_request->obj_request = obj_request; | 2935 | stat_request->obj_request = obj_request; |
| 2924 | stat_request->pages = pages; | 2936 | stat_request->pages = pages; |
| 2925 | stat_request->page_count = page_count; | 2937 | stat_request->page_count = page_count; |
| 2926 | |||
| 2927 | stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1, | ||
| 2928 | stat_request); | ||
| 2929 | if (!stat_request->osd_req) | ||
| 2930 | goto out; | ||
| 2931 | stat_request->callback = rbd_img_obj_exists_callback; | 2938 | stat_request->callback = rbd_img_obj_exists_callback; |
| 2932 | 2939 | ||
| 2933 | osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0); | ||
| 2934 | osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages, size, 0, | ||
| 2935 | false, false); | ||
| 2936 | rbd_osd_req_format_read(stat_request); | 2940 | rbd_osd_req_format_read(stat_request); |
| 2937 | 2941 | ||
| 2938 | rbd_obj_request_submit(stat_request); | 2942 | rbd_obj_request_submit(stat_request); |
| 2939 | return 0; | 2943 | return 0; |
| 2940 | 2944 | ||
| 2941 | out: | 2945 | fail_stat_request: |
| 2942 | if (ret) | 2946 | rbd_obj_request_put(stat_request); |
| 2943 | rbd_obj_request_put(obj_request); | ||
| 2944 | |||
| 2945 | return ret; | 2947 | return ret; |
| 2946 | } | 2948 | } |
| 2947 | 2949 | ||
