diff options
-rw-r--r-- | drivers/md/dm-snap.c | 16 | ||||
-rw-r--r-- | drivers/md/dm-snap.h | 2 |
2 files changed, 17 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])); |
diff --git a/drivers/md/dm-snap.h b/drivers/md/dm-snap.h index f07315fe2362..99c0106ede2d 100644 --- a/drivers/md/dm-snap.h +++ b/drivers/md/dm-snap.h | |||
@@ -160,6 +160,8 @@ struct dm_snapshot { | |||
160 | 160 | ||
161 | mempool_t *pending_pool; | 161 | mempool_t *pending_pool; |
162 | 162 | ||
163 | atomic_t pending_exceptions_count; | ||
164 | |||
163 | struct exception_table pending; | 165 | struct exception_table pending; |
164 | struct exception_table complete; | 166 | struct exception_table complete; |
165 | 167 | ||