Btrfs: modify repair_io_failure and make it suit direct io
authorMiao Xie <miaox@cn.fujitsu.com>
Fri, 12 Sep 2014 10:44:00 +0000 (18:44 +0800)
committerChris Mason <clm@fb.com>
Wed, 17 Sep 2014 20:38:58 +0000 (13:38 -0700)
The original code of repair_io_failure was just used for buffered read,
because it got some filesystem data from page structure, it is safe for
the page in the page cache. But when we do a direct read, the pages in bio
are not in the page cache, that is there is no filesystem data in the page
structure. In order to implement direct read data repair, we need modify
repair_io_failure and pass all filesystem data it need by function
parameters.

Signed-off-by: Miao Xie <miaox@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/scrub.c

index c191ea58750f7c28333489554e76e9c79466ac09..74d47e197ca08455a91ffd9cc2fbb27183c60a09 100644 (file)
@@ -1997,7 +1997,7 @@ static int free_io_failure(struct inode *inode, struct io_failure_record *rec)
  */
 int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
                        u64 length, u64 logical, struct page *page,
-                       int mirror_num)
+                       unsigned int pg_offset, int mirror_num)
 {
        struct bio *bio;
        struct btrfs_device *dev;
@@ -2036,7 +2036,7 @@ int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
                return -EIO;
        }
        bio->bi_bdev = dev->bdev;
-       bio_add_page(bio, page, length, start - page_offset(page));
+       bio_add_page(bio, page, length, pg_offset);
 
        if (btrfsic_submit_bio_wait(WRITE_SYNC, bio)) {
                /* try to remap that extent elsewhere? */
@@ -2067,7 +2067,8 @@ int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
        for (i = 0; i < num_pages; i++) {
                struct page *p = extent_buffer_page(eb, i);
                ret = repair_io_failure(root->fs_info, start, PAGE_CACHE_SIZE,
-                                       start, p, mirror_num);
+                                       start, p, start - page_offset(p),
+                                       mirror_num);
                if (ret)
                        break;
                start += PAGE_CACHE_SIZE;
@@ -2127,6 +2128,7 @@ static int clean_io_failure(u64 start, struct page *page)
                if (num_copies > 1)  {
                        repair_io_failure(fs_info, start, failrec->len,
                                          failrec->logical, page,
+                                         start - page_offset(page),
                                          failrec->failed_mirror);
                }
        }
index 75b621b7cd9fa67f9b32d158472edc820c00114b..a82ecbc2b84264a439bc7f4851e8ced9cfabc7f7 100644 (file)
@@ -340,7 +340,7 @@ struct btrfs_fs_info;
 
 int repair_io_failure(struct btrfs_fs_info *fs_info, u64 start,
                        u64 length, u64 logical, struct page *page,
-                       int mirror_num);
+                       unsigned int pg_offset, int mirror_num);
 int end_extent_writepage(struct page *page, int err, u64 start, u64 end);
 int repair_eb_io_failure(struct btrfs_root *root, struct extent_buffer *eb,
                         int mirror_num);
index 9d80e37044dbb36f73e3ad0d98465b530db0338c..c026fa6b9553df61da4c3f375eae8e0d5772eca5 100644 (file)
@@ -682,6 +682,7 @@ static int scrub_fixup_readpage(u64 inum, u64 offset, u64 root, void *fixup_ctx)
                fs_info = BTRFS_I(inode)->root->fs_info;
                ret = repair_io_failure(fs_info, offset, PAGE_SIZE,
                                        fixup->logical, page,
+                                       offset - page_offset(page),
                                        fixup->mirror_num);
                unlock_page(page);
                corrected = !ret;