libceph, rbd: add error handling for osd_req_op_cls_init()
authorChengguang Xu <cgxu519@gmx.com>
Thu, 12 Apr 2018 04:04:55 +0000 (12:04 +0800)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 4 Jun 2018 18:45:54 +0000 (20:45 +0200)
Add proper error handling for osd_req_op_cls_init() to replace
BUG_ON statement when failing from memory allocation.

Signed-off-by: Chengguang Xu <cgxu519@gmx.com>
Reviewed-by: Ilya Dryomov <idryomov@gmail.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
drivers/block/rbd.c
include/linux/ceph/osd_client.h
net/ceph/osd_client.c

index 33b36fea1d73f0e957dcd7ef4b8107526e764893..ac57bc0f6fcad7af8f28d9c93fd179485e7319c9 100644 (file)
@@ -2339,6 +2339,7 @@ static bool is_zero_bvecs(struct bio_vec *bvecs, u32 bytes)
 static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
 {
        unsigned int num_osd_ops = obj_req->osd_req->r_num_ops;
+       int ret;
 
        dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes);
        rbd_assert(obj_req->osd_req->r_ops[0].op == CEPH_OSD_OP_STAT);
@@ -2353,6 +2354,11 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
        if (!obj_req->osd_req)
                return -ENOMEM;
 
+       ret = osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
+                                 "copyup");
+       if (ret)
+               return ret;
+
        /*
         * Only send non-zero copyup data to save some I/O and network
         * bandwidth -- zero copyup data is equivalent to the object not
@@ -2362,9 +2368,6 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
                dout("%s obj_req %p detected zeroes\n", __func__, obj_req);
                bytes = 0;
        }
-
-       osd_req_op_cls_init(obj_req->osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
-                           "copyup");
        osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0,
                                          obj_req->copyup_bvecs,
                                          obj_req->copyup_bvec_count,
index 96bb3228598927c0cb089b5f4fa88da445cd1b26..b73dd7ebe585a523f32c5cf552b5d786b33e8dd2 100644 (file)
@@ -440,7 +440,7 @@ extern void osd_req_op_cls_response_data_pages(struct ceph_osd_request *,
                                        struct page **pages, u64 length,
                                        u32 alignment, bool pages_from_pool,
                                        bool own_pages);
-extern void osd_req_op_cls_init(struct ceph_osd_request *osd_req,
+extern int osd_req_op_cls_init(struct ceph_osd_request *osd_req,
                                        unsigned int which, u16 opcode,
                                        const char *class, const char *method);
 extern int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which,
index d2667e5dddc3acf4524ae280bee3ac832accdf0f..08b5fc1f90ccfff373b54d0bc0bc8a649326dc48 100644 (file)
@@ -767,7 +767,7 @@ void osd_req_op_extent_dup_last(struct ceph_osd_request *osd_req,
 }
 EXPORT_SYMBOL(osd_req_op_extent_dup_last);
 
-void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
+int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
                        u16 opcode, const char *class, const char *method)
 {
        struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which,
@@ -779,7 +779,9 @@ void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
        BUG_ON(opcode != CEPH_OSD_OP_CALL);
 
        pagelist = kmalloc(sizeof (*pagelist), GFP_NOFS);
-       BUG_ON(!pagelist);
+       if (!pagelist)
+               return -ENOMEM;
+
        ceph_pagelist_init(pagelist);
 
        op->cls.class_name = class;
@@ -799,6 +801,7 @@ void osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
        osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);
 
        op->indata_len = payload_len;
+       return 0;
 }
 EXPORT_SYMBOL(osd_req_op_cls_init);
 
@@ -4928,7 +4931,10 @@ int ceph_osdc_call(struct ceph_osd_client *osdc,
        if (ret)
                goto out_put_req;
 
-       osd_req_op_cls_init(req, 0, CEPH_OSD_OP_CALL, class, method);
+       ret = osd_req_op_cls_init(req, 0, CEPH_OSD_OP_CALL, class, method);
+       if (ret)
+               goto out_put_req;
+
        if (req_page)
                osd_req_op_cls_request_data_pages(req, 0, &req_page, req_len,
                                                  0, false, false);