diff options
author | Chandan Rajendra <chandan@linux.vnet.ibm.com> | 2016-01-21 05:25:55 -0500 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-02-01 13:23:47 -0500 |
commit | 2dabb3248453be9b81906dd028ec6979708de7be (patch) | |
tree | c352bb791f5b331e1bbeac7740c7656abd461c4a /fs/btrfs/inode.c | |
parent | c40a3d38aff4e1c832d1692850621be7d5e5308c (diff) |
Btrfs: Direct I/O read: Work on sectorsized blocks
The direct I/O read's endio and corresponding repair functions work on
page sized blocks. This commit adds the ability for direct I/O read to work on
subpagesized blocks.
Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 98 |
1 files changed, 75 insertions, 23 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index e4565456eb01..53c9dd1c0f28 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -7751,9 +7751,9 @@ static int btrfs_check_dio_repairable(struct inode *inode, | |||
7751 | } | 7751 | } |
7752 | 7752 | ||
7753 | static int dio_read_error(struct inode *inode, struct bio *failed_bio, | 7753 | static int dio_read_error(struct inode *inode, struct bio *failed_bio, |
7754 | struct page *page, u64 start, u64 end, | 7754 | struct page *page, unsigned int pgoff, |
7755 | int failed_mirror, bio_end_io_t *repair_endio, | 7755 | u64 start, u64 end, int failed_mirror, |
7756 | void *repair_arg) | 7756 | bio_end_io_t *repair_endio, void *repair_arg) |
7757 | { | 7757 | { |
7758 | struct io_failure_record *failrec; | 7758 | struct io_failure_record *failrec; |
7759 | struct bio *bio; | 7759 | struct bio *bio; |
@@ -7774,7 +7774,9 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, | |||
7774 | return -EIO; | 7774 | return -EIO; |
7775 | } | 7775 | } |
7776 | 7776 | ||
7777 | if (failed_bio->bi_vcnt > 1) | 7777 | if ((failed_bio->bi_vcnt > 1) |
7778 | || (failed_bio->bi_io_vec->bv_len | ||
7779 | > BTRFS_I(inode)->root->sectorsize)) | ||
7778 | read_mode = READ_SYNC | REQ_FAILFAST_DEV; | 7780 | read_mode = READ_SYNC | REQ_FAILFAST_DEV; |
7779 | else | 7781 | else |
7780 | read_mode = READ_SYNC; | 7782 | read_mode = READ_SYNC; |
@@ -7782,7 +7784,7 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio, | |||
7782 | isector = start - btrfs_io_bio(failed_bio)->logical; | 7784 | isector = start - btrfs_io_bio(failed_bio)->logical; |
7783 | isector >>= inode->i_sb->s_blocksize_bits; | 7785 | isector >>= inode->i_sb->s_blocksize_bits; |
7784 | bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, | 7786 | bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page, |
7785 | 0, isector, repair_endio, repair_arg); | 7787 | pgoff, isector, repair_endio, repair_arg); |
7786 | if (!bio) { | 7788 | if (!bio) { |
7787 | free_io_failure(inode, failrec); | 7789 | free_io_failure(inode, failrec); |
7788 | return -EIO; | 7790 | return -EIO; |
@@ -7812,12 +7814,17 @@ struct btrfs_retry_complete { | |||
7812 | static void btrfs_retry_endio_nocsum(struct bio *bio) | 7814 | static void btrfs_retry_endio_nocsum(struct bio *bio) |
7813 | { | 7815 | { |
7814 | struct btrfs_retry_complete *done = bio->bi_private; | 7816 | struct btrfs_retry_complete *done = bio->bi_private; |
7817 | struct inode *inode; | ||
7815 | struct bio_vec *bvec; | 7818 | struct bio_vec *bvec; |
7816 | int i; | 7819 | int i; |
7817 | 7820 | ||
7818 | if (bio->bi_error) | 7821 | if (bio->bi_error) |
7819 | goto end; | 7822 | goto end; |
7820 | 7823 | ||
7824 | ASSERT(bio->bi_vcnt == 1); | ||
7825 | inode = bio->bi_io_vec->bv_page->mapping->host; | ||
7826 | ASSERT(bio->bi_io_vec->bv_len == BTRFS_I(inode)->root->sectorsize); | ||
7827 | |||
7821 | done->uptodate = 1; | 7828 | done->uptodate = 1; |
7822 | bio_for_each_segment_all(bvec, bio, i) | 7829 | bio_for_each_segment_all(bvec, bio, i) |
7823 | clean_io_failure(done->inode, done->start, bvec->bv_page, 0); | 7830 | clean_io_failure(done->inode, done->start, bvec->bv_page, 0); |
@@ -7829,25 +7836,35 @@ end: | |||
7829 | static int __btrfs_correct_data_nocsum(struct inode *inode, | 7836 | static int __btrfs_correct_data_nocsum(struct inode *inode, |
7830 | struct btrfs_io_bio *io_bio) | 7837 | struct btrfs_io_bio *io_bio) |
7831 | { | 7838 | { |
7839 | struct btrfs_fs_info *fs_info; | ||
7832 | struct bio_vec *bvec; | 7840 | struct bio_vec *bvec; |
7833 | struct btrfs_retry_complete done; | 7841 | struct btrfs_retry_complete done; |
7834 | u64 start; | 7842 | u64 start; |
7843 | unsigned int pgoff; | ||
7844 | u32 sectorsize; | ||
7845 | int nr_sectors; | ||
7835 | int i; | 7846 | int i; |
7836 | int ret; | 7847 | int ret; |
7837 | 7848 | ||
7849 | fs_info = BTRFS_I(inode)->root->fs_info; | ||
7850 | sectorsize = BTRFS_I(inode)->root->sectorsize; | ||
7851 | |||
7838 | start = io_bio->logical; | 7852 | start = io_bio->logical; |
7839 | done.inode = inode; | 7853 | done.inode = inode; |
7840 | 7854 | ||
7841 | bio_for_each_segment_all(bvec, &io_bio->bio, i) { | 7855 | bio_for_each_segment_all(bvec, &io_bio->bio, i) { |
7842 | try_again: | 7856 | nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len); |
7857 | pgoff = bvec->bv_offset; | ||
7858 | |||
7859 | next_block_or_try_again: | ||
7843 | done.uptodate = 0; | 7860 | done.uptodate = 0; |
7844 | done.start = start; | 7861 | done.start = start; |
7845 | init_completion(&done.done); | 7862 | init_completion(&done.done); |
7846 | 7863 | ||
7847 | ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, start, | 7864 | ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, |
7848 | start + bvec->bv_len - 1, | 7865 | pgoff, start, start + sectorsize - 1, |
7849 | io_bio->mirror_num, | 7866 | io_bio->mirror_num, |
7850 | btrfs_retry_endio_nocsum, &done); | 7867 | btrfs_retry_endio_nocsum, &done); |
7851 | if (ret) | 7868 | if (ret) |
7852 | return ret; | 7869 | return ret; |
7853 | 7870 | ||
@@ -7855,10 +7872,15 @@ try_again: | |||
7855 | 7872 | ||
7856 | if (!done.uptodate) { | 7873 | if (!done.uptodate) { |
7857 | /* We might have another mirror, so try again */ | 7874 | /* We might have another mirror, so try again */ |
7858 | goto try_again; | 7875 | goto next_block_or_try_again; |
7859 | } | 7876 | } |
7860 | 7877 | ||
7861 | start += bvec->bv_len; | 7878 | start += sectorsize; |
7879 | |||
7880 | if (nr_sectors--) { | ||
7881 | pgoff += sectorsize; | ||
7882 | goto next_block_or_try_again; | ||
7883 | } | ||
7862 | } | 7884 | } |
7863 | 7885 | ||
7864 | return 0; | 7886 | return 0; |
@@ -7868,7 +7890,9 @@ static void btrfs_retry_endio(struct bio *bio) | |||
7868 | { | 7890 | { |
7869 | struct btrfs_retry_complete *done = bio->bi_private; | 7891 | struct btrfs_retry_complete *done = bio->bi_private; |
7870 | struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); | 7892 | struct btrfs_io_bio *io_bio = btrfs_io_bio(bio); |
7893 | struct inode *inode; | ||
7871 | struct bio_vec *bvec; | 7894 | struct bio_vec *bvec; |
7895 | u64 start; | ||
7872 | int uptodate; | 7896 | int uptodate; |
7873 | int ret; | 7897 | int ret; |
7874 | int i; | 7898 | int i; |
@@ -7877,13 +7901,20 @@ static void btrfs_retry_endio(struct bio *bio) | |||
7877 | goto end; | 7901 | goto end; |
7878 | 7902 | ||
7879 | uptodate = 1; | 7903 | uptodate = 1; |
7904 | |||
7905 | start = done->start; | ||
7906 | |||
7907 | ASSERT(bio->bi_vcnt == 1); | ||
7908 | inode = bio->bi_io_vec->bv_page->mapping->host; | ||
7909 | ASSERT(bio->bi_io_vec->bv_len == BTRFS_I(inode)->root->sectorsize); | ||
7910 | |||
7880 | bio_for_each_segment_all(bvec, bio, i) { | 7911 | bio_for_each_segment_all(bvec, bio, i) { |
7881 | ret = __readpage_endio_check(done->inode, io_bio, i, | 7912 | ret = __readpage_endio_check(done->inode, io_bio, i, |
7882 | bvec->bv_page, 0, | 7913 | bvec->bv_page, bvec->bv_offset, |
7883 | done->start, bvec->bv_len); | 7914 | done->start, bvec->bv_len); |
7884 | if (!ret) | 7915 | if (!ret) |
7885 | clean_io_failure(done->inode, done->start, | 7916 | clean_io_failure(done->inode, done->start, |
7886 | bvec->bv_page, 0); | 7917 | bvec->bv_page, bvec->bv_offset); |
7887 | else | 7918 | else |
7888 | uptodate = 0; | 7919 | uptodate = 0; |
7889 | } | 7920 | } |
@@ -7897,20 +7928,34 @@ end: | |||
7897 | static int __btrfs_subio_endio_read(struct inode *inode, | 7928 | static int __btrfs_subio_endio_read(struct inode *inode, |
7898 | struct btrfs_io_bio *io_bio, int err) | 7929 | struct btrfs_io_bio *io_bio, int err) |
7899 | { | 7930 | { |
7931 | struct btrfs_fs_info *fs_info; | ||
7900 | struct bio_vec *bvec; | 7932 | struct bio_vec *bvec; |
7901 | struct btrfs_retry_complete done; | 7933 | struct btrfs_retry_complete done; |
7902 | u64 start; | 7934 | u64 start; |
7903 | u64 offset = 0; | 7935 | u64 offset = 0; |
7936 | u32 sectorsize; | ||
7937 | int nr_sectors; | ||
7938 | unsigned int pgoff; | ||
7939 | int csum_pos; | ||
7904 | int i; | 7940 | int i; |
7905 | int ret; | 7941 | int ret; |
7906 | 7942 | ||
7943 | fs_info = BTRFS_I(inode)->root->fs_info; | ||
7944 | sectorsize = BTRFS_I(inode)->root->sectorsize; | ||
7945 | |||
7907 | err = 0; | 7946 | err = 0; |
7908 | start = io_bio->logical; | 7947 | start = io_bio->logical; |
7909 | done.inode = inode; | 7948 | done.inode = inode; |
7910 | 7949 | ||
7911 | bio_for_each_segment_all(bvec, &io_bio->bio, i) { | 7950 | bio_for_each_segment_all(bvec, &io_bio->bio, i) { |
7912 | ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page, | 7951 | nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, bvec->bv_len); |
7913 | 0, start, bvec->bv_len); | 7952 | |
7953 | pgoff = bvec->bv_offset; | ||
7954 | next_block: | ||
7955 | csum_pos = BTRFS_BYTES_TO_BLKS(fs_info, offset); | ||
7956 | ret = __readpage_endio_check(inode, io_bio, csum_pos, | ||
7957 | bvec->bv_page, pgoff, start, | ||
7958 | sectorsize); | ||
7914 | if (likely(!ret)) | 7959 | if (likely(!ret)) |
7915 | goto next; | 7960 | goto next; |
7916 | try_again: | 7961 | try_again: |
@@ -7918,10 +7963,10 @@ try_again: | |||
7918 | done.start = start; | 7963 | done.start = start; |
7919 | init_completion(&done.done); | 7964 | init_completion(&done.done); |
7920 | 7965 | ||
7921 | ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, start, | 7966 | ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, |
7922 | start + bvec->bv_len - 1, | 7967 | pgoff, start, start + sectorsize - 1, |
7923 | io_bio->mirror_num, | 7968 | io_bio->mirror_num, |
7924 | btrfs_retry_endio, &done); | 7969 | btrfs_retry_endio, &done); |
7925 | if (ret) { | 7970 | if (ret) { |
7926 | err = ret; | 7971 | err = ret; |
7927 | goto next; | 7972 | goto next; |
@@ -7934,8 +7979,15 @@ try_again: | |||
7934 | goto try_again; | 7979 | goto try_again; |
7935 | } | 7980 | } |
7936 | next: | 7981 | next: |
7937 | offset += bvec->bv_len; | 7982 | offset += sectorsize; |
7938 | start += bvec->bv_len; | 7983 | start += sectorsize; |
7984 | |||
7985 | ASSERT(nr_sectors); | ||
7986 | |||
7987 | if (--nr_sectors) { | ||
7988 | pgoff += sectorsize; | ||
7989 | goto next_block; | ||
7990 | } | ||
7939 | } | 7991 | } |
7940 | 7992 | ||
7941 | return err; | 7993 | return err; |