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: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com>
This commit is contained in:
@@ -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)
|
|||||||
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,9 +2088,20 @@ 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);
|
||||||
|
if (device_is_registered(&snap->dev))
|
||||||
device_unregister(&snap->dev);
|
device_unregister(&snap->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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,
|
|||||||
|
|
||||||
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 @@ err:
|
|||||||
* 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)
|
|||||||
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,
|
|||||||
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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user