Btrfs: btrfs_submit_direct_hook: Handle map_length < bio vector length
In subpagesize-blocksize scenario, map_length can be less than the length of a bio vector. Such a condition may cause btrfs_submit_direct_hook() to submit a zero length bio. Fix this by comparing map_length against block size rather than with bv_len. Signed-off-by: Chandan Rajendra <chandan@linux.vnet.ibm.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Родитель
298cfd3683
Коммит
5f4dc8fc83
|
@ -8244,9 +8244,11 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
|
||||||
u64 file_offset = dip->logical_offset;
|
u64 file_offset = dip->logical_offset;
|
||||||
u64 submit_len = 0;
|
u64 submit_len = 0;
|
||||||
u64 map_length;
|
u64 map_length;
|
||||||
int nr_pages = 0;
|
u32 blocksize = root->sectorsize;
|
||||||
int ret;
|
|
||||||
int async_submit = 0;
|
int async_submit = 0;
|
||||||
|
int nr_sectors;
|
||||||
|
int ret;
|
||||||
|
int i;
|
||||||
|
|
||||||
map_length = orig_bio->bi_iter.bi_size;
|
map_length = orig_bio->bi_iter.bi_size;
|
||||||
ret = btrfs_map_block(root->fs_info, rw, start_sector << 9,
|
ret = btrfs_map_block(root->fs_info, rw, start_sector << 9,
|
||||||
|
@ -8276,9 +8278,12 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
|
||||||
atomic_inc(&dip->pending_bios);
|
atomic_inc(&dip->pending_bios);
|
||||||
|
|
||||||
while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
|
while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
|
||||||
if (map_length < submit_len + bvec->bv_len ||
|
nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, bvec->bv_len);
|
||||||
bio_add_page(bio, bvec->bv_page, bvec->bv_len,
|
i = 0;
|
||||||
bvec->bv_offset) < bvec->bv_len) {
|
next_block:
|
||||||
|
if (unlikely(map_length < submit_len + blocksize ||
|
||||||
|
bio_add_page(bio, bvec->bv_page, blocksize,
|
||||||
|
bvec->bv_offset + (i * blocksize)) < blocksize)) {
|
||||||
/*
|
/*
|
||||||
* inc the count before we submit the bio so
|
* inc the count before we submit the bio so
|
||||||
* we know the end IO handler won't happen before
|
* we know the end IO handler won't happen before
|
||||||
|
@ -8299,7 +8304,6 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
|
||||||
file_offset += submit_len;
|
file_offset += submit_len;
|
||||||
|
|
||||||
submit_len = 0;
|
submit_len = 0;
|
||||||
nr_pages = 0;
|
|
||||||
|
|
||||||
bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev,
|
bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev,
|
||||||
start_sector, GFP_NOFS);
|
start_sector, GFP_NOFS);
|
||||||
|
@ -8317,9 +8321,14 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto next_block;
|
||||||
} else {
|
} else {
|
||||||
submit_len += bvec->bv_len;
|
submit_len += blocksize;
|
||||||
nr_pages++;
|
if (--nr_sectors) {
|
||||||
|
i++;
|
||||||
|
goto next_block;
|
||||||
|
}
|
||||||
bvec++;
|
bvec++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче