[PATCH 4/5] rbd: tie rbd_dev_list changes to rbd_id operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The only time entries are added to or removed from the global
rbd_dev_list is exactly when a "put" or "get" operation is being
performed on a rbd_dev's id.  So just move the list management code
into get/put routines.

Signed-off-by: Alex Elder <elder@xxxxxxxxxxxxx>
---
 drivers/block/rbd.c |   47 +++++++++++++++++++++--------------------------
 1 files changed, 21 insertions(+), 26 deletions(-)

diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e839289..042377b 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2153,26 +2153,36 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
 static atomic_t rbd_id_max = ATOMIC_INIT(0);

 /*
- * Get a unique rbd identifier.  The minimum rbd id is 1.
+ * Get a unique rbd identifier for the given new rbd_dev, and add
+ * the rbd_dev to the global list.  The minimum rbd id is 1.
  */
-static int rbd_id_get(void)
+static void rbd_id_get(struct rbd_device *rbd_dev)
 {
-	return atomic_inc_return(&rbd_id_max);
+	rbd_dev->id = atomic_inc_return(&rbd_id_max);
+
+	spin_lock(&rbd_dev_list_lock);
+	list_add_tail(&rbd_dev->node, &rbd_dev_list);
+	spin_unlock(&rbd_dev_list_lock);
 }

 /*
- * Record that an rbd identifier is no longer in use.
+ * Remove an rbd_dev from the global list, and record that its
+ * identifier is no longer in use.
  */
-static void rbd_id_put(int rbd_id)
+static void rbd_id_put(struct rbd_device *rbd_dev)
 {
-	BUG_ON(rbd_id < 1);
+	BUG_ON(rbd_dev->id < 1);
+
+	spin_lock(&rbd_dev_list_lock);
+	list_del_init(&rbd_dev->node);
+	spin_unlock(&rbd_dev_list_lock);

 	/*
 	 * New id's are always one more than the current maximum.
 	 * If the id being "put" *is* that maximum, decrement the
 	 * maximum so the next one requested just reuses this one.
 	 */
-	atomic_cmpxchg(&rbd_id_max, rbd_id, rbd_id - 1);
+	atomic_cmpxchg(&rbd_id_max, rbd_dev->id, rbd_dev->id - 1);
 }

 static ssize_t rbd_add(struct bus_type *bus,
@@ -2208,12 +2218,7 @@ static ssize_t rbd_add(struct bus_type *bus,
 	INIT_LIST_HEAD(&rbd_dev->snaps);

 	/* generate unique id: one more than highest used so far */
-	rbd_dev->id = rbd_id_get();
-
-	/* add to global list */
-	spin_lock(&rbd_dev_list_lock);
-	list_add_tail(&rbd_dev->node, &rbd_dev_list);
-	spin_unlock(&rbd_dev_list_lock);
+	rbd_id_get(rbd_dev);

 	/* parse add command */
 	if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s "
@@ -2276,10 +2281,7 @@ static ssize_t rbd_add(struct bus_type *bus,
 	return count;

 err_out_bus:
-	spin_lock(&rbd_dev_list_lock);
-	list_del_init(&rbd_dev->node);
-	spin_unlock(&rbd_dev_list_lock);
-	rbd_id_put(target_id);
+	rbd_id_put(rbd_dev);

 	/* this will also clean up rest of rbd_dev stuff */

@@ -2293,10 +2295,7 @@ err_out_blkdev:
 err_out_client:
 	rbd_put_client(rbd_dev);
 err_out_slot:
-	spin_lock(&rbd_dev_list_lock);
-	list_del_init(&rbd_dev->node);
-	spin_unlock(&rbd_dev_list_lock);
-	rbd_id_put(target_id);
+	rbd_id_put(rbd_dev);

 	kfree(rbd_dev);
 err_out_opt:
@@ -2377,11 +2376,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
 		goto done;
 	}

-	spin_lock(&rbd_dev_list_lock);
-	list_del_init(&rbd_dev->node);
-	spin_unlock(&rbd_dev_list_lock);
-
-	rbd_id_put(target_id);
+	rbd_id_put(rbd_dev);

 	__rbd_remove_all_snaps(rbd_dev);
 	rbd_bus_del_dev(rbd_dev);
--
1.7.5.4

--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux