rbd: remove old request handling code

Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
Ilya Dryomov 2018-01-29 14:04:08 +01:00
parent 3da691bf43
commit 51c3509e5e
1 changed files with 4 additions and 730 deletions

View File

@ -231,8 +231,6 @@ enum obj_operation_type {
enum obj_req_flags {
OBJ_REQ_DONE, /* completion flag: not done = 0, done = 1 */
OBJ_REQ_IMG_DATA, /* object usage: standalone = 0, image = 1 */
OBJ_REQ_KNOWN, /* EXISTS flag valid: no = 0, yes = 1 */
OBJ_REQ_EXISTS, /* target exists: no = 0, yes = 1 */
};
/*
@ -271,27 +269,15 @@ struct rbd_obj_request {
* An object request associated with an image will have its
* img_data flag set; a standalone object request will not.
*
* A standalone object request will have which == BAD_WHICH
* and a null obj_request pointer.
*
* An object request initiated in support of a layered image
* object (to check for its existence before a write) will
* have which == BAD_WHICH and a non-null obj_request pointer.
*
* Finally, an object request for rbd image data will have
* which != BAD_WHICH, and will have a non-null img_request
* pointer. The value of which will be in the range
* 0..(img_request->obj_request_count-1).
*/
union {
struct rbd_obj_request *obj_request; /* STAT op */
struct {
struct rbd_img_request *img_request;
u64 img_offset;
/* links for img_request->obj_requests list */
struct list_head links;
};
};
struct rbd_img_request *img_request;
u64 img_offset;
/* links for img_request->obj_requests list */
struct list_head links;
u32 which; /* posn image request list */
enum obj_request_type type;
@ -480,8 +466,6 @@ static bool single_major = true;
module_param(single_major, bool, S_IRUGO);
MODULE_PARM_DESC(single_major, "Use a single major number for all rbd devices (default: true)");
static int rbd_img_request_submit(struct rbd_img_request *img_request);
static ssize_t rbd_add(struct bus_type *bus, const char *buf,
size_t count);
static ssize_t rbd_remove(struct bus_type *bus, const char *buf,
@ -610,9 +594,6 @@ void rbd_warn(struct rbd_device *rbd_dev, const char *fmt, ...)
# define rbd_assert(expr) ((void) 0)
#endif /* !RBD_DEBUG */
static void rbd_osd_copyup_callback(struct rbd_obj_request *obj_request);
static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request);
static void rbd_img_parent_read(struct rbd_obj_request *obj_request);
static void rbd_dev_remove_parent(struct rbd_device *rbd_dev);
static int rbd_dev_refresh(struct rbd_device *rbd_dev);
@ -1369,37 +1350,6 @@ static bool obj_request_done_test(struct rbd_obj_request *obj_request)
return test_bit(OBJ_REQ_DONE, &obj_request->flags) != 0;
}
/*
* This sets the KNOWN flag after (possibly) setting the EXISTS
* flag. The latter is set based on the "exists" value provided.
*
* Note that for our purposes once an object exists it never goes
* away again. It's possible that the response from two existence
* checks are separated by the creation of the target object, and
* the first ("doesn't exist") response arrives *after* the second
* ("does exist"). In that case we ignore the second one.
*/
static void obj_request_existence_set(struct rbd_obj_request *obj_request,
bool exists)
{
if (exists)
set_bit(OBJ_REQ_EXISTS, &obj_request->flags);
set_bit(OBJ_REQ_KNOWN, &obj_request->flags);
smp_mb();
}
static bool obj_request_known_test(struct rbd_obj_request *obj_request)
{
smp_mb();
return test_bit(OBJ_REQ_KNOWN, &obj_request->flags) != 0;
}
static bool obj_request_exists_test(struct rbd_obj_request *obj_request)
{
smp_mb();
return test_bit(OBJ_REQ_EXISTS, &obj_request->flags) != 0;
}
static bool obj_request_overlaps_parent(struct rbd_obj_request *obj_request)
{
struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
@ -1643,42 +1593,6 @@ static bool rbd_img_is_write(struct rbd_img_request *img_req)
}
}
static void
rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
{
u64 xferred = obj_request->xferred;
u64 length = obj_request->length;
dout("%s: obj %p img %p result %d %llu/%llu\n", __func__,
obj_request, obj_request->img_request, obj_request->result,
xferred, length);
/*
* ENOENT means a hole in the image. We zero-fill the entire
* length of the request. A short read also implies zero-fill
* to the end of the request. An error requires the whole
* length of the request to be reported finished with an error
* to the block layer. In each case we update the xferred
* count to indicate the whole request was satisfied.
*/
rbd_assert(obj_request->type != OBJ_REQUEST_NODATA);
if (obj_request->result == -ENOENT) {
if (obj_request->type == OBJ_REQUEST_BIO)
zero_bios(&obj_request->bio_pos, 0, length);
else
zero_bvecs(&obj_request->bvec_pos, 0, length);
obj_request->result = 0;
} else if (xferred < length && !obj_request->result) {
if (obj_request->type == OBJ_REQUEST_BIO)
zero_bios(&obj_request->bio_pos, xferred,
length - xferred);
else
zero_bvecs(&obj_request->bvec_pos, xferred,
length - xferred);
}
obj_request->xferred = length;
obj_request_done_set(obj_request);
}
static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
{
dout("%s: obj %p cb %p\n", __func__, obj_request,
@ -1686,93 +1600,6 @@ static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
obj_request->callback(obj_request);
}
static void rbd_obj_request_error(struct rbd_obj_request *obj_request, int err)
{
obj_request->result = err;
obj_request->xferred = 0;
/*
* kludge - mirror rbd_obj_request_submit() to match a put in
* rbd_img_obj_callback()
*/
if (obj_request_img_data_test(obj_request)) {
WARN_ON(obj_request->callback != rbd_img_obj_callback);
rbd_img_request_get(obj_request->img_request);
}
obj_request_done_set(obj_request);
rbd_obj_request_complete(obj_request);
}
static void rbd_osd_read_callback(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request = NULL;
struct rbd_device *rbd_dev = NULL;
bool layered = false;
if (obj_request_img_data_test(obj_request)) {
img_request = obj_request->img_request;
layered = img_request && img_request_layered_test(img_request);
rbd_dev = img_request->rbd_dev;
}
dout("%s: obj %p img %p result %d %llu/%llu\n", __func__,
obj_request, img_request, obj_request->result,
obj_request->xferred, obj_request->length);
if (layered && obj_request->result == -ENOENT &&
obj_request->img_offset < rbd_dev->parent_overlap)
rbd_img_parent_read(obj_request);
else if (img_request)
rbd_img_obj_request_read_callback(obj_request);
else
obj_request_done_set(obj_request);
}
static void rbd_osd_write_callback(struct rbd_obj_request *obj_request)
{
dout("%s: obj %p result %d %llu\n", __func__, obj_request,
obj_request->result, obj_request->length);
/*
* There is no such thing as a successful short write. Set
* it to our originally-requested length.
*/
obj_request->xferred = obj_request->length;
obj_request_done_set(obj_request);
}
static void rbd_osd_discard_callback(struct rbd_obj_request *obj_request)
{
dout("%s: obj %p result %d %llu\n", __func__, obj_request,
obj_request->result, obj_request->length);
/*
* There is no such thing as a successful short discard. Set
* it to our originally-requested length.
*/
obj_request->xferred = obj_request->length;
/* discarding a non-existent object is not a problem */
if (obj_request->result == -ENOENT)
obj_request->result = 0;
obj_request_done_set(obj_request);
}
/*
* For a simple stat call there's nothing to do. We'll do more if
* this is part of a write sequence for a layered image.
*/
static void rbd_osd_stat_callback(struct rbd_obj_request *obj_request)
{
dout("%s: obj %p\n", __func__, obj_request);
obj_request_done_set(obj_request);
}
static void rbd_osd_call_callback(struct rbd_obj_request *obj_request)
{
dout("%s: obj %p\n", __func__, obj_request);
if (obj_request_img_data_test(obj_request))
rbd_osd_copyup_callback(obj_request);
else
obj_request_done_set(obj_request);
}
static void rbd_obj_handle_request(struct rbd_obj_request *obj_req);
static void rbd_osd_req_callback(struct ceph_osd_request *osd_req)
@ -1871,32 +1698,6 @@ static struct ceph_osd_request *rbd_osd_req_create(
CEPH_OSD_FLAG_WRITE : CEPH_OSD_FLAG_READ, obj_request);
}
/*
* Create a copyup osd request based on the information in the object
* request supplied. A copyup request has two or three osd ops, a
* copyup method call, potentially a hint op, and a write or truncate
* or zero op.
*/
static struct ceph_osd_request *
rbd_osd_req_create_copyup(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request;
int num_osd_ops = 3;
rbd_assert(obj_request_img_data_test(obj_request));
img_request = obj_request->img_request;
rbd_assert(img_request);
rbd_assert(img_request_write_test(img_request) ||
img_request_discard_test(img_request));
if (img_request_discard_test(img_request))
num_osd_ops = 2;
return __rbd_osd_req_create(img_request->rbd_dev,
img_request->snapc, num_osd_ops,
CEPH_OSD_FLAG_WRITE, obj_request);
}
static void rbd_osd_req_destroy(struct ceph_osd_request *osd_req)
{
ceph_osdc_put_request(osd_req);
@ -2217,73 +2018,6 @@ out:
rbd_img_request_complete(img_request);
}
/*
* Add individual osd ops to the given ceph_osd_request and prepare
* them for submission. num_ops is the current number of
* osd operations already to the object request.
*/
static void rbd_img_obj_request_fill(struct rbd_obj_request *obj_request,
struct ceph_osd_request *osd_request,
enum obj_operation_type op_type,
unsigned int num_ops)
{
struct rbd_img_request *img_request = obj_request->img_request;
struct rbd_device *rbd_dev = img_request->rbd_dev;
u64 object_size = rbd_obj_bytes(&rbd_dev->header);
u64 offset = obj_request->offset;
u64 length = obj_request->length;
u64 img_end;
u16 opcode;
if (op_type == OBJ_OP_DISCARD) {
if (!offset && length == object_size &&
(!img_request_layered_test(img_request) ||
!obj_request_overlaps_parent(obj_request))) {
opcode = CEPH_OSD_OP_DELETE;
} else if ((offset + length == object_size)) {
opcode = CEPH_OSD_OP_TRUNCATE;
} else {
down_read(&rbd_dev->header_rwsem);
img_end = rbd_dev->header.image_size;
up_read(&rbd_dev->header_rwsem);
if (obj_request->img_offset + length == img_end)
opcode = CEPH_OSD_OP_TRUNCATE;
else
opcode = CEPH_OSD_OP_ZERO;
}
} else if (op_type == OBJ_OP_WRITE) {
if (!offset && length == object_size)
opcode = CEPH_OSD_OP_WRITEFULL;
else
opcode = CEPH_OSD_OP_WRITE;
osd_req_op_alloc_hint_init(osd_request, num_ops,
object_size, object_size);
num_ops++;
} else {
opcode = CEPH_OSD_OP_READ;
}
if (opcode == CEPH_OSD_OP_DELETE)
osd_req_op_init(osd_request, num_ops, opcode, 0);
else
osd_req_op_extent_init(osd_request, num_ops, opcode,
offset, length, 0, 0);
if (obj_request->type == OBJ_REQUEST_BIO)
osd_req_op_extent_osd_data_bio(osd_request, num_ops,
&obj_request->bio_pos, length);
else if (obj_request->type == OBJ_REQUEST_BVECS)
osd_req_op_extent_osd_data_bvec_pos(osd_request, num_ops,
&obj_request->bvec_pos);
/* Discards are also writes */
if (op_type == OBJ_OP_WRITE || op_type == OBJ_OP_DISCARD)
rbd_osd_req_format_write(obj_request);
else
rbd_osd_req_format_read(obj_request);
}
static void rbd_osd_req_setup_data(struct rbd_obj_request *obj_req, u32 which)
{
switch (obj_req->type) {
@ -2568,366 +2302,6 @@ out_unwind:
return -ENOMEM;
}
static void
rbd_osd_copyup_callback(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request;
struct rbd_device *rbd_dev;
dout("%s: obj %p\n", __func__, obj_request);
rbd_assert(obj_request->type == OBJ_REQUEST_BIO ||
obj_request->type == OBJ_REQUEST_NODATA);
rbd_assert(obj_request_img_data_test(obj_request));
img_request = obj_request->img_request;
rbd_assert(img_request);
rbd_dev = img_request->rbd_dev;
rbd_assert(rbd_dev);
/*
* We want the transfer count to reflect the size of the
* original write request. There is no such thing as a
* successful short write, so if the request was successful
* we can just set it to the originally-requested length.
*/
if (!obj_request->result)
obj_request->xferred = obj_request->length;
obj_request_done_set(obj_request);
}
static void
rbd_img_obj_parent_read_full_callback(struct rbd_img_request *img_request)
{
struct rbd_obj_request *orig_request;
struct ceph_osd_request *osd_req;
struct rbd_device *rbd_dev;
enum obj_operation_type op_type;
int img_result;
u64 parent_length;
rbd_assert(img_request_child_test(img_request));
/* First get what we need from the image request */
orig_request = img_request->obj_request;
rbd_assert(orig_request != NULL);
rbd_assert(obj_request_type_valid(orig_request->type));
img_result = img_request->result;
parent_length = img_request->length;
rbd_assert(img_result || parent_length == img_request->xferred);
rbd_img_request_put(img_request);
rbd_assert(orig_request->img_request);
rbd_dev = orig_request->img_request->rbd_dev;
rbd_assert(rbd_dev);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to free the pages
* and re-submit the original write request.
*/
if (!rbd_dev->parent_overlap) {
rbd_obj_request_submit(orig_request);
return;
}
if (img_result)
goto out_err;
/*
* The original osd request is of no use to use any more.
* We need a new one that can hold the three ops in a copyup
* request. Allocate the new copyup osd request for the
* original request, and release the old one.
*/
img_result = -ENOMEM;
osd_req = rbd_osd_req_create_copyup(orig_request);
if (!osd_req)
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,
parent_length);
/* Add the other op(s) */
op_type = rbd_img_request_op_type(orig_request->img_request);
rbd_img_obj_request_fill(orig_request, osd_req, op_type, 1);
/* All set, send it off. */
rbd_obj_request_submit(orig_request);
return;
out_err:
rbd_obj_request_error(orig_request, img_result);
}
static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap);
/*
* Read from the parent image the range of data that covers the
* entire target of the given object request. This is used for
* satisfying a layered image write request when the target of an
* object request from the image request does not exist.
*
* A page array big enough to hold the returned data is allocated
* and supplied to rbd_img_request_fill() as the "data descriptor."
* When the read completes, this page array will be transferred to
* the original object request for the copyup operation.
*
* If an error occurs, it is recorded as the result of the original
* object request in rbd_img_obj_exists_callback().
*/
static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request)
{
struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
struct rbd_img_request *parent_request = NULL;
struct ceph_bvec_iter bvec_it = { 0 };
u64 img_offset;
u64 length;
int result;
rbd_assert(rbd_dev->parent != NULL);
/*
* Determine the byte range covered by the object in the
* child image to which the original request was to be sent.
*/
img_offset = obj_request->img_offset - obj_request->offset;
length = rbd_obj_bytes(&rbd_dev->header);
/*
* There is no defined parent data beyond the parent
* overlap, so limit what we read at that boundary if
* necessary.
*/
if (img_offset + length > rbd_dev->parent_overlap) {
rbd_assert(img_offset < rbd_dev->parent_overlap);
length = rbd_dev->parent_overlap - img_offset;
}
/*
* Allocate a page array big enough to receive the data read
* from the parent.
*/
result = setup_copyup_bvecs(obj_request, length);
if (result)
goto out_err;
result = -ENOMEM;
parent_request = rbd_parent_request_create(obj_request,
img_offset, length);
if (!parent_request)
goto out_err;
bvec_it.bvecs = obj_request->copyup_bvecs;
bvec_it.iter.bi_size = length;
result = rbd_img_request_fill(parent_request, OBJ_REQUEST_BVECS,
&bvec_it);
if (result)
goto out_err;
parent_request->callback = rbd_img_obj_parent_read_full_callback;
result = rbd_img_request_submit(parent_request);
if (!result)
return 0;
out_err:
if (parent_request)
rbd_img_request_put(parent_request);
return result;
}
static void rbd_img_obj_exists_callback(struct rbd_obj_request *obj_request)
{
struct rbd_obj_request *orig_request;
struct rbd_device *rbd_dev;
int result;
rbd_assert(!obj_request_img_data_test(obj_request));
/*
* All we need from the object request is the original
* request and the result of the STAT op. Grab those, then
* we're done with the request.
*/
orig_request = obj_request->obj_request;
obj_request->obj_request = NULL;
rbd_obj_request_put(orig_request);
rbd_assert(orig_request);
rbd_assert(orig_request->img_request);
result = obj_request->result;
obj_request->result = 0;
dout("%s: obj %p for obj %p result %d %llu/%llu\n", __func__,
obj_request, orig_request, result,
obj_request->xferred, obj_request->length);
rbd_obj_request_put(obj_request);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to re-submit the
* original request.
*/
rbd_dev = orig_request->img_request->rbd_dev;
if (!rbd_dev->parent_overlap) {
rbd_obj_request_submit(orig_request);
return;
}
/*
* Our only purpose here is to determine whether the object
* exists, and we don't want to treat the non-existence as
* an error. If something else comes back, transfer the
* error to the original request and complete it now.
*/
if (!result) {
obj_request_existence_set(orig_request, true);
} else if (result == -ENOENT) {
obj_request_existence_set(orig_request, false);
} else {
goto fail_orig_request;
}
/*
* Resubmit the original request now that we have recorded
* whether the target object exists.
*/
result = rbd_img_obj_request_submit(orig_request);
if (result)
goto fail_orig_request;
return;
fail_orig_request:
rbd_obj_request_error(orig_request, result);
}
static int rbd_img_obj_exists_submit(struct rbd_obj_request *obj_request)
{
struct rbd_device *rbd_dev = obj_request->img_request->rbd_dev;
struct rbd_obj_request *stat_request;
struct page **pages;
int ret;
stat_request = rbd_obj_request_create(OBJ_REQUEST_NODATA);
if (!stat_request)
return -ENOMEM;
stat_request->object_no = obj_request->object_no;
stat_request->osd_req = rbd_osd_req_create(rbd_dev, OBJ_OP_READ, 1,
stat_request);
if (!stat_request->osd_req) {
ret = -ENOMEM;
goto fail_stat_request;
}
/*
* The response data for a STAT call consists of:
* le64 length;
* struct {
* le32 tv_sec;
* le32 tv_nsec;
* } mtime;
*/
pages = ceph_alloc_page_vector(1, GFP_NOIO);
if (IS_ERR(pages)) {
ret = PTR_ERR(pages);
goto fail_stat_request;
}
osd_req_op_init(stat_request->osd_req, 0, CEPH_OSD_OP_STAT, 0);
osd_req_op_raw_data_in_pages(stat_request->osd_req, 0, pages,
8 + sizeof(struct ceph_timespec),
0, false, true);
rbd_obj_request_get(obj_request);
stat_request->obj_request = obj_request;
stat_request->callback = rbd_img_obj_exists_callback;
rbd_obj_request_submit(stat_request);
return 0;
fail_stat_request:
rbd_obj_request_put(stat_request);
return ret;
}
static bool img_obj_request_simple(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request = obj_request->img_request;
struct rbd_device *rbd_dev = img_request->rbd_dev;
/* Reads */
if (!img_request_write_test(img_request) &&
!img_request_discard_test(img_request))
return true;
/* Non-layered writes */
if (!img_request_layered_test(img_request))
return true;
/*
* Layered writes outside of the parent overlap range don't
* share any data with the parent.
*/
if (!obj_request_overlaps_parent(obj_request))
return true;
/*
* Entire-object layered writes - we will overwrite whatever
* parent data there is anyway.
*/
if (!obj_request->offset &&
obj_request->length == rbd_obj_bytes(&rbd_dev->header))
return true;
/*
* If the object is known to already exist, its parent data has
* already been copied.
*/
if (obj_request_known_test(obj_request) &&
obj_request_exists_test(obj_request))
return true;
return false;
}
static int rbd_img_obj_request_submit(struct rbd_obj_request *obj_request)
{
rbd_assert(obj_request_img_data_test(obj_request));
rbd_assert(obj_request_type_valid(obj_request->type));
rbd_assert(obj_request->img_request);
if (img_obj_request_simple(obj_request)) {
rbd_obj_request_submit(obj_request);
return 0;
}
/*
* It's a layered write. The target object might exist but
* we may not know that yet. If we know it doesn't exist,
* start by reading the data for the full target object from
* the parent so we can use it for a copyup to the target.
*/
if (obj_request_known_test(obj_request))
return rbd_img_obj_parent_read_full(obj_request);
/* We don't know whether the target exists. Go find out. */
return rbd_img_obj_exists_submit(obj_request);
}
static int rbd_img_request_submit(struct rbd_img_request *img_request)
{
struct rbd_obj_request *obj_request;
@ -3131,106 +2505,6 @@ static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
return 0;
}
static void rbd_img_parent_read_callback(struct rbd_img_request *img_request)
{
struct rbd_obj_request *obj_request;
struct rbd_device *rbd_dev;
u64 obj_end;
u64 img_xferred;
int img_result;
rbd_assert(img_request_child_test(img_request));
/* First get what we need from the image request and release it */
obj_request = img_request->obj_request;
img_xferred = img_request->xferred;
img_result = img_request->result;
rbd_img_request_put(img_request);
/*
* If the overlap has become 0 (most likely because the
* image has been flattened) we need to re-submit the
* original request.
*/
rbd_assert(obj_request);
rbd_assert(obj_request->img_request);
rbd_dev = obj_request->img_request->rbd_dev;
if (!rbd_dev->parent_overlap) {
rbd_obj_request_submit(obj_request);
return;
}
obj_request->result = img_result;
if (obj_request->result)
goto out;
/*
* We need to zero anything beyond the parent overlap
* boundary. Since rbd_img_obj_request_read_callback()
* will zero anything beyond the end of a short read, an
* easy way to do this is to pretend the data from the
* parent came up short--ending at the overlap boundary.
*/
rbd_assert(obj_request->img_offset < U64_MAX - obj_request->length);
obj_end = obj_request->img_offset + obj_request->length;
if (obj_end > rbd_dev->parent_overlap) {
u64 xferred = 0;
if (obj_request->img_offset < rbd_dev->parent_overlap)
xferred = rbd_dev->parent_overlap -
obj_request->img_offset;
obj_request->xferred = min(img_xferred, xferred);
} else {
obj_request->xferred = img_xferred;
}
out:
rbd_img_obj_request_read_callback(obj_request);
rbd_obj_request_complete(obj_request);
}
static void rbd_img_parent_read(struct rbd_obj_request *obj_request)
{
struct rbd_img_request *img_request;
int result;
rbd_assert(obj_request_img_data_test(obj_request));
rbd_assert(obj_request->img_request != NULL);
rbd_assert(obj_request->result == (s32) -ENOENT);
rbd_assert(obj_request_type_valid(obj_request->type));
/* rbd_read_finish(obj_request, obj_request->length); */
img_request = rbd_parent_request_create(obj_request,
obj_request->img_offset,
obj_request->length);
result = -ENOMEM;
if (!img_request)
goto out_err;
if (obj_request->type == OBJ_REQUEST_BIO)
result = rbd_img_request_fill(img_request, OBJ_REQUEST_BIO,
&obj_request->bio_pos);
else
result = rbd_img_request_fill(img_request, OBJ_REQUEST_BVECS,
&obj_request->bvec_pos);
if (result)
goto out_err;
img_request->callback = rbd_img_parent_read_callback;
result = rbd_img_request_submit(img_request);
if (result)
goto out_err;
return;
out_err:
if (img_request)
rbd_img_request_put(img_request);
obj_request->result = result;
obj_request->xferred = 0;
obj_request_done_set(obj_request);
}
static int rbd_obj_handle_write_guard(struct rbd_obj_request *obj_req)
{
struct rbd_device *rbd_dev = obj_req->img_request->rbd_dev;