diff options
Diffstat (limited to 'drivers/md')
-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 | ||||
-rw-r--r-- | drivers/md/md.c | 7 |
4 files changed, 35 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 | ||
diff --git a/drivers/md/md.c b/drivers/md/md.c index b4162f6f1b79..9abf6ed16535 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -3884,6 +3884,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3884 | if (mode == 0) { | 3884 | if (mode == 0) { |
3885 | mdk_rdev_t *rdev; | 3885 | mdk_rdev_t *rdev; |
3886 | struct list_head *tmp; | 3886 | struct list_head *tmp; |
3887 | struct block_device *bdev; | ||
3887 | 3888 | ||
3888 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); | 3889 | printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); |
3889 | 3890 | ||
@@ -3940,6 +3941,12 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) | |||
3940 | mddev->degraded = 0; | 3941 | mddev->degraded = 0; |
3941 | mddev->barriers_work = 0; | 3942 | mddev->barriers_work = 0; |
3942 | mddev->safemode = 0; | 3943 | mddev->safemode = 0; |
3944 | bdev = bdget_disk(mddev->gendisk, 0); | ||
3945 | if (bdev) { | ||
3946 | blkdev_ioctl(bdev, 0, BLKRRPART, 0); | ||
3947 | bdput(bdev); | ||
3948 | } | ||
3949 | kobject_uevent(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE); | ||
3943 | 3950 | ||
3944 | } else if (mddev->pers) | 3951 | } else if (mddev->pers) |
3945 | printk(KERN_INFO "md: %s switched to read-only mode.\n", | 3952 | printk(KERN_INFO "md: %s switched to read-only mode.\n", |