static LIST_HEAD(rbd_client_list); /* clients */
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 ssize_t rbd_snap_add(struct device *dev,
struct device_attribute *attr,
WARN_ON(strcmp(rbd_dev->header.object_prefix, 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);
.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)
{
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,
dev->parent = parent;
dev->release = rbd_snap_dev_release;
dev_set_name(dev, "snap_%s", snap->name);
+ dout("%s: registering device for snapshot %s\n", __func__, snap->name);
+
ret = device_register(dev);
return ret;
snap->size = rbd_dev->header.snap_sizes[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;
* snapshot id, highest id first. (Snapshots in the rbd_dev's list
* 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;
const u32 snap_count = snapc->num_snaps;
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)
{
struct device *dev;
goto err_out_bus;
/* 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)
goto err_out_bus;