CEPH filesystem development
 help / color / mirror / Atom feed
From: Alex Elder <elder@inktank.com>
To: ceph-devel@vger.kernel.org
Subject: [PATCH 11/11] rbd: split up rbd_get_segment()
Date: Fri, 24 Aug 2012 11:36:27 -0500	[thread overview]
Message-ID: <5037AD8B.2020805@inktank.com> (raw)
In-Reply-To: <5037AB20.4000103@inktank.com>

There are two places where rbd_get_segment() is called.  One, in
rbd_rq_fn(), only needs to know the length within a segment that an
I/O request should be.  The other, in rbd_do_op(), also needs the
name of the object and the offset within it for the I/O request.

Split out rbd_segment_name() into three dedicated functions:
    - rbd_segment_name() allocates and formats the name of the
      object for a segment containing a given rbd image offset
    - rbd_segment_offset() computes the offset within a segment for
      a given rbd image offset
    - rbd_segment_length() computes the length to use for I/O within
      a segment for a request, not to exceed the end of a segment
      object.

In the new functions be a bit more careful, checking for possible
error conditions:
    - watch for errors or overflows returned by snprintf()
    - catch (using BUG_ON()) potential overflow conditions
      when computing segment length

Signed-off-by: Alex Elder <elder@inktank.com>
---
 drivers/block/rbd.c |   66
+++++++++++++++++++++++++++++++--------------------
 1 file changed, 40 insertions(+), 26 deletions(-)

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index b649446..3a79e58 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -656,27 +656,47 @@ static void rbd_header_free(struct
rbd_image_header *header)
 	header->snapc = NULL;
 }

-/*
- * get the actual striped segment name, offset and length
- */
-static u64 rbd_get_segment(struct rbd_image_header *header,
-			   const char *object_prefix,
-			   u64 ofs, u64 len,
-			   char *seg_name, u64 *segofs)
+static char *rbd_segment_name(struct rbd_device *rbd_dev, u64 offset)
+{
+	char *name;
+	u64 segment;
+	int ret;
+
+	name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+	if (!name)
+		return NULL;
+	segment = offset >> rbd_dev->header.obj_order;
+	ret = snprintf(name, RBD_MAX_SEG_NAME_LEN, "%s.%012llx",
+			rbd_dev->header.object_prefix, segment);
+	if (ret < 0 || ret >= RBD_MAX_SEG_NAME_LEN) {
+		pr_err("error formatting segment name for #%llu (%d)\n",
+			segment, ret);
+		kfree(name);
+		name = NULL;
+	}
+
+	return name;
+}
+
+static u64 rbd_segment_offset(struct rbd_device *rbd_dev, u64 offset)
 {
-	u64 seg = ofs >> header->obj_order;
+	u64 segment_size = (u64) 1 << rbd_dev->header.obj_order;

-	if (seg_name)
-		snprintf(seg_name, RBD_MAX_SEG_NAME_LEN,
-			 "%s.%012llx", object_prefix, seg);
+	return offset & (segment_size - 1);
+}
+
+static u64 rbd_segment_length(struct rbd_device *rbd_dev,
+				u64 offset, u64 length)
+{
+	u64 segment_size = (u64) 1 << rbd_dev->header.obj_order;

-	ofs = ofs & ((1 << header->obj_order) - 1);
-	len = min_t(u64, len, (1 << header->obj_order) - ofs);
+	offset &= segment_size - 1;

-	if (segofs)
-		*segofs = ofs;
+	BUG_ON(length > U64_MAX - offset);
+	if (offset + length > segment_size)
+		length = segment_size - offset;

-	return len;
+	return length;
 }

 static int rbd_get_num_segments(struct rbd_image_header *header,
@@ -1114,14 +1134,11 @@ static int rbd_do_op(struct request *rq,
 	struct ceph_osd_req_op *ops;
 	u32 payload_len;

-	seg_name = kmalloc(RBD_MAX_SEG_NAME_LEN + 1, GFP_NOIO);
+	seg_name = rbd_segment_name(rbd_dev, ofs);
 	if (!seg_name)
 		return -ENOMEM;
-
-	seg_len = rbd_get_segment(&rbd_dev->header,
-				  rbd_dev->header.object_prefix,
-				  ofs, len,
-				  seg_name, &seg_ofs);
+	seg_len = rbd_segment_length(rbd_dev, ofs, len);
+	seg_ofs = rbd_segment_offset(rbd_dev, ofs);

 	payload_len = (flags & CEPH_OSD_FLAG_WRITE ? seg_len : 0);

@@ -1532,10 +1549,7 @@ static void rbd_rq_fn(struct request_queue *q)
 		do {
 			/* a bio clone to be passed down to OSD req */
 			dout("rq->bio->bi_vcnt=%hu\n", rq->bio->bi_vcnt);
-			op_size = rbd_get_segment(&rbd_dev->header,
-						  rbd_dev->header.object_prefix,
-						  ofs, size,
-						  NULL, NULL);
+			op_size = rbd_segment_length(rbd_dev, ofs, size);
 			kref_get(&coll->kref);
 			bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
 					      op_size, GFP_ATOMIC);
-- 
1.7.9.5


  parent reply	other threads:[~2012-08-24 16:36 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-24 16:26 [PATCH 00/11] rbd: another set of patches Alex Elder
2012-08-24 16:32 ` [PATCH 01/11] rbd: handle locking inside __rbd_client_find() Alex Elder
2012-08-30 16:09   ` Yehuda Sadeh
2012-08-24 16:32 ` [PATCH 02/11] rbd: don't over-allocate space for object prefix Alex Elder
2012-08-30 16:18   ` Yehuda Sadeh
2012-08-24 16:33 ` [PATCH 03/11] rbd: kill incore snap_names_len Alex Elder
2012-08-30 16:24   ` Yehuda Sadeh
2012-08-30 16:41     ` Alex Elder
2012-09-06 15:36   ` [PATCH, v2 " Alex Elder
2012-09-07 21:22     ` Yehuda Sadeh
2012-08-24 16:33 ` [PATCH 04/11] rbd: more cleanup in rbd_header_from_disk() Alex Elder
2012-08-30 16:48   ` Yehuda Sadeh
2012-08-24 16:33 ` [PATCH 05/11] rbd: move rbd_opts to struct rbd_device Alex Elder
2012-08-30 17:07   ` Yehuda Sadeh
2012-09-06 14:21     ` Alex Elder
2012-09-07 21:40       ` Yehuda Sadeh
2012-08-24 16:34 ` [PATCH 06/11] rbd: add read_only rbd map option Alex Elder
2012-08-30 17:29   ` Yehuda Sadeh
2012-08-30 17:39     ` Alex Elder
2012-09-06 15:36   ` [PATCH, v2 " Alex Elder
2012-09-07 15:45     ` Sage Weil
2012-09-07 20:36       ` Alex Elder
2012-09-07 21:26     ` Yehuda Sadeh Weinraub
2012-08-24 16:34 ` [PATCH 07/11] rbd: kill notify_timeout option Alex Elder
2012-08-30 17:31   ` Yehuda Sadeh
2012-08-24 16:35 ` [PATCH 08/11] rbd: bio_chain_clone() cleanups Alex Elder
2012-08-30 17:40   ` Yehuda Sadeh
2012-08-24 16:35 ` [PATCH 09/11] rbd: drop needless test in rbd_rq_fn() Alex Elder
2012-08-30 17:41   ` Yehuda Sadeh
2012-08-24 16:36 ` [PATCH 10/11] rbd: check for overflow in rbd_get_num_segments() Alex Elder
2012-08-30 17:50   ` Yehuda Sadeh
2012-08-24 16:36 ` Alex Elder [this message]
2012-08-30 18:03   ` [PATCH 11/11] rbd: split up rbd_get_segment() Yehuda Sadeh
2012-08-30 12:32 ` [PATCH 00/11] rbd: another set of patches Alex Elder
2012-09-06 15:34 ` Alex Elder

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5037AD8B.2020805@inktank.com \
    --to=elder@inktank.com \
    --cc=ceph-devel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox