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

Commit 662518b1 authored by Alex Elder's avatar Alex Elder
Browse files

rbd: update in-core header directly



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: default avatarAlex Elder <elder@inktank.com>
Reviewed-by: default avatarJosh Durgin <josh.durgin@inktank.com>
parent bb23e37a
Loading
Loading
Loading
Loading
+27 −71
Original line number Diff line number Diff line
@@ -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;