From: Ilya Yanok <yanok@emcraft.com>
To: linux-raid@vger.kernel.org
Cc: linuxppc-dev@ozlabs.org, dzu@denx.de, wd@denx.de,
Ilya Yanok <yanok@emcraft.com>
Subject: [PATCH 08/11] md: asynchronous handle_parity_check6
Date: Thu, 13 Nov 2008 18:16:01 +0300 [thread overview]
Message-ID: <1226589364-5619-9-git-send-email-yanok@emcraft.com> (raw)
In-Reply-To: <1226589364-5619-1-git-send-email-yanok@emcraft.com>
This patch introduces the state machine for handling the RAID-6 parities
check and repair functionality.
Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
Signed-off-by: Ilya Yanok <yanok@emcraft.com>
---
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();
}
}
--
1.5.6.1
next prev parent reply other threads:[~2008-11-13 15:16 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-11-13 15:15 [RFC PATCH 00/11] md: support for asynchronous execution of RAID6 operations Ilya Yanok
2008-11-13 15:15 ` [PATCH 01/11] async_tx: don't use src_list argument of async_xor() for dma addresses Ilya Yanok
2008-11-15 0:42 ` Dan Williams
2008-11-15 7:12 ` Benjamin Herrenschmidt
2008-11-13 15:15 ` [PATCH 02/11] async_tx: add support for asynchronous GF multiplication Ilya Yanok
2008-11-15 1:28 ` Dan Williams
2008-11-27 1:26 ` Re[2]: " Yuri Tikhonov
2008-11-28 21:18 ` Dan Williams
2008-11-13 15:15 ` [PATCH 03/11] async_tx: add support for asynchronous RAID6 recovery operations Ilya Yanok
2008-11-13 15:15 ` [PATCH 04/11] md: run stripe operations outside the lock Ilya Yanok
2008-11-13 15:15 ` [PATCH 05/11] md: common schedule_reconstruction for raid5/6 Ilya Yanok
2008-11-13 15:15 ` [PATCH 06/11] md: change handle_stripe_fill6 to work in asynchronous way Ilya Yanok
2008-11-13 15:16 ` [PATCH 07/11] md: rewrite handle_stripe_dirtying6 " Ilya Yanok
2008-11-13 15:16 ` Ilya Yanok [this message]
2008-11-13 15:16 ` [PATCH 09/11] md: change handle_stripe6 to work asynchronously Ilya Yanok
2008-11-13 15:16 ` [PATCH 10/11] md: remove unused functions Ilya Yanok
2008-11-13 15:16 ` [PATCH 11/11] ppc440spe-adma: ADMA driver for PPC440SP(e) systems Ilya Yanok
2008-11-13 16:03 ` Josh Boyer
2008-11-13 17:50 ` Ilya Yanok
2008-11-13 17:54 ` Josh Boyer
2008-12-09 1:08 ` Re[2]: " Yuri Tikhonov
2009-05-06 15:32 ` 440SPE ADMA driver Tirumala Reddy Marri
-- strict thread matches above, loose matches on Subject: below --
2008-12-08 21:57 [PATCH 08/11] md: asynchronous handle_parity_check6 Yuri Tikhonov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1226589364-5619-9-git-send-email-yanok@emcraft.com \
--to=yanok@emcraft.com \
--cc=dzu@denx.de \
--cc=linux-raid@vger.kernel.org \
--cc=linuxppc-dev@ozlabs.org \
--cc=wd@denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).