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

Commit f4a8e656 authored by Jan Schmidt's avatar Jan Schmidt Committed by Chris Mason
Browse files

Btrfs: fix meta data raid-repair merge problem



Commit 4a54c8c1 introduced raid-repair, killing the individual
readpage_io_failed_hook entries from inode.c and disk-io.c. Commit
4bb31e92 introduced new readahead code, adding a readpage_io_failed_hook to
disk-io.c.

The raid-repair commit had logic to disable raid-repair, if
readpage_io_failed_hook is set. Thus, the readahead commit effectively
disabled raid-repair for meta data.

This commit changes the logic to always attempt raid-repair when needed and
call the readpage_io_failed_hook in case raid-repair fails. This is much
more straight forward and should have been like that from the beginning.

Signed-off-by: default avatarJan Schmidt <list.btrfs@jan-o-sch.net>
Reported-by: default avatarStefan Behrens <sbehrens@giantdisaster.de>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent be064d11
Loading
Loading
Loading
Loading
+20 −7
Original line number Diff line number Diff line
@@ -2287,14 +2287,20 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
		if (!uptodate) {
			int failed_mirror;
			failed_mirror = (int)(unsigned long)bio->bi_bdev;
			if (tree->ops && tree->ops->readpage_io_failed_hook)
				ret = tree->ops->readpage_io_failed_hook(
						bio, page, start, end,
						failed_mirror, state);
			else
			/*
			 * The generic bio_readpage_error handles errors the
			 * following way: If possible, new read requests are
			 * created and submitted and will end up in
			 * end_bio_extent_readpage as well (if we're lucky, not
			 * in the !uptodate case). In that case it returns 0 and
			 * we just go on with the next page in our bio. If it
			 * can't handle the error it will return -EIO and we
			 * remain responsible for that page.
			 */
			ret = bio_readpage_error(bio, page, start, end,
							failed_mirror, NULL);
			if (ret == 0) {
error_handled:
				uptodate =
					test_bit(BIO_UPTODATE, &bio->bi_flags);
				if (err)
@@ -2302,6 +2308,13 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
				uncache_state(&cached);
				continue;
			}
			if (tree->ops && tree->ops->readpage_io_failed_hook) {
				ret = tree->ops->readpage_io_failed_hook(
							bio, page, start, end,
							failed_mirror, state);
				if (ret == 0)
					goto error_handled;
			}
		}

		if (uptodate) {