aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/extent_io.c
diff options
context:
space:
mode:
authorMiao Xie <miaox@cn.fujitsu.com>2014-09-12 06:44:03 -0400
committerChris Mason <clm@fb.com>2014-09-17 16:39:01 -0400
commit8b110e393c5a6e72d50fcdf9fa7ed8b647cfdfc9 (patch)
tree36f6b0048c79fd63c55892cd45f0b78e8c0cc15b /fs/btrfs/extent_io.c
parent28e1cc7d1baf8038ae4ad4681c8f3dc94fcd7c00 (diff)
Btrfs: implement repair function when direct read fails
This patch implement data repair function when direct read fails. The detail of the implementation is: - When we find the data is not right, we try to read the data from the other mirror. - When the io on the mirror ends, we will insert the endio work into the dedicated btrfs workqueue, not common read endio workqueue, because the original endio work is still blocked in the btrfs endio workqueue, if we insert the endio work of the io on the mirror into that workqueue, deadlock would happen. - After we get right data, we write it back to the corrupted mirror. - And if the data on the new mirror is still corrupted, we will try next mirror until we read right data or all the mirrors are traversed. - After the above work, we set the uptodate flag according to the result. Signed-off-by: Miao Xie <miaox@cn.fujitsu.com> Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r--fs/btrfs/extent_io.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 05533c99f89d..9e2ef27672e5 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -1962,7 +1962,7 @@ static void check_page_uptodate(struct extent_io_tree *tree, struct page *page)
1962 SetPageUptodate(page); 1962 SetPageUptodate(page);
1963} 1963}
1964 1964
1965static int free_io_failure(struct inode *inode, struct io_failure_record *rec) 1965int free_io_failure(struct inode *inode, struct io_failure_record *rec)
1966{ 1966{
1967 int ret; 1967 int ret;
1968 int err = 0; 1968 int err = 0;
@@ -2081,8 +2081,8 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
2081 * each time an IO finishes, we do a fast check in the IO failure tree 2081 * each time an IO finishes, we do a fast check in the IO failure tree
2082 * to see if we need to process or clean up an io_failure_record 2082 * to see if we need to process or clean up an io_failure_record
2083 */ 2083 */
2084static int clean_io_failure(struct inode *inode, u64 start, 2084int clean_io_failure(struct inode *inode, u64 start, struct page *page,
2085 struct page *page, unsigned int pg_offset) 2085 unsigned int pg_offset)
2086{ 2086{
2087 u64 private; 2087 u64 private;
2088 u64 private_failure; 2088 u64 private_failure;
@@ -2291,7 +2291,7 @@ int btrfs_check_repairable(struct inode *inode, struct bio *failed_bio,
2291struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio, 2291struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio,
2292 struct io_failure_record *failrec, 2292 struct io_failure_record *failrec,
2293 struct page *page, int pg_offset, int icsum, 2293 struct page *page, int pg_offset, int icsum,
2294 bio_end_io_t *endio_func) 2294 bio_end_io_t *endio_func, void *data)
2295{ 2295{
2296 struct bio *bio; 2296 struct bio *bio;
2297 struct btrfs_io_bio *btrfs_failed_bio; 2297 struct btrfs_io_bio *btrfs_failed_bio;
@@ -2305,6 +2305,7 @@ struct bio *btrfs_create_repair_bio(struct inode *inode, struct bio *failed_bio,
2305 bio->bi_iter.bi_sector = failrec->logical >> 9; 2305 bio->bi_iter.bi_sector = failrec->logical >> 9;
2306 bio->bi_bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; 2306 bio->bi_bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev;
2307 bio->bi_iter.bi_size = 0; 2307 bio->bi_iter.bi_size = 0;
2308 bio->bi_private = data;
2308 2309
2309 btrfs_failed_bio = btrfs_io_bio(failed_bio); 2310 btrfs_failed_bio = btrfs_io_bio(failed_bio);
2310 if (btrfs_failed_bio->csum) { 2311 if (btrfs_failed_bio->csum) {
@@ -2362,7 +2363,8 @@ static int bio_readpage_error(struct bio *failed_bio, u64 phy_offset,
2362 phy_offset >>= inode->i_sb->s_blocksize_bits; 2363 phy_offset >>= inode->i_sb->s_blocksize_bits;
2363 bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, 2364 bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page,
2364 start - page_offset(page), 2365 start - page_offset(page),
2365 (int)phy_offset, failed_bio->bi_end_io); 2366 (int)phy_offset, failed_bio->bi_end_io,
2367 NULL);
2366 if (!bio) { 2368 if (!bio) {
2367 free_io_failure(inode, failrec); 2369 free_io_failure(inode, failrec);
2368 return -EIO; 2370 return -EIO;