diff options
Diffstat (limited to 'drivers/md/dm-snap.c')
-rw-r--r-- | drivers/md/dm-snap.c | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index 746603b42f86..6c96db26b87c 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
@@ -370,6 +370,7 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps | |||
370 | struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, | 370 | struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, |
371 | GFP_NOIO); | 371 | GFP_NOIO); |
372 | 372 | ||
373 | atomic_inc(&s->pending_exceptions_count); | ||
373 | pe->snap = s; | 374 | pe->snap = s; |
374 | 375 | ||
375 | return pe; | 376 | return pe; |
@@ -377,7 +378,11 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps | |||
377 | 378 | ||
378 | static void free_pending_exception(struct dm_snap_pending_exception *pe) | 379 | static void free_pending_exception(struct dm_snap_pending_exception *pe) |
379 | { | 380 | { |
380 | mempool_free(pe, pe->snap->pending_pool); | 381 | struct dm_snapshot *s = pe->snap; |
382 | |||
383 | mempool_free(pe, s->pending_pool); | ||
384 | smp_mb__before_atomic_dec(); | ||
385 | atomic_dec(&s->pending_exceptions_count); | ||
381 | } | 386 | } |
382 | 387 | ||
383 | static void insert_completed_exception(struct dm_snapshot *s, | 388 | static void insert_completed_exception(struct dm_snapshot *s, |
@@ -602,6 +607,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
602 | 607 | ||
603 | s->valid = 1; | 608 | s->valid = 1; |
604 | s->active = 0; | 609 | s->active = 0; |
610 | atomic_set(&s->pending_exceptions_count, 0); | ||
605 | init_rwsem(&s->lock); | 611 | init_rwsem(&s->lock); |
606 | spin_lock_init(&s->pe_lock); | 612 | spin_lock_init(&s->pe_lock); |
607 | s->ti = ti; | 613 | s->ti = ti; |
@@ -728,6 +734,14 @@ static void snapshot_dtr(struct dm_target *ti) | |||
728 | /* After this returns there can be no new kcopyd jobs. */ | 734 | /* After this returns there can be no new kcopyd jobs. */ |
729 | unregister_snapshot(s); | 735 | unregister_snapshot(s); |
730 | 736 | ||
737 | while (atomic_read(&s->pending_exceptions_count)) | ||
738 | yield(); | ||
739 | /* | ||
740 | * Ensure instructions in mempool_destroy aren't reordered | ||
741 | * before atomic_read. | ||
742 | */ | ||
743 | smp_mb(); | ||
744 | |||
731 | #ifdef CONFIG_DM_DEBUG | 745 | #ifdef CONFIG_DM_DEBUG |
732 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) | 746 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) |
733 | BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); | 747 | BUG_ON(!hlist_empty(&s->tracked_chunk_hash[i])); |