@@ -466,8 +466,15 @@ struct btrfs_super_block {
__le64 reserved[24];
u8 sys_chunk_array[BTRFS_SYSTEM_CHUNK_ARRAY_SIZE];
struct btrfs_root_backup super_roots[BTRFS_NUM_BACKUP_ROOTS];
+
+ /*
+ * How many bytes are reserved at the beginning of a device.
+ * Should be >= BTRFS_DEFAULT_RESERVED.
+ */
+ __le32 reserved_bytes;
+
/* Padded to 4096 bytes */
- u8 padding[565];
+ u8 padding[561];
} __attribute__ ((__packed__));
BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
@@ -485,6 +492,16 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
*/
#define BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID (1ULL << 1)
+/*
+ * Allow btrfs to have extra reserved space (other than the default 1MiB) at
+ * the beginning of each device.
+ *
+ * This feature will enable the usage of btrfs_super_block::reserved_bytes.
+ *
+ * This feature would only be available for non-zoned filesystems.
+ */
+#define BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED (1ULL << 3)
+
#define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF (1ULL << 0)
#define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL (1ULL << 1)
#define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS (1ULL << 2)
@@ -514,7 +531,8 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
*/
#define BTRFS_FEATURE_COMPAT_RO_SUPP \
(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE | \
- BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID)
+ BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |\
+ BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED)
#if EXPERIMENTAL
#define BTRFS_FEATURE_INCOMPAT_SUPP \
@@ -2374,6 +2392,8 @@ BTRFS_SETGET_STACK_FUNCS(super_block_group_root_level,
struct btrfs_super_block, block_group_root_level, 8);
BTRFS_SETGET_STACK_FUNCS(super_nr_global_roots, struct btrfs_super_block,
nr_global_roots, 64);
+BTRFS_SETGET_STACK_FUNCS(super_reserved_bytes, struct btrfs_super_block,
+ reserved_bytes, 32);
static inline unsigned long btrfs_leaf_data(struct extent_buffer *l)
{
@@ -1848,6 +1848,15 @@ int btrfs_check_super(struct btrfs_super_block *sb, unsigned sbflags)
}
}
+ if (btrfs_super_compat_ro_flags(sb) &
+ BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED &&
+ btrfs_super_reserved_bytes(sb) < BTRFS_BLOCK_RESERVED_1M_FOR_SUPER) {
+ error("reserved bytes invalid, has %u expect >= %llu",
+ btrfs_super_reserved_bytes(sb),
+ BTRFS_BLOCK_RESERVED_1M_FOR_SUPER);
+ goto error_out;
+ }
+
if (btrfs_super_incompat_flags(sb) & BTRFS_FEATURE_INCOMPAT_METADATA_UUID)
metadata_uuid = sb->metadata_uuid;
else
@@ -562,10 +562,14 @@ int btrfs_scan_one_device(int fd, const char *path,
static u64 dev_extent_search_start(struct btrfs_device *device, u64 start)
{
+ struct btrfs_fs_info *fs_info = device->fs_info;
u64 zone_size;
switch (device->fs_devices->chunk_alloc_policy) {
case BTRFS_CHUNK_ALLOC_REGULAR:
+ if (btrfs_fs_compat_ro(fs_info, EXTRA_SUPER_RESERVED))
+ return max_t(u64, start,
+ btrfs_super_reserved_bytes(fs_info->super_copy));
/*
* We don't want to overwrite the superblock on the drive nor
* any area used by the boot loader (grub for example), so we
This new compat RO flag allows btrfs to reserve extra space other than the default 1MiB at the beginning of each device. Currently the new RO flag will enable the new super block member, reserved_bytes, to be utilized for chunk allocation, to avoid the specified byte range. Signed-off-by: Qu Wenruo <wqu@suse.com> --- kernel-shared/ctree.h | 24 ++++++++++++++++++++++-- kernel-shared/disk-io.c | 9 +++++++++ kernel-shared/volumes.c | 4 ++++ 3 files changed, 35 insertions(+), 2 deletions(-)