Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5f4dc8fc authored by Chandan Rajendra's avatar Chandan Rajendra Committed by David Sterba
Browse files

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: default avatarChandan Rajendra <chandan@linux.vnet.ibm.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 298cfd36
Loading
Loading
Loading
Loading
+17 −8
Original line number Diff line number Diff line
@@ -8244,9 +8244,11 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
	u64 file_offset = dip->logical_offset;
	u64 submit_len = 0;
	u64 map_length;
	int nr_pages = 0;
	int ret;
	u32 blocksize = root->sectorsize;
	int async_submit = 0;
	int nr_sectors;
	int ret;
	int i;

	map_length = orig_bio->bi_iter.bi_size;
	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);

	while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) {
		if (map_length < submit_len + bvec->bv_len ||
		    bio_add_page(bio, bvec->bv_page, bvec->bv_len,
				 bvec->bv_offset) < bvec->bv_len) {
		nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, bvec->bv_len);
		i = 0;
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
			 * 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;

			submit_len = 0;
			nr_pages = 0;

			bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev,
						  start_sector, GFP_NOFS);
@@ -8317,9 +8321,14 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
				bio_put(bio);
				goto out_err;
			}

			goto next_block;
		} else {
			submit_len += bvec->bv_len;
			nr_pages++;
			submit_len += blocksize;
			if (--nr_sectors) {
				i++;
				goto next_block;
			}
			bvec++;
		}
	}