diff options
| -rw-r--r-- | drivers/md/dm-raid1.c | 3 | ||||
| -rw-r--r-- | drivers/md/dm-snap.c | 32 | ||||
| -rw-r--r-- | drivers/md/dm-snap.h | 2 |
3 files changed, 28 insertions, 9 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 92dcc06832a4..9d7b53ed75b2 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c | |||
| @@ -656,9 +656,10 @@ static void do_failures(struct mirror_set *ms, struct bio_list *failures) | |||
| 656 | return; | 656 | return; |
| 657 | 657 | ||
| 658 | if (!ms->log_failure) { | 658 | if (!ms->log_failure) { |
| 659 | while ((bio = bio_list_pop(failures))) | 659 | while ((bio = bio_list_pop(failures))) { |
| 660 | ms->in_sync = 0; | 660 | ms->in_sync = 0; |
| 661 | dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0); | 661 | dm_rh_mark_nosync(ms->rh, bio, bio->bi_size, 0); |
| 662 | } | ||
| 662 | return; | 663 | return; |
| 663 | } | 664 | } |
| 664 | 665 | ||
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c index b2d9d1ac28ad..6c96db26b87c 100644 --- a/drivers/md/dm-snap.c +++ b/drivers/md/dm-snap.c | |||
| @@ -229,19 +229,21 @@ static void __insert_origin(struct origin *o) | |||
| 229 | */ | 229 | */ |
| 230 | static int register_snapshot(struct dm_snapshot *snap) | 230 | static int register_snapshot(struct dm_snapshot *snap) |
| 231 | { | 231 | { |
| 232 | struct origin *o; | 232 | struct origin *o, *new_o; |
| 233 | struct block_device *bdev = snap->origin->bdev; | 233 | struct block_device *bdev = snap->origin->bdev; |
| 234 | 234 | ||
| 235 | new_o = kmalloc(sizeof(*new_o), GFP_KERNEL); | ||
| 236 | if (!new_o) | ||
| 237 | return -ENOMEM; | ||
| 238 | |||
| 235 | down_write(&_origins_lock); | 239 | down_write(&_origins_lock); |
| 236 | o = __lookup_origin(bdev); | 240 | o = __lookup_origin(bdev); |
| 237 | 241 | ||
| 238 | if (!o) { | 242 | if (o) |
| 243 | kfree(new_o); | ||
| 244 | else { | ||
| 239 | /* New origin */ | 245 | /* New origin */ |
| 240 | o = kmalloc(sizeof(*o), GFP_KERNEL); | 246 | o = new_o; |
| 241 | if (!o) { | ||
| 242 | up_write(&_origins_lock); | ||
| 243 | return -ENOMEM; | ||
| 244 | } | ||
| 245 | 247 | ||
| 246 | /* Initialise the struct */ | 248 | /* Initialise the struct */ |
| 247 | INIT_LIST_HEAD(&o->snapshots); | 249 | INIT_LIST_HEAD(&o->snapshots); |
| @@ -368,6 +370,7 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps | |||
| 368 | struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, | 370 | struct dm_snap_pending_exception *pe = mempool_alloc(s->pending_pool, |
| 369 | GFP_NOIO); | 371 | GFP_NOIO); |
| 370 | 372 | ||
| 373 | atomic_inc(&s->pending_exceptions_count); | ||
| 371 | pe->snap = s; | 374 | pe->snap = s; |
| 372 | 375 | ||
| 373 | return pe; | 376 | return pe; |
| @@ -375,7 +378,11 @@ static struct dm_snap_pending_exception *alloc_pending_exception(struct dm_snaps | |||
| 375 | 378 | ||
| 376 | static void free_pending_exception(struct dm_snap_pending_exception *pe) | 379 | static void free_pending_exception(struct dm_snap_pending_exception *pe) |
| 377 | { | 380 | { |
| 378 | 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); | ||
| 379 | } | 386 | } |
| 380 | 387 | ||
| 381 | static void insert_completed_exception(struct dm_snapshot *s, | 388 | static void insert_completed_exception(struct dm_snapshot *s, |
| @@ -600,6 +607,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv) | |||
| 600 | 607 | ||
| 601 | s->valid = 1; | 608 | s->valid = 1; |
| 602 | s->active = 0; | 609 | s->active = 0; |
| 610 | atomic_set(&s->pending_exceptions_count, 0); | ||
| 603 | init_rwsem(&s->lock); | 611 | init_rwsem(&s->lock); |
| 604 | spin_lock_init(&s->pe_lock); | 612 | spin_lock_init(&s->pe_lock); |
| 605 | s->ti = ti; | 613 | s->ti = ti; |
| @@ -726,6 +734,14 @@ static void snapshot_dtr(struct dm_target *ti) | |||
| 726 | /* After this returns there can be no new kcopyd jobs. */ | 734 | /* After this returns there can be no new kcopyd jobs. */ |
| 727 | unregister_snapshot(s); | 735 | unregister_snapshot(s); |
| 728 | 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 | |||
| 729 | #ifdef CONFIG_DM_DEBUG | 745 | #ifdef CONFIG_DM_DEBUG |
| 730 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) | 746 | for (i = 0; i < DM_TRACKED_CHUNK_HASH_SIZE; i++) |
| 731 | 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 | ||
