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: David Disseldorp <ddiss@suse.de> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
Родитель
3e8730fac9
Коммит
4766815b11
|
@ -841,6 +841,7 @@ int osd_req_op_cls_init(struct ceph_osd_request *osd_req, unsigned int which,
|
||||||
struct ceph_pagelist *pagelist;
|
struct ceph_pagelist *pagelist;
|
||||||
size_t payload_len = 0;
|
size_t payload_len = 0;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
int ret;
|
||||||
|
|
||||||
op = _osd_req_op_init(osd_req, which, CEPH_OSD_OP_CALL, 0);
|
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);
|
size = strlen(class);
|
||||||
BUG_ON(size > (size_t) U8_MAX);
|
BUG_ON(size > (size_t) U8_MAX);
|
||||||
op->cls.class_len = size;
|
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;
|
payload_len += size;
|
||||||
|
|
||||||
op->cls.method_name = method;
|
op->cls.method_name = method;
|
||||||
size = strlen(method);
|
size = strlen(method);
|
||||||
BUG_ON(size > (size_t) U8_MAX);
|
BUG_ON(size > (size_t) U8_MAX);
|
||||||
op->cls.method_len = size;
|
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;
|
payload_len += size;
|
||||||
|
|
||||||
osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);
|
osd_req_op_cls_request_info_pagelist(osd_req, which, pagelist);
|
||||||
|
|
||||||
op->indata_len = payload_len;
|
op->indata_len = payload_len;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_pagelist_free:
|
||||||
|
ceph_pagelist_release(pagelist);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(osd_req_op_cls_init);
|
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);
|
opcode, 0);
|
||||||
struct ceph_pagelist *pagelist;
|
struct ceph_pagelist *pagelist;
|
||||||
size_t payload_len;
|
size_t payload_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
BUG_ON(opcode != CEPH_OSD_OP_SETXATTR && opcode != CEPH_OSD_OP_CMPXATTR);
|
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);
|
payload_len = strlen(name);
|
||||||
op->xattr.name_len = payload_len;
|
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;
|
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;
|
payload_len += size;
|
||||||
|
|
||||||
op->xattr.cmp_op = cmp_op;
|
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);
|
ceph_osd_data_pagelist_init(&op->xattr.osd_data, pagelist);
|
||||||
op->indata_len = payload_len;
|
op->indata_len = payload_len;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
err_pagelist_free:
|
||||||
|
ceph_pagelist_release(pagelist);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(osd_req_op_xattr_init);
|
EXPORT_SYMBOL(osd_req_op_xattr_init);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче