|
@@ -2766,99 +2766,46 @@ static void handle_stripe_dirtying6(raid5_conf_t *conf,
|
|
|
struct stripe_head *sh, struct stripe_head_state *s,
|
|
|
struct r6_state *r6s, int disks)
|
|
|
{
|
|
|
- int rcw = 0, must_compute = 0, pd_idx = sh->pd_idx, i;
|
|
|
+ int rcw = 0, pd_idx = sh->pd_idx, i;
|
|
|
int qd_idx = sh->qd_idx;
|
|
|
+
|
|
|
+ set_bit(STRIPE_HANDLE, &sh->state);
|
|
|
for (i = disks; i--; ) {
|
|
|
struct r5dev *dev = &sh->dev[i];
|
|
|
- /* Would I have to read this buffer for reconstruct_write */
|
|
|
- if (!test_bit(R5_OVERWRITE, &dev->flags)
|
|
|
- && i != pd_idx && i != qd_idx
|
|
|
- && (!test_bit(R5_LOCKED, &dev->flags)
|
|
|
- ) &&
|
|
|
- !test_bit(R5_UPTODATE, &dev->flags)) {
|
|
|
- if (test_bit(R5_Insync, &dev->flags)) rcw++;
|
|
|
- else {
|
|
|
- pr_debug("raid6: must_compute: "
|
|
|
- "disk %d flags=%#lx\n", i, dev->flags);
|
|
|
- must_compute++;
|
|
|
+ /* check if we haven't enough data */
|
|
|
+ if (!test_bit(R5_OVERWRITE, &dev->flags) &&
|
|
|
+ i != pd_idx && i != qd_idx &&
|
|
|
+ !test_bit(R5_LOCKED, &dev->flags) &&
|
|
|
+ !(test_bit(R5_UPTODATE, &dev->flags) ||
|
|
|
+ test_bit(R5_Wantcompute, &dev->flags))) {
|
|
|
+ rcw++;
|
|
|
+ if (!test_bit(R5_Insync, &dev->flags))
|
|
|
+ continue; /* it's a failed drive */
|
|
|
+
|
|
|
+ if (
|
|
|
+ test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
|
|
|
+ pr_debug("Read_old stripe %llu "
|
|
|
+ "block %d for Reconstruct\n",
|
|
|
+ (unsigned long long)sh->sector, i);
|
|
|
+ set_bit(R5_LOCKED, &dev->flags);
|
|
|
+ set_bit(R5_Wantread, &dev->flags);
|
|
|
+ s->locked++;
|
|
|
+ } else {
|
|
|
+ pr_debug("Request delayed stripe %llu "
|
|
|
+ "block %d for Reconstruct\n",
|
|
|
+ (unsigned long long)sh->sector, i);
|
|
|
+ set_bit(STRIPE_DELAYED, &sh->state);
|
|
|
+ set_bit(STRIPE_HANDLE, &sh->state);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- pr_debug("for sector %llu, rcw=%d, must_compute=%d\n",
|
|
|
- (unsigned long long)sh->sector, rcw, must_compute);
|
|
|
- set_bit(STRIPE_HANDLE, &sh->state);
|
|
|
-
|
|
|
- if (rcw > 0)
|
|
|
- /* want reconstruct write, but need to get some data */
|
|
|
- for (i = disks; i--; ) {
|
|
|
- struct r5dev *dev = &sh->dev[i];
|
|
|
- if (!test_bit(R5_OVERWRITE, &dev->flags)
|
|
|
- && !(s->failed == 0 && (i == pd_idx || i == qd_idx))
|
|
|
- && !test_bit(R5_LOCKED, &dev->flags) &&
|
|
|
- !test_bit(R5_UPTODATE, &dev->flags) &&
|
|
|
- test_bit(R5_Insync, &dev->flags)) {
|
|
|
- if (
|
|
|
- test_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
|
|
|
- pr_debug("Read_old stripe %llu "
|
|
|
- "block %d for Reconstruct\n",
|
|
|
- (unsigned long long)sh->sector, i);
|
|
|
- set_bit(R5_LOCKED, &dev->flags);
|
|
|
- set_bit(R5_Wantread, &dev->flags);
|
|
|
- s->locked++;
|
|
|
- } else {
|
|
|
- pr_debug("Request delayed stripe %llu "
|
|
|
- "block %d for Reconstruct\n",
|
|
|
- (unsigned long long)sh->sector, i);
|
|
|
- set_bit(STRIPE_DELAYED, &sh->state);
|
|
|
- set_bit(STRIPE_HANDLE, &sh->state);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
/* now if nothing is locked, and if we have enough data, we can start a
|
|
|
* write request
|
|
|
*/
|
|
|
- if (s->locked == 0 && rcw == 0 &&
|
|
|
+ if ((s->req_compute || !test_bit(STRIPE_COMPUTE_RUN, &sh->state)) &&
|
|
|
+ s->locked == 0 && rcw == 0 &&
|
|
|
!test_bit(STRIPE_BIT_DELAY, &sh->state)) {
|
|
|
- if (must_compute > 0) {
|
|
|
- /* We have failed blocks and need to compute them */
|
|
|
- switch (s->failed) {
|
|
|
- case 0:
|
|
|
- BUG();
|
|
|
- case 1:
|
|
|
- compute_block_1(sh, r6s->failed_num[0], 0);
|
|
|
- break;
|
|
|
- case 2:
|
|
|
- compute_block_2(sh, r6s->failed_num[0],
|
|
|
- r6s->failed_num[1]);
|
|
|
- break;
|
|
|
- default: /* This request should have been failed? */
|
|
|
- BUG();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- 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);
|
|
|
- }
|
|
|
- if (s->locked == disks)
|
|
|
- if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
|
|
|
- atomic_inc(&conf->pending_full_writes);
|
|
|
- /* after a RECONSTRUCT_WRITE, the stripe MUST be in-sync */
|
|
|
- set_bit(STRIPE_INSYNC, &sh->state);
|
|
|
-
|
|
|
- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
|
|
|
- atomic_dec(&conf->preread_active_stripes);
|
|
|
- if (atomic_read(&conf->preread_active_stripes) <
|
|
|
- IO_THRESHOLD)
|
|
|
- md_wakeup_thread(conf->mddev->thread);
|
|
|
- }
|
|
|
+ schedule_reconstruction(sh, s, 1, 0);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3539,8 +3486,13 @@ static bool handle_stripe6(struct stripe_head *sh)
|
|
|
(s.syncing && (s.uptodate < disks)) || s.expanding)
|
|
|
handle_stripe_fill6(sh, &s, &r6s, disks);
|
|
|
|
|
|
- /* now to consider writing and what else, if anything should be read */
|
|
|
- if (s.to_write)
|
|
|
+ /* Now to consider new write requests and what else, if anything
|
|
|
+ * should be read. We do not handle new writes when:
|
|
|
+ * 1/ A 'write' operation (copy+gen_syndrome) is already in flight.
|
|
|
+ * 2/ A 'check' operation is in flight, as it may clobber the parity
|
|
|
+ * block.
|
|
|
+ */
|
|
|
+ if (s.to_write && !sh->reconstruct_state && !sh->check_state)
|
|
|
handle_stripe_dirtying6(conf, sh, &s, &r6s, disks);
|
|
|
|
|
|
/* maybe we need to check and possibly fix the parity for this stripe
|