rbd: introduce rbd_obj_issue_copyup_ops()
In preparation for deep-flatten feature, split rbd_obj_issue_copyup() into two functions and add a new write state to make the state machine slightly more clear. Make the copyup op optional and start using that for when the overlap goes to 0. Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
This commit is contained in:
parent
13488d5377
commit
3a482501cf
|
@ -236,7 +236,8 @@ enum obj_operation_type {
|
||||||
enum rbd_obj_write_state {
|
enum rbd_obj_write_state {
|
||||||
RBD_OBJ_WRITE_FLAT = 1,
|
RBD_OBJ_WRITE_FLAT = 1,
|
||||||
RBD_OBJ_WRITE_GUARD,
|
RBD_OBJ_WRITE_GUARD,
|
||||||
RBD_OBJ_WRITE_COPYUP,
|
RBD_OBJ_WRITE_READ_FROM_PARENT,
|
||||||
|
RBD_OBJ_WRITE_COPYUP_OPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rbd_obj_request {
|
struct rbd_obj_request {
|
||||||
|
@ -2458,10 +2459,13 @@ static bool is_zero_bvecs(struct bio_vec *bvecs, u32 bytes)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
|
#define MODS_ONLY U32_MAX
|
||||||
|
|
||||||
|
static int rbd_obj_issue_copyup_ops(struct rbd_obj_request *obj_req, u32 bytes)
|
||||||
{
|
{
|
||||||
struct rbd_img_request *img_req = obj_req->img_request;
|
struct rbd_img_request *img_req = obj_req->img_request;
|
||||||
unsigned int num_osd_ops = 1;
|
unsigned int num_osd_ops = (bytes != MODS_ONLY);
|
||||||
|
unsigned int which = 0;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes);
|
dout("%s obj_req %p bytes %u\n", __func__, obj_req, bytes);
|
||||||
|
@ -2483,31 +2487,25 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
|
||||||
if (!obj_req->osd_req)
|
if (!obj_req->osd_req)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = osd_req_op_cls_init(obj_req->osd_req, 0, "rbd", "copyup");
|
if (bytes != MODS_ONLY) {
|
||||||
if (ret)
|
ret = osd_req_op_cls_init(obj_req->osd_req, which, "rbd",
|
||||||
return ret;
|
"copyup");
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
/*
|
osd_req_op_cls_request_data_bvecs(obj_req->osd_req, which++,
|
||||||
* Only send non-zero copyup data to save some I/O and network
|
obj_req->copyup_bvecs,
|
||||||
* bandwidth -- zero copyup data is equivalent to the object not
|
obj_req->copyup_bvec_count,
|
||||||
* existing.
|
bytes);
|
||||||
*/
|
|
||||||
if (is_zero_bvecs(obj_req->copyup_bvecs, bytes)) {
|
|
||||||
dout("%s obj_req %p detected zeroes\n", __func__, obj_req);
|
|
||||||
bytes = 0;
|
|
||||||
}
|
}
|
||||||
osd_req_op_cls_request_data_bvecs(obj_req->osd_req, 0,
|
|
||||||
obj_req->copyup_bvecs,
|
|
||||||
obj_req->copyup_bvec_count,
|
|
||||||
bytes);
|
|
||||||
|
|
||||||
switch (img_req->op_type) {
|
switch (img_req->op_type) {
|
||||||
case OBJ_OP_WRITE:
|
case OBJ_OP_WRITE:
|
||||||
__rbd_obj_setup_write(obj_req, 1);
|
__rbd_obj_setup_write(obj_req, which);
|
||||||
break;
|
break;
|
||||||
case OBJ_OP_ZEROOUT:
|
case OBJ_OP_ZEROOUT:
|
||||||
rbd_assert(!rbd_obj_is_entire(obj_req));
|
rbd_assert(!rbd_obj_is_entire(obj_req));
|
||||||
__rbd_obj_setup_zeroout(obj_req, 1);
|
__rbd_obj_setup_zeroout(obj_req, which);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
rbd_assert(0);
|
rbd_assert(0);
|
||||||
|
@ -2521,6 +2519,22 @@ static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rbd_obj_issue_copyup(struct rbd_obj_request *obj_req, u32 bytes)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Only send non-zero copyup data to save some I/O and network
|
||||||
|
* bandwidth -- zero copyup data is equivalent to the object not
|
||||||
|
* existing.
|
||||||
|
*/
|
||||||
|
if (is_zero_bvecs(obj_req->copyup_bvecs, bytes)) {
|
||||||
|
dout("%s obj_req %p detected zeroes\n", __func__, obj_req);
|
||||||
|
bytes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
obj_req->write_state = RBD_OBJ_WRITE_COPYUP_OPS;
|
||||||
|
return rbd_obj_issue_copyup_ops(obj_req, bytes);
|
||||||
|
}
|
||||||
|
|
||||||
static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
|
static int setup_copyup_bvecs(struct rbd_obj_request *obj_req, u64 obj_overlap)
|
||||||
{
|
{
|
||||||
u32 i;
|
u32 i;
|
||||||
|
@ -2560,22 +2574,19 @@ static int rbd_obj_handle_write_guard(struct rbd_obj_request *obj_req)
|
||||||
if (!obj_req->num_img_extents) {
|
if (!obj_req->num_img_extents) {
|
||||||
/*
|
/*
|
||||||
* The overlap has become 0 (most likely because the
|
* The overlap has become 0 (most likely because the
|
||||||
* image has been flattened). Use rbd_obj_issue_copyup()
|
* image has been flattened). Re-submit the original write
|
||||||
* to re-submit the original write request -- the copyup
|
* request -- pass MODS_ONLY since the copyup isn't needed
|
||||||
* operation itself will be a no-op, since someone must
|
* anymore.
|
||||||
* have populated the child object while we weren't
|
|
||||||
* looking. Move to WRITE_FLAT state as we'll be done
|
|
||||||
* with the operation once the null copyup completes.
|
|
||||||
*/
|
*/
|
||||||
obj_req->write_state = RBD_OBJ_WRITE_FLAT;
|
obj_req->write_state = RBD_OBJ_WRITE_COPYUP_OPS;
|
||||||
return rbd_obj_issue_copyup(obj_req, 0);
|
return rbd_obj_issue_copyup_ops(obj_req, MODS_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = setup_copyup_bvecs(obj_req, rbd_obj_img_extents_bytes(obj_req));
|
ret = setup_copyup_bvecs(obj_req, rbd_obj_img_extents_bytes(obj_req));
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
obj_req->write_state = RBD_OBJ_WRITE_COPYUP;
|
obj_req->write_state = RBD_OBJ_WRITE_READ_FROM_PARENT;
|
||||||
return rbd_obj_read_from_parent(obj_req);
|
return rbd_obj_read_from_parent(obj_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2583,7 +2594,6 @@ static bool rbd_obj_handle_write(struct rbd_obj_request *obj_req)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
again:
|
|
||||||
switch (obj_req->write_state) {
|
switch (obj_req->write_state) {
|
||||||
case RBD_OBJ_WRITE_GUARD:
|
case RBD_OBJ_WRITE_GUARD:
|
||||||
rbd_assert(!obj_req->xferred);
|
rbd_assert(!obj_req->xferred);
|
||||||
|
@ -2602,6 +2612,7 @@ again:
|
||||||
}
|
}
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case RBD_OBJ_WRITE_FLAT:
|
case RBD_OBJ_WRITE_FLAT:
|
||||||
|
case RBD_OBJ_WRITE_COPYUP_OPS:
|
||||||
if (!obj_req->result)
|
if (!obj_req->result)
|
||||||
/*
|
/*
|
||||||
* There is no such thing as a successful short
|
* There is no such thing as a successful short
|
||||||
|
@ -2609,10 +2620,9 @@ again:
|
||||||
*/
|
*/
|
||||||
obj_req->xferred = obj_req->ex.oe_len;
|
obj_req->xferred = obj_req->ex.oe_len;
|
||||||
return true;
|
return true;
|
||||||
case RBD_OBJ_WRITE_COPYUP:
|
case RBD_OBJ_WRITE_READ_FROM_PARENT:
|
||||||
obj_req->write_state = RBD_OBJ_WRITE_GUARD;
|
|
||||||
if (obj_req->result)
|
if (obj_req->result)
|
||||||
goto again;
|
return true;
|
||||||
|
|
||||||
rbd_assert(obj_req->xferred);
|
rbd_assert(obj_req->xferred);
|
||||||
ret = rbd_obj_issue_copyup(obj_req, obj_req->xferred);
|
ret = rbd_obj_issue_copyup(obj_req, obj_req->xferred);
|
||||||
|
|
Loading…
Reference in New Issue