--- /dev/null
+From 570b1cac477643cbf01a45fa5d018430a1fddbce Mon Sep 17 00:00:00 2001
+From: Xie Yongji <xieyongji@bytedance.com>
+Date: Tue, 26 Oct 2021 22:40:12 +0800
+Subject: block: Add a helper to validate the block size
+
+From: Xie Yongji <xieyongji@bytedance.com>
+
+commit 570b1cac477643cbf01a45fa5d018430a1fddbce upstream.
+
+There are some duplicated codes to validate the block
+size in block drivers. This limitation actually comes
+from block layer, so this patch tries to add a new block
+layer helper for that.
+
+Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
+Link: https://lore.kernel.org/r/20211026144015.188-2-xieyongji@bytedance.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/blkdev.h | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/include/linux/blkdev.h
++++ b/include/linux/blkdev.h
+@@ -235,6 +235,14 @@ struct request {
+ void *end_io_data;
+ };
+
++static inline int blk_validate_block_size(unsigned int bsize)
++{
++ if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize))
++ return -EINVAL;
++
++ return 0;
++}
++
+ static inline bool blk_op_is_passthrough(unsigned int op)
+ {
+ op &= REQ_OP_MASK;
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:17 +0900
+Subject: btrfs: check for relocation inodes on zoned btrfs in should_nocow
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <2b57613ad55081ae305f66db17dec297f84c04ca.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit 2adada886b26e998b5a624e72f0834ebfdc54cc7 upstream
+
+Prepare for allowing preallocation for relocation inodes.
+
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/inode.c | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1945,7 +1945,15 @@ int btrfs_run_delalloc_range(struct btrf
+ const bool zoned = btrfs_is_zoned(inode->root->fs_info);
+
+ if (should_nocow(inode, start, end)) {
+- ASSERT(!zoned);
++ /*
++ * Normally on a zoned device we're only doing COW writes, but
++ * in case of relocation on a zoned filesystem we have taken
++ * precaution, that we're only writing sequentially. It's safe
++ * to use run_delalloc_nocow() here, like for regular
++ * preallocated inodes.
++ */
++ ASSERT(!zoned ||
++ (zoned && btrfs_is_data_reloc_root(inode->root)));
+ ret = run_delalloc_nocow(inode, locked_page, start, end,
+ page_started, nr_written);
+ } else if (!inode_can_compress(inode) ||
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:13 +0900
+Subject: btrfs: introduce btrfs_is_data_reloc_root
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <04ade7dd079c065161302c626045a8a88d089d8d.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit 37f00a6d2e9c97d6e7b5c3d47c49b714c3d0b99f upstream
+
+There are several places in our codebase where we check if a root is the
+root of the data reloc tree and subsequent patches will introduce more.
+
+Factor out the check into a small helper function instead of open coding
+it multiple times.
+
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/ctree.h | 5 +++++
+ fs/btrfs/disk-io.c | 2 +-
+ fs/btrfs/extent-tree.c | 2 +-
+ fs/btrfs/inode.c | 19 ++++++++-----------
+ fs/btrfs/relocation.c | 3 +--
+ 5 files changed, 16 insertions(+), 15 deletions(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -3842,6 +3842,11 @@ static inline bool btrfs_is_zoned(const
+ return fs_info->zoned != 0;
+ }
+
++static inline bool btrfs_is_data_reloc_root(const struct btrfs_root *root)
++{
++ return root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID;
++}
++
+ /*
+ * We use page status Private2 to indicate there is an ordered extent with
+ * unfinished IO.
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -1500,7 +1500,7 @@ static int btrfs_init_fs_root(struct btr
+ goto fail;
+
+ if (root->root_key.objectid != BTRFS_TREE_LOG_OBJECTID &&
+- root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) {
++ !btrfs_is_data_reloc_root(root)) {
+ set_bit(BTRFS_ROOT_SHAREABLE, &root->state);
+ btrfs_check_and_init_root_item(&root->root_item);
+ }
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -2376,7 +2376,7 @@ int btrfs_cross_ref_exist(struct btrfs_r
+
+ out:
+ btrfs_free_path(path);
+- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
++ if (btrfs_is_data_reloc_root(root))
+ WARN_ON(ret > 0);
+ return ret;
+ }
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -1151,7 +1151,7 @@ static noinline int cow_file_range(struc
+ * fails during the stage where it updates the bytenr of file extent
+ * items.
+ */
+- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
++ if (btrfs_is_data_reloc_root(root))
+ min_alloc_size = num_bytes;
+ else
+ min_alloc_size = fs_info->sectorsize;
+@@ -1187,8 +1187,7 @@ static noinline int cow_file_range(struc
+ if (ret)
+ goto out_drop_extent_cache;
+
+- if (root->root_key.objectid ==
+- BTRFS_DATA_RELOC_TREE_OBJECTID) {
++ if (btrfs_is_data_reloc_root(root)) {
+ ret = btrfs_reloc_clone_csums(inode, start,
+ cur_alloc_size);
+ /*
+@@ -1504,8 +1503,7 @@ static int fallback_to_cow(struct btrfs_
+ int *page_started, unsigned long *nr_written)
+ {
+ const bool is_space_ino = btrfs_is_free_space_inode(inode);
+- const bool is_reloc_ino = (inode->root->root_key.objectid ==
+- BTRFS_DATA_RELOC_TREE_OBJECTID);
++ const bool is_reloc_ino = btrfs_is_data_reloc_root(inode->root);
+ const u64 range_bytes = end + 1 - start;
+ struct extent_io_tree *io_tree = &inode->io_tree;
+ u64 range_start = start;
+@@ -1867,8 +1865,7 @@ out_check:
+ btrfs_dec_nocow_writers(fs_info, disk_bytenr);
+ nocow = false;
+
+- if (root->root_key.objectid ==
+- BTRFS_DATA_RELOC_TREE_OBJECTID)
++ if (btrfs_is_data_reloc_root(root))
+ /*
+ * Error handled later, as we must prevent
+ * extent_clear_unlock_delalloc() in error handler
+@@ -2207,7 +2204,7 @@ void btrfs_clear_delalloc_extent(struct
+ if (btrfs_is_testing(fs_info))
+ return;
+
+- if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID &&
++ if (!btrfs_is_data_reloc_root(root) &&
+ do_list && !(state->state & EXTENT_NORESERVE) &&
+ (*bits & EXTENT_CLEAR_DATA_RESV))
+ btrfs_free_reserved_data_space_noquota(fs_info, len);
+@@ -2532,7 +2529,7 @@ blk_status_t btrfs_submit_data_bio(struc
+ goto mapit;
+ } else if (async && !skip_sum) {
+ /* csum items have already been cloned */
+- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID)
++ if (btrfs_is_data_reloc_root(root))
+ goto mapit;
+ /* we're doing a write, do the async checksumming */
+ ret = btrfs_wq_submit_bio(inode, bio, mirror_num, bio_flags,
+@@ -3304,7 +3301,7 @@ unsigned int btrfs_verify_data_csum(stru
+ u64 file_offset = pg_off + page_offset(page);
+ int ret;
+
+- if (root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID &&
++ if (btrfs_is_data_reloc_root(root) &&
+ test_range_bit(io_tree, file_offset,
+ file_offset + sectorsize - 1,
+ EXTENT_NODATASUM, 1, NULL)) {
+@@ -4005,7 +4002,7 @@ noinline int btrfs_update_inode(struct b
+ * without delay
+ */
+ if (!btrfs_is_free_space_inode(inode)
+- && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
++ && !btrfs_is_data_reloc_root(root)
+ && !test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) {
+ btrfs_update_root_times(trans, root);
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -4386,8 +4386,7 @@ int btrfs_reloc_cow_block(struct btrfs_t
+ if (!rc)
+ return 0;
+
+- BUG_ON(rc->stage == UPDATE_DATA_PTRS &&
+- root->root_key.objectid == BTRFS_DATA_RELOC_TREE_OBJECTID);
++ BUG_ON(rc->stage == UPDATE_DATA_PTRS && btrfs_is_data_reloc_root(root));
+
+ level = btrfs_header_level(buf);
+ if (btrfs_header_generation(buf) <=
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:14 +0900
+Subject: btrfs: zoned: add a dedicated data relocation block group
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <65b0ea66b418feb236d42410795d024a516eb843.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit c2707a25562343511bf9a3a6a636a16a822204eb upstream
+
+Relocation in a zoned filesystem can fail with a transaction abort with
+error -22 (EINVAL). This happens because the relocation code assumes that
+the extents we relocated the data to have the same size the source extents
+had and ensures this by preallocating the extents.
+
+But in a zoned filesystem we currently can't preallocate the extents as
+this would break the sequential write required rule. Therefore it can
+happen that the writeback process kicks in while we're still adding pages
+to a delalloc range and starts writing out dirty pages.
+
+This then creates destination extents that are smaller than the source
+extents, triggering the following safety check in get_new_location():
+
+ 1034 if (num_bytes != btrfs_file_extent_disk_num_bytes(leaf, fi)) {
+ 1035 ret = -EINVAL;
+ 1036 goto out;
+ 1037 }
+
+Temporarily create a dedicated block group for the relocation process, so
+no non-relocation data writes can interfere with the relocation writes.
+
+This is needed that we can switch the relocation process on a zoned
+filesystem from the REQ_OP_ZONE_APPEND writing we use for data to a scheme
+like in a non-zoned filesystem using REQ_OP_WRITE and preallocation.
+
+Fixes: 32430c614844 ("btrfs: zoned: enable relocation on a zoned filesystem")
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/block-group.c | 1
+ fs/btrfs/ctree.h | 7 ++++++
+ fs/btrfs/disk-io.c | 1
+ fs/btrfs/extent-tree.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++--
+ fs/btrfs/zoned.c | 10 +++++++++
+ fs/btrfs/zoned.h | 3 ++
+ 6 files changed, 74 insertions(+), 2 deletions(-)
+
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -902,6 +902,7 @@ int btrfs_remove_block_group(struct btrf
+ spin_unlock(&cluster->refill_lock);
+
+ btrfs_clear_treelog_bg(block_group);
++ btrfs_clear_data_reloc_bg(block_group);
+
+ path = btrfs_alloc_path();
+ if (!path) {
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -1017,6 +1017,13 @@ struct btrfs_fs_info {
+ spinlock_t treelog_bg_lock;
+ u64 treelog_bg;
+
++ /*
++ * Start of the dedicated data relocation block group, protected by
++ * relocation_bg_lock.
++ */
++ spinlock_t relocation_bg_lock;
++ u64 data_reloc_bg;
++
+ #ifdef CONFIG_BTRFS_FS_REF_VERIFY
+ spinlock_t ref_verify_lock;
+ struct rb_root block_tree;
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -2883,6 +2883,7 @@ void btrfs_init_fs_info(struct btrfs_fs_
+ spin_lock_init(&fs_info->buffer_lock);
+ spin_lock_init(&fs_info->unused_bgs_lock);
+ spin_lock_init(&fs_info->treelog_bg_lock);
++ spin_lock_init(&fs_info->relocation_bg_lock);
+ rwlock_init(&fs_info->tree_mod_log_lock);
+ mutex_init(&fs_info->unused_bg_unpin_mutex);
+ mutex_init(&fs_info->reclaim_bgs_lock);
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -3495,6 +3495,9 @@ struct find_free_extent_ctl {
+ /* Allocation is called for tree-log */
+ bool for_treelog;
+
++ /* Allocation is called for data relocation */
++ bool for_data_reloc;
++
+ /* RAID index, converted from flags */
+ int index;
+
+@@ -3756,6 +3759,7 @@ static int do_allocation_zoned(struct bt
+ u64 avail;
+ u64 bytenr = block_group->start;
+ u64 log_bytenr;
++ u64 data_reloc_bytenr;
+ int ret = 0;
+ bool skip;
+
+@@ -3773,13 +3777,31 @@ static int do_allocation_zoned(struct bt
+ if (skip)
+ return 1;
+
++ /*
++ * Do not allow non-relocation blocks in the dedicated relocation block
++ * group, and vice versa.
++ */
++ spin_lock(&fs_info->relocation_bg_lock);
++ data_reloc_bytenr = fs_info->data_reloc_bg;
++ if (data_reloc_bytenr &&
++ ((ffe_ctl->for_data_reloc && bytenr != data_reloc_bytenr) ||
++ (!ffe_ctl->for_data_reloc && bytenr == data_reloc_bytenr)))
++ skip = true;
++ spin_unlock(&fs_info->relocation_bg_lock);
++ if (skip)
++ return 1;
++
+ spin_lock(&space_info->lock);
+ spin_lock(&block_group->lock);
+ spin_lock(&fs_info->treelog_bg_lock);
++ spin_lock(&fs_info->relocation_bg_lock);
+
+ ASSERT(!ffe_ctl->for_treelog ||
+ block_group->start == fs_info->treelog_bg ||
+ fs_info->treelog_bg == 0);
++ ASSERT(!ffe_ctl->for_data_reloc ||
++ block_group->start == fs_info->data_reloc_bg ||
++ fs_info->data_reloc_bg == 0);
+
+ if (block_group->ro) {
+ ret = 1;
+@@ -3796,6 +3818,16 @@ static int do_allocation_zoned(struct bt
+ goto out;
+ }
+
++ /*
++ * Do not allow currently used block group to be the data relocation
++ * dedicated block group.
++ */
++ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg &&
++ (block_group->used || block_group->reserved)) {
++ ret = 1;
++ goto out;
++ }
++
+ avail = block_group->length - block_group->alloc_offset;
+ if (avail < num_bytes) {
+ if (ffe_ctl->max_extent_size < avail) {
+@@ -3813,6 +3845,9 @@ static int do_allocation_zoned(struct bt
+ if (ffe_ctl->for_treelog && !fs_info->treelog_bg)
+ fs_info->treelog_bg = block_group->start;
+
++ if (ffe_ctl->for_data_reloc && !fs_info->data_reloc_bg)
++ fs_info->data_reloc_bg = block_group->start;
++
+ ffe_ctl->found_offset = start + block_group->alloc_offset;
+ block_group->alloc_offset += num_bytes;
+ spin_lock(&ctl->tree_lock);
+@@ -3829,6 +3864,9 @@ static int do_allocation_zoned(struct bt
+ out:
+ if (ret && ffe_ctl->for_treelog)
+ fs_info->treelog_bg = 0;
++ if (ret && ffe_ctl->for_data_reloc)
++ fs_info->data_reloc_bg = 0;
++ spin_unlock(&fs_info->relocation_bg_lock);
+ spin_unlock(&fs_info->treelog_bg_lock);
+ spin_unlock(&block_group->lock);
+ spin_unlock(&space_info->lock);
+@@ -4085,6 +4123,12 @@ static int prepare_allocation(struct btr
+ ffe_ctl->hint_byte = fs_info->treelog_bg;
+ spin_unlock(&fs_info->treelog_bg_lock);
+ }
++ if (ffe_ctl->for_data_reloc) {
++ spin_lock(&fs_info->relocation_bg_lock);
++ if (fs_info->data_reloc_bg)
++ ffe_ctl->hint_byte = fs_info->data_reloc_bg;
++ spin_unlock(&fs_info->relocation_bg_lock);
++ }
+ return 0;
+ default:
+ BUG();
+@@ -4129,6 +4173,8 @@ static noinline int find_free_extent(str
+ struct btrfs_space_info *space_info;
+ bool full_search = false;
+ bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
++ bool for_data_reloc = (btrfs_is_data_reloc_root(root) &&
++ flags & BTRFS_BLOCK_GROUP_DATA);
+
+ WARN_ON(num_bytes < fs_info->sectorsize);
+
+@@ -4143,6 +4189,7 @@ static noinline int find_free_extent(str
+ ffe_ctl.found_offset = 0;
+ ffe_ctl.hint_byte = hint_byte_orig;
+ ffe_ctl.for_treelog = for_treelog;
++ ffe_ctl.for_data_reloc = for_data_reloc;
+ ffe_ctl.policy = BTRFS_EXTENT_ALLOC_CLUSTERED;
+
+ /* For clustered allocation */
+@@ -4220,6 +4267,8 @@ search:
+ if (unlikely(block_group->ro)) {
+ if (for_treelog)
+ btrfs_clear_treelog_bg(block_group);
++ if (ffe_ctl.for_data_reloc)
++ btrfs_clear_data_reloc_bg(block_group);
+ continue;
+ }
+
+@@ -4408,6 +4457,7 @@ int btrfs_reserve_extent(struct btrfs_ro
+ u64 flags;
+ int ret;
+ bool for_treelog = (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
++ bool for_data_reloc = (btrfs_is_data_reloc_root(root) && is_data);
+
+ flags = get_alloc_profile_by_root(root, is_data);
+ again:
+@@ -4431,8 +4481,8 @@ again:
+
+ sinfo = btrfs_find_space_info(fs_info, flags);
+ btrfs_err(fs_info,
+- "allocation failed flags %llu, wanted %llu tree-log %d",
+- flags, num_bytes, for_treelog);
++ "allocation failed flags %llu, wanted %llu tree-log %d, relocation: %d",
++ flags, num_bytes, for_treelog, for_data_reloc);
+ if (sinfo)
+ btrfs_dump_space_info(fs_info, sinfo,
+ num_bytes, 1);
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1530,3 +1530,13 @@ struct btrfs_device *btrfs_zoned_get_dev
+
+ return device;
+ }
++
++void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg)
++{
++ struct btrfs_fs_info *fs_info = bg->fs_info;
++
++ spin_lock(&fs_info->relocation_bg_lock);
++ if (fs_info->data_reloc_bg == bg->start)
++ fs_info->data_reloc_bg = 0;
++ spin_unlock(&fs_info->relocation_bg_lock);
++}
+--- a/fs/btrfs/zoned.h
++++ b/fs/btrfs/zoned.h
+@@ -66,6 +66,7 @@ int btrfs_sync_zone_write_pointer(struct
+ u64 physical_start, u64 physical_pos);
+ struct btrfs_device *btrfs_zoned_get_device(struct btrfs_fs_info *fs_info,
+ u64 logical, u64 length);
++void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg);
+ #else /* CONFIG_BLK_DEV_ZONED */
+ static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
+ struct blk_zone *zone)
+@@ -199,6 +200,8 @@ static inline struct btrfs_device *btrfs
+ return ERR_PTR(-EOPNOTSUPP);
+ }
+
++static inline void btrfs_clear_data_reloc_bg(struct btrfs_block_group *bg) { }
++
+ #endif
+
+ static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:18 +0900
+Subject: btrfs: zoned: allow preallocation for relocation inodes
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <f53fa091456972561fc4abce280bc5773dbe8254.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit 960a3166aed015887cd54423a6589ae4d0b65bd5 upstream
+
+Now that we use a dedicated block group and regular writes for data
+relocation, we can preallocate the space needed for a relocated inode,
+just like we do in regular mode.
+
+Essentially this reverts commit 32430c614844 ("btrfs: zoned: enable
+relocation on a zoned filesystem") as it is not needed anymore.
+
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/relocation.c | 35 ++---------------------------------
+ 1 file changed, 2 insertions(+), 33 deletions(-)
+
+--- a/fs/btrfs/relocation.c
++++ b/fs/btrfs/relocation.c
+@@ -2852,31 +2852,6 @@ static noinline_for_stack int prealloc_f
+ if (ret)
+ return ret;
+
+- /*
+- * On a zoned filesystem, we cannot preallocate the file region.
+- * Instead, we dirty and fiemap_write the region.
+- */
+- if (btrfs_is_zoned(inode->root->fs_info)) {
+- struct btrfs_root *root = inode->root;
+- struct btrfs_trans_handle *trans;
+-
+- end = cluster->end - offset + 1;
+- trans = btrfs_start_transaction(root, 1);
+- if (IS_ERR(trans))
+- return PTR_ERR(trans);
+-
+- inode->vfs_inode.i_ctime = current_time(&inode->vfs_inode);
+- i_size_write(&inode->vfs_inode, end);
+- ret = btrfs_update_inode(trans, root, inode);
+- if (ret) {
+- btrfs_abort_transaction(trans, ret);
+- btrfs_end_transaction(trans);
+- return ret;
+- }
+-
+- return btrfs_end_transaction(trans);
+- }
+-
+ btrfs_inode_lock(&inode->vfs_inode, 0);
+ for (nr = 0; nr < cluster->nr; nr++) {
+ start = cluster->boundary[nr] - offset;
+@@ -3084,7 +3059,6 @@ release_page:
+ static int relocate_file_extent_cluster(struct inode *inode,
+ struct file_extent_cluster *cluster)
+ {
+- struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
+ u64 offset = BTRFS_I(inode)->index_cnt;
+ unsigned long index;
+ unsigned long last_index;
+@@ -3114,8 +3088,6 @@ static int relocate_file_extent_cluster(
+ for (index = (cluster->start - offset) >> PAGE_SHIFT;
+ index <= last_index && !ret; index++)
+ ret = relocate_one_page(inode, ra, cluster, &cluster_nr, index);
+- if (btrfs_is_zoned(fs_info) && !ret)
+- ret = btrfs_wait_ordered_range(inode, 0, (u64)-1);
+ if (ret == 0)
+ WARN_ON(cluster_nr != cluster->nr);
+ out:
+@@ -3770,12 +3742,8 @@ static int __insert_orphan_inode(struct
+ struct btrfs_path *path;
+ struct btrfs_inode_item *item;
+ struct extent_buffer *leaf;
+- u64 flags = BTRFS_INODE_NOCOMPRESS | BTRFS_INODE_PREALLOC;
+ int ret;
+
+- if (btrfs_is_zoned(trans->fs_info))
+- flags &= ~BTRFS_INODE_PREALLOC;
+-
+ path = btrfs_alloc_path();
+ if (!path)
+ return -ENOMEM;
+@@ -3790,7 +3758,8 @@ static int __insert_orphan_inode(struct
+ btrfs_set_inode_generation(leaf, item, 1);
+ btrfs_set_inode_size(leaf, item, 0);
+ btrfs_set_inode_mode(leaf, item, S_IFREG | 0600);
+- btrfs_set_inode_flags(leaf, item, flags);
++ btrfs_set_inode_flags(leaf, item, BTRFS_INODE_NOCOMPRESS |
++ BTRFS_INODE_PREALLOC);
+ btrfs_mark_buffer_dirty(leaf);
+ out:
+ btrfs_free_path(path);
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:15 +0900
+Subject: btrfs: zoned: only allow one process to add pages to a relocation inode
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <c2c15d9992727dc6473d3dedb3d863874a3d3222.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit 35156d852762b58855f513b4f8bb7f32d69dc9c5 upstream
+
+Don't allow more than one process to add pages to a relocation inode on
+a zoned filesystem, otherwise we cannot guarantee the sequential write
+rule once we're filling preallocated extents on a zoned filesystem.
+
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/extent_io.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/fs/btrfs/extent_io.c
++++ b/fs/btrfs/extent_io.c
+@@ -5120,6 +5120,9 @@ int extent_write_locked_range(struct ino
+ int extent_writepages(struct address_space *mapping,
+ struct writeback_control *wbc)
+ {
++ struct inode *inode = mapping->host;
++ const bool data_reloc = btrfs_is_data_reloc_root(BTRFS_I(inode)->root);
++ const bool zoned = btrfs_is_zoned(BTRFS_I(inode)->root->fs_info);
+ int ret = 0;
+ struct extent_page_data epd = {
+ .bio_ctrl = { 0 },
+@@ -5127,7 +5130,15 @@ int extent_writepages(struct address_spa
+ .sync_io = wbc->sync_mode == WB_SYNC_ALL,
+ };
+
++ /*
++ * Allow only a single thread to do the reloc work in zoned mode to
++ * protect the write pointer updates.
++ */
++ if (data_reloc && zoned)
++ btrfs_inode_lock(inode, 0);
+ ret = extent_write_cache_pages(mapping, wbc, &epd);
++ if (data_reloc && zoned)
++ btrfs_inode_unlock(inode, 0);
+ ASSERT(ret <= 0);
+ if (ret < 0) {
+ end_write_bio(&epd, ret);
--- /dev/null
+From foo@baz Fri Nov 19 01:33:42 PM CET 2021
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Date: Thu, 18 Nov 2021 17:58:16 +0900
+Subject: btrfs: zoned: use regular writes for relocation
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-btrfs@vger.kernel.org, stable@vger.kernel.org, Naohiro Aota <naohiro.aota@wdc.com>, David Sterba <dsterba@suse.com>, Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Message-ID: <a6aa5997187d6e0172652cc29aea76be851c4cf6.1637225333.git.johannes.thumshirn@wdc.com>
+
+From: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+
+commit e6d261e3b1f777b499ce8f535ed44dd1b69278b7 upstream
+
+Now that we have a dedicated block group for relocation, we can use
+REQ_OP_WRITE instead of REQ_OP_ZONE_APPEND for writing out the data on
+relocation.
+
+Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/btrfs/zoned.c | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+--- a/fs/btrfs/zoned.c
++++ b/fs/btrfs/zoned.c
+@@ -1304,6 +1304,17 @@ bool btrfs_use_zone_append(struct btrfs_
+ if (!is_data_inode(&inode->vfs_inode))
+ return false;
+
++ /*
++ * Using REQ_OP_ZONE_APPNED for relocation can break assumptions on the
++ * extent layout the relocation code has.
++ * Furthermore we have set aside own block-group from which only the
++ * relocation "process" can allocate and make sure only one process at a
++ * time can add pages to an extent that gets relocated, so it's safe to
++ * use regular REQ_OP_WRITE for this special case.
++ */
++ if (btrfs_is_data_reloc_root(inode->root))
++ return false;
++
+ cache = btrfs_lookup_block_group(fs_info, start);
+ ASSERT(cache);
+ if (!cache)
--- /dev/null
+From a52f8a59aef46b59753e583bf4b28fccb069ce64 Mon Sep 17 00:00:00 2001
+From: Kees Cook <keescook@chromium.org>
+Date: Wed, 12 May 2021 21:51:10 -0700
+Subject: fortify: Explicitly disable Clang support
+
+From: Kees Cook <keescook@chromium.org>
+
+commit a52f8a59aef46b59753e583bf4b28fccb069ce64 upstream.
+
+Clang has never correctly compiled the FORTIFY_SOURCE defenses due to
+a couple bugs:
+
+ Eliding inlines with matching __builtin_* names
+ https://bugs.llvm.org/show_bug.cgi?id=50322
+
+ Incorrect __builtin_constant_p() of some globals
+ https://bugs.llvm.org/show_bug.cgi?id=41459
+
+In the process of making improvements to the FORTIFY_SOURCE defenses, the
+first (silent) bug (coincidentally) becomes worked around, but exposes
+the latter which breaks the build. As such, Clang must not be used with
+CONFIG_FORTIFY_SOURCE until at least latter bug is fixed (in Clang 13),
+and the fortify routines have been rearranged.
+
+Update the Kconfig to reflect the reality of the current situation.
+
+Signed-off-by: Kees Cook <keescook@chromium.org>
+Acked-by: Nick Desaulniers <ndesaulniers@google.com>
+Link: https://lore.kernel.org/lkml/CAKwvOd=A+ueGV2ihdy5GtgR2fQbcXjjAtVxv3=cPjffpebZB7A@mail.gmail.com
+Cc: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/Kconfig | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/security/Kconfig
++++ b/security/Kconfig
+@@ -191,6 +191,9 @@ config HARDENED_USERCOPY_PAGESPAN
+ config FORTIFY_SOURCE
+ bool "Harden common str/mem functions against buffer overflows"
+ depends on ARCH_HAS_FORTIFY_SOURCE
++ # https://bugs.llvm.org/show_bug.cgi?id=50322
++ # https://bugs.llvm.org/show_bug.cgi?id=41459
++ depends on !CC_IS_CLANG
+ help
+ Detect overflows of buffers in common string and memory functions
+ where the compiler can determine and validate the buffer sizes.
--- /dev/null
+From 964b7aa0b040bdc6ec1c543ee620cda3f8b4c68a Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw@amazon.co.uk>
+Date: Sun, 14 Nov 2021 08:59:02 +0000
+Subject: KVM: Fix steal time asm constraints
+
+From: David Woodhouse <dwmw@amazon.co.uk>
+
+commit 964b7aa0b040bdc6ec1c543ee620cda3f8b4c68a upstream.
+
+In 64-bit mode, x86 instruction encoding allows us to use the low 8 bits
+of any GPR as an 8-bit operand. In 32-bit mode, however, we can only use
+the [abcd] registers. For which, GCC has the "q" constraint instead of
+the less restrictive "r".
+
+Also fix st->preempted, which is an input/output operand rather than an
+input.
+
+Fixes: 7e2175ebd695 ("KVM: x86: Fix recording of guest steal time / preempted status")
+Reported-by: kernel test robot <lkp@intel.com>
+Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
+Message-Id: <89bf72db1b859990355f9c40713a34e0d2d86c98.camel@infradead.org>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/x86/kvm/x86.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -3242,9 +3242,9 @@ static void record_steal_time(struct kvm
+ "xor %1, %1\n"
+ "2:\n"
+ _ASM_EXTABLE_UA(1b, 2b)
+- : "+r" (st_preempted),
+- "+&r" (err)
+- : "m" (st->preempted));
++ : "+q" (st_preempted),
++ "+&r" (err),
++ "+m" (st->preempted));
+ if (err)
+ goto out;
+
--- /dev/null
+From af3c570fb0df422b4906ebd11c1bf363d89961d5 Mon Sep 17 00:00:00 2001
+From: Xie Yongji <xieyongji@bytedance.com>
+Date: Tue, 26 Oct 2021 22:40:14 +0800
+Subject: loop: Use blk_validate_block_size() to validate block size
+
+From: Xie Yongji <xieyongji@bytedance.com>
+
+commit af3c570fb0df422b4906ebd11c1bf363d89961d5 upstream.
+
+Remove loop_validate_block_size() and use the block layer helper
+to validate block size.
+
+Signed-off-by: Xie Yongji <xieyongji@bytedance.com>
+Link: https://lore.kernel.org/r/20211026144015.188-4-xieyongji@bytedance.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/loop.c | 17 ++---------------
+ 1 file changed, 2 insertions(+), 15 deletions(-)
+
+--- a/drivers/block/loop.c
++++ b/drivers/block/loop.c
+@@ -273,19 +273,6 @@ static void __loop_update_dio(struct loo
+ }
+
+ /**
+- * loop_validate_block_size() - validates the passed in block size
+- * @bsize: size to validate
+- */
+-static int
+-loop_validate_block_size(unsigned short bsize)
+-{
+- if (bsize < 512 || bsize > PAGE_SIZE || !is_power_of_2(bsize))
+- return -EINVAL;
+-
+- return 0;
+-}
+-
+-/**
+ * loop_set_size() - sets device size and notifies userspace
+ * @lo: struct loop_device to set the size for
+ * @size: new size of the loop device
+@@ -1236,7 +1223,7 @@ static int loop_configure(struct loop_de
+ }
+
+ if (config->block_size) {
+- error = loop_validate_block_size(config->block_size);
++ error = blk_validate_block_size(config->block_size);
+ if (error)
+ goto out_unlock;
+ }
+@@ -1759,7 +1746,7 @@ static int loop_set_block_size(struct lo
+ if (lo->lo_state != Lo_bound)
+ return -ENXIO;
+
+- err = loop_validate_block_size(arg);
++ err = blk_validate_block_size(arg);
+ if (err)
+ return err;
+
--- /dev/null
+From acae23dd371a39f792d5da13666876285b58c35b Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Fri, 19 Nov 2021 12:30:13 +0100
+Subject: Revert "drm: fb_helper: fix CONFIG_FB dependency"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit c95380ba527ae0aee29b2a133c5d0c481d472759 which is
+commit 606b102876e3741851dfb09d53f3ee57f650a52c upstream.
+
+It causes some build problems as reported by Jiri.
+
+Link: https://lore.kernel.org/r/9fdb2bf1-de52-1b9d-4783-c61ce39e8f51@kernel.org
+Reported-by: Jiri Slaby <jirislaby@kernel.org>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/Kconfig | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -103,7 +103,7 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
+ config DRM_FBDEV_EMULATION
+ bool "Enable legacy fbdev support for your modesetting driver"
+ depends on DRM
+- depends on FB=y || FB=DRM
++ depends on FB
+ select DRM_KMS_HELPER
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
--- /dev/null
+From 84705e42a0d08434045955845e0c53ee0acbd7b5 Mon Sep 17 00:00:00 2001
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Date: Fri, 19 Nov 2021 12:30:10 +0100
+Subject: Revert "drm: fb_helper: improve CONFIG_FB dependency"
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+This reverts commit 94e18f5a5dd1b5e3b89c665fc5ff780858b1c9f6 which is
+commit 9d6366e743f37d36ef69347924ead7bcc596076e upstream.
+
+It causes some build problems as reported by Jiri.
+
+Link: https://lore.kernel.org/r/9fdb2bf1-de52-1b9d-4783-c61ce39e8f51@kernel.org
+Reported-by: Jiri Slaby <jirislaby@kernel.org>
+Cc: Jani Nikula <jani.nikula@intel.com>
+Cc: Javier Martinez Canillas <javierm@redhat.com>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
+Cc: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/Kconfig | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/Kconfig
++++ b/drivers/gpu/drm/Kconfig
+@@ -102,8 +102,9 @@ config DRM_DEBUG_DP_MST_TOPOLOGY_REFS
+
+ config DRM_FBDEV_EMULATION
+ bool "Enable legacy fbdev support for your modesetting driver"
+- depends on DRM_KMS_HELPER
+- depends on FB=y || FB=DRM_KMS_HELPER
++ depends on DRM
++ depends on FB=y || FB=DRM
++ select DRM_KMS_HELPER
+ select FB_CFB_FILLRECT
+ select FB_CFB_COPYAREA
+ select FB_CFB_IMAGEBLIT
string-uninline-memcpy_and_pad.patch
+revert-drm-fb_helper-improve-config_fb-dependency.patch
+revert-drm-fb_helper-fix-config_fb-dependency.patch
+kvm-fix-steal-time-asm-constraints.patch
+btrfs-introduce-btrfs_is_data_reloc_root.patch
+btrfs-zoned-add-a-dedicated-data-relocation-block-group.patch
+btrfs-zoned-only-allow-one-process-to-add-pages-to-a-relocation-inode.patch
+btrfs-zoned-use-regular-writes-for-relocation.patch
+btrfs-check-for-relocation-inodes-on-zoned-btrfs-in-should_nocow.patch
+btrfs-zoned-allow-preallocation-for-relocation-inodes.patch
+fortify-explicitly-disable-clang-support.patch
+block-add-a-helper-to-validate-the-block-size.patch
+loop-use-blk_validate_block_size-to-validate-block-size.patch