diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index 48901b51f648b28a81818d0426c5038d26e07f36..0d812603e6d5f3c921a8f44fe9568b71ca592a6a 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -204,7 +204,9 @@ static DEFINE_SPINLOCK(rbd_dev_list_lock);
 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,
@@ -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));
 	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);
 
@@ -2084,10 +2088,21 @@ static struct device_type rbd_snap_device_type = {
 	.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,
@@ -2100,6 +2115,8 @@ 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;
@@ -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->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;
 
@@ -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
  * 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;
@@ -2236,6 +2248,31 @@ static int rbd_dev_snap_devs_update(struct rbd_device *rbd_dev)
 	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;
@@ -2585,7 +2622,10 @@ static ssize_t rbd_add(struct bus_type *bus,
 		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;