aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/raid5.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-05-20 22:00:47 -0400
committerNeilBrown <neilb@suse.de>2015-05-27 21:36:25 -0400
commitfb642b92c267beeefd352af9bc461eac93a7552c (patch)
treeb65a1548db0ed487de3fe42ac8a072c3a8a59c05 /drivers/md/raid5.c
parent4e3d62ff4976f26d22b8b91572a49136bb3a23f1 (diff)
md/raid5: duplicate some more handle_stripe_clean_event code in break_stripe_batch_list
break_stripe_batch list didn't clear head_sh->batch_head. This was probably a bug. Also clear all R5_Overlap flags and if any were cleared, wake up 'wait_for_overlap'. This isn't always necessary but the worst effect is a little extra checking for code that is waiting on wait_for_overlap. Also, don't use wake_up_nr() because that does the wrong thing if 'nr' is zero, and it number of flags cleared doesn't strongly correlate with the number of threads to wake. Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r--drivers/md/raid5.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index fc5c4039c394..6de2e1edd492 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -3557,7 +3557,8 @@ unhash:
3557 spin_lock_irq(&head_sh->stripe_lock); 3557 spin_lock_irq(&head_sh->stripe_lock);
3558 head_sh->batch_head = NULL; 3558 head_sh->batch_head = NULL;
3559 spin_unlock_irq(&head_sh->stripe_lock); 3559 spin_unlock_irq(&head_sh->stripe_lock);
3560 wake_up_nr(&conf->wait_for_overlap, wakeup_nr); 3560 if (wakeup_nr)
3561 wake_up(&conf->wait_for_overlap);
3561 if (head_sh->state & STRIPE_EXPAND_SYNC_FLAG) 3562 if (head_sh->state & STRIPE_EXPAND_SYNC_FLAG)
3562 set_bit(STRIPE_HANDLE, &head_sh->state); 3563 set_bit(STRIPE_HANDLE, &head_sh->state);
3563} 3564}
@@ -4238,6 +4239,7 @@ static void break_stripe_batch_list(struct stripe_head *head_sh)
4238{ 4239{
4239 struct stripe_head *sh, *next; 4240 struct stripe_head *sh, *next;
4240 int i; 4241 int i;
4242 int do_wakeup = 0;
4241 4243
4242 list_for_each_entry_safe(sh, next, &head_sh->batch_list, batch_list) { 4244 list_for_each_entry_safe(sh, next, &head_sh->batch_list, batch_list) {
4243 4245
@@ -4250,10 +4252,12 @@ static void break_stripe_batch_list(struct stripe_head *head_sh)
4250 STRIPE_EXPAND_SYNC_FLAG)); 4252 STRIPE_EXPAND_SYNC_FLAG));
4251 sh->check_state = head_sh->check_state; 4253 sh->check_state = head_sh->check_state;
4252 sh->reconstruct_state = head_sh->reconstruct_state; 4254 sh->reconstruct_state = head_sh->reconstruct_state;
4253 for (i = 0; i < sh->disks; i++) 4255 for (i = 0; i < sh->disks; i++) {
4256 if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
4257 do_wakeup = 1;
4254 sh->dev[i].flags = head_sh->dev[i].flags & 4258 sh->dev[i].flags = head_sh->dev[i].flags &
4255 (~((1 << R5_WriteError) | (1 << R5_Overlap))); 4259 (~((1 << R5_WriteError) | (1 << R5_Overlap)));
4256 4260 }
4257 spin_lock_irq(&sh->stripe_lock); 4261 spin_lock_irq(&sh->stripe_lock);
4258 sh->batch_head = NULL; 4262 sh->batch_head = NULL;
4259 spin_unlock_irq(&sh->stripe_lock); 4263 spin_unlock_irq(&sh->stripe_lock);
@@ -4261,6 +4265,15 @@ static void break_stripe_batch_list(struct stripe_head *head_sh)
4261 set_bit(STRIPE_HANDLE, &sh->state); 4265 set_bit(STRIPE_HANDLE, &sh->state);
4262 release_stripe(sh); 4266 release_stripe(sh);
4263 } 4267 }
4268 spin_lock_irq(&head_sh->stripe_lock);
4269 head_sh->batch_head = NULL;
4270 spin_unlock_irq(&head_sh->stripe_lock);
4271 for (i = 0; i < head_sh->disks; i++)
4272 if (test_and_clear_bit(R5_Overlap, &head_sh->dev[i].flags))
4273 do_wakeup = 1;
4274
4275 if (do_wakeup)
4276 wake_up(&head_sh->raid_conf->wait_for_overlap);
4264} 4277}
4265 4278
4266static void handle_stripe(struct stripe_head *sh) 4279static void handle_stripe(struct stripe_head *sh)