aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r--drivers/md/dm-snap.c93
1 files changed, 84 insertions, 9 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 8b204ae216ab..c2bf822bad6f 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -20,6 +20,8 @@
20#include <linux/log2.h> 20#include <linux/log2.h>
21#include <linux/dm-kcopyd.h> 21#include <linux/dm-kcopyd.h>
22 22
23#include "dm.h"
24
23#include "dm-exception-store.h" 25#include "dm-exception-store.h"
24 26
25#define DM_MSG_PREFIX "snapshots" 27#define DM_MSG_PREFIX "snapshots"
@@ -291,12 +293,23 @@ struct origin {
291}; 293};
292 294
293/* 295/*
296 * This structure is allocated for each origin target
297 */
298struct dm_origin {
299 struct dm_dev *dev;
300 struct dm_target *ti;
301 unsigned split_boundary;
302 struct list_head hash_list;
303};
304
305/*
294 * Size of the hash table for origin volumes. If we make this 306 * Size of the hash table for origin volumes. If we make this
295 * the size of the minors list then it should be nearly perfect 307 * the size of the minors list then it should be nearly perfect
296 */ 308 */
297#define ORIGIN_HASH_SIZE 256 309#define ORIGIN_HASH_SIZE 256
298#define ORIGIN_MASK 0xFF 310#define ORIGIN_MASK 0xFF
299static struct list_head *_origins; 311static struct list_head *_origins;
312static struct list_head *_dm_origins;
300static struct rw_semaphore _origins_lock; 313static struct rw_semaphore _origins_lock;
301 314
302static DECLARE_WAIT_QUEUE_HEAD(_pending_exceptions_done); 315static DECLARE_WAIT_QUEUE_HEAD(_pending_exceptions_done);
@@ -310,12 +323,22 @@ static int init_origin_hash(void)
310 _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head), 323 _origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
311 GFP_KERNEL); 324 GFP_KERNEL);
312 if (!_origins) { 325 if (!_origins) {
313 DMERR("unable to allocate memory"); 326 DMERR("unable to allocate memory for _origins");
314 return -ENOMEM; 327 return -ENOMEM;
315 } 328 }
316
317 for (i = 0; i < ORIGIN_HASH_SIZE; i++) 329 for (i = 0; i < ORIGIN_HASH_SIZE; i++)
318 INIT_LIST_HEAD(_origins + i); 330 INIT_LIST_HEAD(_origins + i);
331
332 _dm_origins = kmalloc(ORIGIN_HASH_SIZE * sizeof(struct list_head),
333 GFP_KERNEL);
334 if (!_dm_origins) {
335 DMERR("unable to allocate memory for _dm_origins");
336 kfree(_origins);
337 return -ENOMEM;
338 }
339 for (i = 0; i < ORIGIN_HASH_SIZE; i++)
340 INIT_LIST_HEAD(_dm_origins + i);
341
319 init_rwsem(&_origins_lock); 342 init_rwsem(&_origins_lock);
320 343
321 return 0; 344 return 0;
@@ -324,6 +347,7 @@ static int init_origin_hash(void)
324static void exit_origin_hash(void) 347static void exit_origin_hash(void)
325{ 348{
326 kfree(_origins); 349 kfree(_origins);
350 kfree(_dm_origins);
327} 351}
328 352
329static unsigned origin_hash(struct block_device *bdev) 353static unsigned origin_hash(struct block_device *bdev)
@@ -350,6 +374,30 @@ static void __insert_origin(struct origin *o)
350 list_add_tail(&o->hash_list, sl); 374 list_add_tail(&o->hash_list, sl);
351} 375}
352 376
377static struct dm_origin *__lookup_dm_origin(struct block_device *origin)
378{
379 struct list_head *ol;
380 struct dm_origin *o;
381
382 ol = &_dm_origins[origin_hash(origin)];
383 list_for_each_entry (o, ol, hash_list)
384 if (bdev_equal(o->dev->bdev, origin))
385 return o;
386
387 return NULL;
388}
389
390static void __insert_dm_origin(struct dm_origin *o)
391{
392 struct list_head *sl = &_dm_origins[origin_hash(o->dev->bdev)];
393 list_add_tail(&o->hash_list, sl);
394}
395
396static void __remove_dm_origin(struct dm_origin *o)
397{
398 list_del(&o->hash_list);
399}
400
353/* 401/*
354 * _origins_lock must be held when calling this function. 402 * _origins_lock must be held when calling this function.
355 * Returns number of snapshots registered using the supplied cow device, plus: 403 * Returns number of snapshots registered using the supplied cow device, plus:
@@ -1841,8 +1889,20 @@ static void snapshot_resume(struct dm_target *ti)
1841{ 1889{
1842 struct dm_snapshot *s = ti->private; 1890 struct dm_snapshot *s = ti->private;
1843 struct dm_snapshot *snap_src = NULL, *snap_dest = NULL; 1891 struct dm_snapshot *snap_src = NULL, *snap_dest = NULL;
1892 struct dm_origin *o;
1893 struct mapped_device *origin_md = NULL;
1844 1894
1845 down_read(&_origins_lock); 1895 down_read(&_origins_lock);
1896
1897 o = __lookup_dm_origin(s->origin->bdev);
1898 if (o)
1899 origin_md = dm_table_get_md(o->ti->table);
1900 if (origin_md == dm_table_get_md(ti->table))
1901 origin_md = NULL;
1902
1903 if (origin_md)
1904 dm_internal_suspend_fast(origin_md);
1905
1846 (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL); 1906 (void) __find_snapshots_sharing_cow(s, &snap_src, &snap_dest, NULL);
1847 if (snap_src && snap_dest) { 1907 if (snap_src && snap_dest) {
1848 down_write(&snap_src->lock); 1908 down_write(&snap_src->lock);
@@ -1851,6 +1911,10 @@ static void snapshot_resume(struct dm_target *ti)
1851 up_write(&snap_dest->lock); 1911 up_write(&snap_dest->lock);
1852 up_write(&snap_src->lock); 1912 up_write(&snap_src->lock);
1853 } 1913 }
1914
1915 if (origin_md)
1916 dm_internal_resume_fast(origin_md);
1917
1854 up_read(&_origins_lock); 1918 up_read(&_origins_lock);
1855 1919
1856 /* Now we have correct chunk size, reregister */ 1920 /* Now we have correct chunk size, reregister */
@@ -2133,11 +2197,6 @@ static int origin_write_extent(struct dm_snapshot *merging_snap,
2133 * Origin: maps a linear range of a device, with hooks for snapshotting. 2197 * Origin: maps a linear range of a device, with hooks for snapshotting.
2134 */ 2198 */
2135 2199
2136struct dm_origin {
2137 struct dm_dev *dev;
2138 unsigned split_boundary;
2139};
2140
2141/* 2200/*
2142 * Construct an origin mapping: <dev_path> 2201 * Construct an origin mapping: <dev_path>
2143 * The context for an origin is merely a 'struct dm_dev *' 2202 * The context for an origin is merely a 'struct dm_dev *'
@@ -2166,6 +2225,7 @@ static int origin_ctr(struct dm_target *ti, unsigned int argc, char **argv)
2166 goto bad_open; 2225 goto bad_open;
2167 } 2226 }
2168 2227
2228 o->ti = ti;
2169 ti->private = o; 2229 ti->private = o;
2170 ti->num_flush_bios = 1; 2230 ti->num_flush_bios = 1;
2171 2231
@@ -2180,6 +2240,7 @@ bad_alloc:
2180static void origin_dtr(struct dm_target *ti) 2240static void origin_dtr(struct dm_target *ti)
2181{ 2241{
2182 struct dm_origin *o = ti->private; 2242 struct dm_origin *o = ti->private;
2243
2183 dm_put_device(ti, o->dev); 2244 dm_put_device(ti, o->dev);
2184 kfree(o); 2245 kfree(o);
2185} 2246}
@@ -2216,6 +2277,19 @@ static void origin_resume(struct dm_target *ti)
2216 struct dm_origin *o = ti->private; 2277 struct dm_origin *o = ti->private;
2217 2278
2218 o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev); 2279 o->split_boundary = get_origin_minimum_chunksize(o->dev->bdev);
2280
2281 down_write(&_origins_lock);
2282 __insert_dm_origin(o);
2283 up_write(&_origins_lock);
2284}
2285
2286static void origin_postsuspend(struct dm_target *ti)
2287{
2288 struct dm_origin *o = ti->private;
2289
2290 down_write(&_origins_lock);
2291 __remove_dm_origin(o);
2292 up_write(&_origins_lock);
2219} 2293}
2220 2294
2221static void origin_status(struct dm_target *ti, status_type_t type, 2295static void origin_status(struct dm_target *ti, status_type_t type,
@@ -2258,12 +2332,13 @@ static int origin_iterate_devices(struct dm_target *ti,
2258 2332
2259static struct target_type origin_target = { 2333static struct target_type origin_target = {
2260 .name = "snapshot-origin", 2334 .name = "snapshot-origin",
2261 .version = {1, 8, 1}, 2335 .version = {1, 9, 0},
2262 .module = THIS_MODULE, 2336 .module = THIS_MODULE,
2263 .ctr = origin_ctr, 2337 .ctr = origin_ctr,
2264 .dtr = origin_dtr, 2338 .dtr = origin_dtr,
2265 .map = origin_map, 2339 .map = origin_map,
2266 .resume = origin_resume, 2340 .resume = origin_resume,
2341 .postsuspend = origin_postsuspend,
2267 .status = origin_status, 2342 .status = origin_status,
2268 .merge = origin_merge, 2343 .merge = origin_merge,
2269 .iterate_devices = origin_iterate_devices, 2344 .iterate_devices = origin_iterate_devices,
@@ -2271,7 +2346,7 @@ static struct target_type origin_target = {
2271 2346
2272static struct target_type snapshot_target = { 2347static struct target_type snapshot_target = {
2273 .name = "snapshot", 2348 .name = "snapshot",
2274 .version = {1, 12, 0}, 2349 .version = {1, 13, 0},
2275 .module = THIS_MODULE, 2350 .module = THIS_MODULE,
2276 .ctr = snapshot_ctr, 2351 .ctr = snapshot_ctr,
2277 .dtr = snapshot_dtr, 2352 .dtr = snapshot_dtr,