Skip to content

Commit 2dabb32

Browse files
Chandan Rajendrakdave
authored andcommitted
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 <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent c40a3d3 commit 2dabb32

File tree

1 file changed

+75
-23
lines changed

1 file changed

+75
-23
lines changed

fs/btrfs/inode.c

Lines changed: 75 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7751,9 +7751,9 @@ static int btrfs_check_dio_repairable(struct inode *inode,
77517751
}
77527752

77537753
static int dio_read_error(struct inode *inode, struct bio *failed_bio,
7754-
struct page *page, u64 start, u64 end,
7755-
int failed_mirror, bio_end_io_t *repair_endio,
7756-
void *repair_arg)
7754+
struct page *page, unsigned int pgoff,
7755+
u64 start, u64 end, int failed_mirror,
7756+
bio_end_io_t *repair_endio, void *repair_arg)
77577757
{
77587758
struct io_failure_record *failrec;
77597759
struct bio *bio;
@@ -7774,15 +7774,17 @@ static int dio_read_error(struct inode *inode, struct bio *failed_bio,
77747774
return -EIO;
77757775
}
77767776

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))
77787780
read_mode = READ_SYNC | REQ_FAILFAST_DEV;
77797781
else
77807782
read_mode = READ_SYNC;
77817783

77827784
isector = start - btrfs_io_bio(failed_bio)->logical;
77837785
isector >>= inode->i_sb->s_blocksize_bits;
77847786
bio = btrfs_create_repair_bio(inode, failed_bio, failrec, page,
7785-
0, isector, repair_endio, repair_arg);
7787+
pgoff, isector, repair_endio, repair_arg);
77867788
if (!bio) {
77877789
free_io_failure(inode, failrec);
77887790
return -EIO;
@@ -7812,12 +7814,17 @@ struct btrfs_retry_complete {
78127814
static void btrfs_retry_endio_nocsum(struct bio *bio)
78137815
{
78147816
struct btrfs_retry_complete *done = bio->bi_private;
7817+
struct inode *inode;
78157818
struct bio_vec *bvec;
78167819
int i;
78177820

78187821
if (bio->bi_error)
78197822
goto end;
78207823

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+
78217828
done->uptodate = 1;
78227829
bio_for_each_segment_all(bvec, bio, i)
78237830
clean_io_failure(done->inode, done->start, bvec->bv_page, 0);
@@ -7829,36 +7836,51 @@ static void btrfs_retry_endio_nocsum(struct bio *bio)
78297836
static int __btrfs_correct_data_nocsum(struct inode *inode,
78307837
struct btrfs_io_bio *io_bio)
78317838
{
7839+
struct btrfs_fs_info *fs_info;
78327840
struct bio_vec *bvec;
78337841
struct btrfs_retry_complete done;
78347842
u64 start;
7843+
unsigned int pgoff;
7844+
u32 sectorsize;
7845+
int nr_sectors;
78357846
int i;
78367847
int ret;
78377848

7849+
fs_info = BTRFS_I(inode)->root->fs_info;
7850+
sectorsize = BTRFS_I(inode)->root->sectorsize;
7851+
78387852
start = io_bio->logical;
78397853
done.inode = inode;
78407854

78417855
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:
78437860
done.uptodate = 0;
78447861
done.start = start;
78457862
init_completion(&done.done);
78467863

7847-
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, start,
7848-
start + bvec->bv_len - 1,
7849-
io_bio->mirror_num,
7850-
btrfs_retry_endio_nocsum, &done);
7864+
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page,
7865+
pgoff, start, start + sectorsize - 1,
7866+
io_bio->mirror_num,
7867+
btrfs_retry_endio_nocsum, &done);
78517868
if (ret)
78527869
return ret;
78537870

78547871
wait_for_completion(&done.done);
78557872

78567873
if (!done.uptodate) {
78577874
/* We might have another mirror, so try again */
7858-
goto try_again;
7875+
goto next_block_or_try_again;
78597876
}
78607877

7861-
start += bvec->bv_len;
7878+
start += sectorsize;
7879+
7880+
if (nr_sectors--) {
7881+
pgoff += sectorsize;
7882+
goto next_block_or_try_again;
7883+
}
78627884
}
78637885

78647886
return 0;
@@ -7868,7 +7890,9 @@ static void btrfs_retry_endio(struct bio *bio)
78687890
{
78697891
struct btrfs_retry_complete *done = bio->bi_private;
78707892
struct btrfs_io_bio *io_bio = btrfs_io_bio(bio);
7893+
struct inode *inode;
78717894
struct bio_vec *bvec;
7895+
u64 start;
78727896
int uptodate;
78737897
int ret;
78747898
int i;
@@ -7877,13 +7901,20 @@ static void btrfs_retry_endio(struct bio *bio)
78777901
goto end;
78787902

78797903
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+
78807911
bio_for_each_segment_all(bvec, bio, i) {
78817912
ret = __readpage_endio_check(done->inode, io_bio, i,
7882-
bvec->bv_page, 0,
7883-
done->start, bvec->bv_len);
7913+
bvec->bv_page, bvec->bv_offset,
7914+
done->start, bvec->bv_len);
78847915
if (!ret)
78857916
clean_io_failure(done->inode, done->start,
7886-
bvec->bv_page, 0);
7917+
bvec->bv_page, bvec->bv_offset);
78877918
else
78887919
uptodate = 0;
78897920
}
@@ -7897,31 +7928,45 @@ static void btrfs_retry_endio(struct bio *bio)
78977928
static int __btrfs_subio_endio_read(struct inode *inode,
78987929
struct btrfs_io_bio *io_bio, int err)
78997930
{
7931+
struct btrfs_fs_info *fs_info;
79007932
struct bio_vec *bvec;
79017933
struct btrfs_retry_complete done;
79027934
u64 start;
79037935
u64 offset = 0;
7936+
u32 sectorsize;
7937+
int nr_sectors;
7938+
unsigned int pgoff;
7939+
int csum_pos;
79047940
int i;
79057941
int ret;
79067942

7943+
fs_info = BTRFS_I(inode)->root->fs_info;
7944+
sectorsize = BTRFS_I(inode)->root->sectorsize;
7945+
79077946
err = 0;
79087947
start = io_bio->logical;
79097948
done.inode = inode;
79107949

79117950
bio_for_each_segment_all(bvec, &io_bio->bio, i) {
7912-
ret = __readpage_endio_check(inode, io_bio, i, bvec->bv_page,
7913-
0, start, bvec->bv_len);
7951+
nr_sectors = BTRFS_BYTES_TO_BLKS(fs_info, 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);
79147959
if (likely(!ret))
79157960
goto next;
79167961
try_again:
79177962
done.uptodate = 0;
79187963
done.start = start;
79197964
init_completion(&done.done);
79207965

7921-
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page, start,
7922-
start + bvec->bv_len - 1,
7923-
io_bio->mirror_num,
7924-
btrfs_retry_endio, &done);
7966+
ret = dio_read_error(inode, &io_bio->bio, bvec->bv_page,
7967+
pgoff, start, start + sectorsize - 1,
7968+
io_bio->mirror_num,
7969+
btrfs_retry_endio, &done);
79257970
if (ret) {
79267971
err = ret;
79277972
goto next;
@@ -7934,8 +7979,15 @@ static int __btrfs_subio_endio_read(struct inode *inode,
79347979
goto try_again;
79357980
}
79367981
next:
7937-
offset += bvec->bv_len;
7938-
start += bvec->bv_len;
7982+
offset += sectorsize;
7983+
start += sectorsize;
7984+
7985+
ASSERT(nr_sectors);
7986+
7987+
if (--nr_sectors) {
7988+
pgoff += sectorsize;
7989+
goto next_block;
7990+
}
79397991
}
79407992

79417993
return err;

0 commit comments

Comments
 (0)