Skip to content

Commit

Permalink
rbd: define image specification structure
Browse files Browse the repository at this point in the history
Group the fields that uniquely specify an rbd image into a new
reference-counted rbd_spec structure.  This structure will be used
to describe the desired image when mapping an image, and when
probing parent images in layered rbd devices.  Replace the set of
fields in the rbd device structure with a pointer to a dynamically
allocated rbd_spec.

Signed-off-by: Alex Elder <elder@inktank.com>
Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
  • Loading branch information
Alex Elder committed Oct 30, 2012
1 parent dc79b11 commit 0d7dbfc
Showing 1 changed file with 90 additions and 68 deletions.
158 changes: 90 additions & 68 deletions drivers/block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,27 @@ struct rbd_image_header {
u64 obj_version;
};

/*
* An rbd image specification.
*
* The tuple (pool_id, image_id, snap_id) is sufficient to uniquely
* identify an image.
*/
struct rbd_spec {
u64 pool_id;
char *pool_name;

char *image_id;
size_t image_id_len;
char *image_name;
size_t image_name_len;

u64 snap_id;
char *snap_name;

struct kref kref;
};

struct rbd_options {
bool read_only;
};
Expand Down Expand Up @@ -189,16 +210,9 @@ struct rbd_device {

struct rbd_image_header header;
bool exists;
char *image_id;
size_t image_id_len;
char *image_name;
size_t image_name_len;
char *header_name;
char *pool_name;
u64 pool_id;
struct rbd_spec *spec;

char *snap_name;
u64 snap_id;
char *header_name;

struct ceph_osd_event *watch_event;
struct ceph_osd_request *watch_request;
Expand Down Expand Up @@ -654,7 +668,7 @@ static int snap_by_name(struct rbd_device *rbd_dev, const char *snap_name)

list_for_each_entry(snap, &rbd_dev->snaps, node) {
if (!strcmp(snap_name, snap->name)) {
rbd_dev->snap_id = snap->id;
rbd_dev->spec->snap_id = snap->id;
rbd_dev->mapping.size = snap->size;
rbd_dev->mapping.features = snap->features;

Expand All @@ -669,14 +683,14 @@ static int rbd_dev_set_mapping(struct rbd_device *rbd_dev)
{
int ret;

if (!memcmp(rbd_dev->snap_name, RBD_SNAP_HEAD_NAME,
if (!memcmp(rbd_dev->spec->snap_name, RBD_SNAP_HEAD_NAME,
sizeof (RBD_SNAP_HEAD_NAME))) {
rbd_dev->snap_id = CEPH_NOSNAP;
rbd_dev->spec->snap_id = CEPH_NOSNAP;
rbd_dev->mapping.size = rbd_dev->header.image_size;
rbd_dev->mapping.features = rbd_dev->header.features;
ret = 0;
} else {
ret = snap_by_name(rbd_dev, rbd_dev->snap_name);
ret = snap_by_name(rbd_dev, rbd_dev->spec->snap_name);
if (ret < 0)
goto done;
rbd_dev->mapping.read_only = true;
Expand Down Expand Up @@ -1096,7 +1110,7 @@ static int rbd_do_request(struct request *rq,
layout->fl_stripe_unit = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
layout->fl_stripe_count = cpu_to_le32(1);
layout->fl_object_size = cpu_to_le32(1 << RBD_MAX_OBJ_ORDER);
layout->fl_pg_pool = cpu_to_le32((int) rbd_dev->pool_id);
layout->fl_pg_pool = cpu_to_le32((int) rbd_dev->spec->pool_id);
ret = ceph_calc_raw_layout(osdc, layout, snapid, ofs, &len, &bno,
req, ops);
rbd_assert(ret == 0);
Expand Down Expand Up @@ -1261,7 +1275,7 @@ static int rbd_do_op(struct request *rq,
opcode = CEPH_OSD_OP_READ;
flags = CEPH_OSD_FLAG_READ;
snapc = NULL;
snapid = rbd_dev->snap_id;
snapid = rbd_dev->spec->snap_id;
payload_len = 0;
}

Expand Down Expand Up @@ -1545,7 +1559,7 @@ static void rbd_rq_fn(struct request_queue *q)
down_read(&rbd_dev->header_rwsem);

if (!rbd_dev->exists) {
rbd_assert(rbd_dev->snap_id != CEPH_NOSNAP);
rbd_assert(rbd_dev->spec->snap_id != CEPH_NOSNAP);
up_read(&rbd_dev->header_rwsem);
dout("request for non-existent snapshot");
spin_lock_irq(q->queue_lock);
Expand Down Expand Up @@ -1726,13 +1740,13 @@ rbd_dev_v1_header_read(struct rbd_device *rbd_dev, u64 *version)
ret = -ENXIO;
pr_warning("short header read for image %s"
" (want %zd got %d)\n",
rbd_dev->image_name, size, ret);
rbd_dev->spec->image_name, size, ret);
goto out_err;
}
if (!rbd_dev_ondisk_valid(ondisk)) {
ret = -ENXIO;
pr_warning("invalid header for image %s\n",
rbd_dev->image_name);
rbd_dev->spec->image_name);
goto out_err;
}

Expand Down Expand Up @@ -1783,7 +1797,7 @@ static void rbd_update_mapping_size(struct rbd_device *rbd_dev)
{
sector_t size;

if (rbd_dev->snap_id != CEPH_NOSNAP)
if (rbd_dev->spec->snap_id != CEPH_NOSNAP)
return;

size = (sector_t) rbd_dev->header.image_size / SECTOR_SIZE;
Expand Down Expand Up @@ -1957,31 +1971,32 @@ static ssize_t rbd_pool_show(struct device *dev,
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);

return sprintf(buf, "%s\n", rbd_dev->pool_name);
return sprintf(buf, "%s\n", rbd_dev->spec->pool_name);
}

static ssize_t rbd_pool_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);

return sprintf(buf, "%llu\n", (unsigned long long) rbd_dev->pool_id);
return sprintf(buf, "%llu\n",
(unsigned long long) rbd_dev->spec->pool_id);
}

static ssize_t rbd_name_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);

return sprintf(buf, "%s\n", rbd_dev->image_name);
return sprintf(buf, "%s\n", rbd_dev->spec->image_name);
}

static ssize_t rbd_image_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);

return sprintf(buf, "%s\n", rbd_dev->image_id);
return sprintf(buf, "%s\n", rbd_dev->spec->image_id);
}

/*
Expand All @@ -1994,7 +2009,7 @@ static ssize_t rbd_snap_show(struct device *dev,
{
struct rbd_device *rbd_dev = dev_to_rbd_dev(dev);

return sprintf(buf, "%s\n", rbd_dev->snap_name);
return sprintf(buf, "%s\n", rbd_dev->spec->snap_name);
}

static ssize_t rbd_image_refresh(struct device *dev,
Expand Down Expand Up @@ -2547,11 +2562,12 @@ static int rbd_dev_snaps_update(struct rbd_device *rbd_dev)

/* Existing snapshot not in the new snap context */

if (rbd_dev->snap_id == snap->id)
if (rbd_dev->spec->snap_id == snap->id)
rbd_dev->exists = false;
rbd_remove_snap_dev(snap);
dout("%ssnap id %llu has been removed\n",
rbd_dev->snap_id == snap->id ? "mapped " : "",
rbd_dev->spec->snap_id == snap->id ?
"mapped " : "",
(unsigned long long) snap->id);

/* Done with this list entry; advance */
Expand Down Expand Up @@ -2869,16 +2885,17 @@ static int rbd_add_parse_args(struct rbd_device *rbd_dev,
if (!*options)
goto out_err; /* Missing options */

rbd_dev->pool_name = dup_token(&buf, NULL);
if (!rbd_dev->pool_name)
rbd_dev->spec->pool_name = dup_token(&buf, NULL);
if (!rbd_dev->spec->pool_name)
goto out_mem;
if (!*rbd_dev->pool_name)
if (!*rbd_dev->spec->pool_name)
goto out_err; /* Missing pool name */

rbd_dev->image_name = dup_token(&buf, &rbd_dev->image_name_len);
if (!rbd_dev->image_name)
rbd_dev->spec->image_name =
dup_token(&buf, &rbd_dev->spec->image_name_len);
if (!rbd_dev->spec->image_name)
goto out_mem;
if (!*rbd_dev->image_name)
if (!*rbd_dev->spec->image_name)
goto out_err; /* Missing image name */

/*
Expand All @@ -2893,11 +2910,11 @@ static int rbd_add_parse_args(struct rbd_device *rbd_dev,
ret = -ENAMETOOLONG;
goto out_err;
}
rbd_dev->snap_name = kmalloc(len + 1, GFP_KERNEL);
if (!rbd_dev->snap_name)
rbd_dev->spec->snap_name = kmalloc(len + 1, GFP_KERNEL);
if (!rbd_dev->spec->snap_name)
goto out_mem;
memcpy(rbd_dev->snap_name, buf, len);
*(rbd_dev->snap_name + len) = '\0';
memcpy(rbd_dev->spec->snap_name, buf, len);
*(rbd_dev->spec->snap_name + len) = '\0';

/* Initialize all rbd options to the defaults */

Expand All @@ -2921,11 +2938,11 @@ static int rbd_add_parse_args(struct rbd_device *rbd_dev,
out_mem:
ret = -ENOMEM;
out_err:
kfree(rbd_dev->image_name);
rbd_dev->image_name = NULL;
rbd_dev->image_name_len = 0;
kfree(rbd_dev->pool_name);
rbd_dev->pool_name = NULL;
kfree(rbd_dev->spec->image_name);
rbd_dev->spec->image_name = NULL;
rbd_dev->spec->image_name_len = 0;
kfree(rbd_dev->spec->pool_name);
rbd_dev->spec->pool_name = NULL;
kfree(options);

return ret;
Expand Down Expand Up @@ -2957,11 +2974,11 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
* First, see if the format 2 image id file exists, and if
* so, get the image's persistent id from it.
*/
size = sizeof (RBD_ID_PREFIX) + rbd_dev->image_name_len;
size = sizeof (RBD_ID_PREFIX) + rbd_dev->spec->image_name_len;
object_name = kmalloc(size, GFP_NOIO);
if (!object_name)
return -ENOMEM;
sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->image_name);
sprintf(object_name, "%s%s", RBD_ID_PREFIX, rbd_dev->spec->image_name);
dout("rbd id object name is %s\n", object_name);

/* Response will be an encoded string, which includes a length */
Expand All @@ -2984,15 +3001,15 @@ static int rbd_dev_image_id(struct rbd_device *rbd_dev)
ret = 0; /* rbd_req_sync_exec() can return positive */

p = response;
rbd_dev->image_id = ceph_extract_encoded_string(&p,
rbd_dev->spec->image_id = ceph_extract_encoded_string(&p,
p + RBD_IMAGE_ID_LEN_MAX,
&rbd_dev->image_id_len,
&rbd_dev->spec->image_id_len,
GFP_NOIO);
if (IS_ERR(rbd_dev->image_id)) {
ret = PTR_ERR(rbd_dev->image_id);
rbd_dev->image_id = NULL;
if (IS_ERR(rbd_dev->spec->image_id)) {
ret = PTR_ERR(rbd_dev->spec->image_id);
rbd_dev->spec->image_id = NULL;
} else {
dout("image_id is %s\n", rbd_dev->image_id);
dout("image_id is %s\n", rbd_dev->spec->image_id);
}
out:
kfree(response);
Expand All @@ -3008,20 +3025,21 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)

/* Version 1 images have no id; empty string is used */

rbd_dev->image_id = kstrdup("", GFP_KERNEL);
if (!rbd_dev->image_id)
rbd_dev->spec->image_id = kstrdup("", GFP_KERNEL);
if (!rbd_dev->spec->image_id)
return -ENOMEM;
rbd_dev->image_id_len = 0;
rbd_dev->spec->image_id_len = 0;

/* Record the header object name for this rbd image. */

size = rbd_dev->image_name_len + sizeof (RBD_SUFFIX);
size = rbd_dev->spec->image_name_len + sizeof (RBD_SUFFIX);
rbd_dev->header_name = kmalloc(size, GFP_KERNEL);
if (!rbd_dev->header_name) {
ret = -ENOMEM;
goto out_err;
}
sprintf(rbd_dev->header_name, "%s%s", rbd_dev->image_name, RBD_SUFFIX);
sprintf(rbd_dev->header_name, "%s%s",
rbd_dev->spec->image_name, RBD_SUFFIX);

/* Populate rbd image metadata */

Expand All @@ -3038,8 +3056,8 @@ static int rbd_dev_v1_probe(struct rbd_device *rbd_dev)
out_err:
kfree(rbd_dev->header_name);
rbd_dev->header_name = NULL;
kfree(rbd_dev->image_id);
rbd_dev->image_id = NULL;
kfree(rbd_dev->spec->image_id);
rbd_dev->spec->image_id = NULL;

return ret;
}
Expand All @@ -3054,12 +3072,12 @@ static int rbd_dev_v2_probe(struct rbd_device *rbd_dev)
* Image id was filled in by the caller. Record the header
* object name for this rbd image.
*/
size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->image_id_len;
size = sizeof (RBD_HEADER_PREFIX) + rbd_dev->spec->image_id_len;
rbd_dev->header_name = kmalloc(size, GFP_KERNEL);
if (!rbd_dev->header_name)
return -ENOMEM;
sprintf(rbd_dev->header_name, "%s%s",
RBD_HEADER_PREFIX, rbd_dev->image_id);
RBD_HEADER_PREFIX, rbd_dev->spec->image_id);

/* Get the size and object order for the image */

Expand Down Expand Up @@ -3147,6 +3165,9 @@ static ssize_t rbd_add(struct bus_type *bus,
rbd_dev = kzalloc(sizeof(*rbd_dev), GFP_KERNEL);
if (!rbd_dev)
return -ENOMEM;
rbd_dev->spec = kzalloc(sizeof (*rbd_dev->spec), GFP_KERNEL);
if (!rbd_dev->spec)
goto err_out_mem;

/* static rbd_device initialization */
spin_lock_init(&rbd_dev->lock);
Expand All @@ -3167,10 +3188,10 @@ static ssize_t rbd_add(struct bus_type *bus,

/* pick the pool */
osdc = &rbd_dev->rbd_client->client->osdc;
rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->pool_name);
rc = ceph_pg_poolid_by_name(osdc->osdmap, rbd_dev->spec->pool_name);
if (rc < 0)
goto err_out_client;
rbd_dev->pool_id = (u64) rc;
rbd_dev->spec->pool_id = (u64) rc;

rc = rbd_dev_probe(rbd_dev);
if (rc < 0)
Expand Down Expand Up @@ -3257,15 +3278,16 @@ static ssize_t rbd_add(struct bus_type *bus,
err_out_client:
kfree(rbd_dev->header_name);
rbd_put_client(rbd_dev);
kfree(rbd_dev->image_id);
kfree(rbd_dev->spec->image_id);
err_out_args:
if (ceph_opts)
ceph_destroy_options(ceph_opts);
kfree(rbd_dev->snap_name);
kfree(rbd_dev->image_name);
kfree(rbd_dev->pool_name);
kfree(rbd_dev->spec->snap_name);
kfree(rbd_dev->spec->image_name);
kfree(rbd_dev->spec->pool_name);
kfree(rbd_opts);
err_out_mem:
kfree(rbd_dev->spec);
kfree(rbd_dev);

dout("Error adding device %s\n", buf);
Expand Down Expand Up @@ -3314,11 +3336,11 @@ static void rbd_dev_release(struct device *dev)
rbd_header_free(&rbd_dev->header);

/* done with the id, and with the rbd_dev */
kfree(rbd_dev->snap_name);
kfree(rbd_dev->image_id);
kfree(rbd_dev->spec->snap_name);
kfree(rbd_dev->spec->image_id);
kfree(rbd_dev->header_name);
kfree(rbd_dev->pool_name);
kfree(rbd_dev->image_name);
kfree(rbd_dev->spec->pool_name);
kfree(rbd_dev->spec->image_name);
rbd_dev_id_put(rbd_dev);
kfree(rbd_dev);

Expand Down

0 comments on commit 0d7dbfc

Please sign in to comment.