aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-raid1.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2009-12-10 18:52:06 -0500
committerAlasdair G Kergon <agk@redhat.com>2009-12-10 18:52:06 -0500
commit929be8fcb4b4b65d038e73d3bb34715851a95ca2 (patch)
tree7c008317d90232b5b2d3869b9fa68c1ec023d7f6 /drivers/md/dm-raid1.c
parent60f355ead31e2be8d06ac8acb163df91a1c64e3b (diff)
dm raid1: hold all write bios when leg fails
Hold all write bios when leg fails and errors are handled When using a userspace daemon such as dmeventd to handle errors, we must delay completing bios until it has done its job. This patch prevents the following race: - primary leg fails - write "1" fail, the write is held, secondary leg is set default - write "2" goes straight to the secondary leg Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Reviewed-by: Takahiro Yasui <tyasui@redhat.com> Tested-by: Takahiro Yasui <tyasui@redhat.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r--drivers/md/dm-raid1.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index e363335e8d81..f8d7b3aa46c6 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -69,6 +69,7 @@ struct mirror_set {
69 region_t nr_regions; 69 region_t nr_regions;
70 int in_sync; 70 int in_sync;
71 int log_failure; 71 int log_failure;
72 int leg_failure;
72 atomic_t suspend; 73 atomic_t suspend;
73 74
74 atomic_t default_mirror; /* Default mirror */ 75 atomic_t default_mirror; /* Default mirror */
@@ -211,6 +212,8 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
211 struct mirror_set *ms = m->ms; 212 struct mirror_set *ms = m->ms;
212 struct mirror *new; 213 struct mirror *new;
213 214
215 ms->leg_failure = 1;
216
214 /* 217 /*
215 * error_count is used for nothing more than a 218 * error_count is used for nothing more than a
216 * simple way to tell if a device has encountered 219 * simple way to tell if a device has encountered
@@ -734,8 +737,12 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
734 dm_rh_delay(ms->rh, bio); 737 dm_rh_delay(ms->rh, bio);
735 738
736 while ((bio = bio_list_pop(&nosync))) { 739 while ((bio = bio_list_pop(&nosync))) {
737 map_bio(get_default_mirror(ms), bio); 740 if (unlikely(ms->leg_failure) && errors_handled(ms))
738 generic_make_request(bio); 741 hold_bio(ms, bio);
742 else {
743 map_bio(get_default_mirror(ms), bio);
744 generic_make_request(bio);
745 }
739 } 746 }
740} 747}
741 748
@@ -848,6 +855,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
848 ms->nr_regions = dm_sector_div_up(ti->len, region_size); 855 ms->nr_regions = dm_sector_div_up(ti->len, region_size);
849 ms->in_sync = 0; 856 ms->in_sync = 0;
850 ms->log_failure = 0; 857 ms->log_failure = 0;
858 ms->leg_failure = 0;
851 atomic_set(&ms->suspend, 0); 859 atomic_set(&ms->suspend, 0);
852 atomic_set(&ms->default_mirror, DEFAULT_MIRROR); 860 atomic_set(&ms->default_mirror, DEFAULT_MIRROR);
853 861