Blob Blame History Raw
From: Chengguang Xu <cgxu519@gmx.com>
Date: Thu, 12 Apr 2018 12:04:55 +0800
Subject: libceph, rbd: add error handling for osd_req_op_cls_init()
Git-commit: fe943d50425b6646606f8ef1ef8b8d4975fdbee2
Patch-mainline: v4.18-rc1
References: bsc#1135897

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>
[luis: adjusted rbd context as we don't have commit 89a59c1ca73b ("rbd: copyup
 with an empty snapshot context (aka deep-copyup)") ]
Acked-by: Luis Henriques <lhenriques@suse.com>
---
 drivers/block/rbd.c             |    7 ++++++-
 include/linux/ceph/osd_client.h |    2 +-
 net/ceph/osd_client.c           |   12 +++++++++---
 3 files changed, 16 insertions(+), 5 deletions(-)

--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2452,12 +2452,17 @@ rbd_img_obj_parent_read_full_callback(st
 	osd_req = rbd_osd_req_create_copyup(orig_request);
 	if (!osd_req)
 		goto out_err;
+
+	img_result = osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd",
+					 "copyup");
+	if (img_result)
+		goto out_err;
+
 	rbd_osd_req_destroy(orig_request->osd_req);
 	orig_request->osd_req = osd_req;
 
 	/* Initialize the copyup op */
 
-	osd_req_op_cls_init(osd_req, 0, CEPH_OSD_OP_CALL, "rbd", "copyup");
 	osd_req_op_cls_request_data_bvecs(osd_req, 0, orig_request->copyup_bvecs,
 					  orig_request->copyup_bvec_count,
 					  parent_length);
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -439,7 +439,7 @@ extern void osd_req_op_cls_response_data
 					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,
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -767,7 +767,7 @@ void osd_req_op_extent_dup_last(struct c
 }
 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
 	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
 	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_clien
 	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);