* [md-raid6-accel PATCH 05/12] md: req/comp logic for async write operations
@ 2007-12-04 11:32 Yuri Tikhonov
0 siblings, 0 replies; only message in thread
From: Yuri Tikhonov @ 2007-12-04 11:32 UTC (permalink / raw)
To: Williams, Dan J; +Cc: Neil Brown, Wolfgang Denk, Detlev Zundel, linux-raid
The RAID-6 driver shares handle_write_operations() with RAID-5. For this
purpose, some modifications to handle_write_operations5() had been made. The
function itself was renamed as well. The handle_write_operations() is being
triggered either from handle_stripe6() or handle_stripe5().
This patch introduces one more RAID-5/6 shared function, it is
handle_completed_postxor_requests(), to be called when either handle_stripe5()
or handle_stripe6() discover the completeness of a post-xor operation for the
stripe.
Signed-off-by: Yuri Tikhonov <yur@emcraft.com>
Signed-off-by: Mikhail Cherkashin <mike@emcraft.com>
--
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2c6fee0..3e8f896 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -2447,11 +2447,12 @@ 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)
+handle_write_operations(struct stripe_head *sh, int rcw, int expand)
{
int locked = 0;
struct stripe_queue *sq = sh->sq;
int i, pd_idx = sq->pd_idx, disks = sq->disks;
+ int level = sq->raid_conf->level;
if (rcw) {
/* if we are not expanding this is a proper write request, and
@@ -2478,6 +2479,7 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
}
}
} else {
+ BUG_ON(level == 6);
BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
@@ -2510,13 +2512,20 @@ handle_write_operations5(struct stripe_head *sh, int rcw, int expand)
}
}
- /* keep the parity disk locked while asynchronous operations
+ /* keep the parity disks 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++;
+ if (level == 6) {
+ int qd_idx = raid6_next_disk(pd_idx, disks);
+ set_bit(R5_LOCKED, &sh->dev[qd_idx].flags);
+ clear_bit(R5_UPTODATE, &sh->dev[qd_idx].flags);
+ locked++;
+ }
+
pr_debug("%s: stripe %llu locked: %d pending: %lx\n",
__FUNCTION__, (unsigned long long)sh->sector,
locked, sh->ops.pending);
@@ -2881,6 +2890,47 @@ static void handle_issuing_new_read_requests6(struct stripe_head *sh,
set_bit(STRIPE_HANDLE, &sh->state);
}
+static void handle_completed_postxor_requests(struct stripe_head *sh,
+ struct stripe_head_state *s, int disks)
+{
+ struct stripe_queue *sq = sh->sq;
+ int i, pd_idx = sq->pd_idx;
+ int qd_idx = (sq->raid_conf->level != 6) ? -1 :
+ raid6_next_disk(pd_idx, disks);
+ struct r5dev *dev;
+
+ 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' buffers and the parity block are ready to be
+ * written back to disk
+ */
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags));
+ if (!(qd_idx < 0))
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags));
+
+ for (i = disks; i--;) {
+ struct r5_queue_dev *dev_q = &sq->dev[i];
+
+ dev = &sh->dev[i];
+ if (test_bit(R5_LOCKED, &dev->flags) &&
+ (i == pd_idx || i == qd_idx || dev_q->written)) {
+ pr_debug("Writing block %d\n", i);
+ set_bit(R5_Wantwrite, &dev->flags);
+ if (!test_and_set_bit(STRIPE_OP_IO, &sh->ops.pending))
+ sh->ops.count++;
+ if (!test_bit(R5_Insync, &dev->flags) ||
+ ((i == pd_idx || i == qd_idx) &&
+ s->failed == 0))
+ set_bit(STRIPE_INSYNC, &sh->state);
+ }
+ }
+}
/* handle_completed_write_requests
* any written block on an uptodate or failed drive can be returned.
@@ -3016,7 +3066,7 @@ static void handle_issuing_new_write_requests5(raid5_conf_t *conf,
if ((s->req_compute ||
!test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending)) &&
(s->locked == 0 && (rcw == 0 || rmw == 0)))
- s->locked += handle_write_operations5(sh, rcw == 0, 0);
+ s->locked += handle_write_operations(sh, rcw == 0, 0);
}
static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
@@ -3066,6 +3116,14 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
/* now if nothing is locked, and if we have enough data, we can start a
* write request
*/
+ /* since handle_stripe can be called at any time we need to handle the case
+ * where a compute block operation has been submitted and then a subsequent
+ * call wants to start a write request. raid_run_ops only handles the case where
+ * compute block and postxor are requested simultaneously. If this
+ * is not the case then new writes need to be held off until the compute
+ * completes.
+ */
+
if (s->locked == 0 && rcw == 0) {
if (must_compute > 0) {
/* We have failed blocks and need to compute them */
@@ -3084,19 +3142,9 @@ static void handle_issuing_new_write_requests6(raid5_conf_t *conf,
}
}
- pr_debug("Computing parity for stripe %llu\n",
- (unsigned long long)sh->sector);
- compute_parity6(sh, RECONSTRUCT_WRITE);
- /* now every locked buffer is ready to be written */
- for (i = disks; i--; )
- if (test_bit(R5_LOCKED, &sh->dev[i].flags)) {
- pr_debug("Writing stripe %llu block %d\n",
- (unsigned long long)sh->sector, i);
- s->locked++;
- set_bit(R5_Wantwrite, &sh->dev[i].flags);
- }
- /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
- set_bit(STRIPE_INSYNC, &sh->state);
+ if (s->req_compute ||
+ !test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending))
+ s->locked += handle_write_operations(sh, rcw == 0, 0);
}
}
@@ -3514,37 +3562,8 @@ static void handle_stripe5(struct stripe_head *sh)
/* 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' buffers and the parity block are ready to
- * be written back to disk
- */
- BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sq->pd_idx].flags));
- for (i = disks; i--; ) {
- struct r5_queue_dev *dev_q = &sq->dev[i];
-
- dev = &sh->dev[i];
- if (test_bit(R5_LOCKED, &dev->flags) &&
- (i == sq->pd_idx || dev_q->written)) {
- pr_debug("Writing block %d\n", i);
- set_bit(R5_Wantwrite, &dev->flags);
- if (!test_and_set_bit(
- STRIPE_OP_IO, &sh->ops.pending))
- sh->ops.count++;
- if (!test_bit(R5_Insync, &dev->flags) ||
- (i == sq->pd_idx && s.failed == 0))
- set_bit(STRIPE_INSYNC, &sh->state);
- }
- }
- }
+ test_bit(STRIPE_OP_POSTXOR, &sh->ops.complete))
+ handle_completed_postxor_requests(sh, &s, disks);
/* Now to consider new write requests and what else, if anything
* should be read. We do not handle new writes when:
@@ -3624,7 +3643,7 @@ static void handle_stripe5(struct stripe_head *sh)
sq->disks = conf->raid_disks;
sq->pd_idx = stripe_to_pdidx(sh->sector, conf,
conf->raid_disks);
- s.locked += handle_write_operations5(sh, 1, 1);
+ s.locked += handle_write_operations(sh, 1, 1);
} else if (s.expanded &&
!test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) {
clear_bit(STRIPE_EXPAND_READY, &sh->state);
@@ -3787,8 +3806,23 @@ static void handle_stripe6(struct stripe_head *sh, struct page *tmp_page)
(s.syncing && (s.uptodate < disks)) || s.expanding)
handle_issuing_new_read_requests6(sh, &s, &r6s, disks);
- /* now to consider writing and what else, if anything should be read */
- if (s.to_write)
+ /* Now we check to see if any write operations have recently
+ * completed
+ */
+
+ /* 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))
+ handle_completed_postxor_requests(sh, &s, disks);
+
+ /* 1/ Now to consider new write requests and what else,
+ * if anything shuold be read
+ * 2/ Check operations clobber the parity block so do not start
+ * new writes while a check is in flight
+ * 3/ Write operations do not stack
+ */
+ if (s.to_write && !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending) &&
+ !test_bit(STRIPE_OP_CHECK, &sh->ops.pending))
handle_issuing_new_write_requests6(conf, sh, &s, &r6s, disks);
/* maybe we need to check and possibly fix the parity for this stripe
--
Yuri Tikhonov, Senior Software Engineer
Emcraft Systems, www.emcraft.com
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2007-12-04 11:32 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-04 11:32 [md-raid6-accel PATCH 05/12] md: req/comp logic for async write operations Yuri Tikhonov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.