[PATCH 06/12] md: move raid5 compute block operations to raid5_run_ops
From: Dan Williams <[EMAIL PROTECTED]> handle_stripe sets STRIPE_OP_COMPUTE_BLK to request servicing from raid5_run_ops. It also sets a flag for the block being computed to let other parts of handle_stripe submit dependent operations. raid5_run_ops guarantees that the compute operation completes before any dependent operation starts. Signed-off-by: Dan Williams <[EMAIL PROTECTED]> --- drivers/md/raid5.c | 125 +++- 1 files changed, 93 insertions(+), 32 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2390657..279a30c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1980,7 +1980,7 @@ static void handle_stripe5(struct stripe_head *sh) int i; int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; - int non_overwrite = 0; + int compute=0, req_compute=0, non_overwrite=0; int failed_num=0; struct r5dev *dev; unsigned long pending=0; @@ -2032,8 +2032,8 @@ static void handle_stripe5(struct stripe_head *sh) /* now count some things */ if (test_bit(R5_LOCKED, >flags)) locked++; if (test_bit(R5_UPTODATE, >flags)) uptodate++; + if (test_bit(R5_Wantcompute, >flags)) BUG_ON(++compute > 1); - if (dev->toread) to_read++; if (dev->towrite) { to_write++; @@ -2188,31 +2188,82 @@ static void handle_stripe5(struct stripe_head *sh) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (syncing && (uptodate < disks)) || expanding) { - for (i=disks; i--;) { - dev = >dev[i]; - if (!test_bit(R5_LOCKED, >flags) && !test_bit(R5_UPTODATE, >flags) && - (dev->toread || -(dev->towrite && !test_bit(R5_OVERWRITE, >flags)) || -syncing || -expanding || -(failed && (sh->dev[failed_num].toread || -(sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, >dev[failed_num].flags - ) - ) { - /* we would like to get this block, possibly -* by computing it, but we might not be able to + if (to_read || non_overwrite || (syncing && (uptodate + compute < disks)) || expanding || + test_bit(STRIPE_OP_COMPUTE_BLK, >ops.pending)) { + + /* Clear completed compute operations. Parity recovery +* (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled +* later on in this routine +*/ + if (test_bit(STRIPE_OP_COMPUTE_BLK, >ops.complete) && + !test_bit(STRIPE_OP_MOD_REPAIR_PD, >ops.pending)) { + clear_bit(STRIPE_OP_COMPUTE_BLK, >ops.complete); + clear_bit(STRIPE_OP_COMPUTE_BLK, >ops.ack); + clear_bit(STRIPE_OP_COMPUTE_BLK, >ops.pending); + } + + /* look for blocks to read/compute, skip this if a compute +* is already in flight, or if the stripe contents are in the +* midst of changing due to a write +*/ + if (!test_bit(STRIPE_OP_COMPUTE_BLK, >ops.pending) && + !test_bit(STRIPE_OP_PREXOR, >ops.pending) && + !test_bit(STRIPE_OP_POSTXOR, >ops.pending)) { + for (i=disks; i--;) { + dev = >dev[i]; + + /* don't schedule compute operations or reads on +* the parity block while a check is in flight */ - if (uptodate == disks-1) { - PRINTK("Computing block %d\n", i); - compute_block(sh, i); - uptodate++; - } else if (test_bit(R5_Insync, >flags)) { - set_bit(R5_LOCKED, >flags); - set_bit(R5_Wantread, >flags); - locked++; - PRINTK("Reading block %d (sync=%d)\n", - i, syncing); + if ((i == sh->pd_idx) && test_bit(STRIPE_OP_CHECK, >ops.pending)) + continue; + + if (!test_bit(R5_LOCKED, >flags) && !test_bit(R5_UPTODATE, >flags) && +
[PATCH 06/12] md: move raid5 compute block operations to raid5_run_ops
From: Dan Williams [EMAIL PROTECTED] handle_stripe sets STRIPE_OP_COMPUTE_BLK to request servicing from raid5_run_ops. It also sets a flag for the block being computed to let other parts of handle_stripe submit dependent operations. raid5_run_ops guarantees that the compute operation completes before any dependent operation starts. Signed-off-by: Dan Williams [EMAIL PROTECTED] --- drivers/md/raid5.c | 125 +++- 1 files changed, 93 insertions(+), 32 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2390657..279a30c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1980,7 +1980,7 @@ static void handle_stripe5(struct stripe_head *sh) int i; int syncing, expanding, expanded; int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0; - int non_overwrite = 0; + int compute=0, req_compute=0, non_overwrite=0; int failed_num=0; struct r5dev *dev; unsigned long pending=0; @@ -2032,8 +2032,8 @@ static void handle_stripe5(struct stripe_head *sh) /* now count some things */ if (test_bit(R5_LOCKED, dev-flags)) locked++; if (test_bit(R5_UPTODATE, dev-flags)) uptodate++; + if (test_bit(R5_Wantcompute, dev-flags)) BUG_ON(++compute 1); - if (dev-toread) to_read++; if (dev-towrite) { to_write++; @@ -2188,31 +2188,82 @@ static void handle_stripe5(struct stripe_head *sh) * parity, or to satisfy requests * or to load a block that is being partially written. */ - if (to_read || non_overwrite || (syncing (uptodate disks)) || expanding) { - for (i=disks; i--;) { - dev = sh-dev[i]; - if (!test_bit(R5_LOCKED, dev-flags) !test_bit(R5_UPTODATE, dev-flags) - (dev-toread || -(dev-towrite !test_bit(R5_OVERWRITE, dev-flags)) || -syncing || -expanding || -(failed (sh-dev[failed_num].toread || -(sh-dev[failed_num].towrite !test_bit(R5_OVERWRITE, sh-dev[failed_num].flags - ) - ) { - /* we would like to get this block, possibly -* by computing it, but we might not be able to + if (to_read || non_overwrite || (syncing (uptodate + compute disks)) || expanding || + test_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.pending)) { + + /* Clear completed compute operations. Parity recovery +* (STRIPE_OP_MOD_REPAIR_PD) implies a write-back which is handled +* later on in this routine +*/ + if (test_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.complete) + !test_bit(STRIPE_OP_MOD_REPAIR_PD, sh-ops.pending)) { + clear_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.complete); + clear_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.ack); + clear_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.pending); + } + + /* look for blocks to read/compute, skip this if a compute +* is already in flight, or if the stripe contents are in the +* midst of changing due to a write +*/ + if (!test_bit(STRIPE_OP_COMPUTE_BLK, sh-ops.pending) + !test_bit(STRIPE_OP_PREXOR, sh-ops.pending) + !test_bit(STRIPE_OP_POSTXOR, sh-ops.pending)) { + for (i=disks; i--;) { + dev = sh-dev[i]; + + /* don't schedule compute operations or reads on +* the parity block while a check is in flight */ - if (uptodate == disks-1) { - PRINTK(Computing block %d\n, i); - compute_block(sh, i); - uptodate++; - } else if (test_bit(R5_Insync, dev-flags)) { - set_bit(R5_LOCKED, dev-flags); - set_bit(R5_Wantread, dev-flags); - locked++; - PRINTK(Reading block %d (sync=%d)\n, - i, syncing); + if ((i == sh-pd_idx) test_bit(STRIPE_OP_CHECK, sh-ops.pending)) + continue; + + if (!test_bit(R5_LOCKED, dev-flags) !test_bit(R5_UPTODATE, dev-flags) +