Commit 4766815b authored by David Disseldorp's avatar David Disseldorp Committed by Ilya Dryomov
Browse files

libceph: handle OSD op ceph_pagelist_append() errors



osd_req_op_cls_init() and osd_req_op_xattr_init() currently propagate
ceph_pagelist_alloc() ENOMEM errors but ignore ceph_pagelist_append()
memory allocation failures. Add these checks and cleanup on error.

Signed-off-by: default avatarDavid Disseldorp <ddiss@suse.de>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
parent 3e8730fa
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -841,6 +841,7 @@ int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
	struct ceph_pagelist *pagelist;
	size_t payload_len = 0;
	size_t size;
	int ret;

	op = _osd_req_op_init(osd_req, which, CEPH_OSD_OP_CALL, 0);

@@ -852,20 +853,27 @@ int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
	size = strlen(class);
	BUG_ON(size > (size_t) U8_MAX);
	op->cls.class_len = size;
	ceph_pagelist_append(pagelist, class, size);
	ret = ceph_pagelist_append(pagelist, class, size);
	if (ret)
		goto err_pagelist_free;
	payload_len += size;

	op->cls.method_name = method;
	size = strlen(method);
	BUG_ON(size > (size_t) U8_MAX);
	op->cls.method_len = size;
	ceph_pagelist_append(pagelist, method, size);
	ret = ceph_pagelist_append(pagelist, method, size);
	if (ret)
		goto err_pagelist_free;
	payload_len += size;

	osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);

	op->indata_len = payload_len;
	return 0;

err_pagelist_free:
	ceph_pagelist_release(pagelist);
	return ret;
}
EXPORT_SYMBOL(osd_req_op_cls_init);

@@ -877,6 +885,7 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which,
						      opcode, 0);
	struct ceph_pagelist *pagelist;
	size_t payload_len;
	int ret;

	BUG_ON(opcode != CEPH_OSD_OP_SETXATTR && opcode != CEPH_OSD_OP_CMPXATTR);

@@ -886,10 +895,14 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which,

	payload_len = strlen(name);
	op->xattr.name_len = payload_len;
	ceph_pagelist_append(pagelist, name, payload_len);
	ret = ceph_pagelist_append(pagelist, name, payload_len);
	if (ret)
		goto err_pagelist_free;

	op->xattr.value_len = size;
	ceph_pagelist_append(pagelist, value, size);
	ret = ceph_pagelist_append(pagelist, value, size);
	if (ret)
		goto err_pagelist_free;
	payload_len += size;

	op->xattr.cmp_op = cmp_op;
@@ -898,6 +911,10 @@ int osd_req_op_xattr_init(struct ceph_osd_request *osd_req, unsigned int which,
	ceph_osd_data_pagelist_init(&op->xattr.osd_data, pagelist);
	op->indata_len = payload_len;
	return 0;

err_pagelist_free:
	ceph_pagelist_release(pagelist);
	return ret;
}
EXPORT_SYMBOL(osd_req_op_xattr_init);