[PATCH 05/12] md: move write operations to raid5_run_ops
From: Dan Williams <[EMAIL PROTECTED]> handle_stripe sets STRIPE_OP_PREXOR, STRIPE_OP_BIODRAIN, STRIPE_OP_POSTXOR to request a write to the stripe cache. raid5_run_ops is triggerred to run and executes the request outside the stripe lock. Signed-off-by: Dan Williams <[EMAIL PROTECTED]> --- drivers/md/raid5.c | 152 +--- 1 files changed, 131 insertions(+), 21 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2c74f9b..2390657 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1788,7 +1788,75 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) } } +static int handle_write_operations5(struct stripe_head *sh, int rcw, int expand) +{ + int i, pd_idx = sh->pd_idx, disks = sh->disks; + int locked=0; + + if (rcw == 0) { + /* skip the drain operation on an expand */ + if (!expand) { + BUG_ON(test_and_set_bit(STRIPE_OP_BIODRAIN, + >ops.pending)); + sh->ops.count++; + } + + BUG_ON(test_and_set_bit(STRIPE_OP_POSTXOR, >ops.pending)); + sh->ops.count++; + + for (i=disks ; i-- ;) { + struct r5dev *dev = >dev[i]; + + if (dev->towrite) { + set_bit(R5_LOCKED, >flags); + if (!expand) + clear_bit(R5_UPTODATE, >flags); + locked++; + } + } + } else { + BUG_ON(!(test_bit(R5_UPTODATE, >dev[pd_idx].flags) || + test_bit(R5_Wantcompute, >dev[pd_idx].flags))); + + BUG_ON(test_and_set_bit(STRIPE_OP_PREXOR, >ops.pending) || + test_and_set_bit(STRIPE_OP_BIODRAIN, >ops.pending) || + test_and_set_bit(STRIPE_OP_POSTXOR, >ops.pending)); + + sh->ops.count += 3; + + for (i=disks ; i-- ;) { + struct r5dev *dev = >dev[i]; + if (i==pd_idx) + continue; + /* For a read-modify write there may be blocks that are +* locked for reading while others are ready to be written +* so we distinguish these blocks by the R5_Wantprexor bit +*/ + if (dev->towrite && + (test_bit(R5_UPTODATE, >flags) || + test_bit(R5_Wantcompute, >flags))) { + set_bit(R5_Wantprexor, >flags); + set_bit(R5_LOCKED, >flags); + clear_bit(R5_UPTODATE, >flags); + locked++; + } + } + } + + /* keep the parity disk locked while asynchronous operations +* are in flight +*/ + set_bit(R5_LOCKED, >dev[pd_idx].flags); + clear_bit(R5_UPTODATE, >dev[pd_idx].flags); + locked++; + + PRINTK("%s: stripe %llu locked: %d pending: %lx\n", + __FUNCTION__, (unsigned long long)sh->sector, + locked, sh->ops.pending); + + return locked; +} /* * Each stripe/dev can have one or more bion attached. @@ -2151,8 +2219,67 @@ static void handle_stripe5(struct stripe_head *sh) set_bit(STRIPE_HANDLE, >state); } - /* now to consider writing and what else, if anything should be read */ - if (to_write) { + /* Now we check to see if any write operations have recently +* completed +*/ + + /* leave prexor set until postxor is done, allows us to distinguish +* a rmw from a rcw during biodrain +*/ + if (test_bit(STRIPE_OP_PREXOR, >ops.complete) && + test_bit(STRIPE_OP_POSTXOR, >ops.complete)) { + + clear_bit(STRIPE_OP_PREXOR, >ops.complete); + clear_bit(STRIPE_OP_PREXOR, >ops.ack); + clear_bit(STRIPE_OP_PREXOR, >ops.pending); + + for (i=disks; i--;) + clear_bit(R5_Wantprexor, >dev[i].flags); + } + + /* if only POSTXOR is set then this is an 'expand' postxor */ + if (test_bit(STRIPE_OP_BIODRAIN, >ops.complete) && + test_bit(STRIPE_OP_POSTXOR, >ops.complete)) { + + clear_bit(STRIPE_OP_BIODRAIN, >ops.complete); + clear_bit(STRIPE_OP_BIODRAIN, >ops.ack); + clear_bit(STRIPE_OP_BIODRAIN, >ops.pending); + + clear_bit(STRIPE_OP_POSTXOR, >ops.complete); + clear_bit(STRIPE_OP_POSTXOR, >ops.ack); + clear_bit(STRIPE_OP_POSTXOR, >ops.pending); + + /* All the 'written' buffers and the parity block are ready to be +
[PATCH 05/12] md: move write operations to raid5_run_ops
From: Dan Williams [EMAIL PROTECTED] handle_stripe sets STRIPE_OP_PREXOR, STRIPE_OP_BIODRAIN, STRIPE_OP_POSTXOR to request a write to the stripe cache. raid5_run_ops is triggerred to run and executes the request outside the stripe lock. Signed-off-by: Dan Williams [EMAIL PROTECTED] --- drivers/md/raid5.c | 152 +--- 1 files changed, 131 insertions(+), 21 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2c74f9b..2390657 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1788,7 +1788,75 @@ static void compute_block_2(struct stripe_head *sh, int dd_idx1, int dd_idx2) } } +static int handle_write_operations5(struct stripe_head *sh, int rcw, int expand) +{ + int i, pd_idx = sh-pd_idx, disks = sh-disks; + int locked=0; + + if (rcw == 0) { + /* skip the drain operation on an expand */ + if (!expand) { + BUG_ON(test_and_set_bit(STRIPE_OP_BIODRAIN, + sh-ops.pending)); + sh-ops.count++; + } + + BUG_ON(test_and_set_bit(STRIPE_OP_POSTXOR, sh-ops.pending)); + sh-ops.count++; + + for (i=disks ; i-- ;) { + struct r5dev *dev = sh-dev[i]; + + if (dev-towrite) { + set_bit(R5_LOCKED, dev-flags); + if (!expand) + clear_bit(R5_UPTODATE, dev-flags); + locked++; + } + } + } else { + BUG_ON(!(test_bit(R5_UPTODATE, sh-dev[pd_idx].flags) || + test_bit(R5_Wantcompute, sh-dev[pd_idx].flags))); + + BUG_ON(test_and_set_bit(STRIPE_OP_PREXOR, sh-ops.pending) || + test_and_set_bit(STRIPE_OP_BIODRAIN, sh-ops.pending) || + test_and_set_bit(STRIPE_OP_POSTXOR, sh-ops.pending)); + + sh-ops.count += 3; + + for (i=disks ; i-- ;) { + struct r5dev *dev = sh-dev[i]; + if (i==pd_idx) + continue; + /* For a read-modify write there may be blocks that are +* locked for reading while others are ready to be written +* so we distinguish these blocks by the R5_Wantprexor bit +*/ + if (dev-towrite + (test_bit(R5_UPTODATE, dev-flags) || + test_bit(R5_Wantcompute, dev-flags))) { + set_bit(R5_Wantprexor, dev-flags); + set_bit(R5_LOCKED, dev-flags); + clear_bit(R5_UPTODATE, dev-flags); + locked++; + } + } + } + + /* keep the parity disk locked while asynchronous operations +* are in flight +*/ + set_bit(R5_LOCKED, sh-dev[pd_idx].flags); + clear_bit(R5_UPTODATE, sh-dev[pd_idx].flags); + locked++; + + PRINTK(%s: stripe %llu locked: %d pending: %lx\n, + __FUNCTION__, (unsigned long long)sh-sector, + locked, sh-ops.pending); + + return locked; +} /* * Each stripe/dev can have one or more bion attached. @@ -2151,8 +2219,67 @@ static void handle_stripe5(struct stripe_head *sh) set_bit(STRIPE_HANDLE, sh-state); } - /* now to consider writing and what else, if anything should be read */ - if (to_write) { + /* Now we check to see if any write operations have recently +* completed +*/ + + /* leave prexor set until postxor is done, allows us to distinguish +* a rmw from a rcw during biodrain +*/ + if (test_bit(STRIPE_OP_PREXOR, sh-ops.complete) + test_bit(STRIPE_OP_POSTXOR, sh-ops.complete)) { + + clear_bit(STRIPE_OP_PREXOR, sh-ops.complete); + clear_bit(STRIPE_OP_PREXOR, sh-ops.ack); + clear_bit(STRIPE_OP_PREXOR, sh-ops.pending); + + for (i=disks; i--;) + clear_bit(R5_Wantprexor, sh-dev[i].flags); + } + + /* if only POSTXOR is set then this is an 'expand' postxor */ + if (test_bit(STRIPE_OP_BIODRAIN, sh-ops.complete) + test_bit(STRIPE_OP_POSTXOR, sh-ops.complete)) { + + clear_bit(STRIPE_OP_BIODRAIN, sh-ops.complete); + clear_bit(STRIPE_OP_BIODRAIN, sh-ops.ack); + clear_bit(STRIPE_OP_BIODRAIN, sh-ops.pending); + + clear_bit(STRIPE_OP_POSTXOR, sh-ops.complete); + clear_bit(STRIPE_OP_POSTXOR, sh-ops.ack); + clear_bit(STRIPE_OP_POSTXOR, sh-ops.pending); + + /* All the 'written'