Commit 6814d536 authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds

[PATCH] md: factor out part of raid10d into a separate function.

raid10d has toooo many nested block, so take the fix_read_error functionality
out into a separate function.
Signed-off-by: default avatarNeil Brown <neilb@suse.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent b5c124af
......@@ -1350,76 +1350,19 @@ static void recovery_request_write(mddev_t *mddev, r10bio_t *r10_bio)
*
* 1. Retries failed read operations on working mirrors.
* 2. Updates the raid superblock when problems encounter.
* 3. Performs writes following reads for array syncronising.
* 3. Performs writes following reads for array synchronising.
*/
static void raid10d(mddev_t *mddev)
static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
{
r10bio_t *r10_bio;
struct bio *bio;
unsigned long flags;
conf_t *conf = mddev_to_conf(mddev);
struct list_head *head = &conf->retry_list;
int unplug=0;
mdk_rdev_t *rdev;
md_check_recovery(mddev);
for (;;) {
char b[BDEVNAME_SIZE];
spin_lock_irqsave(&conf->device_lock, flags);
if (conf->pending_bio_list.head) {
bio = bio_list_get(&conf->pending_bio_list);
blk_remove_plug(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
if (bitmap_unplug(mddev->bitmap) != 0)
printk("%s: bitmap file write failed!\n", mdname(mddev));
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
bio->bi_next = NULL;
generic_make_request(bio);
bio = next;
}
unplug = 1;
continue;
}
if (list_empty(head))
break;
r10_bio = list_entry(head->prev, r10bio_t, retry_list);
list_del(head->prev);
conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r10_bio->mddev;
conf = mddev_to_conf(mddev);
if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
sync_request_write(mddev, r10_bio);
unplug = 1;
} else if (test_bit(R10BIO_IsRecover, &r10_bio->state)) {
recovery_request_write(mddev, r10_bio);
unplug = 1;
} else {
int mirror;
/* we got a read error. Maybe the drive is bad. Maybe just
* the block and we can fix it.
* We freeze all other IO, and try reading the block from
* other devices. When we find one, we re-write
* and check it that fixes the read error.
* This is all done synchronously while the array is
* frozen.
*/
int sect = 0; /* Offset from r10_bio->sector */
int sectors = r10_bio->sectors;
freeze_array(conf);
if (mddev->ro == 0) while(sectors) {
mdk_rdev_t*rdev;
while(sectors) {
int s = sectors;
int sl = r10_bio->read_slot;
int success = 0;
int start;
if (s > (PAGE_SIZE>>9))
s = PAGE_SIZE >> 9;
......@@ -1448,8 +1391,14 @@ static void raid10d(mddev_t *mddev)
} while (!success && sl != r10_bio->read_slot);
rcu_read_unlock();
if (success) {
int start = sl;
if (!success) {
/* Cannot read from anywhere -- bye bye array */
int dn = r10_bio->devs[r10_bio->read_slot].devnum;
md_error(mddev, conf->mirrors[dn].rdev);
break;
}
start = sl;
/* write it back and re-read */
rcu_read_lock();
while (sl != r10_bio->read_slot) {
......@@ -1467,7 +1416,8 @@ static void raid10d(mddev_t *mddev)
if (sync_page_io(rdev->bdev,
r10_bio->devs[sl].addr +
sect + rdev->data_offset,
s<<9, conf->tmppage, WRITE) == 0)
s<<9, conf->tmppage, WRITE)
== 0)
/* Well, this device is dead */
md_error(mddev, rdev);
rdev_dec_pending(rdev, mddev);
......@@ -1484,6 +1434,7 @@ static void raid10d(mddev_t *mddev)
rdev = rcu_dereference(conf->mirrors[d].rdev);
if (rdev &&
test_bit(In_sync, &rdev->flags)) {
char b[BDEVNAME_SIZE];
atomic_inc(&rdev->nr_pending);
rcu_read_unlock();
if (sync_page_io(rdev->bdev,
......@@ -1493,24 +1444,90 @@ static void raid10d(mddev_t *mddev)
/* Well, this device is dead */
md_error(mddev, rdev);
else
printk(KERN_INFO "raid10:%s: read error corrected (%d sectors at %llu on %s)\n",
mdname(mddev), s, (unsigned long long)(sect+rdev->data_offset), bdevname(rdev->bdev, b));
printk(KERN_INFO
"raid10:%s: read error corrected"
" (%d sectors at %llu on %s)\n",
mdname(mddev), s,
(unsigned long long)sect+
rdev->data_offset,
bdevname(rdev->bdev, b));
rdev_dec_pending(rdev, mddev);
rcu_read_lock();
}
}
rcu_read_unlock();
} else {
/* Cannot read from anywhere -- bye bye array */
md_error(mddev, conf->mirrors[r10_bio->devs[r10_bio->read_slot].devnum].rdev);
break;
}
sectors -= s;
sect += s;
}
}
static void raid10d(mddev_t *mddev)
{
r10bio_t *r10_bio;
struct bio *bio;
unsigned long flags;
conf_t *conf = mddev_to_conf(mddev);
struct list_head *head = &conf->retry_list;
int unplug=0;
mdk_rdev_t *rdev;
md_check_recovery(mddev);
for (;;) {
char b[BDEVNAME_SIZE];
spin_lock_irqsave(&conf->device_lock, flags);
if (conf->pending_bio_list.head) {
bio = bio_list_get(&conf->pending_bio_list);
blk_remove_plug(mddev->queue);
spin_unlock_irqrestore(&conf->device_lock, flags);
/* flush any pending bitmap writes to disk before proceeding w/ I/O */
if (bitmap_unplug(mddev->bitmap) != 0)
printk("%s: bitmap file write failed!\n", mdname(mddev));
while (bio) { /* submit pending writes */
struct bio *next = bio->bi_next;
bio->bi_next = NULL;
generic_make_request(bio);
bio = next;
}
unplug = 1;
continue;
}
if (list_empty(head))
break;
r10_bio = list_entry(head->prev, r10bio_t, retry_list);
list_del(head->prev);
conf->nr_queued--;
spin_unlock_irqrestore(&conf->device_lock, flags);
mddev = r10_bio->mddev;
conf = mddev_to_conf(mddev);
if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
sync_request_write(mddev, r10_bio);
unplug = 1;
} else if (test_bit(R10BIO_IsRecover, &r10_bio->state)) {
recovery_request_write(mddev, r10_bio);
unplug = 1;
} else {
int mirror;
/* we got a read error. Maybe the drive is bad. Maybe just
* the block and we can fix it.
* We freeze all other IO, and try reading the block from
* other devices. When we find one, we re-write
* and check it that fixes the read error.
* This is all done synchronously while the array is
* frozen.
*/
if (mddev->ro == 0) {
freeze_array(conf);
fix_read_error(conf, mddev, r10_bio);
unfreeze_array(conf);
}
bio = r10_bio->devs[r10_bio->read_slot].bio;
r10_bio->devs[r10_bio->read_slot].bio =
......
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