From 474af965fe0005b334cabdb2904a7d712c21489b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Wed, 27 Jul 2011 11:00:36 +1000 Subject: md/raid5: move some more common code into handle_stripe The RAID6 version of this code is usable for RAID5 providing: - we test "conf->max_degraded" rather than "2" as appropriate - we make sure s->failed_num[1] is meaningful (and not '-1') when s->failed > 1 The 'return 1' must become 'goto finish' in the new location. Signed-off-by: NeilBrown Reviewed-by: Namhyung Kim --- drivers/md/raid5.c | 180 ++++++++++++++++++++--------------------------------- 1 file changed, 67 insertions(+), 113 deletions(-) (limited to 'drivers/md/raid5.c') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index cf60b15b4e3a..63acc51e8406 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2968,63 +2968,14 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s) if (test_bit(R5_ReadError, &dev->flags)) clear_bit(R5_Insync, &dev->flags); if (!test_bit(R5_Insync, &dev->flags)) { + if (s->failed < 2) + s->failed_num[s->failed] = i; s->failed++; - s->failed_num[0] = i; } } spin_unlock_irq(&conf->device_lock); rcu_read_unlock(); - if (unlikely(s->blocked_rdev)) { - if (s->syncing || s->expanding || s->expanded || - s->to_write || s->written) { - set_bit(STRIPE_HANDLE, &sh->state); - return 1; - } - /* There is nothing for the blocked_rdev to block */ - rdev_dec_pending(s->blocked_rdev, conf->mddev); - s->blocked_rdev = NULL; - } - - if (s->to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { - set_bit(STRIPE_OP_BIOFILL, &s->ops_request); - set_bit(STRIPE_BIOFILL_RUN, &sh->state); - } - - pr_debug("locked=%d uptodate=%d to_read=%d" - " to_write=%d failed=%d failed_num=%d\n", - s->locked, s->uptodate, s->to_read, s->to_write, - s->failed, s->failed_num[0]); - /* check if the array has lost two devices and, if so, some requests might - * need to be failed - */ - if (s->failed > 1 && s->to_read+s->to_write+s->written) - handle_failed_stripe(conf, sh, s, disks, &s->return_bi); - if (s->failed > 1 && s->syncing) { - md_done_sync(conf->mddev, STRIPE_SECTORS,0); - clear_bit(STRIPE_SYNCING, &sh->state); - s->syncing = 0; - } - - /* might be able to return some write requests if the parity block - * is safe, or on a failed drive - */ - dev = &sh->dev[sh->pd_idx]; - if (s->written && - ((test_bit(R5_Insync, &dev->flags) && - !test_bit(R5_LOCKED, &dev->flags) && - test_bit(R5_UPTODATE, &dev->flags)) || - (s->failed == 1 && s->failed_num[0] == sh->pd_idx))) - handle_stripe_clean_event(conf, sh, disks, &s->return_bi); - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (s->to_read || s->non_overwrite || - (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) - handle_stripe_fill(sh, s, disks); - return 0; } @@ -3032,8 +2983,8 @@ static int handle_stripe6(struct stripe_head *sh, struct stripe_head_state *s) { raid5_conf_t *conf = sh->raid_conf; int disks = sh->disks; - int i, pd_idx = sh->pd_idx, qd_idx = sh->qd_idx; - struct r5dev *dev, *pdev, *qdev; + struct r5dev *dev; + int i; /* Now to look around and see what can be done */ @@ -3107,65 +3058,6 @@ static int handle_stripe6(struct stripe_head *sh, struct stripe_head_state *s) spin_unlock_irq(&conf->device_lock); rcu_read_unlock(); - if (unlikely(s->blocked_rdev)) { - if (s->syncing || s->expanding || s->expanded || - s->to_write || s->written) { - set_bit(STRIPE_HANDLE, &sh->state); - return 1; - } - /* There is nothing for the blocked_rdev to block */ - rdev_dec_pending(s->blocked_rdev, conf->mddev); - s->blocked_rdev = NULL; - } - - if (s->to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { - set_bit(STRIPE_OP_BIOFILL, &s->ops_request); - set_bit(STRIPE_BIOFILL_RUN, &sh->state); - } - - pr_debug("locked=%d uptodate=%d to_read=%d" - " to_write=%d failed=%d failed_num=%d,%d\n", - s->locked, s->uptodate, s->to_read, s->to_write, s->failed, - s->failed_num[0], s->failed_num[1]); - /* check if the array has lost >2 devices and, if so, some requests - * might need to be failed - */ - if (s->failed > 2 && s->to_read+s->to_write+s->written) - handle_failed_stripe(conf, sh, s, disks, &s->return_bi); - if (s->failed > 2 && s->syncing) { - md_done_sync(conf->mddev, STRIPE_SECTORS,0); - clear_bit(STRIPE_SYNCING, &sh->state); - s->syncing = 0; - } - - /* - * might be able to return some write requests if the parity blocks - * are safe, or on a failed drive - */ - pdev = &sh->dev[pd_idx]; - s->p_failed = (s->failed >= 1 && s->failed_num[0] == pd_idx) - || (s->failed >= 2 && s->failed_num[1] == pd_idx); - qdev = &sh->dev[qd_idx]; - s->q_failed = (s->failed >= 1 && s->failed_num[0] == qd_idx) - || (s->failed >= 2 && s->failed_num[1] == qd_idx); - - if (s->written && - (s->p_failed || ((test_bit(R5_Insync, &pdev->flags) - && !test_bit(R5_LOCKED, &pdev->flags) - && test_bit(R5_UPTODATE, &pdev->flags)))) && - (s->q_failed || ((test_bit(R5_Insync, &qdev->flags) - && !test_bit(R5_LOCKED, &qdev->flags) - && test_bit(R5_UPTODATE, &qdev->flags))))) - handle_stripe_clean_event(conf, sh, disks, &s->return_bi); - - /* Now we might consider reading some blocks, either to check/generate - * parity, or to satisfy requests - * or to load a block that is being partially written. - */ - if (s->to_read || s->non_overwrite || (s->to_write && s->failed) || - (s->syncing && (s->uptodate + s->compute < disks)) || s->expanding) - handle_stripe_fill(sh, s, disks); - return 0; } @@ -3173,10 +3065,11 @@ static void handle_stripe(struct stripe_head *sh) { struct stripe_head_state s; int done; + raid5_conf_t *conf = sh->raid_conf; int i; int prexor; int disks = sh->disks; - raid5_conf_t *conf = sh->raid_conf; + struct r5dev *pdev, *qdev; clear_bit(STRIPE_HANDLE, &sh->state); if (test_and_set_bit(STRIPE_ACTIVE, &sh->state)) { @@ -3213,6 +3106,67 @@ static void handle_stripe(struct stripe_head *sh) if (done) goto finish; + if (unlikely(s.blocked_rdev)) { + if (s.syncing || s.expanding || s.expanded || + s.to_write || s.written) { + set_bit(STRIPE_HANDLE, &sh->state); + goto finish; + } + /* There is nothing for the blocked_rdev to block */ + rdev_dec_pending(s.blocked_rdev, conf->mddev); + s.blocked_rdev = NULL; + } + + if (s.to_fill && !test_bit(STRIPE_BIOFILL_RUN, &sh->state)) { + set_bit(STRIPE_OP_BIOFILL, &s.ops_request); + set_bit(STRIPE_BIOFILL_RUN, &sh->state); + } + + pr_debug("locked=%d uptodate=%d to_read=%d" + " to_write=%d failed=%d failed_num=%d,%d\n", + s.locked, s.uptodate, s.to_read, s.to_write, s.failed, + s.failed_num[0], s.failed_num[1]); + /* check if the array has lost more than max_degraded devices and, + * if so, some requests might need to be failed. + */ + if (s.failed > conf->max_degraded && s.to_read+s.to_write+s.written) + handle_failed_stripe(conf, sh, &s, disks, &s.return_bi); + if (s.failed > conf->max_degraded && s.syncing) { + md_done_sync(conf->mddev, STRIPE_SECTORS, 0); + clear_bit(STRIPE_SYNCING, &sh->state); + s.syncing = 0; + } + + /* + * might be able to return some write requests if the parity blocks + * are safe, or on a failed drive + */ + pdev = &sh->dev[sh->pd_idx]; + s.p_failed = (s.failed >= 1 && s.failed_num[0] == sh->pd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->pd_idx); + qdev = &sh->dev[sh->qd_idx]; + s.q_failed = (s.failed >= 1 && s.failed_num[0] == sh->qd_idx) + || (s.failed >= 2 && s.failed_num[1] == sh->qd_idx) + || conf->level < 6; + + if (s.written && + (s.p_failed || ((test_bit(R5_Insync, &pdev->flags) + && !test_bit(R5_LOCKED, &pdev->flags) + && test_bit(R5_UPTODATE, &pdev->flags)))) && + (s.q_failed || ((test_bit(R5_Insync, &qdev->flags) + && !test_bit(R5_LOCKED, &qdev->flags) + && test_bit(R5_UPTODATE, &qdev->flags))))) + handle_stripe_clean_event(conf, sh, disks, &s.return_bi); + + /* Now we might consider reading some blocks, either to check/generate + * parity, or to satisfy requests + * or to load a block that is being partially written. + */ + if (s.to_read || s.non_overwrite + || (conf->level == 6 && s.to_write && s.failed) + || (s.syncing && (s.uptodate + s.compute < disks)) || s.expanding) + handle_stripe_fill(sh, &s, disks); + /* Now we check to see if any write operations have recently * completed */ -- cgit v1.2.3