forked from Minki/linux
md/raid5: move more common code into handle_stripe
Apart from 'prexor' which can only be set for RAID5, and 'qd_idx' which can only be meaningful for RAID6, these two chunks of code are nearly the same. So combine them into one adding a test to call either handle_parity_checks5 or handle_parity_checks6 as appropriate. Signed-off-by: NeilBrown <neilb@suse.de> Reviewed-by: Namhyung Kim <namhyung@gmail.com>
This commit is contained in:
parent
c8ac1803ff
commit
84789554e9
@ -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.
|
* Select the parity disk based on the user selected algorithm.
|
||||||
*/
|
*/
|
||||||
pd_idx = qd_idx = ~0;
|
pd_idx = qd_idx = -1;
|
||||||
switch(conf->level) {
|
switch(conf->level) {
|
||||||
case 4:
|
case 4:
|
||||||
pd_idx = data_disks;
|
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;
|
raid5_conf_t *conf = sh->raid_conf;
|
||||||
int disks = sh->disks, i;
|
int disks = sh->disks, i;
|
||||||
struct r5dev *dev;
|
struct r5dev *dev;
|
||||||
int prexor;
|
|
||||||
|
|
||||||
/* Now to look around and see what can be done */
|
/* Now to look around and see what can be done */
|
||||||
rcu_read_lock();
|
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)
|
(s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
|
||||||
handle_stripe_fill(sh, s, disks);
|
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;
|
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)
|
(s->syncing && (s->uptodate + s->compute < disks)) || s->expanding)
|
||||||
handle_stripe_fill(sh, s, disks);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3273,6 +3174,8 @@ static void handle_stripe(struct stripe_head *sh)
|
|||||||
struct stripe_head_state s;
|
struct stripe_head_state s;
|
||||||
int done;
|
int done;
|
||||||
int i;
|
int i;
|
||||||
|
int prexor;
|
||||||
|
int disks = sh->disks;
|
||||||
raid5_conf_t *conf = sh->raid_conf;
|
raid5_conf_t *conf = sh->raid_conf;
|
||||||
|
|
||||||
clear_bit(STRIPE_HANDLE, &sh->state);
|
clear_bit(STRIPE_HANDLE, &sh->state);
|
||||||
@ -3310,6 +3213,64 @@ static void handle_stripe(struct stripe_head *sh)
|
|||||||
if (done)
|
if (done)
|
||||||
goto finish;
|
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)) {
|
if (s.syncing && s.locked == 0 && test_bit(STRIPE_INSYNC, &sh->state)) {
|
||||||
md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
|
md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
|
||||||
|
Loading…
Reference in New Issue
Block a user