diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
| -rw-r--r-- | drivers/md/dm-raid1.c | 12 | 
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c index e363335e8d8..f8d7b3aa46c 100644 --- a/drivers/md/dm-raid1.c +++ b/drivers/md/dm-raid1.c @@ -69,6 +69,7 @@ struct mirror_set {  	region_t nr_regions;  	int in_sync;  	int log_failure; +	int leg_failure;  	atomic_t suspend;  	atomic_t default_mirror;	/* Default mirror */ @@ -211,6 +212,8 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)  	struct mirror_set *ms = m->ms;  	struct mirror *new; +	ms->leg_failure = 1; +  	/*  	 * error_count is used for nothing more than a  	 * 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)  		dm_rh_delay(ms->rh, bio);  	while ((bio = bio_list_pop(&nosync))) { -		map_bio(get_default_mirror(ms), bio); -		generic_make_request(bio); +		if (unlikely(ms->leg_failure) && errors_handled(ms)) +			hold_bio(ms, bio); +		else { +			map_bio(get_default_mirror(ms), bio); +			generic_make_request(bio); +		}  	}  } @@ -848,6 +855,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,  	ms->nr_regions = dm_sector_div_up(ti->len, region_size);  	ms->in_sync = 0;  	ms->log_failure = 0; +	ms->leg_failure = 0;  	atomic_set(&ms->suspend, 0);  	atomic_set(&ms->default_mirror, DEFAULT_MIRROR);  |