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.c163
1 files changed, 141 insertions, 22 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 1ba8a47d61b1..6e5528aecc98 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -40,6 +40,11 @@
40 */ 40 */
41#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1) 41#define SNAPSHOT_PAGES (((1UL << 20) >> PAGE_SHIFT) ? : 1)
42 42
43/*
44 * The size of the mempool used to track chunks in use.
45 */
46#define MIN_IOS 256
47
43static struct workqueue_struct *ksnapd; 48static struct workqueue_struct *ksnapd;
44static void flush_queued_bios(struct work_struct *work); 49static void flush_queued_bios(struct work_struct *work);
45 50
@@ -91,7 +96,63 @@ struct dm_snap_pending_exception {
91 */ 96 */
92static struct kmem_cache *exception_cache; 97static struct kmem_cache *exception_cache;
93static struct kmem_cache *pending_cache; 98static struct kmem_cache *pending_cache;
94static mempool_t *pending_pool; 99
100struct dm_snap_tracked_chunk {
101 struct hlist_node node;
102 chunk_t chunk;
103};
104
105static struct kmem_cache *tracked_chunk_cache;
106
107static struct dm_snap_tracked_chunk *track_chunk(struct dm_snapshot *s,
108 chunk_t chunk)
109{
110 struct dm_snap_tracked_chunk *c = mempool_alloc(s->tracked_chunk_pool,
111 GFP_NOIO);
112 unsigned long flags;
113
114 c->chunk = chunk;
115
116 spin_lock_irqsave(&s->tracked_chunk_lock, flags);
117 hlist_add_head(&c->node,
118 &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)]);
119 spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
120
121 return c;
122}
123
124static void stop_tracking_chunk(struct dm_snapshot *s,
125 struct dm_snap_tracked_chunk *c)
126{
127 unsigned long flags;
128
129 spin_lock_irqsave(&s->tracked_chunk_lock, flags);
130 hlist_del(&c->node);
131 spin_unlock_irqrestore(&s->tracked_chunk_lock, flags);
132
133 mempool_free(c, s->tracked_chunk_pool);
134}
135
136static int __chunk_is_tracked(struct dm_snapshot *s, chunk_t chunk)
137{
138 struct dm_snap_tracked_chunk *c;
139 struct hlist_node *hn;
140 int found = 0;
141
142 spin_lock_irq(&s->tracked_chunk_lock);
143
144 hlist_for_each_entry(c, hn,
145 &s->tracked_chunk_hash[DM_TRACKED_CHUNK_HASH(chunk)], node) {
146 if (c->chunk == chunk) {
147 found = 1;
148 break;
149 }
150 }
151
152 spin_unlock_irq(&s->tracked_chunk_lock);
153
154 return found;
155}
95 156
96/* 157/*
97 * One of these per registered origin, held in the snapshot_origins hash 158 * One of these per registered origin, held in the snapshot_origins hash
@@ -302,14 +363,19 @@ static void free_exception(struct dm_snap_exception *e)
302 kmem_cache_free(exception_cache, e); 363 kmem_cache_free(exception_cache, e);
303} 364}
304 365
305static struct dm_snap_pending_exception *alloc_pending_exception(void) 366static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snapshot *s)
306{ 367{
307 return mempool_alloc(pending_pool, GFP_NOIO); 368 struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool,
369 GFP_NOIO);
370
371 pe->snap = s;
372
373 return pe;
308} 374}
309 375
310static void free_pending_exception(struct dm_snap_pending_exception *pe) 376static void free_pending_exception(struct dm_snap_pending_exception *pe)
311{ 377{
312 mempool_free(pe, pending_pool); 378 mempool_free(pe, pe->snap->pending_pool);
313} 379}
314 380
315static void insert_completed_exception(struct dm_snapshot *s, 381static void insert_completed_exception(struct dm_snapshot *s,
@@ -482,6 +548,7 @@ static int set_chunk_size(struct dm_snapshot *s, const char *chunk_size_arg,
482static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) 548static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
483{ 549{
484 struct dm_snapshot *s; 550 struct dm_snapshot *s;
551 int i;
485 int r = -EINVAL; 552 int r = -EINVAL;
486 char persistent; 553 char persistent;
487 char *origin_path; 554 char *origin_path;
@@ -564,11 +631,30 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
564 goto bad5; 631 goto bad5;
565 } 632 }
566 633
634 s->pending_pool = mempool_create_slab_pool(MIN_IOS, pending_cache);
635 if (!s->pending_pool) {
636 ti->error = "Could not allocate mempool for pending exceptions";
637 goto bad6;
638 }
639
640 s->tracked_chunk_pool = mempool_create_slab_pool(MIN_IOS,
641 tracked_chunk_cache);
642 if (!s->tracked_chunk_pool) {
643 ti->error = "Could not allocate tracked_chunk mempool for "
644 "tracking reads";
645 goto bad_tracked_chunk_pool;
646 }
647
648 for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
649 INIT_HLIST_HEAD(&s->tracked_chunk_hash[i]);
650
651 spin_lock_init(&s->tracked_chunk_lock);
652
567 /* Metadata must only be loaded into one table at once */ 653 /* Metadata must only be loaded into one table at once */
568 r = s->store.read_metadata(&s->store); 654 r = s->store.read_metadata(&s->store);
569 if (r < 0) { 655 if (r < 0) {
570 ti->error = "Failed to read snapshot metadata"; 656 ti->error = "Failed to read snapshot metadata";
571 goto bad6; 657 goto bad_load_and_register;
572 } else if (r > 0) { 658 } else if (r > 0) {
573 s->valid = 0; 659 s->valid = 0;
574 DMWARN("Snapshot is marked invalid."); 660 DMWARN("Snapshot is marked invalid.");
@@ -582,7 +668,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
582 if (register_snapshot(s)) { 668 if (register_snapshot(s)) {
583 r = -EINVAL; 669 r = -EINVAL;
584 ti->error = "Cannot register snapshot origin"; 670 ti->error = "Cannot register snapshot origin";
585 goto bad6; 671 goto bad_load_and_register;
586 } 672 }
587 673
588 ti->private = s; 674 ti->private = s;
@@ -590,6 +676,12 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
590 676
591 return 0; 677 return 0;
592 678
679 bad_load_and_register:
680 mempool_destroy(s->tracked_chunk_pool);
681
682 bad_tracked_chunk_pool:
683 mempool_destroy(s->pending_pool);
684
593 bad6: 685 bad6:
594 dm_kcopyd_client_destroy(s->kcopyd_client); 686 dm_kcopyd_client_destroy(s->kcopyd_client);
595 687
@@ -624,6 +716,9 @@ static void __free_exceptions(struct dm_snapshot *s)
624 716
625static void snapshot_dtr(struct dm_target *ti) 717static void snapshot_dtr(struct dm_target *ti)
626{ 718{
719#ifdef CONFIG_DM_DEBUG
720 int i;
721#endif
627 struct dm_snapshot *s = ti->private; 722 struct dm_snapshot *s = ti->private;
628 723
629 flush_workqueue(ksnapd); 724 flush_workqueue(ksnapd);
@@ -632,8 +727,17 @@ static void snapshot_dtr(struct dm_target *ti)
632 /* After this returns there can be no new kcopyd jobs. */ 727 /* After this returns there can be no new kcopyd jobs. */
633 unregister_snapshot(s); 728 unregister_snapshot(s);
634 729
730#ifdef CONFIG_DM_DEBUG
731 for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++)
732 BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i]));
733#endif
734
735 mempool_destroy(s->tracked_chunk_pool);
736
635 __free_exceptions(s); 737 __free_exceptions(s);
636 738
739 mempool_destroy(s->pending_pool);
740
637 dm_put_device(ti, s->origin); 741 dm_put_device(ti, s->origin);
638 dm_put_device(ti, s->cow); 742 dm_put_device(ti, s->cow);
639 743
@@ -772,6 +876,13 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
772 } 876 }
773 877
774 /* 878 /*
879 * Check for conflicting reads. This is extremely improbable,
880 * so yield() is sufficient and there is no need for a wait queue.
881 */
882 while (__chunk_is_tracked(s, pe->e.old_chunk))
883 yield();
884
885 /*
775 * Add a proper exception, and remove the 886 * Add a proper exception, and remove the
776 * in-flight exception from the list. 887 * in-flight exception from the list.
777 */ 888 */
@@ -873,7 +984,7 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
873 * to hold the lock while we do this. 984 * to hold the lock while we do this.
874 */ 985 */
875 up_write(&s->lock); 986 up_write(&s->lock);
876 pe = alloc_pending_exception(); 987 pe = alloc_pending_exception(s);
877 down_write(&s->lock); 988 down_write(&s->lock);
878 989
879 if (!s->valid) { 990 if (!s->valid) {
@@ -893,7 +1004,6 @@ __find_pending_exception(struct dm_snapshot *s, struct bio *bio)
893 bio_list_init(&pe->snapshot_bios); 1004 bio_list_init(&pe->snapshot_bios);
894 pe->primary_pe = NULL; 1005 pe->primary_pe = NULL;
895 atomic_set(&pe->ref_count, 0); 1006 atomic_set(&pe->ref_count, 0);
896 pe->snap = s;
897 pe->started = 0; 1007 pe->started = 0;
898 1008
899 if (s->store.prepare_exception(&s->store, &pe->e)) { 1009 if (s->store.prepare_exception(&s->store, &pe->e)) {
@@ -974,14 +1084,10 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
974 start_copy(pe); 1084 start_copy(pe);
975 goto out; 1085 goto out;
976 } 1086 }
977 } else 1087 } else {
978 /*
979 * FIXME: this read path scares me because we
980 * always use the origin when we have a pending
981 * exception. However I can't think of a
982 * situation where this is wrong - ejt.
983 */
984 bio->bi_bdev = s->origin->bdev; 1088 bio->bi_bdev = s->origin->bdev;
1089 map_context->ptr = track_chunk(s, chunk);
1090 }
985 1091
986 out_unlock: 1092 out_unlock:
987 up_write(&s->lock); 1093 up_write(&s->lock);
@@ -989,6 +1095,18 @@ static int snapshot_map(struct dm_target *ti, struct bio *bio,
989 return r; 1095 return r;
990} 1096}
991 1097
1098static int snapshot_end_io(struct dm_target *ti, struct bio *bio,
1099 int error, union map_info *map_context)
1100{
1101 struct dm_snapshot *s = ti->private;
1102 struct dm_snap_tracked_chunk *c = map_context->ptr;
1103
1104 if (c)
1105 stop_tracking_chunk(s, c);
1106
1107 return 0;
1108}
1109
992static void snapshot_resume(struct dm_target *ti) 1110static void snapshot_resume(struct dm_target *ti)
993{ 1111{
994 struct dm_snapshot *s = ti->private; 1112 struct dm_snapshot *s = ti->private;
@@ -1266,6 +1384,7 @@ static struct target_type snapshot_target = {
1266 .ctr = snapshot_ctr, 1384 .ctr = snapshot_ctr,
1267 .dtr = snapshot_dtr, 1385 .dtr = snapshot_dtr,
1268 .map = snapshot_map, 1386 .map = snapshot_map,
1387 .end_io = snapshot_end_io,
1269 .resume = snapshot_resume, 1388 .resume = snapshot_resume,
1270 .status = snapshot_status, 1389 .status = snapshot_status,
1271}; 1390};
@@ -1306,9 +1425,9 @@ static int __init dm_snapshot_init(void)
1306 goto bad4; 1425 goto bad4;
1307 } 1426 }
1308 1427
1309 pending_pool = mempool_create_slab_pool(128, pending_cache); 1428 tracked_chunk_cache = KMEM_CACHE(dm_snap_tracked_chunk, 0);
1310 if (!pending_pool) { 1429 if (!tracked_chunk_cache) {
1311 DMERR("Couldn't create pending pool."); 1430 DMERR("Couldn't create cache to track chunks in use.");
1312 r = -ENOMEM; 1431 r = -ENOMEM;
1313 goto bad5; 1432 goto bad5;
1314 } 1433 }
@@ -1317,13 +1436,13 @@ static int __init dm_snapshot_init(void)
1317 if (!ksnapd) { 1436 if (!ksnapd) {
1318 DMERR("Failed to create ksnapd workqueue."); 1437 DMERR("Failed to create ksnapd workqueue.");
1319 r = -ENOMEM; 1438 r = -ENOMEM;
1320 goto bad6; 1439 goto bad_pending_pool;
1321 } 1440 }
1322 1441
1323 return 0; 1442 return 0;
1324 1443
1325 bad6: 1444 bad_pending_pool:
1326 mempool_destroy(pending_pool); 1445 kmem_cache_destroy(tracked_chunk_cache);
1327 bad5: 1446 bad5:
1328 kmem_cache_destroy(pending_cache); 1447 kmem_cache_destroy(pending_cache);
1329 bad4: 1448 bad4:
@@ -1352,9 +1471,9 @@ static void __exit dm_snapshot_exit(void)
1352 DMERR("origin unregister failed %d", r); 1471 DMERR("origin unregister failed %d", r);
1353 1472
1354 exit_origin_hash(); 1473 exit_origin_hash();
1355 mempool_destroy(pending_pool);
1356 kmem_cache_destroy(pending_cache); 1474 kmem_cache_destroy(pending_cache);
1357 kmem_cache_destroy(exception_cache); 1475 kmem_cache_destroy(exception_cache);
1476 kmem_cache_destroy(tracked_chunk_cache);
1358} 1477}
1359 1478
1360/* Module hooks */ 1479/* Module hooks */