From patchwork Thu Nov 13 15:16:01 2008 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilya Yanok X-Patchwork-Id: 8584 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from ozlabs.org (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id E00C1DE90E for ; Fri, 14 Nov 2008 02:19:27 +1100 (EST) X-Original-To: linuxppc-dev@ozlabs.org Delivered-To: linuxppc-dev@ozlabs.org Received: from ocean.emcraft.com (ocean.emcraft.com [213.221.7.182]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9BDBBDDED8 for ; Fri, 14 Nov 2008 02:16:57 +1100 (EST) Received: from [172.17.0.9] (helo=localhost.localdomain) by ocean.emcraft.com with esmtp (Exim 4.43) id 1L0dwA-00055K-MP; Thu, 13 Nov 2008 18:16:51 +0300 From: Ilya Yanok To: linux-raid@vger.kernel.org Subject: [PATCH 08/11] md: asynchronous handle_parity_check6 Date: Thu, 13 Nov 2008 18:16:01 +0300 Message-Id: <1226589364-5619-9-git-send-email-yanok@emcraft.com> X-Mailer: git-send-email 1.5.6.5 In-Reply-To: <1226589364-5619-1-git-send-email-yanok@emcraft.com> References: <1226589364-5619-1-git-send-email-yanok@emcraft.com> X-Spam-Score: -4.3 (----) X-Spam-Report: Spam detection software, running on the system "pacific.emcraft.com", has identified this incoming email as possible spam. The original message has been attached to this so you can view it (if it isn't spam) or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This patch introduces the state machine for handling the RAID-6 parities check and repair functionality. Signed-off-by: Yuri Tikhonov Signed-off-by: Ilya Yanok --- drivers/md/raid5.c | 163 +++++++++++++++++++++++++++++++++++ 1 files changed, 110 insertions(+), 53 deletions(-) [...] Content analysis details: (-4.3 points, 2.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -1.8 ALL_TRUSTED Passed through trusted hosts only via SMTP -2.6 BAYES_00 BODY: Bayesian spam probability is 0 to 1% [score: 0.0000] 0.1 AWL AWL: From: address is in the auto white-list Cc: linuxppc-dev@ozlabs.org, dzu@denx.de, wd@denx.de, Ilya Yanok X-BeenThere: linuxppc-dev@ozlabs.org X-Mailman-Version: 2.1.11 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@ozlabs.org This patch introduces the state machine for handling the RAID-6 parities check and repair functionality. Signed-off-by: Yuri Tikhonov Signed-off-by: Ilya Yanok --- drivers/md/raid5.c | 163 +++++++++++++++++++++++++++++++++++----------------- 1 files changed, 110 insertions(+), 53 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index c1125cd..963bc4b 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2623,91 +2623,148 @@ static void handle_parity_checks6(raid5_conf_t *conf, struct stripe_head *sh, struct r6_state *r6s, struct page *tmp_page, int disks) { - int update_p = 0, update_q = 0; - struct r5dev *dev; + int i; + struct r5dev *devs[2] = {NULL, NULL}; int pd_idx = sh->pd_idx; int qd_idx = r6s->qd_idx; set_bit(STRIPE_HANDLE, &sh->state); BUG_ON(s->failed > 2); - BUG_ON(s->uptodate < disks); + /* Want to check and possibly repair P and Q. * However there could be one 'failed' device, in which * case we can only check one of them, possibly using the * other to generate missing data */ - /* If !tmp_page, we cannot do the calculations, - * but as we have set STRIPE_HANDLE, we will soon be called - * by stripe_handle with a tmp_page - just wait until then. - */ - if (tmp_page) { + switch (sh->check_state) { + case check_state_idle: + /* start a new check operation if there are < 2 failures */ if (s->failed == r6s->q_failed) { /* The only possible failed device holds 'Q', so it * makes sense to check P (If anything else were failed, * we would have used P to recreate it). */ - compute_block_1(sh, pd_idx, 1); - if (!page_is_zero(sh->dev[pd_idx].page)) { - compute_block_1(sh, pd_idx, 0); - update_p = 1; - } + sh->check_state = check_state_run; + set_bit(STRIPE_OP_CHECK_PP, &s->ops_request); + clear_bit(R5_UPTODATE, &sh->dev[pd_idx].flags); + s->uptodate--; } if (!r6s->q_failed && s->failed < 2) { /* q is not failed, and we didn't use it to generate * anything, so it makes sense to check it */ - memcpy(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE); - compute_parity6(sh, UPDATE_PARITY); - if (memcmp(page_address(tmp_page), - page_address(sh->dev[qd_idx].page), - STRIPE_SIZE) != 0) { - clear_bit(STRIPE_INSYNC, &sh->state); - update_q = 1; - } + sh->check_state = check_state_run; + set_bit(STRIPE_OP_CHECK_QP, &s->ops_request); + clear_bit(R5_UPTODATE, &sh->dev[qd_idx].flags); + s->uptodate--; } - if (update_p || update_q) { - conf->mddev->resync_mismatches += STRIPE_SECTORS; - if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) - /* don't try to repair!! */ - update_p = update_q = 0; + if (sh->check_state == check_state_run) { + break; } - /* now write out any block on a failed drive, - * or P or Q if they need it - */ + /* we have 2-disk failure */ + BUG_ON(s->failed != 2); + devs[0] = &sh->dev[r6s->failed_num[0]]; + devs[1] = &sh->dev[r6s->failed_num[1]]; + /* fall through */ + case check_state_compute_result: + sh->check_state = check_state_idle; - if (s->failed == 2) { - dev = &sh->dev[r6s->failed_num[1]]; - s->locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); + BUG_ON((devs[0] && !devs[1]) || + (!devs[0] && devs[1])); + + BUG_ON(s->uptodate < (disks - 1)); + + if (!devs[0]) { + if (s->failed >= 1) + devs[0] = &sh->dev[r6s->failed_num[0]]; + else + devs[0] = &sh->dev[pd_idx]; } - if (s->failed >= 1) { - dev = &sh->dev[r6s->failed_num[0]]; - s->locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); + if (!devs[1]) { + if (s->failed >= 2) + devs[1] = &sh->dev[r6s->failed_num[1]]; + else + devs[1] = &sh->dev[qd_idx]; } - if (update_p) { - dev = &sh->dev[pd_idx]; - s->locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); - } - if (update_q) { - dev = &sh->dev[qd_idx]; - s->locked++; - set_bit(R5_LOCKED, &dev->flags); - set_bit(R5_Wantwrite, &dev->flags); + BUG_ON(!test_bit(R5_UPTODATE, &devs[0]->flags) && + !test_bit(R5_UPTODATE, &devs[1]->flags)); + + /* check that a write has not made the stripe insync */ + if (test_bit(STRIPE_INSYNC, &sh->state)) + break; + + for (i=0; i < 2; i++) { + if (test_bit(R5_UPTODATE, &devs[i]->flags)) { + s->locked++; + set_bit(R5_LOCKED, &devs[i]->flags); + set_bit(R5_Wantwrite, &devs[i]->flags); + } } - clear_bit(STRIPE_DEGRADED, &sh->state); + clear_bit(STRIPE_DEGRADED, &sh->state); set_bit(STRIPE_INSYNC, &sh->state); + break; + case check_state_run: + break; /* we will be called again upon completion */ + case check_state_check_result: + sh->check_state = check_state_idle; + + /* if a failure occurred during the check operation, leave + * STRIPE_INSYNC not set and let the stripe be handled again + */ + if (s->failed > 1) { + break; + } + + /* handle a successful check operation, if parity is correct + * we are done. Otherwise update the mismatch count and repair + * parity if !MD_RECOVERY_CHECK + */ + if (sh->ops.zero_sum_result == 0 && + sh->ops.zero_qsum_result == 0) { + /* both parities are correct */ + if (!s->failed) { + set_bit(STRIPE_INSYNC, &sh->state); + } else { + sh->check_state = check_state_compute_result; + } + } else { + conf->mddev->resync_mismatches += STRIPE_SECTORS; + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + /* don't try to repair!! */ + set_bit(STRIPE_INSYNC, &sh->state); + else { + sh->check_state = check_state_compute_run; + set_bit(STRIPE_COMPUTE_RUN, &sh->state); + set_bit(STRIPE_OP_COMPUTE_BLK, &s->ops_request); + if (sh->ops.zero_sum_result) { + set_bit(R5_Wantcompute, + &sh->dev[pd_idx].flags); + sh->ops.target = pd_idx; + s->uptodate++; + } else + sh->ops.target = -1; + if (sh->ops.zero_qsum_result) { + set_bit(R5_Wantcompute, + &sh->dev[qd_idx].flags); + sh->ops.target2 = qd_idx; + s->uptodate++; + } else + sh->ops.target2 = -1; + } + } + break; + case check_state_compute_run: + break; + default: + printk(KERN_ERR "%s: unknown check_state: %d sector: %llu\n", + __func__, sh->check_state, + (unsigned long long) sh->sector); + BUG(); } }