diff options
author | NeilBrown <neilb@suse.de> | 2007-09-11 18:23:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-09-11 20:21:19 -0400 |
commit | a2e0855182e2be26b252745b2bb7558705cb0dd2 (patch) | |
tree | d7a1457b1785cff5c018b37587ce2dbef159e83d /drivers/md/raid5.c | |
parent | b70ae1d9f69ba52767af89f90fd79587669bc7ff (diff) |
md: fix some bugs with growing raid5/raid6 arrays.
The recent changed to raid5 to allow offload of parity calculation etc
introduced some bugs in the code for growing (i.e. adding a disk to) raid5
and raid6. This fixes them
Acked-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2aff4be35dc4..4d63773ee73a 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -2541,7 +2541,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
2541 | struct dma_async_tx_descriptor *tx = NULL; | 2541 | struct dma_async_tx_descriptor *tx = NULL; |
2542 | clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); | 2542 | clear_bit(STRIPE_EXPAND_SOURCE, &sh->state); |
2543 | for (i = 0; i < sh->disks; i++) | 2543 | for (i = 0; i < sh->disks; i++) |
2544 | if (i != sh->pd_idx && (r6s && i != r6s->qd_idx)) { | 2544 | if (i != sh->pd_idx && (!r6s || i != r6s->qd_idx)) { |
2545 | int dd_idx, pd_idx, j; | 2545 | int dd_idx, pd_idx, j; |
2546 | struct stripe_head *sh2; | 2546 | struct stripe_head *sh2; |
2547 | 2547 | ||
@@ -2574,7 +2574,8 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
2574 | set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags); | 2574 | set_bit(R5_UPTODATE, &sh2->dev[dd_idx].flags); |
2575 | for (j = 0; j < conf->raid_disks; j++) | 2575 | for (j = 0; j < conf->raid_disks; j++) |
2576 | if (j != sh2->pd_idx && | 2576 | if (j != sh2->pd_idx && |
2577 | (r6s && j != r6s->qd_idx) && | 2577 | (!r6s || j != raid6_next_disk(sh2->pd_idx, |
2578 | sh2->disks)) && | ||
2578 | !test_bit(R5_Expanded, &sh2->dev[j].flags)) | 2579 | !test_bit(R5_Expanded, &sh2->dev[j].flags)) |
2579 | break; | 2580 | break; |
2580 | if (j == conf->raid_disks) { | 2581 | if (j == conf->raid_disks) { |
@@ -2583,12 +2584,12 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
2583 | } | 2584 | } |
2584 | release_stripe(sh2); | 2585 | release_stripe(sh2); |
2585 | 2586 | ||
2586 | /* done submitting copies, wait for them to complete */ | ||
2587 | if (i + 1 >= sh->disks) { | ||
2588 | async_tx_ack(tx); | ||
2589 | dma_wait_for_async_tx(tx); | ||
2590 | } | ||
2591 | } | 2587 | } |
2588 | /* done submitting copies, wait for them to complete */ | ||
2589 | if (tx) { | ||
2590 | async_tx_ack(tx); | ||
2591 | dma_wait_for_async_tx(tx); | ||
2592 | } | ||
2592 | } | 2593 | } |
2593 | 2594 | ||
2594 | /* | 2595 | /* |
@@ -2855,7 +2856,7 @@ static void handle_stripe5(struct stripe_head *sh) | |||
2855 | sh->disks = conf->raid_disks; | 2856 | sh->disks = conf->raid_disks; |
2856 | sh->pd_idx = stripe_to_pdidx(sh->sector, conf, | 2857 | sh->pd_idx = stripe_to_pdidx(sh->sector, conf, |
2857 | conf->raid_disks); | 2858 | conf->raid_disks); |
2858 | s.locked += handle_write_operations5(sh, 0, 1); | 2859 | s.locked += handle_write_operations5(sh, 1, 1); |
2859 | } else if (s.expanded && | 2860 | } else if (s.expanded && |
2860 | !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) { | 2861 | !test_bit(STRIPE_OP_POSTXOR, &sh->ops.pending)) { |
2861 | clear_bit(STRIPE_EXPAND_READY, &sh->state); | 2862 | clear_bit(STRIPE_EXPAND_READY, &sh->state); |