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.c48
1 files changed, 28 insertions, 20 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 6c96db26b87c..65ff82ff124e 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -9,6 +9,7 @@
9#include <linux/blkdev.h> 9#include <linux/blkdev.h>
10#include <linux/ctype.h> 10#include <linux/ctype.h>
11#include <linux/device-mapper.h> 11#include <linux/device-mapper.h>
12#include <linux/delay.h>
12#include <linux/fs.h> 13#include <linux/fs.h>
13#include <linux/init.h> 14#include <linux/init.h>
14#include <linux/kdev_t.h> 15#include <linux/kdev_t.h>
@@ -20,6 +21,7 @@
20#include <linux/log2.h> 21#include <linux/log2.h>
21#include <linux/dm-kcopyd.h> 22#include <linux/dm-kcopyd.h>
22 23
24#include "dm-exception-store.h"
23#include "dm-snap.h" 25#include "dm-snap.h"
24#include "dm-bio-list.h" 26#include "dm-bio-list.h"
25 27
@@ -428,8 +430,13 @@ out:
428 list_add(&new_e->hash_list, e ? &e->hash_list : l); 430 list_add(&new_e->hash_list, e ? &e->hash_list : l);
429} 431}
430 432
431int dm_add_exception(struct dm_snapshot *s, chunk_t old, chunk_t new) 433/*
434 * Callback used by the exception stores to load exceptions when
435 * initialising.
436 */
437static int dm_add_exception(void *context, chunk_t old, chunk_t new)
432{ 438{
439 struct dm_snapshot *s = context;
433 struct dm_snap_exception *e; 440 struct dm_snap_exception *e;
434 441
435 e = alloc_exception(); 442 e = alloc_exception();
@@ -658,7 +665,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
658 spin_lock_init(&s->tracked_chunk_lock); 665 spin_lock_init(&s->tracked_chunk_lock);
659 666
660 /* Metadata must only be loaded into one table at once */ 667 /* Metadata must only be loaded into one table at once */
661 r = s->store.read_metadata(&s->store); 668 r = s->store.read_metadata(&s->store, dm_add_exception, (void *)s);
662 if (r < 0) { 669 if (r < 0) {
663 ti->error = "Failed to read snapshot metadata"; 670 ti->error = "Failed to read snapshot metadata";
664 goto bad_load_and_register; 671 goto bad_load_and_register;
@@ -735,7 +742,7 @@ static void snapshot_dtr(struct dm_target *ti)
735 unregister_snapshot(s); 742 unregister_snapshot(s);
736 743
737 while (atomic_read(&s->pending_exceptions_count)) 744 while (atomic_read(&s->pending_exceptions_count))
738 yield(); 745 msleep(1);
739 /* 746 /*
740 * Ensure instructions in mempool_destroy aren't reordered 747 * Ensure instructions in mempool_destroy aren't reordered
741 * before atomic_read. 748 * before atomic_read.
@@ -888,10 +895,10 @@ static void pending_complete(struct dm_snap_pending_exception *pe, int success)
888 895
889 /* 896 /*
890 * Check for conflicting reads. This is extremely improbable, 897 * Check for conflicting reads. This is extremely improbable,
891 * so yield() is sufficient and there is no need for a wait queue. 898 * so msleep(1) is sufficient and there is no need for a wait queue.
892 */ 899 */
893 while (__chunk_is_tracked(s, pe->e.old_chunk)) 900 while (__chunk_is_tracked(s, pe->e.old_chunk))
894 yield(); 901 msleep(1);
895 902
896 /* 903 /*
897 * Add a proper exception, and remove the 904 * Add a proper exception, and remove the
@@ -1404,6 +1411,12 @@ static int __init dm_snapshot_init(void)
1404{ 1411{
1405 int r; 1412 int r;
1406 1413
1414 r = dm_exception_store_init();
1415 if (r) {
1416 DMERR("Failed to initialize exception stores");
1417 return r;
1418 }
1419
1407 r = dm_register_target(&snapshot_target); 1420 r = dm_register_target(&snapshot_target);
1408 if (r) { 1421 if (r) {
1409 DMERR("snapshot target register failed %d", r); 1422 DMERR("snapshot target register failed %d", r);
@@ -1452,39 +1465,34 @@ static int __init dm_snapshot_init(void)
1452 1465
1453 return 0; 1466 return 0;
1454 1467
1455 bad_pending_pool: 1468bad_pending_pool:
1456 kmem_cache_destroy(tracked_chunk_cache); 1469 kmem_cache_destroy(tracked_chunk_cache);
1457 bad5: 1470bad5:
1458 kmem_cache_destroy(pending_cache); 1471 kmem_cache_destroy(pending_cache);
1459 bad4: 1472bad4:
1460 kmem_cache_destroy(exception_cache); 1473 kmem_cache_destroy(exception_cache);
1461 bad3: 1474bad3:
1462 exit_origin_hash(); 1475 exit_origin_hash();
1463 bad2: 1476bad2:
1464 dm_unregister_target(&origin_target); 1477 dm_unregister_target(&origin_target);
1465 bad1: 1478bad1:
1466 dm_unregister_target(&snapshot_target); 1479 dm_unregister_target(&snapshot_target);
1467 return r; 1480 return r;
1468} 1481}
1469 1482
1470static void __exit dm_snapshot_exit(void) 1483static void __exit dm_snapshot_exit(void)
1471{ 1484{
1472 int r;
1473
1474 destroy_workqueue(ksnapd); 1485 destroy_workqueue(ksnapd);
1475 1486
1476 r = dm_unregister_target(&snapshot_target); 1487 dm_unregister_target(&snapshot_target);
1477 if (r) 1488 dm_unregister_target(&origin_target);
1478 DMERR("snapshot unregister failed %d", r);
1479
1480 r = dm_unregister_target(&origin_target);
1481 if (r)
1482 DMERR("origin unregister failed %d", r);
1483 1489
1484 exit_origin_hash(); 1490 exit_origin_hash();
1485 kmem_cache_destroy(pending_cache); 1491 kmem_cache_destroy(pending_cache);
1486 kmem_cache_destroy(exception_cache); 1492 kmem_cache_destroy(exception_cache);
1487 kmem_cache_destroy(tracked_chunk_cache); 1493 kmem_cache_destroy(tracked_chunk_cache);
1494
1495 dm_exception_store_exit();
1488} 1496}
1489 1497
1490/* Module hooks */ 1498/* Module hooks */