Commit 499afd5b authored by Alex Elder's avatar Alex Elder

rbd: tie rbd_dev_list changes to rbd_id operations

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: default avatarAlex Elder <elder@dreamhost.com>
Signed-off-by: default avatarSage Weil <sage@newdream.net>
parent e124a82f
...@@ -2154,26 +2154,36 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) ...@@ -2154,26 +2154,36 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
static atomic64_t rbd_id_max = ATOMIC64_INIT(0); static atomic64_t rbd_id_max = ATOMIC64_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 atomic64_inc_return(&rbd_id_max); rbd_dev->id = atomic64_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. * New id's are always one more than the current maximum.
* If the id being "put" *is* that maximum, decrement the * If the id being "put" *is* that maximum, decrement the
* maximum so the next one requested just reuses this one. * maximum so the next one requested just reuses this one.
*/ */
atomic64_cmpxchg(&rbd_id_max, rbd_id, rbd_id - 1); atomic64_cmpxchg(&rbd_id_max, rbd_dev->id, rbd_dev->id - 1);
} }
static ssize_t rbd_add(struct bus_type *bus, static ssize_t rbd_add(struct bus_type *bus,
...@@ -2211,12 +2221,7 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2211,12 +2221,7 @@ static ssize_t rbd_add(struct bus_type *bus,
init_rwsem(&rbd_dev->header.snap_rwsem); init_rwsem(&rbd_dev->header.snap_rwsem);
/* generate unique id: one more than highest used so far */ /* generate unique id: one more than highest used so far */
rbd_dev->id = rbd_id_get(); rbd_id_get(rbd_dev);
/* 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);
/* parse add command */ /* parse add command */
if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s " if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s "
...@@ -2279,10 +2284,7 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2279,10 +2284,7 @@ static ssize_t rbd_add(struct bus_type *bus,
return count; return count;
err_out_bus: err_out_bus:
spin_lock(&rbd_dev_list_lock); rbd_id_put(rbd_dev);
list_del_init(&rbd_dev->node);
spin_unlock(&rbd_dev_list_lock);
rbd_id_put(target_id);
/* this will also clean up rest of rbd_dev stuff */ /* this will also clean up rest of rbd_dev stuff */
...@@ -2296,10 +2298,7 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2296,10 +2298,7 @@ static ssize_t rbd_add(struct bus_type *bus,
err_out_client: err_out_client:
rbd_put_client(rbd_dev); rbd_put_client(rbd_dev);
err_out_slot: err_out_slot:
spin_lock(&rbd_dev_list_lock); rbd_id_put(rbd_dev);
list_del_init(&rbd_dev->node);
spin_unlock(&rbd_dev_list_lock);
rbd_id_put(target_id);
kfree(rbd_dev); kfree(rbd_dev);
err_out_opt: err_out_opt:
...@@ -2380,11 +2379,7 @@ static ssize_t rbd_remove(struct bus_type *bus, ...@@ -2380,11 +2379,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
goto done; goto done;
} }
spin_lock(&rbd_dev_list_lock); rbd_id_put(rbd_dev);
list_del_init(&rbd_dev->node);
spin_unlock(&rbd_dev_list_lock);
rbd_id_put(target_id);
__rbd_remove_all_snaps(rbd_dev); __rbd_remove_all_snaps(rbd_dev);
rbd_bus_del_dev(rbd_dev); rbd_bus_del_dev(rbd_dev);
......
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