summaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorshli@kernel.org <shli@kernel.org>2014-12-14 20:57:03 -0500
committerNeilBrown <neilb@suse.de>2015-04-21 18:00:41 -0400
commit72ac733015bbdc0356ba3e92c52137a265910a91 (patch)
tree20dfdc319ebbd53033f325017f24b5ad92970c31 /drivers/md/raid5.c
parent59fc630b8b5f9f21c8ce3ba153341c107dce1b0c (diff)
raid5: handle io error of batch list
If io error happens in any stripe of a batch list, the batch list will be split, then normal process will run for the stripes in the list. Signed-off-by: Shaohua Li <shli@fusionio.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 717189e74243..54f3cb312b42 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -1070,6 +1070,9 @@ again:
1070 pr_debug("skip op %ld on disc %d for sector %llu\n", 1070 pr_debug("skip op %ld on disc %d for sector %llu\n",
1071 bi->bi_rw, i, (unsigned long long)sh->sector); 1071 bi->bi_rw, i, (unsigned long long)sh->sector);
1072 clear_bit(R5_LOCKED, &sh->dev[i].flags); 1072 clear_bit(R5_LOCKED, &sh->dev[i].flags);
1073 if (sh->batch_head)
1074 set_bit(STRIPE_BATCH_ERR,
1075 &sh->batch_head->state);
1073 set_bit(STRIPE_HANDLE, &sh->state); 1076 set_bit(STRIPE_HANDLE, &sh->state);
1074 } 1077 }
1075 1078
@@ -2380,6 +2383,9 @@ static void raid5_end_write_request(struct bio *bi, int error)
2380 } 2383 }
2381 rdev_dec_pending(rdev, conf->mddev); 2384 rdev_dec_pending(rdev, conf->mddev);
2382 2385
2386 if (sh->batch_head && !uptodate)
2387 set_bit(STRIPE_BATCH_ERR, &sh->batch_head->state);
2388
2383 if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags)) 2389 if (!test_and_clear_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags))
2384 clear_bit(R5_LOCKED, &sh->dev[i].flags); 2390 clear_bit(R5_LOCKED, &sh->dev[i].flags);
2385 set_bit(STRIPE_HANDLE, &sh->state); 2391 set_bit(STRIPE_HANDLE, &sh->state);
@@ -4124,6 +4130,46 @@ static int clear_batch_ready(struct stripe_head *sh)
4124 return 0; 4130 return 0;
4125} 4131}
4126 4132
4133static void check_break_stripe_batch_list(struct stripe_head *sh)
4134{
4135 struct stripe_head *head_sh, *next;
4136 int i;
4137
4138 if (!test_and_clear_bit(STRIPE_BATCH_ERR, &sh->state))
4139 return;
4140
4141 head_sh = sh;
4142 do {
4143 sh = list_first_entry(&sh->batch_list,
4144 struct stripe_head, batch_list);
4145 BUG_ON(sh == head_sh);
4146 } while (!test_bit(STRIPE_DEGRADED, &sh->state));
4147
4148 while (sh != head_sh) {
4149 next = list_first_entry(&sh->batch_list,
4150 struct stripe_head, batch_list);
4151 list_del_init(&sh->batch_list);
4152
4153 sh->state = head_sh->state & ~((1 << STRIPE_ACTIVE) |
4154 (1 << STRIPE_PREREAD_ACTIVE) |
4155 (1 << STRIPE_DEGRADED));
4156 sh->check_state = head_sh->check_state;
4157 sh->reconstruct_state = head_sh->reconstruct_state;
4158 for (i = 0; i < sh->disks; i++)
4159 sh->dev[i].flags = head_sh->dev[i].flags &
4160 (~((1 << R5_WriteError) | (1 << R5_Overlap)));
4161
4162 spin_lock_irq(&sh->stripe_lock);
4163 sh->batch_head = NULL;
4164 spin_unlock_irq(&sh->stripe_lock);
4165
4166 set_bit(STRIPE_HANDLE, &sh->state);
4167 release_stripe(sh);
4168
4169 sh = next;
4170 }
4171}
4172
4127static void handle_stripe(struct stripe_head *sh) 4173static void handle_stripe(struct stripe_head *sh)
4128{ 4174{
4129 struct stripe_head_state s; 4175 struct stripe_head_state s;
@@ -4146,6 +4192,8 @@ static void handle_stripe(struct stripe_head *sh)
4146 return; 4192 return;
4147 } 4193 }
4148 4194
4195 check_break_stripe_batch_list(sh);
4196
4149 if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { 4197 if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
4150 spin_lock(&sh->stripe_lock); 4198 spin_lock(&sh->stripe_lock);
4151 /* Cannot process 'sync' concurrently with 'discard' */ 4199 /* Cannot process 'sync' concurrently with 'discard' */