diff options
author | Alex Elder <elder@dreamhost.com> | 2012-02-02 09:13:29 -0500 |
---|---|---|
committer | Alex Elder <elder@dreamhost.com> | 2012-03-22 11:47:47 -0400 |
commit | 499afd5b8e742792fda6bd7730c738ad83aecf6b (patch) | |
tree | a3cac0fa73a3251e80d8c6eb2e0eb9addbcc5e22 /drivers/block/rbd.c | |
parent | e124a82f3c4efc2cc2bae68a2bf30020fb8c4fc2 (diff) |
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: 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.c | 47 |
1 files changed, 21 insertions, 26 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index e259feedc7d0..e7727e8337fc 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -2154,26 +2154,36 @@ static int rbd_init_watch_dev(struct rbd_device *rbd_dev) | |||
2154 | static atomic64_t rbd_id_max = ATOMIC64_INIT(0); | 2154 | static atomic64_t rbd_id_max = ATOMIC64_INIT(0); |
2155 | 2155 | ||
2156 | /* | 2156 | /* |
2157 | * Get a unique rbd identifier. The minimum rbd id is 1. | 2157 | * Get a unique rbd identifier for the given new rbd_dev, and add |
2158 | * the rbd_dev to the global list. The minimum rbd id is 1. | ||
2158 | */ | 2159 | */ |
2159 | static int rbd_id_get(void) | 2160 | static void rbd_id_get(struct rbd_device *rbd_dev) |
2160 | { | 2161 | { |
2161 | return atomic64_inc_return(&rbd_id_max); | 2162 | rbd_dev->id = atomic64_inc_return(&rbd_id_max); |
2163 | |||
2164 | spin_lock(&rbd_dev_list_lock); | ||
2165 | list_add_tail(&rbd_dev->node, &rbd_dev_list); | ||
2166 | spin_unlock(&rbd_dev_list_lock); | ||
2162 | } | 2167 | } |
2163 | 2168 | ||
2164 | /* | 2169 | /* |
2165 | * Record that an rbd identifier is no longer in use. | 2170 | * Remove an rbd_dev from the global list, and record that its |
2171 | * identifier is no longer in use. | ||
2166 | */ | 2172 | */ |
2167 | static void rbd_id_put(int rbd_id) | 2173 | static void rbd_id_put(struct rbd_device *rbd_dev) |
2168 | { | 2174 | { |
2169 | BUG_ON(rbd_id < 1); | 2175 | BUG_ON(rbd_dev->id < 1); |
2176 | |||
2177 | spin_lock(&rbd_dev_list_lock); | ||
2178 | list_del_init(&rbd_dev->node); | ||
2179 | spin_unlock(&rbd_dev_list_lock); | ||
2170 | 2180 | ||
2171 | /* | 2181 | /* |
2172 | * New id's are always one more than the current maximum. | 2182 | * New id's are always one more than the current maximum. |
2173 | * If the id being "put" *is* that maximum, decrement the | 2183 | * If the id being "put" *is* that maximum, decrement the |
2174 | * maximum so the next one requested just reuses this one. | 2184 | * maximum so the next one requested just reuses this one. |
2175 | */ | 2185 | */ |
2176 | atomic64_cmpxchg(&rbd_id_max, rbd_id, rbd_id - 1); | 2186 | atomic64_cmpxchg(&rbd_id_max, rbd_dev->id, rbd_dev->id - 1); |
2177 | } | 2187 | } |
2178 | 2188 | ||
2179 | static ssize_t rbd_add(struct bus_type *bus, | 2189 | static ssize_t rbd_add(struct bus_type *bus, |
@@ -2211,12 +2221,7 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
2211 | init_rwsem(&rbd_dev->header.snap_rwsem); | 2221 | init_rwsem(&rbd_dev->header.snap_rwsem); |
2212 | 2222 | ||
2213 | /* generate unique id: one more than highest used so far */ | 2223 | /* generate unique id: one more than highest used so far */ |
2214 | rbd_dev->id = rbd_id_get(); | 2224 | rbd_id_get(rbd_dev); |
2215 | |||
2216 | /* add to global list */ | ||
2217 | spin_lock(&rbd_dev_list_lock); | ||
2218 | list_add_tail(&rbd_dev->node, &rbd_dev_list); | ||
2219 | spin_unlock(&rbd_dev_list_lock); | ||
2220 | 2225 | ||
2221 | /* parse add command */ | 2226 | /* parse add command */ |
2222 | if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s " | 2227 | if (sscanf(buf, "%" __stringify(RBD_MAX_OPT_LEN) "s " |
@@ -2279,10 +2284,7 @@ static ssize_t rbd_add(struct bus_type *bus, | |||
2279 | return count; | 2284 | return count; |
2280 | 2285 | ||
2281 | err_out_bus: | 2286 | err_out_bus: |
2282 | spin_lock(&rbd_dev_list_lock); | 2287 | rbd_id_put(rbd_dev); |
2283 | list_del_init(&rbd_dev->node); | ||
2284 | spin_unlock(&rbd_dev_list_lock); | ||
2285 | rbd_id_put(target_id); | ||
2286 | 2288 | ||
2287 | /* this will also clean up rest of rbd_dev stuff */ | 2289 | /* this will also clean up rest of rbd_dev stuff */ |
2288 | 2290 | ||
@@ -2296,10 +2298,7 @@ err_out_blkdev: | |||
2296 | err_out_client: | 2298 | err_out_client: |
2297 | rbd_put_client(rbd_dev); | 2299 | rbd_put_client(rbd_dev); |
2298 | err_out_slot: | 2300 | err_out_slot: |
2299 | spin_lock(&rbd_dev_list_lock); | 2301 | rbd_id_put(rbd_dev); |
2300 | list_del_init(&rbd_dev->node); | ||
2301 | spin_unlock(&rbd_dev_list_lock); | ||
2302 | rbd_id_put(target_id); | ||
2303 | 2302 | ||
2304 | kfree(rbd_dev); | 2303 | kfree(rbd_dev); |
2305 | err_out_opt: | 2304 | err_out_opt: |
@@ -2380,11 +2379,7 @@ static ssize_t rbd_remove(struct bus_type *bus, | |||
2380 | goto done; | 2379 | goto done; |
2381 | } | 2380 | } |
2382 | 2381 | ||
2383 | spin_lock(&rbd_dev_list_lock); | 2382 | rbd_id_put(rbd_dev); |
2384 | list_del_init(&rbd_dev->node); | ||
2385 | spin_unlock(&rbd_dev_list_lock); | ||
2386 | |||
2387 | rbd_id_put(target_id); | ||
2388 | 2383 | ||
2389 | __rbd_remove_all_snaps(rbd_dev); | 2384 | __rbd_remove_all_snaps(rbd_dev); |
2390 | rbd_bus_del_dev(rbd_dev); | 2385 | rbd_bus_del_dev(rbd_dev); |