Commit 571f3078 authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] md: Fix another two bug in raid5

 A partial block write over a block on a failed device
 would need to pre-read that block, which means pre-read all
 blocks in stripe and generate that block.  But the generate-block
 code never checked for this possibility, so it wouldn't happen.
parent a531b8fc
......@@ -836,6 +836,7 @@ static void handle_stripe(struct stripe_head *sh)
int i;
int syncing;
int locked=0, uptodate=0, to_read=0, to_write=0, failed=0, written=0;
int non_overwrite = 0;
int failed_num=0;
struct r5dev *dev;
......@@ -883,7 +884,11 @@ static void handle_stripe(struct stripe_head *sh)
if (dev->toread) to_read++;
if (dev->towrite) to_write++;
if (dev->towrite) {
to_write++;
if (!test_bit(R5_OVERWRITE, &dev->flags))
non_overwrite++;
}
if (dev->written) written++;
rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */
if (!rdev || !rdev->in_sync) {
......@@ -975,12 +980,19 @@ static void handle_stripe(struct stripe_head *sh)
/* Now we might consider reading some blocks, either to check/generate
* parity, or to satisfy requests
* or to load a block that is being partially written.
*/
if (to_read || (syncing && (uptodate+failed < disks))) {
if (to_read || non_overwrite || (syncing && (uptodate+failed < disks))) {
for (i=disks; i--;) {
dev = &sh->dev[i];
if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
(dev->toread || syncing || (failed && sh->dev[failed_num].toread))) {
(dev->toread ||
(dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
syncing ||
(failed && (sh->dev[failed_num].toread ||
(sh->dev[failed_num].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num].flags))))
)
) {
/* we would like to get this block, possibly
* by computing it, but we might not be able to
*/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment