Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 867868fb authored by NeilBrown's avatar NeilBrown Committed by Linus Torvalds
Browse files

[PATCH] md: Factor out part of raid1d into a separate function



raid1d 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 2d2063ce
Loading
Loading
Loading
Loading
+95 −78
Original line number Diff line number Diff line
@@ -1368,6 +1368,95 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
 *	3.	Performs writes following reads for array syncronising.
 */

static void fix_read_error(conf_t *conf, int read_disk,
			   sector_t sect, int sectors)
{
	mddev_t *mddev = conf->mddev;
	while(sectors) {
		int s = sectors;
		int d = read_disk;
		int success = 0;
		int start;
		mdk_rdev_t *rdev;

		if (s > (PAGE_SIZE>>9))
			s = PAGE_SIZE >> 9;

		do {
			/* Note: no rcu protection needed here
			 * as this is synchronous in the raid1d thread
			 * which is the thread that might remove
			 * a device.  If raid1d ever becomes multi-threaded....
			 */
			rdev = conf->mirrors[d].rdev;
			if (rdev &&
			    test_bit(In_sync, &rdev->flags) &&
			    sync_page_io(rdev->bdev,
					 sect + rdev->data_offset,
					 s<<9,
					 conf->tmppage, READ))
				success = 1;
			else {
				d++;
				if (d == conf->raid_disks)
					d = 0;
			}
		} while (!success && d != read_disk);

		if (!success) {
			/* Cannot read from anywhere -- bye bye array */
			md_error(mddev, conf->mirrors[read_disk].rdev);
			break;
		}
		/* write it back and re-read */
		start = d;
		while (d != read_disk) {
			if (d==0)
				d = conf->raid_disks;
			d--;
			rdev = conf->mirrors[d].rdev;
			if (rdev &&
			    test_bit(In_sync, &rdev->flags)) {
				if (sync_page_io(rdev->bdev,
						 sect + rdev->data_offset,
						 s<<9, conf->tmppage, WRITE)
				    == 0)
					/* Well, this device is dead */
					md_error(mddev, rdev);
			}
		}
		d = start;
		while (d != read_disk) {
			char b[BDEVNAME_SIZE];
			if (d==0)
				d = conf->raid_disks;
			d--;
			rdev = conf->mirrors[d].rdev;
			if (rdev &&
			    test_bit(In_sync, &rdev->flags)) {
				if (sync_page_io(rdev->bdev,
						 sect + rdev->data_offset,
						 s<<9, conf->tmppage, READ)
				    == 0)
					/* Well, this device is dead */
					md_error(mddev, rdev);
				else {
					atomic_add(s, &rdev->corrected_errors);
					printk(KERN_INFO
					       "raid1:%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));
				}
			}
		}
		sectors -= s;
		sect += s;
	}
}

static void raid1d(mddev_t *mddev)
{
	r1bio_t *r1_bio;
@@ -1460,85 +1549,13 @@ static void raid1d(mddev_t *mddev)
			 * This is all done synchronously while the array is
			 * frozen
			 */
			sector_t sect = r1_bio->sector;
			int sectors = r1_bio->sectors;
			if (mddev->ro == 0) {
				freeze_array(conf);
			if (mddev->ro == 0) while(sectors) {
				int s = sectors;
				int d = r1_bio->read_disk;
				int success = 0;

				if (s > (PAGE_SIZE>>9))
					s = PAGE_SIZE >> 9;

				do {
					/* Note: no rcu protection needed here
					 * as this is synchronous in the raid1d thread
					 * which is the thread that might remove
					 * a device.  If raid1d ever becomes multi-threaded....
					 */
					rdev = conf->mirrors[d].rdev;
					if (rdev &&
					    test_bit(In_sync, &rdev->flags) &&
					    sync_page_io(rdev->bdev,
							 sect + rdev->data_offset,
							 s<<9,
							 conf->tmppage, READ))
						success = 1;
					else {
						d++;
						if (d == conf->raid_disks)
							d = 0;
					}
				} while (!success && d != r1_bio->read_disk);

				if (success) {
					/* write it back and re-read */
					int start = d;
					while (d != r1_bio->read_disk) {
						if (d==0)
							d = conf->raid_disks;
						d--;
						rdev = conf->mirrors[d].rdev;
						if (rdev &&
						    test_bit(In_sync, &rdev->flags)) {
							if (sync_page_io(rdev->bdev,
									 sect + rdev->data_offset,
									 s<<9, conf->tmppage, WRITE) == 0)
								/* Well, this device is dead */
								md_error(mddev, rdev);
						}
					}
					d = start;
					while (d != r1_bio->read_disk) {
						if (d==0)
							d = conf->raid_disks;
						d--;
						rdev = conf->mirrors[d].rdev;
						if (rdev &&
						    test_bit(In_sync, &rdev->flags)) {
							if (sync_page_io(rdev->bdev,
									 sect + rdev->data_offset,
									 s<<9, conf->tmppage, READ) == 0)
								/* Well, this device is dead */
								md_error(mddev, rdev);
							else {
								atomic_add(s, &rdev->corrected_errors);
								printk(KERN_INFO "raid1:%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));
							}
						}
					}
				} else {
					/* Cannot read from anywhere -- bye bye array */
					md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
					break;
				}
				sectors -= s;
				sect += s;
			}

				fix_read_error(conf, r1_bio->read_disk,
					       r1_bio->sector,
					       r1_bio->sectors);
				unfreeze_array(conf);
			}

			bio = r1_bio->bios[r1_bio->read_disk];
			if ((disk=read_balance(conf, r1_bio)) == -1) {