btrfs: subpage: allow submit_extent_page() to do bio split
authorQu Wenruo <wqu@suse.com>
Mon, 26 Jul 2021 06:35:00 +0000 (14:35 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 23 Aug 2021 11:19:05 +0000 (13:19 +0200)
commite0eefe07f89516f57dac3fbb759b75a5f0a19ae4
tree3b7d7945f9aecb3e998d8013aa055606d4014d6a
parent7367253a351ef7202d215d3145d7e83e1472be7d
btrfs: subpage: allow submit_extent_page() to do bio split

Current submit_extent_page() just checks if the current page range can
be fitted into current bio, and if not, submit then re-add.

But this behavior can't handle subpage case at all.

For subpage case, the problem is in the page size, 64K, which is also
the same size as stripe size.

This means, if we can't fit a full 64K into a bio, due to stripe limit,
then it won't fit into next bio without crossing stripe either.

The proper way to handle it is:

- Check how many bytes we can be put into current bio
- Put as many bytes as possible into current bio first
- Submit current bio
- Create a new bio
- Add the remaining bytes into the new bio

Refactor submit_extent_page() so that it does the above iteration.

The main loop inside submit_extent_page() will look like this:

cur = pg_offset;
while (cur < pg_offset + size) {
u32 offset = cur - pg_offset;
int added;
if (!bio_ctrl->bio) {
/* Allocate new bio if needed */
}

/* Add as many bytes into the bio */
added = btrfs_bio_add_page();

if (added < size - offset) {
/* The current bio is full, submit it */
}
cur += added;
}

Also, since we're doing new bio allocation deep inside the main loop,
extract that code into a new helper, alloc_new_bio().

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c