aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/rbd.c
diff options
context:
space:
mode:
authorAlex Elder <elder@dreamhost.com>2012-01-29 14:57:44 -0500
committerAlex Elder <elder@dreamhost.com>2012-03-22 11:47:47 -0400
commit1ddbe94eda58597cb6dd464b455cb62d3f68be7b (patch)
tree02a6b829191d218ed861f81b0dcedb8deef53ff4 /drivers/block/rbd.c
parentb7f23c361b65a0bdcc81acd8d38471b7810df3ff (diff)
rbd: rework calculation of new rbd id's
In order to select a new unique identifier for an added rbd device, the list of all existing ones is searched and a value one greater than the highest id is used. The list search can be avoided by using an atomic variable that keeps track of the current highest id. Using a get/put model for id's we can limit the boundless growth of id numbers a bit by arranging to reuse the current highest id once it gets released. Add these calls to "put" the id when an rbd is getting removed. Note that this changes the pattern of device id's used--new values will never be below the highest one seen so far (even if there exists an unused lower one). I assert this is OK because the key property of an rbd id is its uniqueness, not its magnitude. Regardless, a follow-on patch will restore the old way of doing things, I just think this commit just makes the incremental change to atomics a little easier to understand. Signed-off-by: Alex Elder <elder@dreamhost.com> Signed-off-by: Sage Weil <sage@newdream.net>
Diffstat (limited to 'drivers/block/rbd.c')
-rw-r--r--drivers/block/rbd.c35
1 files changed, 23 insertions, 12 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index aaa19d8c3670..62da8ccc5fcb 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -2149,21 +2149,29 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
2149 return ret; 2149 return ret;
2150} 2150}
2151 2151
2152/* caller must hold ctl_mutex */ 2152static atomic64_t rbd_id_max = ATOMIC64_INIT(0);
2153
2154/*
2155 * Get a unique rbd identifier. The minimum rbd id is 1.
2156 */
2153static int rbd_id_get(void) 2157static int rbd_id_get(void)
2154{ 2158{
2155 struct list_head *tmp; 2159 return atomic64_inc_return(&rbd_id_max);
2156 int new_id = 0; 2160}
2157
2158 list_for_each(tmp, &rbd_dev_list) {
2159 struct rbd_device *rbd_dev;
2160 2161
2161 rbd_dev = list_entry(tmp, struct rbd_device, node); 2162/*
2162 if (rbd_dev->id >= new_id) 2163 * Record that an rbd identifier is no longer in use.
2163 new_id = rbd_dev->id + 1; 2164 */
2164 } 2165static void rbd_id_put(int rbd_id)
2166{
2167 BUG_ON(rbd_id < 1);
2165 2168
2166 return new_id; 2169 /*
2170 * New id's are always one more than the current maximum.
2171 * If the id being "put" *is* that maximum, decrement the
2172 * maximum so the next one requested just reuses this one.
2173 */
2174 atomic64_cmpxchg(&rbd_id_max, rbd_id, rbd_id - 1);
2167} 2175}
2168 2176
2169static ssize_t rbd_add(struct bus_type *bus, 2177static ssize_t rbd_add(struct bus_type *bus,
@@ -2200,7 +2208,7 @@ static ssize_t rbd_add(struct bus_type *bus,
2200 2208
2201 init_rwsem(&rbd_dev->header.snap_rwsem); 2209 init_rwsem(&rbd_dev->header.snap_rwsem);
2202 2210
2203 /* generate unique id: find highest unique id, add one */ 2211 /* generate unique id: one more than highest used so far */
2204 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 2212 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
2205 2213
2206 rbd_dev->id = rbd_id_get(); 2214 rbd_dev->id = rbd_id_get();
@@ -2270,6 +2278,7 @@ err_out_bus:
2270 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING); 2278 mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
2271 list_del_init(&rbd_dev->node); 2279 list_del_init(&rbd_dev->node);
2272 mutex_unlock(&ctl_mutex); 2280 mutex_unlock(&ctl_mutex);
2281 rbd_id_put(target_id);
2273 2282
2274 /* this will also clean up rest of rbd_dev stuff */ 2283 /* this will also clean up rest of rbd_dev stuff */
2275 2284
@@ -2286,6 +2295,7 @@ err_out_client:
2286err_out_slot: 2295err_out_slot:
2287 list_del_init(&rbd_dev->node); 2296 list_del_init(&rbd_dev->node);
2288 mutex_unlock(&ctl_mutex); 2297 mutex_unlock(&ctl_mutex);
2298 rbd_id_put(target_id);
2289 2299
2290 kfree(rbd_dev); 2300 kfree(rbd_dev);
2291err_out_opt: 2301err_out_opt:
@@ -2363,6 +2373,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
2363 } 2373 }
2364 2374
2365 list_del_init(&rbd_dev->node); 2375 list_del_init(&rbd_dev->node);
2376 rbd_id_put(target_id);
2366 2377
2367 __rbd_remove_all_snaps(rbd_dev); 2378 __rbd_remove_all_snaps(rbd_dev);
2368 rbd_bus_del_dev(rbd_dev); 2379 rbd_bus_del_dev(rbd_dev);