Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b434a2a authored by Josh Durgin's avatar Josh Durgin Committed by Ilya Dryomov
Browse files

rbd: extract a method for adding object operations



rbd_img_request_fill() creates a ceph_osd_request and has logic for
adding the appropriate osd ops to it based on the request type and
image properties.

For layered images, the original rbd_obj_request is resent with a
copyup operation in front, using a new ceph_osd_request. The logic for
adding the original operations should be the same as when first
sending them, so move it to a helper function.

op_type only needs to be checked once, so create a helper for that as
well and call it outside the loop in rbd_img_request_fill().

Signed-off-by: default avatarJosh Durgin <josh.durgin@inktank.com>
parent 1c220881
Loading
Loading
Loading
Loading
+78 −55
Original line number Original line Diff line number Diff line
@@ -1672,6 +1672,17 @@ static bool img_request_layered_test(struct rbd_img_request *img_request)
	return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0;
	return test_bit(IMG_REQ_LAYERED, &img_request->flags) != 0;
}
}


static enum obj_operation_type
rbd_img_request_op_type(struct rbd_img_request *img_request)
{
	if (img_request_write_test(img_request))
		return OBJ_OP_WRITE;
	else if (img_request_discard_test(img_request))
		return OBJ_OP_DISCARD;
	else
		return OBJ_OP_READ;
}

static void
static void
rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
{
{
@@ -2307,6 +2318,68 @@ static void rbd_img_obj_callback(struct rbd_obj_request *obj_request)
		rbd_img_request_complete(img_request);
		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) ||
				(rbd_dev->parent_overlap <=
					obj_request->img_offset))) {
			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) {
		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;
	}

	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_list, length);
	else if (obj_request->type == OBJ_REQUEST_PAGES)
		osd_req_op_extent_osd_data_pages(osd_request, num_ops,
					obj_request->pages, length,
					offset & ~PAGE_MASK, false, false);

	/* 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);
}

/*
/*
 * Split up an image request into one or more object requests, each
 * Split up an image request into one or more object requests, each
 * to a different object.  The "type" parameter indicates whether
 * to a different object.  The "type" parameter indicates whether
@@ -2326,11 +2399,8 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
	unsigned int bio_offset = 0;
	unsigned int bio_offset = 0;
	struct page **pages = NULL;
	struct page **pages = NULL;
	enum obj_operation_type op_type;
	enum obj_operation_type op_type;
	u64 object_size = rbd_obj_bytes(&rbd_dev->header);
	u64 img_offset;
	u64 img_offset;
	u64 img_end;
	u64 resid;
	u64 resid;
	u16 opcode;


	dout("%s: img %p type %d data_desc %p\n", __func__, img_request,
	dout("%s: img %p type %d data_desc %p\n", __func__, img_request,
		(int)type, data_desc);
		(int)type, data_desc);
@@ -2338,6 +2408,7 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
	img_offset = img_request->offset;
	img_offset = img_request->offset;
	resid = img_request->length;
	resid = img_request->length;
	rbd_assert(resid > 0);
	rbd_assert(resid > 0);
	op_type = rbd_img_request_op_type(img_request);


	if (type == OBJ_REQUEST_BIO) {
	if (type == OBJ_REQUEST_BIO) {
		bio_list = data_desc;
		bio_list = data_desc;
@@ -2352,7 +2423,6 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
		const char *object_name;
		const char *object_name;
		u64 offset;
		u64 offset;
		u64 length;
		u64 length;
		unsigned int which = 0;


		object_name = rbd_segment_name(rbd_dev, img_offset);
		object_name = rbd_segment_name(rbd_dev, img_offset);
		if (!object_name)
		if (!object_name)
@@ -2395,66 +2465,19 @@ static int rbd_img_request_fill(struct rbd_img_request *img_request,
			pages += page_count;
			pages += page_count;
		}
		}


		if (img_request_discard_test(img_request)) {
			op_type = OBJ_OP_DISCARD;
			if (!offset && (length == object_size)
				&& (!img_request_layered_test(img_request) ||
					(rbd_dev->parent_overlap <=
						obj_request->img_offset))) {
				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 (img_request_write_test(img_request)) {
			op_type = OBJ_OP_WRITE;
			opcode = CEPH_OSD_OP_WRITE;
		} else {
			op_type = OBJ_OP_READ;
			opcode = CEPH_OSD_OP_READ;
		}

		osd_req = rbd_osd_req_create(rbd_dev, op_type,
		osd_req = rbd_osd_req_create(rbd_dev, op_type,
					(op_type == OBJ_OP_WRITE) ? 2 : 1,
					(op_type == OBJ_OP_WRITE) ? 2 : 1,
					obj_request);
					obj_request);
		if (!osd_req)
		if (!osd_req)
			goto out_unwind;
			goto out_unwind;

		obj_request->osd_req = osd_req;
		obj_request->osd_req = osd_req;
		obj_request->callback = rbd_img_obj_callback;
		obj_request->callback = rbd_img_obj_callback;
		rbd_img_request_get(img_request);
		obj_request->img_offset = img_offset;

		if (op_type == OBJ_OP_WRITE) {
			osd_req_op_alloc_hint_init(osd_req, which,
					     rbd_obj_bytes(&rbd_dev->header),
					     rbd_obj_bytes(&rbd_dev->header));
			which++;
		}

		osd_req_op_extent_init(osd_req, which, opcode, offset, length,
				       0, 0);
		if (type == OBJ_REQUEST_BIO)
			osd_req_op_extent_osd_data_bio(osd_req, which,
					obj_request->bio_list, length);
		else if (type == OBJ_REQUEST_PAGES)
			osd_req_op_extent_osd_data_pages(osd_req, which,
					obj_request->pages, length,
					offset & ~PAGE_MASK, false, false);


		/* Discards are also writes */
		rbd_img_obj_request_fill(obj_request, osd_req, op_type, 0);
		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);


		obj_request->img_offset = img_offset;
		rbd_img_request_get(img_request);


		img_offset += length;
		img_offset += length;
		resid -= length;
		resid -= length;