|
@@ -1756,7 +1756,7 @@ static sector_t raid5_compute_sector(raid5_conf_t *conf, sector_t r_sector,
|
|
|
/*
|
|
|
* Select the parity disk based on the user selected algorithm.
|
|
|
*/
|
|
|
- pd_idx = qd_idx = ~0;
|
|
|
+ pd_idx = qd_idx = -1;
|
|
|
switch(conf->level) {
|
|
|
case 4:
|
|
|
pd_idx = data_disks;
|
|
@@ -2903,7 +2903,6 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s)
|
|
|
raid5_conf_t *conf = sh->raid_conf;
|
|
|
int disks = sh->disks, i;
|
|
|
struct r5dev *dev;
|
|
|
- int prexor;
|
|
|
|
|
|
/* Now to look around and see what can be done */
|
|
|
rcu_read_lock();
|
|
@@ -3026,56 +3025,6 @@ static int handle_stripe5(struct stripe_head *sh, struct stripe_head_state *s)
|
|
|
(s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
|
|
|
handle_stripe_fill(sh, s, disks);
|
|
|
|
|
|
- /* Now we check to see if any write operations have recently
|
|
|
- * completed
|
|
|
- */
|
|
|
- prexor = 0;
|
|
|
- if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
|
|
|
- prexor = 1;
|
|
|
- if (sh->reconstruct_state == reconstruct_state_drain_result ||
|
|
|
- sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
|
|
|
- sh->reconstruct_state = reconstruct_state_idle;
|
|
|
-
|
|
|
- /* All the 'written' buffers and the parity block are ready to
|
|
|
- * be written back to disk
|
|
|
- */
|
|
|
- BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
|
|
|
- for (i = disks; i--; ) {
|
|
|
- dev = &sh->dev[i];
|
|
|
- if (test_bit(R5_LOCKED, &dev->flags) &&
|
|
|
- (i == sh->pd_idx || dev->written)) {
|
|
|
- pr_debug("Writing block %d\n", i);
|
|
|
- set_bit(R5_Wantwrite, &dev->flags);
|
|
|
- if (prexor)
|
|
|
- continue;
|
|
|
- if (!test_bit(R5_Insync, &dev->flags) ||
|
|
|
- (i == sh->pd_idx && s->failed == 0))
|
|
|
- set_bit(STRIPE_INSYNC, &sh->state);
|
|
|
- }
|
|
|
- }
|
|
|
- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
|
|
|
- s->dec_preread_active = 1;
|
|
|
- }
|
|
|
-
|
|
|
- /* 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+xor) 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_dirtying(conf, sh, s, disks);
|
|
|
-
|
|
|
- /* maybe we need to check and possibly fix the parity for this stripe
|
|
|
- * Any reads will already have been scheduled, so we just see if enough
|
|
|
- * data is available. The parity check is held off while parity
|
|
|
- * dependent operations are in flight.
|
|
|
- */
|
|
|
- if (sh->check_state ||
|
|
|
- (s->syncing && s->locked == 0 &&
|
|
|
- !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
|
|
|
- !test_bit(STRIPE_INSYNC, &sh->state)))
|
|
|
- handle_parity_checks5(conf, sh, s, disks);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3217,54 +3166,6 @@ static int handle_stripe6(struct stripe_head *sh, struct stripe_head_state *s)
|
|
|
(s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
|
|
|
handle_stripe_fill(sh, s, disks);
|
|
|
|
|
|
- /* Now we check to see if any write operations have recently
|
|
|
- * completed
|
|
|
- */
|
|
|
- if (sh->reconstruct_state == reconstruct_state_drain_result) {
|
|
|
-
|
|
|
- sh->reconstruct_state = reconstruct_state_idle;
|
|
|
- /* All the 'written' buffers and the parity blocks are ready to
|
|
|
- * be written back to disk
|
|
|
- */
|
|
|
- BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
|
|
|
- BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[qd_idx].flags));
|
|
|
- for (i = disks; i--; ) {
|
|
|
- dev = &sh->dev[i];
|
|
|
- if (test_bit(R5_LOCKED, &dev->flags) &&
|
|
|
- (i == sh->pd_idx || i == qd_idx ||
|
|
|
- dev->written)) {
|
|
|
- pr_debug("Writing block %d\n", i);
|
|
|
- BUG_ON(!test_bit(R5_UPTODATE, &dev->flags));
|
|
|
- set_bit(R5_Wantwrite, &dev->flags);
|
|
|
- if (!test_bit(R5_Insync, &dev->flags) ||
|
|
|
- ((i == sh->pd_idx || i == qd_idx) &&
|
|
|
- s->failed == 0))
|
|
|
- set_bit(STRIPE_INSYNC, &sh->state);
|
|
|
- }
|
|
|
- }
|
|
|
- if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
|
|
|
- s->dec_preread_active = 1;
|
|
|
- }
|
|
|
-
|
|
|
- /* 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_dirtying(conf, sh, s, disks);
|
|
|
-
|
|
|
- /* maybe we need to check and possibly fix the parity for this stripe
|
|
|
- * Any reads will already have been scheduled, so we just see if enough
|
|
|
- * data is available. The parity check is held off while parity
|
|
|
- * dependent operations are in flight.
|
|
|
- */
|
|
|
- if (sh->check_state ||
|
|
|
- (s->syncing && s->locked == 0 &&
|
|
|
- !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
|
|
|
- !test_bit(STRIPE_INSYNC, &sh->state)))
|
|
|
- handle_parity_checks6(conf, sh, s, disks);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -3273,6 +3174,8 @@ static void handle_stripe(struct stripe_head *sh)
|
|
|
struct stripe_head_state s;
|
|
|
int done;
|
|
|
int i;
|
|
|
+ int prexor;
|
|
|
+ int disks = sh->disks;
|
|
|
raid5_conf_t *conf = sh->raid_conf;
|
|
|
|
|
|
clear_bit(STRIPE_HANDLE, &sh->state);
|
|
@@ -3310,6 +3213,64 @@ static void handle_stripe(struct stripe_head *sh)
|
|
|
if (done)
|
|
|
goto finish;
|
|
|
|
|
|
+ /* Now we check to see if any write operations have recently
|
|
|
+ * completed
|
|
|
+ */
|
|
|
+ prexor = 0;
|
|
|
+ if (sh->reconstruct_state == reconstruct_state_prexor_drain_result)
|
|
|
+ prexor = 1;
|
|
|
+ if (sh->reconstruct_state == reconstruct_state_drain_result ||
|
|
|
+ sh->reconstruct_state == reconstruct_state_prexor_drain_result) {
|
|
|
+ sh->reconstruct_state = reconstruct_state_idle;
|
|
|
+
|
|
|
+ /* All the 'written' buffers and the parity block are ready to
|
|
|
+ * be written back to disk
|
|
|
+ */
|
|
|
+ BUG_ON(!test_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags));
|
|
|
+ BUG_ON(sh->qd_idx >= 0 &&
|
|
|
+ !test_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags));
|
|
|
+ for (i = disks; i--; ) {
|
|
|
+ struct r5dev *dev = &sh->dev[i];
|
|
|
+ if (test_bit(R5_LOCKED, &dev->flags) &&
|
|
|
+ (i == sh->pd_idx || i == sh->qd_idx ||
|
|
|
+ dev->written)) {
|
|
|
+ pr_debug("Writing block %d\n", i);
|
|
|
+ set_bit(R5_Wantwrite, &dev->flags);
|
|
|
+ if (prexor)
|
|
|
+ continue;
|
|
|
+ if (!test_bit(R5_Insync, &dev->flags) ||
|
|
|
+ ((i == sh->pd_idx || i == sh->qd_idx) &&
|
|
|
+ s.failed == 0))
|
|
|
+ set_bit(STRIPE_INSYNC, &sh->state);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
|
|
|
+ s.dec_preread_active = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 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+xor) 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_dirtying(conf, sh, &s, disks);
|
|
|
+
|
|
|
+ /* maybe we need to check and possibly fix the parity for this stripe
|
|
|
+ * Any reads will already have been scheduled, so we just see if enough
|
|
|
+ * data is available. The parity check is held off while parity
|
|
|
+ * dependent operations are in flight.
|
|
|
+ */
|
|
|
+ if (sh->check_state ||
|
|
|
+ (s.syncing && s.locked == 0 &&
|
|
|
+ !test_bit(STRIPE_COMPUTE_RUN, &sh->state) &&
|
|
|
+ !test_bit(STRIPE_INSYNC, &sh->state))) {
|
|
|
+ if (conf->level == 6)
|
|
|
+ handle_parity_checks6(conf, sh, &s, disks);
|
|
|
+ else
|
|
|
+ handle_parity_checks5(conf, sh, &s, disks);
|
|
|
+ }
|
|
|
|
|
|
if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
|
|
|
md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
|