All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/7] rbd: use common code for probe and refresh
@ 2013-05-07  1:51 Alex Elder
  2013-05-07  1:52 ` [PATCH 1/7] rbd: set the mapping size and features later Alex Elder
                   ` (7 more replies)
  0 siblings, 8 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:51 UTC (permalink / raw)
  To: ceph-devel

This is some work I had nearly done a long time ago.  It didn't even
have a bug associated with it.  I resurrected it over the weekend
and ported it to the new code.

It's basically cleanup though.  For format 1 rbd images, when
probing an image, header information for it is read in and
translated directly into the rbd_dev->header structure.

For an image refresh, instead, we use a stack structure to
hold the translated header, and then in a second step we
copy that into rbd_dev->header.

This series gets rid of the local variable, and always just
puts things directly into rbd_dev->header.  It also simplifies
probe and refresh for both format 1 and format 2, using a
common rbd_dev_vX_header_info() function for both purposes.

This set of patches, as well as the two single patches
and series of six I just posted, are available in the
"review/wip-rbd-cleanup-1" branch of the ceph-client git
repository.

					-Alex

[PATCH 1/7] rbd: set the mapping size and features later
[PATCH 2/7] rbd: zero format 1 header structure earlier
[PATCH 3/7] rbd: refactor rbd_header_from_disk()
[PATCH 4/7] rbd: update in-core header directly
[PATCH 5/7] rbd: simplify rbd_dev_v1_probe()
[PATCH 6/7] rbd: get rid of trivial v1 header wrappers
[PATCH 7/7] rbd: define rbd_dev_v1_header_info()


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 1/7] rbd: set the mapping size and features later
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
@ 2013-05-07  1:52 ` Alex Elder
  2013-05-07  1:52 ` [PATCH 2/7] rbd: zero format 1 header structure earlier Alex Elder
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:52 UTC (permalink / raw)
  To: ceph-devel

Defer setting the size and features fields of a mapped image until
after the Linux disk structure is set up.  Set the capacity of the
disk after that.

Rearrange the definition of rbd_image_header, separating the fields
that are set only once from those that can be updated.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 0c72643..357a11f 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -100,21 +100,20 @@
  * block device image metadata (in-memory version)
  */
 struct rbd_image_header {
-	/* These four fields never change for a given rbd image */
+	/* These six fields never change for a given rbd image */
 	char *object_prefix;
-	u64 features;
 	__u8 obj_order;
 	__u8 crypt_type;
 	__u8 comp_type;
+	u64 stripe_unit;
+	u64 stripe_count;
+	u64 features;		/* Might be changeable someday? */

 	/* The remaining fields need to be updated occasionally */
 	u64 image_size;
 	struct ceph_snap_context *snapc;
-	char *snap_names;
-	u64 *snap_sizes;
-
-	u64 stripe_unit;
-	u64 stripe_count;
+	char *snap_names;	/* format 1 only */
+	u64 *snap_sizes;	/* format 1 only */
 };

 /*
@@ -4637,10 +4636,6 @@ static int rbd_dev_device_setup(struct rbd_device
*rbd_dev)
 {
 	int ret;

-	ret = rbd_dev_mapping_set(rbd_dev);
-	if (ret)
-		return ret;
-
 	/* generate unique id: find highest unique id, add one */
 	rbd_dev_id_get(rbd_dev);

@@ -4662,13 +4657,17 @@ static int rbd_dev_device_setup(struct
rbd_device *rbd_dev)
 	if (ret)
 		goto err_out_blkdev;

-	ret = rbd_bus_add_dev(rbd_dev);
+	ret = rbd_dev_mapping_set(rbd_dev);
 	if (ret)
 		goto err_out_disk;
+	set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
+
+	ret = rbd_bus_add_dev(rbd_dev);
+	if (ret)
+		goto err_out_mapping;

 	/* Everything's ready.  Announce the disk to the world. */

-	set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
 	set_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
 	add_disk(rbd_dev->disk);

@@ -4677,6 +4676,8 @@ static int rbd_dev_device_setup(struct rbd_device
*rbd_dev)

 	return ret;

+err_out_mapping:
+	rbd_dev_mapping_clear(rbd_dev);
 err_out_disk:
 	rbd_free_disk(rbd_dev);
 err_out_blkdev:
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 2/7] rbd: zero format 1 header structure earlier
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
  2013-05-07  1:52 ` [PATCH 1/7] rbd: set the mapping size and features later Alex Elder
@ 2013-05-07  1:52 ` Alex Elder
  2013-05-07  1:53 ` [PATCH 3/7] rbd: refactor rbd_header_from_disk() Alex Elder
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:52 UTC (permalink / raw)
  To: ceph-devel

The passed-in header structure is zeroed in rbd_header_from_disk().
Instead, have the caller do it.  Note that there are two callers,
rbd_dev_v1_refresh() and rbd_dev_v1_probe().  The latter already has
a zeroed header structure so zeroing it isn't necessary there.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 357a11f..cdba93b 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -738,8 +738,6 @@ static int rbd_header_from_disk(struct
rbd_image_header *header,
 	size_t size;
 	u32 i;

-	memset(header, 0, sizeof (*header));
-
 	snap_count = le32_to_cpu(ondisk->snap_count);

 	len = strnlen(ondisk->object_prefix, sizeof (ondisk->object_prefix));
@@ -3103,6 +3101,7 @@ static int rbd_dev_v1_refresh(struct rbd_device
*rbd_dev)
 	int ret;
 	struct rbd_image_header h;

+	memset(&h, 0, sizeof (h));
 	ret = rbd_read_header(rbd_dev, &h);
 	if (ret < 0)
 		return ret;
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/7] rbd: refactor rbd_header_from_disk()
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
  2013-05-07  1:52 ` [PATCH 1/7] rbd: set the mapping size and features later Alex Elder
  2013-05-07  1:52 ` [PATCH 2/7] rbd: zero format 1 header structure earlier Alex Elder
@ 2013-05-07  1:53 ` Alex Elder
  2013-05-07  1:53 ` [PATCH 4/7] rbd: update in-core header directly Alex Elder
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:53 UTC (permalink / raw)
  To: ceph-devel

This rearranges rbd_header_from_disk so that it:
    - allocates the snapshot context right away
    - keeps results in local variables, not changing the passed-in
      header until it's known we'll succeed
    - does initialization of set-once fields in a header only if
      they have not already been set

The last point is moot at the moment, because rbd_read_header()
(the only caller) always supplies a zero-filled header buffer.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index cdba93b..2403098 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -727,86 +727,109 @@ static bool rbd_dev_ondisk_valid(struct
rbd_image_header_ondisk *ondisk)
 }

 /*
- * Create a new header structure, translate header format from the on-disk
- * header.
+ * Fill an rbd image header with information from the given format 1
+ * on-disk header.
  */
 static int rbd_header_from_disk(struct rbd_image_header *header,
 				 struct rbd_image_header_ondisk *ondisk)
 {
+	bool first_time = header->object_prefix == NULL;
+	struct ceph_snap_context *snapc;
+	char *object_prefix = NULL;
+	char *snap_names = NULL;
+	u64 *snap_sizes = NULL;
 	u32 snap_count;
-	size_t len;
 	size_t size;
+	int ret = -ENOMEM;
 	u32 i;

-	snap_count = le32_to_cpu(ondisk->snap_count);
+	/* Allocate this now to avoid having to handle failure below */

-	len = strnlen(ondisk->object_prefix, sizeof (ondisk->object_prefix));
-	header->object_prefix = kmalloc(len + 1, GFP_KERNEL);
-	if (!header->object_prefix)
-		return -ENOMEM;
-	memcpy(header->object_prefix, ondisk->object_prefix, len);
-	header->object_prefix[len] = '\0';
+	if (first_time) {
+		size_t len;

+		len = strnlen(ondisk->object_prefix,
+				sizeof (ondisk->object_prefix));
+		object_prefix = kmalloc(len + 1, GFP_KERNEL);
+		if (!object_prefix)
+			return -ENOMEM;
+		memcpy(object_prefix, ondisk->object_prefix, len);
+		object_prefix[len] = '\0';
+	}
+
+	/* Allocate the snapshot context and fill it in */
+
+	snap_count = le32_to_cpu(ondisk->snap_count);
+	snapc = ceph_create_snap_context(snap_count, GFP_KERNEL);
+	if (!snapc)
+		goto out_err;
+	snapc->seq = le64_to_cpu(ondisk->snap_seq);
 	if (snap_count) {
+		struct rbd_image_snap_ondisk *snaps;
 		u64 snap_names_len = le64_to_cpu(ondisk->snap_names_len);

-		/* Save a copy of the snapshot names */
+		/* We'll keep a copy of the snapshot names... */

-		if (snap_names_len > (u64) SIZE_MAX)
-			return -EIO;
-		header->snap_names = kmalloc(snap_names_len, GFP_KERNEL);
-		if (!header->snap_names)
+		if (snap_names_len > (u64)SIZE_MAX)
+			goto out_2big;
+		snap_names = kmalloc(snap_names_len, GFP_KERNEL);
+		if (!snap_names)
 			goto out_err;
-		/*
-		 * Note that rbd_dev_v1_header_read() guarantees
-		 * the ondisk buffer we're working with has
-		 * snap_names_len bytes beyond the end of the
-		 * snapshot id array, this memcpy() is safe.
-		 */
-		memcpy(header->snap_names, &ondisk->snaps[snap_count],
-			snap_names_len);

-		/* Record each snapshot's size */
+		/* ...as well as the array of their sizes. */

 		size = snap_count * sizeof (*header->snap_sizes);
-		header->snap_sizes = kmalloc(size, GFP_KERNEL);
-		if (!header->snap_sizes)
+		snap_sizes = kmalloc(size, GFP_KERNEL);
+		if (!snap_sizes)
 			goto out_err;
-		for (i = 0; i < snap_count; i++)
-			header->snap_sizes[i] =
-				le64_to_cpu(ondisk->snaps[i].image_size);
-	} else {
-		header->snap_names = NULL;
-		header->snap_sizes = NULL;
+
+		/*
+		 * Copy the names, and fill in each snapshot's id
+		 * and size.
+		 *
+		 * Note that rbd_dev_v1_header_read() guarantees the
+		 * ondisk buffer we're working with has
+		 * snap_names_len bytes beyond the end of the
+		 * snapshot id array, this memcpy() is safe.
+		 */
+		memcpy(snap_names, &ondisk->snaps[snap_count], snap_names_len);
+		snaps = ondisk->snaps;
+		for (i = 0; i < snap_count; i++) {
+			snapc->snaps[i] = le64_to_cpu(snaps[i].id);
+			snap_sizes[i] = le64_to_cpu(snaps[i].image_size);
+		}
 	}

-	header->features = 0;	/* No features support in v1 images */
-	header->obj_order = ondisk->options.order;
-	header->crypt_type = ondisk->options.crypt_type;
-	header->comp_type = ondisk->options.comp_type;
+	/* We won't fail any more, fill in the header */
+
+	if (first_time) {
+		header->object_prefix = object_prefix;
+		header->obj_order = ondisk->options.order;
+		header->crypt_type = ondisk->options.crypt_type;
+		header->comp_type = ondisk->options.comp_type;
+		/* The rest aren't used for format 1 images */
+		header->stripe_unit = 0;
+		header->stripe_count = 0;
+		header->features = 0;
+	}

-	/* Allocate and fill in the snapshot context */
+	/* The remaining fields always get updated (when we refresh) */

 	header->image_size = le64_to_cpu(ondisk->image_size);
-
-	header->snapc = ceph_create_snap_context(snap_count, GFP_KERNEL);
-	if (!header->snapc)
-		goto out_err;
-	header->snapc->seq = le64_to_cpu(ondisk->snap_seq);
-	for (i = 0; i < snap_count; i++)
-		header->snapc->snaps[i] = le64_to_cpu(ondisk->snaps[i].id);
+	header->snapc = snapc;
+	header->snap_names = snap_names;
+	header->snap_sizes = snap_sizes;

 	return 0;
-
+out_2big:
+	ret = -EIO;
 out_err:
-	kfree(header->snap_sizes);
-	header->snap_sizes = NULL;
-	kfree(header->snap_names);
-	header->snap_names = NULL;
-	kfree(header->object_prefix);
-	header->object_prefix = NULL;
+	kfree(snap_sizes);
+	kfree(snap_names);
+	ceph_put_snap_context(snapc);
+	kfree(object_prefix);

-	return -ENOMEM;
+	return ret;
 }

 static const char *_rbd_dev_v1_snap_name(struct rbd_device *rbd_dev,
u32 which)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/7] rbd: update in-core header directly
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
                   ` (2 preceding siblings ...)
  2013-05-07  1:53 ` [PATCH 3/7] rbd: refactor rbd_header_from_disk() Alex Elder
@ 2013-05-07  1:53 ` Alex Elder
  2013-05-07  1:53 ` [PATCH 5/7] rbd: simplify rbd_dev_v1_probe() Alex Elder
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:53 UTC (permalink / raw)
  To: ceph-devel

Now that rbd_header_from_disk() only fills in one-time fields once,
we can extend it slightly so it releases the other fields before
replacing their values.  This way there's no need to pass a
temporary buffer and then copy all the results in.  Just use the rbd
device header structure in rbd_header_from_disk() so its values get
updated directly.

Note that this means we need to take the header semaphore at the
point we update things.  So pass the rbd_dev rather than the address
of its header as its first argument to rbd_header_from_disk(), and
have it return an error code.

As a result, rbd_dev_v1_header_read() does all the work,
rbd_read_header() becomes unnecessary, and rbd_dev_v1_refresh()
becomes a very simple wrapper.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 2403098..a7985d9 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -730,9 +730,10 @@ static bool rbd_dev_ondisk_valid(struct
rbd_image_header_ondisk *ondisk)
  * Fill an rbd image header with information from the given format 1
  * on-disk header.
  */
-static int rbd_header_from_disk(struct rbd_image_header *header,
+static int rbd_header_from_disk(struct rbd_device *rbd_dev,
 				 struct rbd_image_header_ondisk *ondisk)
 {
+	struct rbd_image_header *header = &rbd_dev->header;
 	bool first_time = header->object_prefix == NULL;
 	struct ceph_snap_context *snapc;
 	char *object_prefix = NULL;
@@ -802,6 +803,7 @@ static int rbd_header_from_disk(struct
rbd_image_header *header,

 	/* We won't fail any more, fill in the header */

+	down_write(&rbd_dev->header_rwsem);
 	if (first_time) {
 		header->object_prefix = object_prefix;
 		header->obj_order = ondisk->options.order;
@@ -811,6 +813,10 @@ static int rbd_header_from_disk(struct
rbd_image_header *header,
 		header->stripe_unit = 0;
 		header->stripe_count = 0;
 		header->features = 0;
+	} else {
+		ceph_put_snap_context(header->snapc);
+		kfree(header->snap_names);
+		kfree(header->snap_sizes);
 	}

 	/* The remaining fields always get updated (when we refresh) */
@@ -820,6 +826,14 @@ static int rbd_header_from_disk(struct
rbd_image_header *header,
 	header->snap_names = snap_names;
 	header->snap_sizes = snap_sizes;

+	/* Make sure mapping size is consistent with header info */
+
+	if (rbd_dev->spec->snap_id == CEPH_NOSNAP || first_time)
+		if (rbd_dev->mapping.size != header->image_size)
+			rbd_dev->mapping.size = header->image_size;
+
+	up_write(&rbd_dev->header_rwsem);
+
 	return 0;
 out_2big:
 	ret = -EIO;
@@ -3032,17 +3046,11 @@ out:
 }

 /*
- * Read the complete header for the given rbd device.
- *
- * Returns a pointer to a dynamically-allocated buffer containing
- * the complete and validated header.  Caller can pass the address
- * of a variable that will be filled in with the version of the
- * header object at the time it was read.
- *
- * Returns a pointer-coded errno if a failure occurs.
+ * Read the complete header for the given rbd device.  On successful
+ * return, the rbd_dev->header field will contain up-to-date
+ * information about the image.
  */
-static struct rbd_image_header_ondisk *
-rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
+static int rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
 {
 	struct rbd_image_header_ondisk *ondisk = NULL;
 	u32 snap_count = 0;
@@ -3067,22 +3075,22 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
 		size += names_size;
 		ondisk = kmalloc(size, GFP_KERNEL);
 		if (!ondisk)
-			return ERR_PTR(-ENOMEM);
+			return -ENOMEM;

 		ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
 				       0, size, ondisk);
 		if (ret < 0)
-			goto out_err;
+			goto out;
 		if ((size_t)ret < size) {
 			ret = -ENXIO;
 			rbd_warn(rbd_dev, "short header read (want %zd got %d)",
 				size, ret);
-			goto out_err;
+			goto out;
 		}
 		if (!rbd_dev_ondisk_valid(ondisk)) {
 			ret = -ENXIO;
 			rbd_warn(rbd_dev, "invalid header");
-			goto out_err;
+			goto out;
 		}

 		names_size = le64_to_cpu(ondisk->snap_names_len);
@@ -3090,27 +3098,8 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
 		snap_count = le32_to_cpu(ondisk->snap_count);
 	} while (snap_count != want_count);

-	return ondisk;
-
-out_err:
-	kfree(ondisk);
-
-	return ERR_PTR(ret);
-}
-
-/*
- * reload the ondisk the header
- */
-static int rbd_read_header(struct rbd_device *rbd_dev,
-			   struct rbd_image_header *header)
-{
-	struct rbd_image_header_ondisk *ondisk;
-	int ret;
-
-	ondisk = rbd_dev_v1_header_read(rbd_dev);
-	if (IS_ERR(ondisk))
-		return PTR_ERR(ondisk);
-	ret = rbd_header_from_disk(header, ondisk);
+	ret = rbd_header_from_disk(rbd_dev, ondisk);
+out:
 	kfree(ondisk);

 	return ret;
@@ -3121,40 +3110,7 @@ static int rbd_read_header(struct rbd_device
*rbd_dev,
  */
 static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev)
 {
-	int ret;
-	struct rbd_image_header h;
-
-	memset(&h, 0, sizeof (h));
-	ret = rbd_read_header(rbd_dev, &h);
-	if (ret < 0)
-		return ret;
-
-	down_write(&rbd_dev->header_rwsem);
-
-	/* Update image size, and check for resize of mapped image */
-	rbd_dev->header.image_size = h.image_size;
-	if (rbd_dev->spec->snap_id == CEPH_NOSNAP)
-		if (rbd_dev->mapping.size != rbd_dev->header.image_size)
-			rbd_dev->mapping.size = rbd_dev->header.image_size;
-
-	/* rbd_dev->header.object_prefix shouldn't change */
-	kfree(rbd_dev->header.snap_sizes);
-	kfree(rbd_dev->header.snap_names);
-	/* osd requests may still refer to snapc */
-	ceph_put_snap_context(rbd_dev->header.snapc);
-
-	rbd_dev->header.image_size = h.image_size;
-	rbd_dev->header.snapc = h.snapc;
-	rbd_dev->header.snap_names = h.snap_names;
-	rbd_dev->header.snap_sizes = h.snap_sizes;
-	/* Free the extra copy of the object prefix */
-	if (strcmp(rbd_dev->header.object_prefix, h.object_prefix))
-		rbd_warn(rbd_dev, "object prefix changed (ignoring)");
-	kfree(h.object_prefix);
-
-	up_write(&rbd_dev->header_rwsem);
-
-	return ret;
+	return rbd_dev_v1_header_read(rbd_dev);
 }

 /*
@@ -4517,7 +4473,7 @@ static int rbd_dev_v1_probe(struct rbd_device
*rbd_dev)

 	/* Populate rbd image metadata */

-	ret = rbd_read_header(rbd_dev, &rbd_dev->header);
+	ret = rbd_dev_v1_header_read(rbd_dev);
 	if (ret < 0)
 		goto out_err;

-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/7] rbd: simplify rbd_dev_v1_probe()
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
                   ` (3 preceding siblings ...)
  2013-05-07  1:53 ` [PATCH 4/7] rbd: update in-core header directly Alex Elder
@ 2013-05-07  1:53 ` Alex Elder
  2013-05-07  1:53 ` [PATCH 6/7] rbd: get rid of trivial v1 header wrappers Alex Elder
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:53 UTC (permalink / raw)
  To: ceph-devel

An rbd_dev structure's fields are all zero-filled for an initial
probe, so there's no need to explicitly zero the parent_spec
and parent_overlap fields in rbd_dev_v1_probe().  Removing these
assignments makes rbd_dev_v1_probe() *almost* trivial.

Move the dout() message that announces discovery of an image into
rbd_dev_image_probe(), generalize to support images in either format
and only show it if an image is fully discovered.

This highlights that are some unnecessary cleanups in the error
path for rbd_dev_v1_probe(), so they can be removed.

Now rbd_dev_v1_probe() *is* a trivial wrapper function.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index a7985d9..ed18888 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4469,31 +4469,7 @@ static void rbd_dev_unprobe(struct rbd_device
*rbd_dev)

 static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
 {
-	int ret;
-
-	/* Populate rbd image metadata */
-
-	ret = rbd_dev_v1_header_read(rbd_dev);
-	if (ret < 0)
-		goto out_err;
-
-	/* Version 1 images have no parent (no layering) */
-
-	rbd_dev->parent_spec = NULL;
-	rbd_dev->parent_overlap = 0;
-
-	dout("discovered version 1 image, header name is %s\n",
-		rbd_dev->header_name);
-
-	return 0;
-
-out_err:
-	kfree(rbd_dev->header_name);
-	rbd_dev->header_name = NULL;
-	kfree(rbd_dev->spec->image_id);
-	rbd_dev->spec->image_id = NULL;
-
-	return ret;
+	return rbd_dev_v1_header_read(rbd_dev);
 }

 static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
@@ -4553,9 +4529,6 @@ static int rbd_dev_v2_probe(struct rbd_device
*rbd_dev)
 	if (ret)
 		goto out_err;

-	dout("discovered version 2 image, header name is %s\n",
-		rbd_dev->header_name);
-
 	return 0;
 out_err:
 	rbd_dev->parent_overlap = 0;
@@ -4758,9 +4731,13 @@ static int rbd_dev_image_probe(struct rbd_device
*rbd_dev, bool read_only)
 	rbd_dev->mapping.read_only = read_only;

 	ret = rbd_dev_probe_parent(rbd_dev);
-	if (!ret)
-		return 0;
+	if (ret)
+		goto err_out_probe;
+
+	dout("discovered format %u image, header name is %s\n",
+		rbd_dev->image_format, rbd_dev->header_name);

+	return 0;
 err_out_probe:
 	rbd_dev_unprobe(rbd_dev);
 err_out_watch:
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/7] rbd: get rid of trivial v1 header wrappers
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
                   ` (4 preceding siblings ...)
  2013-05-07  1:53 ` [PATCH 5/7] rbd: simplify rbd_dev_v1_probe() Alex Elder
@ 2013-05-07  1:53 ` Alex Elder
  2013-05-07  1:54 ` [PATCH 7/7] rbd: define rbd_dev_v1_header_info() Alex Elder
  2013-05-08 19:29 ` [PATCH 0/7] rbd: use common code for probe and refresh Josh Durgin
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:53 UTC (permalink / raw)
  To: ceph-devel

Get rid of the trivial wrapper functions rbd_dev_v1_refresh() and
rbd_dev_v1_probe(), substituting rbd_dev_v1_header_read() calls
in their place.

Rename rbd_dev_v1_header_read() to be rbd_dev_v1_header_info(), to
be more generic (it will better reflect what happens with format 2
images).

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index ed18888..9e667c5 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -788,7 +788,7 @@ static int rbd_header_from_disk(struct rbd_device
*rbd_dev,
 		 * Copy the names, and fill in each snapshot's id
 		 * and size.
 		 *
-		 * Note that rbd_dev_v1_header_read() guarantees the
+		 * Note that rbd_dev_v1_header_info() guarantees the
 		 * ondisk buffer we're working with has
 		 * snap_names_len bytes beyond the end of the
 		 * snapshot id array, this memcpy() is safe.
@@ -3050,7 +3050,7 @@ out:
  * return, the rbd_dev->header field will contain up-to-date
  * information about the image.
  */
-static int rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
+static int rbd_dev_v1_header_info(struct rbd_device *rbd_dev)
 {
 	struct rbd_image_header_ondisk *ondisk = NULL;
 	u32 snap_count = 0;
@@ -3106,14 +3106,6 @@ out:
 }

 /*
- * only read the first part of the ondisk header, without the snaps info
- */
-static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev)
-{
-	return rbd_dev_v1_header_read(rbd_dev);
-}
-
-/*
  * Clear the rbd device's EXISTS flag if the snapshot it's mapped to
  * has disappeared from the (just updated) snapshot context.
  */
@@ -3141,7 +3133,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
 	mapping_size = rbd_dev->mapping.size;
 	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
 	if (rbd_dev->image_format == 1)
-		ret = rbd_dev_v1_refresh(rbd_dev);
+		ret = rbd_dev_v1_header_info(rbd_dev);
 	else
 		ret = rbd_dev_v2_refresh(rbd_dev);

@@ -4467,11 +4459,6 @@ static void rbd_dev_unprobe(struct rbd_device
*rbd_dev)
 	memset(header, 0, sizeof (*header));
 }

-static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
-{
-	return rbd_dev_v1_header_read(rbd_dev);
-}
-
 static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
 {
 	int ret;
@@ -4714,7 +4701,7 @@ static int rbd_dev_image_probe(struct rbd_device
*rbd_dev, bool read_only)
 		goto out_header_name;

 	if (rbd_dev->image_format == 1)
-		ret = rbd_dev_v1_probe(rbd_dev);
+		ret = rbd_dev_v1_header_info(rbd_dev);
 	else
 		ret = rbd_dev_v2_probe(rbd_dev);
 	if (ret)
-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/7] rbd: define rbd_dev_v1_header_info()
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
                   ` (5 preceding siblings ...)
  2013-05-07  1:53 ` [PATCH 6/7] rbd: get rid of trivial v1 header wrappers Alex Elder
@ 2013-05-07  1:54 ` Alex Elder
  2013-05-08 19:29 ` [PATCH 0/7] rbd: use common code for probe and refresh Josh Durgin
  7 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-07  1:54 UTC (permalink / raw)
  To: ceph-devel

This rearranges rbd_dev_v2_refresh() so it works more like
rbd_dev_v1_header_info().  While format 1 images need to read the
whole header object to get any information, format 2 can collect
almost all information selectively.  So the one-time initialization
will remain in a separate function--based on rbd_dev_v2_probe().

Rename rbd_dev_v2_refresh() to be rbd_dev_v2_header_info(), and have
it call rbd_dev_v2_header_onetime() if it's being called for the
first time for the given rbd device.

Rename rbd_dev_v2_probe() to be rbd_dev_v2_header_onetime() and
remove the image size and snapshot context calls it held in
common with the refresh function.

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

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 9e667c5..a300c03 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -425,7 +425,8 @@ 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);
-static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev);
+static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev);
 static const char *rbd_dev_v2_snap_name(struct rbd_device *rbd_dev,
 					u64 snap_id);
 static int _rbd_dev_v2_snap_size(struct rbd_device *rbd_dev, u64 snap_id,
@@ -3135,7 +3136,7 @@ static int rbd_dev_refresh(struct rbd_device *rbd_dev)
 	if (rbd_dev->image_format == 1)
 		ret = rbd_dev_v1_header_info(rbd_dev);
 	else
-		ret = rbd_dev_v2_refresh(rbd_dev);
+		ret = rbd_dev_v2_header_info(rbd_dev);

 	/* If it's a mapped snapshot, validate its EXISTS flag */

@@ -4005,12 +4006,19 @@ out:
 	return snap_name;
 }

-static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_info(struct rbd_device *rbd_dev)
 {
+	bool first_time = rbd_dev->header.object_prefix == NULL;
 	int ret;

 	down_write(&rbd_dev->header_rwsem);

+	if (first_time) {
+		ret = rbd_dev_v2_header_onetime(rbd_dev);
+		if (ret)
+			goto out;
+	}
+
 	ret = rbd_dev_v2_image_size(rbd_dev);
 	if (ret)
 		goto out;
@@ -4459,22 +4467,18 @@ static void rbd_dev_unprobe(struct rbd_device
*rbd_dev)
 	memset(header, 0, sizeof (*header));
 }

-static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
+static int rbd_dev_v2_header_onetime(struct rbd_device *rbd_dev)
 {
 	int ret;

-	ret = rbd_dev_v2_image_size(rbd_dev);
-	if (ret)
-		goto out_err;
-
-	/* Get the object prefix (a.k.a. block_name) for the image */
-
 	ret = rbd_dev_v2_object_prefix(rbd_dev);
 	if (ret)
 		goto out_err;

-	/* Get the and check features for the image */
-
+	/*
+	 * Get the and check features for the image.  Currently the
+	 * features are assumed to never change.
+	 */
 	ret = rbd_dev_v2_features(rbd_dev);
 	if (ret)
 		goto out_err;
@@ -4504,17 +4508,7 @@ static int rbd_dev_v2_probe(struct rbd_device
*rbd_dev)
 		if (ret < 0)
 			goto out_err;
 	}
-
-	/* crypto and compression type aren't (yet) supported for v2 images */
-
-	rbd_dev->header.crypt_type = 0;
-	rbd_dev->header.comp_type = 0;
-
-	/* Get the snapshot context, plus the header version */
-
-	ret = rbd_dev_v2_snap_context(rbd_dev);
-	if (ret)
-		goto out_err;
+	/* No support for crypto and compression type format 2 images */

 	return 0;
 out_err:
@@ -4703,7 +4697,7 @@ static int rbd_dev_image_probe(struct rbd_device
*rbd_dev, bool read_only)
 	if (rbd_dev->image_format == 1)
 		ret = rbd_dev_v1_header_info(rbd_dev);
 	else
-		ret = rbd_dev_v2_probe(rbd_dev);
+		ret = rbd_dev_v2_header_info(rbd_dev);
 	if (ret)
 		goto err_out_watch;

-- 
1.7.9.5


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/7] rbd: use common code for probe and refresh
  2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
                   ` (6 preceding siblings ...)
  2013-05-07  1:54 ` [PATCH 7/7] rbd: define rbd_dev_v1_header_info() Alex Elder
@ 2013-05-08 19:29 ` Josh Durgin
  2013-05-08 20:39   ` Alex Elder
  7 siblings, 1 reply; 10+ messages in thread
From: Josh Durgin @ 2013-05-08 19:29 UTC (permalink / raw)
  To: Alex Elder; +Cc: ceph-devel

On 05/06/2013 06:51 PM, Alex Elder wrote:
> This is some work I had nearly done a long time ago.  It didn't even
> have a bug associated with it.  I resurrected it over the weekend
> and ported it to the new code.
>
> It's basically cleanup though.  For format 1 rbd images, when
> probing an image, header information for it is read in and
> translated directly into the rbd_dev->header structure.
>
> For an image refresh, instead, we use a stack structure to
> hold the translated header, and then in a second step we
> copy that into rbd_dev->header.
>
> This series gets rid of the local variable, and always just
> puts things directly into rbd_dev->header.  It also simplifies
> probe and refresh for both format 1 and format 2, using a
> common rbd_dev_vX_header_info() function for both purposes.
>
> This set of patches, as well as the two single patches
> and series of six I just posted, are available in the
> "review/wip-rbd-cleanup-1" branch of the ceph-client git
> repository.
>
> 					-Alex
>
> [PATCH 1/7] rbd: set the mapping size and features later
> [PATCH 2/7] rbd: zero format 1 header structure earlier
> [PATCH 3/7] rbd: refactor rbd_header_from_disk()
> [PATCH 4/7] rbd: update in-core header directly
> [PATCH 5/7] rbd: simplify rbd_dev_v1_probe()
> [PATCH 6/7] rbd: get rid of trivial v1 header wrappers
> [PATCH 7/7] rbd: define rbd_dev_v1_header_info()

These all look good.
The last one leaves the only call to rbd_dev_v2_parent_info() in
rbd_dev_v2_header_onetime(), but I'm guessing you already moved it
in your upcoming flatten-handling patches.

Reviewed-by: Josh Durgin <josh.durgin@inktank.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH 0/7] rbd: use common code for probe and refresh
  2013-05-08 19:29 ` [PATCH 0/7] rbd: use common code for probe and refresh Josh Durgin
@ 2013-05-08 20:39   ` Alex Elder
  0 siblings, 0 replies; 10+ messages in thread
From: Alex Elder @ 2013-05-08 20:39 UTC (permalink / raw)
  To: Josh Durgin; +Cc: ceph-devel

On 05/08/2013 02:29 PM, Josh Durgin wrote:
> On 05/06/2013 06:51 PM, Alex Elder wrote:
>> This is some work I had nearly done a long time ago.  It didn't even
>> have a bug associated with it.  I resurrected it over the weekend
>> and ported it to the new code.
>>
>> It's basically cleanup though.  For format 1 rbd images, when
>> probing an image, header information for it is read in and
>> translated directly into the rbd_dev->header structure.
>>
>> For an image refresh, instead, we use a stack structure to
>> hold the translated header, and then in a second step we
>> copy that into rbd_dev->header.
>>
>> This series gets rid of the local variable, and always just
>> puts things directly into rbd_dev->header.  It also simplifies
>> probe and refresh for both format 1 and format 2, using a
>> common rbd_dev_vX_header_info() function for both purposes.
>>
>> This set of patches, as well as the two single patches
>> and series of six I just posted, are available in the
>> "review/wip-rbd-cleanup-1" branch of the ceph-client git
>> repository.
>>
>>                     -Alex
>>
>> [PATCH 1/7] rbd: set the mapping size and features later
>> [PATCH 2/7] rbd: zero format 1 header structure earlier
>> [PATCH 3/7] rbd: refactor rbd_header_from_disk()
>> [PATCH 4/7] rbd: update in-core header directly
>> [PATCH 5/7] rbd: simplify rbd_dev_v1_probe()
>> [PATCH 6/7] rbd: get rid of trivial v1 header wrappers
>> [PATCH 7/7] rbd: define rbd_dev_v1_header_info()
> 
> These all look good.
> The last one leaves the only call to rbd_dev_v2_parent_info() in
> rbd_dev_v2_header_onetime(), but I'm guessing you already moved it
> in your upcoming flatten-handling patches.

It took me a minute to figure out your point, but yes, I move
that into rbd_dev_v2_header_info() in an upcoming patch.

					-Alex

> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-05-08 20:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-05-07  1:51 [PATCH 0/7] rbd: use common code for probe and refresh Alex Elder
2013-05-07  1:52 ` [PATCH 1/7] rbd: set the mapping size and features later Alex Elder
2013-05-07  1:52 ` [PATCH 2/7] rbd: zero format 1 header structure earlier Alex Elder
2013-05-07  1:53 ` [PATCH 3/7] rbd: refactor rbd_header_from_disk() Alex Elder
2013-05-07  1:53 ` [PATCH 4/7] rbd: update in-core header directly Alex Elder
2013-05-07  1:53 ` [PATCH 5/7] rbd: simplify rbd_dev_v1_probe() Alex Elder
2013-05-07  1:53 ` [PATCH 6/7] rbd: get rid of trivial v1 header wrappers Alex Elder
2013-05-07  1:54 ` [PATCH 7/7] rbd: define rbd_dev_v1_header_info() Alex Elder
2013-05-08 19:29 ` [PATCH 0/7] rbd: use common code for probe and refresh Josh Durgin
2013-05-08 20:39   ` Alex Elder

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.