@@ -3032,6 +3032,7 @@ bool btrfs_bio_add_page(struct bio *bio, struct page *page, u64 logical,
{
sector_t sector = logical >> SECTOR_SHIFT;
bool contig;
+ int ret;
if (prev_bio_flags != bio_flags)
return false;
@@ -3046,7 +3047,19 @@ bool btrfs_bio_add_page(struct bio *bio, struct page *page, u64 logical,
if (btrfs_bio_fits_in_stripe(page, size, bio, bio_flags))
return false;
- return bio_add_page(bio, page, size, pg_offset) == size;
+ if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
+ struct bio orig_bio;
+
+ memset(&orig_bio, 0, sizeof(orig_bio));
+ bio_copy_dev(&orig_bio, bio);
+ bio_set_dev(bio, btrfs_io_bio(bio)->device->bdev);
+ ret = bio_add_zone_append_page(bio, page, size, pg_offset);
+ bio_copy_dev(bio, &orig_bio);
+ } else {
+ ret = bio_add_page(bio, page, size, pg_offset);
+ }
+
+ return ret == size;
}
/*
@@ -3077,7 +3090,9 @@ static int submit_extent_page(unsigned int opf,
int ret = 0;
struct bio *bio;
size_t page_size = min_t(size_t, size, PAGE_SIZE);
- struct extent_io_tree *tree = &BTRFS_I(page->mapping->host)->io_tree;
+ struct btrfs_inode *inode = BTRFS_I(page->mapping->host);
+ struct extent_io_tree *tree = &inode->io_tree;
+ struct btrfs_fs_info *fs_info = inode->root->fs_info;
ASSERT(bio_ret);
@@ -3108,11 +3123,27 @@ static int submit_extent_page(unsigned int opf,
if (wbc) {
struct block_device *bdev;
- bdev = BTRFS_I(page->mapping->host)->root->fs_info->fs_devices->latest_bdev;
+ bdev = fs_info->fs_devices->latest_bdev;
bio_set_dev(bio, bdev);
wbc_init_bio(wbc, bio);
wbc_account_cgroup_owner(wbc, page, page_size);
}
+ if (btrfs_fs_incompat(fs_info, ZONED) &&
+ bio_op(bio) == REQ_OP_ZONE_APPEND) {
+ struct extent_map *em;
+ struct map_lookup *map;
+
+ em = btrfs_get_chunk_map(fs_info, offset, page_size);
+ if (IS_ERR(em))
+ return PTR_ERR(em);
+
+ map = em->map_lookup;
+ /* only support SINGLE profile for now */
+ ASSERT(map->num_stripes == 1);
+ btrfs_io_bio(bio)->device = map->stripes[0].dev;
+
+ free_extent_map(em);
+ }
*bio_ret = bio;
Zoned device has its own hardware restrictions e.g. max_zone_append_size when using REQ_OP_ZONE_APPEND. To follow the restrictions, use bio_add_zone_append_page() instead of bio_add_page(). We need target device to use bio_add_zone_append_page(), so this commit reads the chunk information to memoize the target device to btrfs_io_bio(bio)->device. Currently, zoned btrfs only supports SINGLE profile. In the feature, btrfs_io_bio can hold extent_map and check the restrictions for all the devices the bio will be mapped. Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> --- fs/btrfs/extent_io.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-)