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: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
parent
bb23e37acb
commit
662518b128
|
@ -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
|
* Fill an rbd image header with information from the given format 1
|
||||||
* on-disk header.
|
* 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_ondisk *ondisk)
|
||||||
{
|
{
|
||||||
|
struct rbd_image_header *header = &rbd_dev->header;
|
||||||
bool first_time = header->object_prefix == NULL;
|
bool first_time = header->object_prefix == NULL;
|
||||||
struct ceph_snap_context *snapc;
|
struct ceph_snap_context *snapc;
|
||||||
char *object_prefix = NULL;
|
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 */
|
/* We won't fail any more, fill in the header */
|
||||||
|
|
||||||
|
down_write(&rbd_dev->header_rwsem);
|
||||||
if (first_time) {
|
if (first_time) {
|
||||||
header->object_prefix = object_prefix;
|
header->object_prefix = object_prefix;
|
||||||
header->obj_order = ondisk->options.order;
|
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_unit = 0;
|
||||||
header->stripe_count = 0;
|
header->stripe_count = 0;
|
||||||
header->features = 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) */
|
/* 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_names = snap_names;
|
||||||
header->snap_sizes = snap_sizes;
|
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;
|
return 0;
|
||||||
out_2big:
|
out_2big:
|
||||||
ret = -EIO;
|
ret = -EIO;
|
||||||
|
@ -3032,17 +3046,11 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the complete header for the given rbd device.
|
* Read the complete header for the given rbd device. On successful
|
||||||
*
|
* return, the rbd_dev->header field will contain up-to-date
|
||||||
* Returns a pointer to a dynamically-allocated buffer containing
|
* information about the image.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
static struct rbd_image_header_ondisk *
|
static int rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
|
||||||
rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
|
|
||||||
{
|
{
|
||||||
struct rbd_image_header_ondisk *ondisk = NULL;
|
struct rbd_image_header_ondisk *ondisk = NULL;
|
||||||
u32 snap_count = 0;
|
u32 snap_count = 0;
|
||||||
|
@ -3067,22 +3075,22 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev)
|
||||||
size += names_size;
|
size += names_size;
|
||||||
ondisk = kmalloc(size, GFP_KERNEL);
|
ondisk = kmalloc(size, GFP_KERNEL);
|
||||||
if (!ondisk)
|
if (!ondisk)
|
||||||
return ERR_PTR(-ENOMEM);
|
return -ENOMEM;
|
||||||
|
|
||||||
ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
|
ret = rbd_obj_read_sync(rbd_dev, rbd_dev->header_name,
|
||||||
0, size, ondisk);
|
0, size, ondisk);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_err;
|
goto out;
|
||||||
if ((size_t)ret < size) {
|
if ((size_t)ret < size) {
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
rbd_warn(rbd_dev, "short header read (want %zd got %d)",
|
rbd_warn(rbd_dev, "short header read (want %zd got %d)",
|
||||||
size, ret);
|
size, ret);
|
||||||
goto out_err;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!rbd_dev_ondisk_valid(ondisk)) {
|
if (!rbd_dev_ondisk_valid(ondisk)) {
|
||||||
ret = -ENXIO;
|
ret = -ENXIO;
|
||||||
rbd_warn(rbd_dev, "invalid header");
|
rbd_warn(rbd_dev, "invalid header");
|
||||||
goto out_err;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
names_size = le64_to_cpu(ondisk->snap_names_len);
|
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);
|
snap_count = le32_to_cpu(ondisk->snap_count);
|
||||||
} while (snap_count != want_count);
|
} while (snap_count != want_count);
|
||||||
|
|
||||||
return ondisk;
|
ret = rbd_header_from_disk(rbd_dev, ondisk);
|
||||||
|
out:
|
||||||
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);
|
|
||||||
kfree(ondisk);
|
kfree(ondisk);
|
||||||
|
|
||||||
return ret;
|
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)
|
static int rbd_dev_v1_refresh(struct rbd_device *rbd_dev)
|
||||||
{
|
{
|
||||||
int ret;
|
return rbd_dev_v1_header_read(rbd_dev);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4517,7 +4473,7 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
|
||||||
|
|
||||||
/* Populate rbd image metadata */
|
/* Populate rbd image metadata */
|
||||||
|
|
||||||
ret = rbd_read_header(rbd_dev, &rbd_dev->header);
|
ret = rbd_dev_v1_header_read(rbd_dev);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue