[PATCH] raid5: Avoid doing more read on dev of a stripe at the same time

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



In func 'ops_run_bio' if you read the dev which the last reading
of this dev didn't return,it will destrory the  req/rreq'source of rdev.
It may call hung-task.
For example, for badsector or other reasons, read-operation only used
stripe instead of chunk_aligned_read.
First:stripe 0;second: stripe 8;third:stripe 16.At the block-layer,three
bios merged.
Because media error of sector from 0 to 7, the request retried.
At this time, raid5d readed stripe0 again.But it will set 'bio->next =
NULL'.So the stripe 8 and 16 didn't return.

Signed-off-by: Jianpeng Ma <majianpeng@xxxxxxxxx>
---
 drivers/md/raid5.c |   13 ++++++++++---
 drivers/md/raid5.h |    1 +
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index adda94d..e52ba1b 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -547,9 +547,14 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 				rw = WRITE_FUA;
 			else
 				rw = WRITE;
-		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags))
-			rw = READ;
-		else if (test_and_clear_bit(R5_WantReplace,
+		} else if (test_and_clear_bit(R5_Wantread, &sh->dev[i].flags)) {
+			/*The last read did not return,so skip this read*/
+			if (test_and_set_bit(R5_Reading, &sh->dev[i].flags)) {
+				clear_bit(R5_LOCKED, &sh->dev[i].flags);
+				continue;
+			} else
+				rw = READ;
+		} else if (test_and_clear_bit(R5_WantReplace,
 					    &sh->dev[i].flags)) {
 			rw = WRITE;
 			replace_only = 1;
@@ -700,6 +705,7 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
 			pr_debug("skip op %ld on disc %d for sector %llu\n",
 				bi->bi_rw, i, (unsigned long long)sh->sector);
 			clear_bit(R5_LOCKED, &sh->dev[i].flags);
+			clear_bit(R5_Reading, &sh->dev[i].flags);
 			set_bit(STRIPE_HANDLE, &sh->state);
 		}
 	}
@@ -1818,6 +1824,7 @@ static void raid5_end_read_request(struct bio * bi, int error)
 	}
 	rdev_dec_pending(rdev, conf->mddev);
 	clear_bit(R5_LOCKED, &sh->dev[i].flags);
+	clear_bit(R5_Reading, &sh->dev[i].flags);
 	set_bit(STRIPE_HANDLE, &sh->state);
 	release_stripe(sh);
 }
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index a9fc249..a596df8 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -298,6 +298,7 @@ enum r5dev_flags {
 	R5_WantReplace, /* We need to update the replacement, we have read
 			 * data in, and now is a good time to write it out.
 			 */
+	R5_Reading,	/* this dev on reading on lld*/
 };
 
 /*
-- 
1.7.9.5
?韬{.n?????%??檩??w?{.n???{炳盯w???塄}?财??j:+v??????2??璀??摺?囤??z夸z罐?+?????w棹f



[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux