From 51fc59608f823ab32e39305acd19a13546d73d44 Mon Sep 17 00:00:00 2001 From: Takahiro Yasui Date: Sat, 6 Mar 2010 02:32:35 +0000 Subject: [PATCH] --- yaml --- r: 186435 b: refs/heads/master c: f070304094edb8d516423e79edd27c97ec2020b0 h: refs/heads/master i: 186433: 97eb02f8f86fc2fa656cf3e305cadc0fad1f525c 186431: 4d345f0553b2cea83d1ee27ce5f33b8c98d62879 v: v3 --- [refs] | 2 +- trunk/drivers/md/dm-raid1.c | 41 +++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/[refs] b/[refs] index d9deaae1cdf6..71d804b6c8a4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 924e600d417ead9ef67043988055ba236f114718 +refs/heads/master: f070304094edb8d516423e79edd27c97ec2020b0 diff --git a/trunk/drivers/md/dm-raid1.c b/trunk/drivers/md/dm-raid1.c index 6d66ddf39071..ddda531723dc 100644 --- a/trunk/drivers/md/dm-raid1.c +++ b/trunk/drivers/md/dm-raid1.c @@ -465,9 +465,17 @@ static void map_region(struct dm_io_region *io, struct mirror *m, static void hold_bio(struct mirror_set *ms, struct bio *bio) { /* - * If device is suspended, complete the bio. + * Lock is required to avoid race condition during suspend + * process. */ + spin_lock_irq(&ms->lock); + if (atomic_read(&ms->suspend)) { + spin_unlock_irq(&ms->lock); + + /* + * If device is suspended, complete the bio. + */ if (dm_noflush_suspending(ms->ti)) bio_endio(bio, DM_ENDIO_REQUEUE); else @@ -478,7 +486,6 @@ static void hold_bio(struct mirror_set *ms, struct bio *bio) /* * Hold bio until the suspend is complete. */ - spin_lock_irq(&ms->lock); bio_list_add(&ms->holds, bio); spin_unlock_irq(&ms->lock); } @@ -1260,6 +1267,20 @@ static void mirror_presuspend(struct dm_target *ti) atomic_set(&ms->suspend, 1); + /* + * Process bios in the hold list to start recovery waiting + * for bios in the hold list. After the process, no bio has + * a chance to be added in the hold list because ms->suspend + * is set. + */ + spin_lock_irq(&ms->lock); + holds = ms->holds; + bio_list_init(&ms->holds); + spin_unlock_irq(&ms->lock); + + while ((bio = bio_list_pop(&holds))) + hold_bio(ms, bio); + /* * We must finish up all the work that we've * generated (i.e. recovery work). @@ -1280,22 +1301,6 @@ static void mirror_presuspend(struct dm_target *ti) * we know that all of our I/O has been pushed. */ flush_workqueue(ms->kmirrord_wq); - - /* - * Now set ms->suspend is set and the workqueue flushed, no more - * entries can be added to ms->hold list, so process it. - * - * Bios can still arrive concurrently with or after this - * presuspend function, but they cannot join the hold list - * because ms->suspend is set. - */ - spin_lock_irq(&ms->lock); - holds = ms->holds; - bio_list_init(&ms->holds); - spin_unlock_irq(&ms->lock); - - while ((bio = bio_list_pop(&holds))) - hold_bio(ms, bio); } static void mirror_postsuspend(struct dm_target *ti)