Commit 304f6808 authored by Alex Elder's avatar Alex Elder

rbd: defer registering snapshot devices

When a new snapshot is found in an rbd device's updated snapshot
context, __rbd_add_snap_dev() is called to create and insert an
entry in the rbd devices list of snapshots.  In addition, a Linux
device is registered to represent the snapshot.

For version 2 rbd images, it will be undesirable to initialize the
device right away.  So in anticipation of that, this patch separates
the insertion of a snapshot entry in the snaps list from the
creation of devices for those snapshots.

To do this, create a new function rbd_dev_snaps_register() which
traverses the list of snapshots and calls rbd_register_snap_dev()
on any that have not yet been registered.

Rename rbd_dev_snap_devs_update() to be rbd_dev_snaps_update()
to better reflect that only the entry in the snaps list and not
the snapshot's device is affected by the function.

For now, call rbd_dev_snaps_register() immediately after each
call to rbd_dev_snaps_update().
Signed-off-by: default avatarAlex Elder <elder@inktank.com>
Reviewed-by: default avatarJosh Durgin <josh.durgin@inktank.com>
parent 3fcf2581
...@@ -204,7 +204,9 @@ static DEFINE_SPINLOCK(rbd_dev_list_lock); ...@@ -204,7 +204,9 @@ static DEFINE_SPINLOCK(rbd_dev_list_lock);
static LIST_HEAD(rbd_client_list); /* clients */ static LIST_HEAD(rbd_client_list); /* clients */
static DEFINE_SPINLOCK(rbd_client_list_lock); static DEFINE_SPINLOCK(rbd_client_list_lock);
static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev); static int rbd_dev_snaps_update(struct rbd_device *rbd_dev);
static int rbd_dev_snaps_register(struct rbd_device *rbd_dev);
static void rbd_dev_release(struct device *dev); static void rbd_dev_release(struct device *dev);
static ssize_t rbd_snap_add(struct device *dev, static ssize_t rbd_snap_add(struct device *dev,
struct device_attribute *attr, struct device_attribute *attr,
...@@ -1839,7 +1841,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver) ...@@ -1839,7 +1841,9 @@ static int __rbd_refresh_header(struct rbd_device *rbd_dev, u64 *hver)
WARN_ON(strcmp(rbd_dev->header.object_prefix, h.object_prefix)); WARN_ON(strcmp(rbd_dev->header.object_prefix, h.object_prefix));
kfree(h.object_prefix); kfree(h.object_prefix);
ret = rbd_dev_snap_devs_update(rbd_dev); ret = rbd_dev_snaps_update(rbd_dev);
if (!ret)
ret = rbd_dev_snaps_register(rbd_dev);
up_write(&rbd_dev->header_rwsem); up_write(&rbd_dev->header_rwsem);
...@@ -2084,10 +2088,21 @@ static struct device_type rbd_snap_device_type = { ...@@ -2084,10 +2088,21 @@ static struct device_type rbd_snap_device_type = {
.release = rbd_snap_dev_release, .release = rbd_snap_dev_release,
}; };
static bool rbd_snap_registered(struct rbd_snap *snap)
{
bool ret = snap->dev.type == &rbd_snap_device_type;
bool reg = device_is_registered(&snap->dev);
rbd_assert(!ret ^ reg);
return ret;
}
static void __rbd_remove_snap_dev(struct rbd_snap *snap) static void __rbd_remove_snap_dev(struct rbd_snap *snap)
{ {
list_del(&snap->node); list_del(&snap->node);
device_unregister(&snap->dev); if (device_is_registered(&snap->dev))
device_unregister(&snap->dev);
} }
static int rbd_register_snap_dev(struct rbd_snap *snap, static int rbd_register_snap_dev(struct rbd_snap *snap,
...@@ -2100,6 +2115,8 @@ static int rbd_register_snap_dev(struct rbd_snap *snap, ...@@ -2100,6 +2115,8 @@ static int rbd_register_snap_dev(struct rbd_snap *snap,
dev->parent = parent; dev->parent = parent;
dev->release = rbd_snap_dev_release; dev->release = rbd_snap_dev_release;
dev_set_name(dev, "snap_%s", snap->name); dev_set_name(dev, "snap_%s", snap->name);
dout("%s: registering device for snapshot %s\n", __func__, snap->name);
ret = device_register(dev); ret = device_register(dev);
return ret; return ret;
...@@ -2122,11 +2139,6 @@ static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev, ...@@ -2122,11 +2139,6 @@ static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev,
snap->size = rbd_dev->header.snap_sizes[i]; snap->size = rbd_dev->header.snap_sizes[i];
snap->id = rbd_dev->header.snapc->snaps[i]; snap->id = rbd_dev->header.snapc->snaps[i];
if (device_is_registered(&rbd_dev->dev)) {
ret = rbd_register_snap_dev(snap, &rbd_dev->dev);
if (ret < 0)
goto err;
}
return snap; return snap;
...@@ -2149,7 +2161,7 @@ static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev, ...@@ -2149,7 +2161,7 @@ static struct rbd_snap *__rbd_add_snap_dev(struct rbd_device *rbd_dev,
* snapshot id, highest id first. (Snapshots in the rbd_dev's list * snapshot id, highest id first. (Snapshots in the rbd_dev's list
* are also maintained in that order.) * are also maintained in that order.)
*/ */
static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev) static int rbd_dev_snaps_update(struct rbd_device *rbd_dev)
{ {
struct ceph_snap_context *snapc = rbd_dev->header.snapc; struct ceph_snap_context *snapc = rbd_dev->header.snapc;
const u32 snap_count = snapc->num_snaps; const u32 snap_count = snapc->num_snaps;
...@@ -2236,6 +2248,31 @@ static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev) ...@@ -2236,6 +2248,31 @@ static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev)
return 0; return 0;
} }
/*
* Scan the list of snapshots and register the devices for any that
* have not already been registered.
*/
static int rbd_dev_snaps_register(struct rbd_device *rbd_dev)
{
struct rbd_snap *snap;
int ret = 0;
dout("%s called\n", __func__);
if (!device_is_registered(&rbd_dev->dev))
return 0;
list_for_each_entry(snap, &rbd_dev->snaps, node) {
if (!rbd_snap_registered(snap)) {
ret = rbd_register_snap_dev(snap, &rbd_dev->dev);
if (ret < 0)
break;
}
}
dout("%s: returning %d\n", __func__, ret);
return ret;
}
static int rbd_bus_add_dev(struct rbd_device *rbd_dev) static int rbd_bus_add_dev(struct rbd_device *rbd_dev)
{ {
struct device *dev; struct device *dev;
...@@ -2585,7 +2622,10 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2585,7 +2622,10 @@ static ssize_t rbd_add(struct bus_type *bus,
goto err_out_bus; goto err_out_bus;
/* no need to lock here, as rbd_dev is not registered yet */ /* no need to lock here, as rbd_dev is not registered yet */
rc = rbd_dev_snap_devs_update(rbd_dev); rc = rbd_dev_snaps_update(rbd_dev);
if (rc)
goto err_out_bus;
rc = rbd_dev_snaps_register(rbd_dev);
if (rc) if (rc)
goto err_out_bus; goto err_out_bus;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment