diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index 6e3cf7e1345..86328251375 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -375,16 +375,18 @@ static void rh_inc(struct region_hash *rh, region_t region) read_lock(&rh->hash_lock); reg = __rh_find(rh, region); + + atomic_inc(®->pending); + + spin_lock_irq(&rh->region_lock); if (reg->state == RH_CLEAN) { rh->log->type->mark_region(rh->log, reg->key); - spin_lock_irq(&rh->region_lock); reg->state = RH_DIRTY; list_del_init(®->list); /* take off the clean list */ - spin_unlock_irq(&rh->region_lock); } + spin_unlock_irq(&rh->region_lock); - atomic_inc(®->pending); read_unlock(&rh->hash_lock); } @@ -408,6 +410,10 @@ static void rh_dec(struct region_hash *rh, region_t region) if (atomic_dec_and_test(®->pending)) { spin_lock_irqsave(&rh->region_lock, flags); + if (atomic_read(®->pending)) { /* check race */ + spin_unlock_irqrestore(&rh->region_lock, flags); + return; + } if (reg->state == RH_RECOVERING) { list_add_tail(®->list, &rh->quiesced_regions); } else { @@ -1060,6 +1066,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) } ti->private = ms; + ti->split_io = ms->rh.region_size; r = kcopyd_client_create(DM_IO_PAGES, &ms->kcopyd_client); if (r) { @@ -1229,7 +1236,7 @@ static int __init dm_mirror_init(void) if (r) return r; - _kmirrord_wq = create_workqueue("kmirrord"); + _kmirrord_wq = create_singlethread_workqueue("kmirrord"); if (!_kmirrord_wq) { DMERR("couldn't start kmirrord"); dm_dirty_log_exit(); |