When a read request that bypassed the cache needs to be retried
(due to device failure) we need to process it one stripe_head at a time,
and record where we were up to.
We were recording this in bi_hw_segments. But as there is only
ever one such request that is being resubmitted, this info can
be stored in ->conf thus not misusing a field in the bio.
Signed-off-by: Neil Brown <[email protected]>
### Diffstat output
./drivers/md/raid5.c | 21 ++++++++++++---------
./include/linux/raid/raid5.h | 1 +
2 files changed, 13 insertions(+), 9 deletions(-)
diff .prev/drivers/md/raid5.c ./drivers/md/raid5.c
--- .prev/drivers/md/raid5.c 2007-07-31 11:20:52.000000000 +1000
+++ ./drivers/md/raid5.c 2007-07-31 11:20:53.000000000 +1000
@@ -3857,13 +3857,14 @@ static void add_bio_to_retry(struct bio
}
-static struct bio *remove_bio_from_retry(raid5_conf_t *conf)
+static struct bio *remove_bio_from_retry(raid5_conf_t *conf, int *already_done)
{
struct bio *bi;
bi = conf->retry_read_aligned;
if (bi) {
conf->retry_read_aligned = NULL;
+ *already_done = conf->retry_read_aligned_scnt;
return bi;
}
bi = conf->retry_read_aligned_list;
@@ -3871,7 +3872,7 @@ static struct bio *remove_bio_from_retry
conf->retry_read_aligned_list = bi->bi_next;
bi->bi_next = NULL;
atomic_set(&bi->bi_iocnt, 1);
- bi->bi_hw_segments = 0; /* count of processed stripes */
+ *already_done = 0;
}
return bi;
@@ -4388,14 +4389,15 @@ static inline sector_t sync_request(mdde
return STRIPE_SECTORS;
}
-static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
+static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio,
+ int start_scnt)
{
/* We may not be able to submit a whole bio at once as there
* may not be enough stripe_heads available.
* We cannot pre-allocate enough stripe_heads as we may need
* more than exist in the cache (if we allow ever large chunks).
* So we do one stripe head at a time and record in
- * ->bi_hw_segments how many have been done.
+ * conf->retry_read_aligned_scnt how many have been done.
*
* We *know* that this entire raid_bio is in one chunk, so
* it will be only one 'dd_idx' and only need one call to raid5_compute_sector.
@@ -4423,7 +4425,7 @@ static int retry_aligned_read(raid5_con
scnt++) {
struct stripe_head *sh;
- if (scnt < raid_bio->bi_hw_segments)
+ if (scnt < start_scnt )
/* already done this stripe */
continue;
@@ -4431,7 +4433,7 @@ static int retry_aligned_read(raid5_con
sh = get_active_stripe(sq, disks, 1);
if (!(sq && sh)) {
/* failed to get a queue/stripe - must wait */
- raid_bio->bi_hw_segments = scnt;
+ conf->retry_read_aligned_scnt = scnt;
conf->retry_read_aligned = raid_bio;
if (sq)
release_queue(sq);
@@ -4442,7 +4444,7 @@ static int retry_aligned_read(raid5_con
if (!add_queue_bio(sq, raid_bio, dd_idx, 0)) {
release_queue(sq);
release_stripe(sh);
- raid_bio->bi_hw_segments = scnt;
+ conf->retry_read_aligned_scnt = scnt;
conf->retry_read_aligned = raid_bio;
return handled;
}
@@ -4538,6 +4540,7 @@ static void raid5d (mddev_t *mddev)
while (1) {
struct list_head *first;
struct bio *bio;
+ int scnt;
if (conf->seq_flush != conf->seq_write) {
int seq = conf->seq_flush;
@@ -4548,10 +4551,10 @@ static void raid5d (mddev_t *mddev)
activate_bit_delay(conf);
}
- while ((bio = remove_bio_from_retry(conf))) {
+ while ((bio = remove_bio_from_retry(conf, &scnt))) {
int ok;
spin_unlock_irq(&conf->device_lock);
- ok = retry_aligned_read(conf, bio);
+ ok = retry_aligned_read(conf, bio, scnt);
spin_lock_irq(&conf->device_lock);
if (!ok)
break;
diff .prev/include/linux/raid/raid5.h ./include/linux/raid/raid5.h
--- .prev/include/linux/raid/raid5.h 2007-07-31 11:20:15.000000000 +1000
+++ ./include/linux/raid/raid5.h 2007-07-31 11:20:53.000000000 +1000
@@ -362,6 +362,7 @@ struct raid5_private_data {
char workqueue_name[20];
struct bio *retry_read_aligned; /* currently retrying aligned bios */
+ int retry_read_aligned_scnt; /* how far through */
struct bio *retry_read_aligned_list; /* aligned bios retry list */
atomic_t active_aligned_reads;
atomic_t preread_active_queues; /* queues with scheduled
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]