linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps
@ 2022-07-05  7:37 Qu Wenruo
  2022-07-05  7:37 ` [PATCH 1/8] btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED Qu Wenruo
                   ` (7 more replies)
  0 siblings, 8 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

This patchset introduces the following support for WRITE_INTENT_BITMAP
compat RO flags:

- mkfs support for EXTRA_SUPER_RESERVED and WRITE_INTENT_BITMAP

  The extra reservation size is 1MiB, and is hardcoded so far.
  Although write-intent bitmaps will only utilize 4KiB of the extra
  1MiB.

- dump-supper support for both compat RO flags

- extra fsck warning when the reserved space is not properly respected

- new "btrfs inspect-internal dump-write-intent" command
  This is to dump the content of the write-intent bitmap for debug
  purpose.

Qu Wenruo (8):
  btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED
  btrfs-progs: mkfs: add support for extra-super-reserved runtime flag
  btrfs-progs: print-tree: remove duplicated definition for compat RO
    flags
  btrfs-progs: print-tree: support btrfs_super_block::reserved_bytes
  btrfs-progs: check: add extra warning for dev extents inside the
    reserved range
  btrfs-progs: introduce the experimental compat RO flag,
    WRITE_INTENT_BITMAP
  btrfs-progs: introduce the on-disk format of btrfs write intent
    bitmaps
  btrfs-progs: cmds/inspect: add the ability to dump write intent
    bitmaps

 Makefile                         |   3 +-
 check/main.c                     |  17 +++
 check/mode-lowmem.c              |  22 ++++
 cmds/commands.h                  |   1 +
 cmds/inspect-dump-write-intent.c | 158 +++++++++++++++++++++++++++
 cmds/inspect.c                   |   1 +
 common/fsfeatures.c              |  19 ++++
 common/fsfeatures.h              |   2 +
 kernel-shared/ctree.h            |  40 ++++++-
 kernel-shared/disk-io.c          |  18 ++++
 kernel-shared/print-tree.c       | 104 +++++++++++++++++-
 kernel-shared/print-tree.h       |   1 +
 kernel-shared/volumes.c          |   4 +
 kernel-shared/write-intent.h     | 177 +++++++++++++++++++++++++++++++
 mkfs/common.c                    |  25 +++++
 mkfs/main.c                      |  14 +++
 16 files changed, 600 insertions(+), 6 deletions(-)
 create mode 100644 cmds/inspect-dump-write-intent.c
 create mode 100644 kernel-shared/write-intent.h

-- 
2.36.1


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/8] btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 2/8] btrfs-progs: mkfs: add support for extra-super-reserved runtime flag Qu Wenruo
                   ` (6 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

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(-)

diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index fc8b61eda829..eb49aa8da919 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -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)
 {
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index 26b1c9aa192a..bf3ea5e63165 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -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
diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c
index 40032a4b4059..58254c9df5e1 100644
--- a/kernel-shared/volumes.c
+++ b/kernel-shared/volumes.c
@@ -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
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/8] btrfs-progs: mkfs: add support for extra-super-reserved runtime flag
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
  2022-07-05  7:37 ` [PATCH 1/8] btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 3/8] btrfs-progs: print-tree: remove duplicated definition for compat RO flags Qu Wenruo
                   ` (5 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

This allows mkfs to reserved extra 1MiB (2MiB in total).

The extra 1MiB should be large enough for either write-intent bitmap or
full journal.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 common/fsfeatures.c |  8 ++++++++
 common/fsfeatures.h |  1 +
 mkfs/common.c       | 16 ++++++++++++++++
 mkfs/main.c         |  9 +++++++++
 4 files changed, 34 insertions(+)

diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index 23a92c21a2cc..057519c50c54 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -172,6 +172,14 @@ static const struct btrfs_feature runtime_features[] = {
 		VERSION_TO_STRING2(safe, 4,9),
 		VERSION_TO_STRING2(default, 5,15),
 		.desc		= "free space tree (space_cache=v2)"
+	}, {
+		.name		= "extra-super-reserved",
+		.flag		= BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED,
+		.sysfs_name = "extra_super_reserved",
+		VERSION_TO_STRING2(compat, 6,0),
+		VERSION_NULL(safe),
+		VERSION_NULL(default),
+		.desc		= "extra super block reserved space for each device"
 	},
 	/* Keep this one last */
 	{
diff --git a/common/fsfeatures.h b/common/fsfeatures.h
index 9e39c667b900..565873ec0e4f 100644
--- a/common/fsfeatures.h
+++ b/common/fsfeatures.h
@@ -45,6 +45,7 @@
 
 #define BTRFS_RUNTIME_FEATURE_QUOTA		(1ULL << 0)
 #define BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE	(1ULL << 1)
+#define BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED (1ULL << 2)
 
 void btrfs_list_all_fs_features(u64 mask_disallowed);
 void btrfs_list_all_runtime_features(u64 mask_disallowed);
diff --git a/mkfs/common.c b/mkfs/common.c
index 218854491c14..f3c00f08826d 100644
--- a/mkfs/common.c
+++ b/mkfs/common.c
@@ -314,6 +314,8 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
 				  BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE);
 	bool extent_tree_v2 = !!(cfg->features &
 				 BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2);
+	bool extra_super_reserved = !!(cfg->runtime_features &
+				 BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED);
 
 	/* Don't include the free space tree in the blocks to process. */
 	if (!free_space_tree)
@@ -324,6 +326,12 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
 		blocks_nr = ARRAY_SIZE(extent_tree_v2_blocks);
 		add_block_group = false;
 	}
+	/*
+	 * The extra 1MiB should be enough for either write-intent bitmap or
+	 * future full journal.
+	 */
+	if (extra_super_reserved)
+		system_group_offset += SZ_1M;
 
 	if ((cfg->features & BTRFS_FEATURE_INCOMPAT_ZONED)) {
 		system_group_offset = zoned_system_group_offset(cfg->zone_size);
@@ -641,6 +649,14 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
 			goto out;
 	}
 
+	if (extra_super_reserved) {
+		u64 ro_flags = btrfs_super_compat_ro_flags(&super) |
+			       BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED;
+
+		btrfs_set_super_compat_ro_flags(&super, ro_flags);
+		btrfs_set_super_reserved_bytes(&super, system_group_offset);
+	}
+
 	if (extent_tree_v2) {
 		ret = create_block_group_tree(fd, cfg, buf,
 					      system_group_offset,
diff --git a/mkfs/main.c b/mkfs/main.c
index 4e0a46a77aa5..4ccf4e161d06 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1239,6 +1239,15 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
 		features |= BTRFS_FEATURE_INCOMPAT_ZONED;
 	}
 
+	/*
+	 * Runtime extra-super-reserved feature conflicts with zoned support,
+	 * as it's for regular devices explicitly.
+	 */
+	if (zoned && (runtime_features &
+		      BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED)) {
+		error("extra-super-reserved runtime feature conflicts with zoned devices");
+		exit(1);
+	}
 	/*
 	* Set default profiles according to number of added devices.
 	* For mixed groups defaults are single/single.
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/8] btrfs-progs: print-tree: remove duplicated definition for compat RO flags
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
  2022-07-05  7:37 ` [PATCH 1/8] btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED Qu Wenruo
  2022-07-05  7:37 ` [PATCH 2/8] btrfs-progs: mkfs: add support for extra-super-reserved runtime flag Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 4/8] btrfs-progs: print-tree: support btrfs_super_block::reserved_bytes Qu Wenruo
                   ` (4 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

In print_readable_compat_ro_flag(), we provide
BTRFS_FEATURE_COMPAT_RO_SUPP | BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |
BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID for supported flags.

However BTRFS_FEATURE_COMPAT_RO_SUPP already includes the latter two
flags.

Just remove the unnecessary flags.

Signed-off-by: Qu Wenruo <wqu@suse.com>

t#
---
 kernel-shared/print-tree.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index a5886ff602ee..db486553f448 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -1754,9 +1754,7 @@ static void print_readable_compat_ro_flag(u64 flag)
 	 */
 	return __print_readable_flag(flag, compat_ro_flags_array,
 				     compat_ro_flags_num,
-				     BTRFS_FEATURE_COMPAT_RO_SUPP |
-				     BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |
-				     BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID);
+				     BTRFS_FEATURE_COMPAT_RO_SUPP);
 }
 
 static void print_readable_incompat_flag(u64 flag)
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/8] btrfs-progs: print-tree: support btrfs_super_block::reserved_bytes
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
                   ` (2 preceding siblings ...)
  2022-07-05  7:37 ` [PATCH 3/8] btrfs-progs: print-tree: remove duplicated definition for compat RO flags Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 5/8] btrfs-progs: check: add extra warning for dev extents inside the reserved range Qu Wenruo
                   ` (3 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

This only needs two things:

- Add readable flags for EXTRA_SUPER_RESERVED flag

- Add optional output for reserved_bytes

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/print-tree.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index db486553f448..918ebe02144a 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -1668,6 +1668,7 @@ struct readable_flag_entry {
 static struct readable_flag_entry compat_ro_flags_array[] = {
 	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE),
 	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE_VALID),
+	DEF_COMPAT_RO_FLAG_ENTRY(EXTRA_SUPER_RESERVED),
 };
 static const int compat_ro_flags_num = sizeof(compat_ro_flags_array) /
 				       sizeof(struct readable_flag_entry);
@@ -2051,6 +2052,11 @@ void btrfs_print_superblock(struct btrfs_super_block *sb, int full)
 	printf("block_group_root_level\t%llu\n",
 	       (unsigned long long)btrfs_super_block_group_root_level(sb));
 
+	if (btrfs_super_compat_ro_flags(sb) &
+	    BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED)
+		printf("reserved_bytes\t\t%u\n",
+			btrfs_super_reserved_bytes(sb));
+
 	uuid_unparse(sb->dev_item.uuid, buf);
 	printf("dev_item.uuid\t\t%s\n", buf);
 
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/8] btrfs-progs: check: add extra warning for dev extents inside the reserved range
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
                   ` (3 preceding siblings ...)
  2022-07-05  7:37 ` [PATCH 4/8] btrfs-progs: print-tree: support btrfs_super_block::reserved_bytes Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 6/8] btrfs-progs: introduce the experimental compat RO flag, WRITE_INTENT_BITMAP Qu Wenruo
                   ` (2 subsequent siblings)
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

Since kernel can handle it without problem, and we rely on balance to
relocate those offending dev extents, we only need to output warning
when such dev extents are detected.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 check/main.c          | 17 +++++++++++++++++
 check/mode-lowmem.c   | 22 ++++++++++++++++++++++
 kernel-shared/ctree.h |  1 +
 3 files changed, 40 insertions(+)

diff --git a/check/main.c b/check/main.c
index 6b2be57a1505..6c230cf05acb 100644
--- a/check/main.c
+++ b/check/main.c
@@ -8918,6 +8918,7 @@ static int check_dev_extents(void)
 	struct btrfs_key key;
 	struct btrfs_root *dev_root = gfs_info->dev_root;
 	int ret;
+	u32 super_reserved = BTRFS_BLOCK_RESERVED_1M_FOR_SUPER;
 	u64 prev_devid = 0;
 	u64 prev_dev_ext_end = 0;
 
@@ -8927,6 +8928,10 @@ static int check_dev_extents(void)
 	key.type = BTRFS_DEV_EXTENT_KEY;
 	key.offset = 0;
 
+	if (btrfs_fs_compat_ro(gfs_info, EXTRA_SUPER_RESERVED) &&
+	    btrfs_super_reserved_bytes(gfs_info->super_copy) >= super_reserved)
+		super_reserved = btrfs_super_reserved_bytes(gfs_info->super_copy);
+
 	ret = btrfs_search_slot(NULL, dev_root, &key, &path, 0, 0);
 	if (ret < 0) {
 		errno = -ret;
@@ -8983,6 +8988,13 @@ static int check_dev_extents(void)
 			ret = -EUCLEAN;
 			goto out;
 		}
+		if (physical_offset < super_reserved) {
+			warning(
+"dev extent devid %llu physical offset %llu is inside the reserved range (%u)",
+				devid, physical_offset,
+				super_reserved);
+			gfs_info->found_dev_extents_in_reserved = 1;
+		}
 		prev_devid = devid;
 		prev_dev_ext_end = physical_offset + physical_len;
 
@@ -8998,6 +9010,11 @@ static int check_dev_extents(void)
 		}
 	}
 out:
+	if (gfs_info->found_dev_extents_in_reserved) {
+		warning("to relocate the dev extents in reserved range, mount the fs and run:");
+		warning("\tbtrfs balance start -mdrange=0..%u -ddrange=0..%u -sdrange=0..%u",
+			super_reserved, super_reserved, super_reserved);
+	}
 	btrfs_release_path(&path);
 	return ret;
 }
diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c
index fa324506dd5d..103c27c6d0bf 100644
--- a/check/mode-lowmem.c
+++ b/check/mode-lowmem.c
@@ -4433,12 +4433,17 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot)
 	struct btrfs_key devext_key;
 	struct btrfs_chunk *chunk;
 	struct extent_buffer *l;
+	u32 super_reserved = BTRFS_BLOCK_RESERVED_1M_FOR_SUPER;
 	int num_stripes;
 	u64 length;
 	int i;
 	int found_chunk = 0;
 	int ret;
 
+	if (btrfs_fs_compat_ro(gfs_info, EXTRA_SUPER_RESERVED) &&
+	    btrfs_super_reserved_bytes(gfs_info->super_copy) >= super_reserved)
+		super_reserved = btrfs_super_reserved_bytes(gfs_info->super_copy);
+
 	btrfs_item_key_to_cpu(eb, &devext_key, slot);
 	ptr = btrfs_item_ptr(eb, slot, struct btrfs_dev_extent);
 	length = btrfs_dev_extent_length(eb, ptr);
@@ -4447,6 +4452,13 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot)
 	chunk_key.type = BTRFS_CHUNK_ITEM_KEY;
 	chunk_key.offset = btrfs_dev_extent_chunk_offset(eb, ptr);
 
+	if (devext_key.offset < super_reserved) {
+		warning(
+"dev extent devid %llu physical offset %llu is inside the reserved range (%u)",
+			devext_key.objectid, devext_key.offset,
+			super_reserved);
+		gfs_info->found_dev_extents_in_reserved = 1;
+	}
 	btrfs_init_path(&path);
 	ret = btrfs_search_slot(NULL, chunk_root, &chunk_key, &path, 0, 0);
 	if (ret)
@@ -5526,9 +5538,14 @@ int check_chunks_and_extents_lowmem(void)
 	struct btrfs_key key;
 	struct btrfs_root *root;
 	struct btrfs_root *cur_root;
+	u32 super_reserved = BTRFS_BLOCK_RESERVED_1M_FOR_SUPER;
 	int err = 0;
 	int ret;
 
+	if (btrfs_fs_compat_ro(gfs_info, EXTRA_SUPER_RESERVED) &&
+	    btrfs_super_reserved_bytes(gfs_info->super_copy) >= super_reserved)
+		super_reserved = btrfs_super_reserved_bytes(gfs_info->super_copy);
+
 	root = gfs_info->chunk_root;
 	ret = check_btrfs_root(root, 1);
 	err |= ret;
@@ -5590,6 +5607,11 @@ out:
 			total_used);
 		err |= SUPER_BYTES_USED_ERROR;
 	}
+	if (gfs_info->found_dev_extents_in_reserved) {
+		warning("to relocate the dev extents in reserved range, mount the fs and run:");
+		warning("\tbtrfs balance start -mdrange=0..%u -ddrange=0..%u -sdrange=0..%u",
+			super_reserved, super_reserved, super_reserved);
+	}
 
 	if (repair) {
 		ret = end_avoid_extents_overwrite();
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index eb49aa8da919..0b4a8d60ceb4 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -1271,6 +1271,7 @@ struct btrfs_fs_info {
 	unsigned int finalize_on_close:1;
 	unsigned int hide_names:1;
 	unsigned int allow_transid_mismatch:1;
+	unsigned int found_dev_extents_in_reserved:1;
 
 	int transaction_aborted;
 	int force_csum_type;
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/8] btrfs-progs: introduce the experimental compat RO flag, WRITE_INTENT_BITMAP
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
                   ` (4 preceding siblings ...)
  2022-07-05  7:37 ` [PATCH 5/8] btrfs-progs: check: add extra warning for dev extents inside the reserved range Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 7/8] btrfs-progs: introduce the on-disk format of btrfs write intent bitmaps Qu Wenruo
  2022-07-05  7:37 ` [PATCH 8/8] btrfs-progs: cmds/inspect: add the ability to dump " Qu Wenruo
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

This new compat RO flag will only be enabled through experimental
features.

Since this feature has no real code implementation yet, only the
following code changes are added:

- New super block check
  To ensure WRITE_INTENT_BITMAP is enabled along with
  EXTRA_SUPER_RESERVED

- New compat RO flag readable string output

- New mkfs runtime features

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 common/fsfeatures.c        | 11 +++++++++++
 common/fsfeatures.h        |  1 +
 kernel-shared/ctree.h      | 15 +++++++++++++++
 kernel-shared/disk-io.c    |  9 +++++++++
 kernel-shared/print-tree.c |  1 +
 mkfs/common.c              |  9 +++++++++
 mkfs/main.c                |  5 +++++
 7 files changed, 51 insertions(+)

diff --git a/common/fsfeatures.c b/common/fsfeatures.c
index 057519c50c54..63258262437d 100644
--- a/common/fsfeatures.c
+++ b/common/fsfeatures.c
@@ -181,6 +181,17 @@ static const struct btrfs_feature runtime_features[] = {
 		VERSION_NULL(default),
 		.desc		= "extra super block reserved space for each device"
 	},
+#if EXPERIMENTAL
+	{
+		.name		= "write-intent-bitmap",
+		.flag		= BTRFS_RUNTIME_FEATURE_WRITE_INTENT_BITMAP,
+		.sysfs_name = "write_intent_bitmap",
+		VERSION_NULL(compat),
+		VERSION_NULL(safe),
+		VERSION_NULL(default),
+		.desc		= "write intent bitmap"
+	},
+#endif
 	/* Keep this one last */
 	{
 		.name = "list-all",
diff --git a/common/fsfeatures.h b/common/fsfeatures.h
index 565873ec0e4f..c48aa5d05ac0 100644
--- a/common/fsfeatures.h
+++ b/common/fsfeatures.h
@@ -46,6 +46,7 @@
 #define BTRFS_RUNTIME_FEATURE_QUOTA		(1ULL << 0)
 #define BTRFS_RUNTIME_FEATURE_FREE_SPACE_TREE	(1ULL << 1)
 #define BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED (1ULL << 2)
+#define BTRFS_RUNTIME_FEATURE_WRITE_INTENT_BITMAP  (1ULL << 3)
 
 void btrfs_list_all_fs_features(u64 mask_disallowed);
 void btrfs_list_all_runtime_features(u64 mask_disallowed);
diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h
index 0b4a8d60ceb4..c746c0d3ab89 100644
--- a/kernel-shared/ctree.h
+++ b/kernel-shared/ctree.h
@@ -502,6 +502,13 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
  */
 #define BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED	(1ULL << 3)
 
+/*
+ * Allow btrfs to have per-device write-intent bitmap.
+ * Will be utilized to close the RAID56 write-hole (by forced scrub for dirty
+ * partial written stripes at mount time).
+ */
+#define BTRFS_FEATURE_COMPAT_RO_WRITE_INTENT_BITMAP	(1ULL << 4)
+
 #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF	(1ULL << 0)
 #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL	(1ULL << 1)
 #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS	(1ULL << 2)
@@ -524,6 +531,13 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
 
 #define BTRFS_FEATURE_COMPAT_SUPP		0ULL
 
+#if EXPERIMENTAL
+#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_EXTRA_SUPER_RESERVED |	\
+	 BTRFS_FEATURE_COMPAT_RO_WRITE_INTENT_BITMAP)
+#else
 /*
  * The FREE_SPACE_TREE and FREE_SPACE_TREE_VALID compat_ro bits must not be
  * added here until read-write support for the free space tree is implemented in
@@ -533,6 +547,7 @@ BUILD_ASSERT(sizeof(struct btrfs_super_block) == BTRFS_SUPER_INFO_SIZE);
 	(BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE |	\
 	 BTRFS_FEATURE_COMPAT_RO_FREE_SPACE_TREE_VALID |\
 	 BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED)
+#endif
 
 #if EXPERIMENTAL
 #define BTRFS_FEATURE_INCOMPAT_SUPP			\
diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index bf3ea5e63165..843fe0e73940 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -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_WRITE_INTENT_BITMAP &&
+	    !(btrfs_super_compat_ro_flags(sb) &
+	      BTRFS_FEATURE_COMPAT_RO_EXTRA_SUPER_RESERVED)) {
+		error(
+"write intent bitmap feature enabled without extra super reserved feature");
+		goto error_out;
+	}
+
 	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) {
diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index 918ebe02144a..55875a7bc2d3 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -1669,6 +1669,7 @@ static struct readable_flag_entry compat_ro_flags_array[] = {
 	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE),
 	DEF_COMPAT_RO_FLAG_ENTRY(FREE_SPACE_TREE_VALID),
 	DEF_COMPAT_RO_FLAG_ENTRY(EXTRA_SUPER_RESERVED),
+	DEF_COMPAT_RO_FLAG_ENTRY(WRITE_INTENT_BITMAP),
 };
 static const int compat_ro_flags_num = sizeof(compat_ro_flags_array) /
 				       sizeof(struct readable_flag_entry);
diff --git a/mkfs/common.c b/mkfs/common.c
index f3c00f08826d..98da10718e7b 100644
--- a/mkfs/common.c
+++ b/mkfs/common.c
@@ -316,6 +316,8 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
 				 BTRFS_FEATURE_INCOMPAT_EXTENT_TREE_V2);
 	bool extra_super_reserved = !!(cfg->runtime_features &
 				 BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED);
+	bool write_intent_bitmap = !!(cfg->runtime_features &
+				 BTRFS_RUNTIME_FEATURE_WRITE_INTENT_BITMAP);
 
 	/* Don't include the free space tree in the blocks to process. */
 	if (!free_space_tree)
@@ -657,6 +659,13 @@ int make_btrfs(int fd, struct btrfs_mkfs_config *cfg)
 		btrfs_set_super_reserved_bytes(&super, system_group_offset);
 	}
 
+	if (write_intent_bitmap) {
+		u64 ro_flags = btrfs_super_compat_ro_flags(&super) |
+			       BTRFS_FEATURE_COMPAT_RO_WRITE_INTENT_BITMAP;
+
+		btrfs_set_super_compat_ro_flags(&super, ro_flags);
+	}
+
 	if (extent_tree_v2) {
 		ret = create_block_group_tree(fd, cfg, buf,
 					      system_group_offset,
diff --git a/mkfs/main.c b/mkfs/main.c
index 4ccf4e161d06..049d6f1dae2a 100644
--- a/mkfs/main.c
+++ b/mkfs/main.c
@@ -1248,6 +1248,11 @@ int BOX_MAIN(mkfs)(int argc, char **argv)
 		error("extra-super-reserved runtime feature conflicts with zoned devices");
 		exit(1);
 	}
+
+	/* Write intent bitmap must has extra reserved space. */
+	if (runtime_features & BTRFS_RUNTIME_FEATURE_WRITE_INTENT_BITMAP)
+		runtime_features |= BTRFS_RUNTIME_FEATURE_EXTRA_SUPER_RESERVED;
+
 	/*
 	* Set default profiles according to number of added devices.
 	* For mixed groups defaults are single/single.
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 7/8] btrfs-progs: introduce the on-disk format of btrfs write intent bitmaps
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
                   ` (5 preceding siblings ...)
  2022-07-05  7:37 ` [PATCH 6/8] btrfs-progs: introduce the experimental compat RO flag, WRITE_INTENT_BITMAP Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  2022-07-05  7:37 ` [PATCH 8/8] btrfs-progs: cmds/inspect: add the ability to dump " Qu Wenruo
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

With extra comments explaining the on-disk format and the basic
workflow.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 kernel-shared/write-intent.h | 177 +++++++++++++++++++++++++++++++++++
 1 file changed, 177 insertions(+)
 create mode 100644 kernel-shared/write-intent.h

diff --git a/kernel-shared/write-intent.h b/kernel-shared/write-intent.h
new file mode 100644
index 000000000000..a208e5cafb68
--- /dev/null
+++ b/kernel-shared/write-intent.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* Btrfs specific write-intent bitmaps. */
+
+#ifndef BTRFS_WRITE_INTENT_H
+#define BTRFS_WRITE_INTENT_H
+
+#include "kerncompat.h"
+
+#define WRITE_INTENT_SUPER_MAGIC 0x515F62536249775FULL /* ascii _wIbSb_Q */
+
+/* This write-intent bitmap records writes for RAID56 writes. */
+#define WRITE_INTENT_FLAGS_TARGET_RAID56	(1ULL << 0)
+
+/* This write-intent bitmap is internal, aka locates at 1MiB of each device. */
+#define WRITE_INTENT_FLAGS_INTERNAL		(1ULL << 1)
+
+/* This write-intent bitmap uses logical bytenr. */
+#define WRITE_INTENT_FLAGS_BYTENR_LOGICAL	(1ULL << 2)
+
+#define WRITE_INTENT_FLAGS_SUPPORTED			\
+	(WRITE_INTENT_FLAGS_TARGET_RAID56 |		\
+	 WRITE_INTENT_FLAGS_INTERNAL |			\
+	 WRITE_INTENT_FLAGS_BYTENR_LOGICAL)
+
+/*
+ * We use BTRFS_STRIPE_LEN as blocksize.
+ * This makes a RAID56 full stripe to @nr_data bits, and greatly
+ * enlarge how many bytes we can represent just using 4KiB.
+ */
+#define WRITE_INTENT_BLOCKSIZE			(BTRFS_STRIPE_LEN)
+
+/*
+ * For now, 4KiB is enough, as using 64KiB blocksize we can save bitmaps
+ * for 896MiB (224 entries, each entri can cache 64KiB * 64) sized logical
+ * range.
+ */
+#define WRITE_INTENT_BITMAPS_SIZE		(SZ_4K)
+
+/*
+ * For now, 4KiB is enough, as using 64KiB blocksize we can save bitmaps
+ * for 896MiB (224 entries, each entri can cache 64KiB * 64) sized logical
+ * range.
+ */
+#define WRITE_INTENT_BITMAPS_SIZE		(SZ_4K)
+
+/*
+ * The super block of write intent bitmaps, should be at physical offset 1MiB of
+ * every writeable device.
+ */
+struct write_intent_super {
+	/* Csum for the super block and all the internal entries. */
+	__u8 csum[BTRFS_CSUM_SIZE];
+	__u8 fsid[BTRFS_FSID_SIZE];
+
+	__le64 magic;
+
+	/* Important behavior flags would be set here. */
+	__le64 flags;
+
+	/*
+	 * Event counter for the bitmap, every time the bitmaps get written
+	 * this value increases.
+	 */
+	__le64 events;
+
+	/*
+	 * Total size of the bitmaps, including this super block and all the
+	 * entries.
+	 *
+	 * U32 should be enough for internal bitmaps, but just in case we want
+	 * to support external device as dedicated journal/bitmap device.
+	 */
+	__le64 size;
+
+	/* How many entries we have utilized. */
+	__le64 nr_entries;
+
+	/* How many bytes one bit represents. */
+	__le32 blocksize;
+	/*
+	 * This should be the same as btrfs_super_block::csum_type.
+	 * Cache csum type here so we read the write intent superblock without
+	 * a fully opened btrfs (for dump purpose).
+	 */
+	__le16 csum_type;
+
+	/* For future expansion, padding to 512 bytes. */
+	__u8 reserved1[418];
+} __attribute__ ((__packed__));
+
+static_assert(sizeof(struct write_intent_super) == 512);
+
+struct write_intent_entry {
+	/*
+	 * Bytenr 0 is special, means this entry is empty, and also means the
+	 * end of the bitmaps.
+	 */
+	__le64 bytenr;
+	__le32 bitmaps[2];
+};
+
+/*
+ * ON-DISK FORMAT
+ * ==============
+ *
+ * [ super ][ entry 1 ][ entry 2 ] ... [entry N]
+ * |<------------  super::size --------------->|
+ *
+ * Normally it's 4KiB in size.
+ *
+ * Currently the write-intent bitmaps is only for RAID56 writes, thus its
+ * blocksize is always 64KiB.
+ * Thus one entry can represent 4MiB (64 * 64 KiB) of logical range.
+ *
+ * When one raid56 full stripe needs partial writeback, the full stripe logical
+ * bytenr range will be included into at least one entry.
+ *
+ * After the last used entry, the remaining entries will all be filled with 0.
+ *
+ * WORKFLOW
+ * ========
+ *
+ * 1) Write bio arrive
+ *    Every write meets the requirement (so far, only RAID56 partial write) will
+ *    have its bio delayed, until corresponding range are marked in the entry.
+ *
+ * 2) Update the write-intent bitmaps
+ *    The entries will be populated, and write back to all writeable devices,
+ *    with FUA flag set.
+ *    Will wait until the write reaches disks.
+ *
+ * 3) Allow the involved write bios to be submitted
+ *
+ * 4) Write bios finish
+ *    The corresponding range will be recorded to be freed at next flush.
+ *
+ * 5) All devices get flushed (caused by btrfs super block writeback or bitmaps
+ *    pressure)
+ *    The recorded ranges will be cleared. And if an entry is empty, it will be
+ *    freed.
+ *    Then update the write-intent bitmaps with its superblock (writeback with FUA
+ *    flag and wait for it).
+ */
+
+#define WRITE_INTENT_SETGET_FUNCS(name, type, member, bits)	\
+static inline u##bits wi_##name(const type *s)			\
+{								\
+	return le##bits##_to_cpu(s->member);			\
+}								\
+static inline void wi_set_##name(type *s, u##bits val)		\
+{								\
+	s->member = cpu_to_le##bits(val);			\
+}
+
+WRITE_INTENT_SETGET_FUNCS(super_magic, struct write_intent_super, magic, 64);
+WRITE_INTENT_SETGET_FUNCS(super_flags, struct write_intent_super, flags, 64);
+WRITE_INTENT_SETGET_FUNCS(super_events, struct write_intent_super, events, 64);
+WRITE_INTENT_SETGET_FUNCS(super_size, struct write_intent_super, size, 64);
+WRITE_INTENT_SETGET_FUNCS(super_nr_entries, struct write_intent_super,
+			  nr_entries, 64);
+WRITE_INTENT_SETGET_FUNCS(super_blocksize, struct write_intent_super,
+			  blocksize, 32);
+WRITE_INTENT_SETGET_FUNCS(super_csum_type, struct write_intent_super,
+			  csum_type, 16);
+WRITE_INTENT_SETGET_FUNCS(entry_bytenr, struct write_intent_entry, bytenr, 64);
+
+static inline u32 wie_get_bitmap0(struct write_intent_entry *entry)
+{
+	return le32_to_cpu(entry->bitmaps[0]);
+}
+static inline u32 wie_get_bitmap1(struct write_intent_entry *entry)
+{
+	return le32_to_cpu(entry->bitmaps[1]);
+}
+
+#endif
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 8/8] btrfs-progs: cmds/inspect: add the ability to dump write intent bitmaps
  2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
                   ` (6 preceding siblings ...)
  2022-07-05  7:37 ` [PATCH 7/8] btrfs-progs: introduce the on-disk format of btrfs write intent bitmaps Qu Wenruo
@ 2022-07-05  7:37 ` Qu Wenruo
  7 siblings, 0 replies; 9+ messages in thread
From: Qu Wenruo @ 2022-07-05  7:37 UTC (permalink / raw)
  To: linux-btrfs

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 Makefile                         |   3 +-
 cmds/commands.h                  |   1 +
 cmds/inspect-dump-write-intent.c | 158 +++++++++++++++++++++++++++++++
 cmds/inspect.c                   |   1 +
 kernel-shared/print-tree.c       |  93 ++++++++++++++++++
 kernel-shared/print-tree.h       |   1 +
 6 files changed, 256 insertions(+), 1 deletion(-)
 create mode 100644 cmds/inspect-dump-write-intent.c

diff --git a/Makefile b/Makefile
index ea5a1ae86f30..314a22078a9a 100644
--- a/Makefile
+++ b/Makefile
@@ -203,7 +203,8 @@ cmds_objects = cmds/subvolume.o cmds/subvolume-list.o \
 	       cmds/restore.o cmds/rescue.o cmds/rescue-chunk-recover.o \
 	       cmds/rescue-super-recover.o \
 	       cmds/property.o cmds/filesystem-usage.o cmds/inspect-dump-tree.o \
-	       cmds/inspect-dump-super.o cmds/inspect-tree-stats.o cmds/filesystem-du.o \
+	       cmds/inspect-dump-super.o cmds/inspect-dump-write-intent.o \
+	       cmds/inspect-tree-stats.o cmds/filesystem-du.o \
 	       mkfs/common.o check/mode-common.o check/mode-lowmem.o
 
 libbtrfs_objects = \
diff --git a/cmds/commands.h b/cmds/commands.h
index 9ec50136e29a..166686454137 100644
--- a/cmds/commands.h
+++ b/cmds/commands.h
@@ -141,6 +141,7 @@ DECLARE_COMMAND(check);
 DECLARE_COMMAND(inspect);
 DECLARE_COMMAND(inspect_dump_super);
 DECLARE_COMMAND(inspect_dump_tree);
+DECLARE_COMMAND(inspect_dump_write_intent);
 DECLARE_COMMAND(inspect_tree_stats);
 DECLARE_COMMAND(property);
 DECLARE_COMMAND(send);
diff --git a/cmds/inspect-dump-write-intent.c b/cmds/inspect-dump-write-intent.c
new file mode 100644
index 000000000000..c4d792f23659
--- /dev/null
+++ b/cmds/inspect-dump-write-intent.c
@@ -0,0 +1,158 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include "kerncompat.h"
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <getopt.h>
+#include <uuid/uuid.h>
+
+#include "kernel-shared/ctree.h"
+#include "kernel-shared/disk-io.h"
+#include "kernel-shared/volumes.h"
+#include "kernel-shared/write-intent.h"
+#include "kernel-shared/print-tree.h"
+#include "crypto/hash.h"
+#include "common/utils.h"
+#include "cmds/commands.h"
+#include "common/help.h"
+
+static const char * const cmd_inspect_dump_write_intent_usage[] = {
+	"btrfs inspect-internal dump-write-intet [options] device",
+	"Dump the write-intent bitmaps in a textual form",
+	"",
+	"-a|--all              print write-intent bitmaps from every device",
+	"-b|--bytenr <offset>  print write-intent bitmaps using specific physical offset",
+	"-f|--force            print write-intent bitmaps with bad magic",
+};
+
+static int cmd_inspect_dump_write_intent(const struct cmd_struct *cmd,
+					int argc, char **argv)
+{
+	struct open_ctree_flags ocf = { .flags = OPEN_CTREE_PARTIAL |
+						 OPEN_CTREE_NO_BLOCK_GROUPS };
+	struct btrfs_fs_info *fs_info;
+	u8 buf[WRITE_INTENT_BITMAPS_SIZE] = {0};
+	/* Dump all write-intent bitmaps from all involved devices. */
+	bool all = false;
+	/* Force dump even very basic checks failed. */
+	bool force = 0;
+	/* Read the write intent bitmaps from specific physical offset. */
+	u64 bytenr = SZ_1M;
+	char *dev;
+	int fd;
+	int ret = 0;
+
+	while (1) {
+		int c;
+		enum { GETOPT_VAL_BYTENR = 257 };
+		static const struct option long_options[] = {
+			{"all", no_argument, NULL, 'a'},
+			{"bytenr", required_argument, NULL, 'b'},
+			{"force", no_argument, NULL, 'F'},
+			{NULL, 0, NULL, 0}
+		};
+
+		c = getopt_long(argc, argv, "Fb:a", long_options, NULL);
+		if (c < 0)
+			break;
+
+		switch (c) {
+		case 'a':
+			all = 1;
+			break;
+		case 'F':
+			force = 1;
+			break;
+		case 'b':
+			bytenr = arg_strtou64(optarg);
+			break;
+		default:
+			usage_unknown_option(cmd, argv);
+		}
+	}
+	if (check_argc_exact(argc - optind, 1))
+		return 1;
+
+	dev = argv[optind];
+
+	fd = open(argv[optind], O_RDONLY);
+	if (fd < 0) {
+		error("failed to open %s: %m", dev);
+		return 1;
+	}
+	ret = pread64(fd, buf, WRITE_INTENT_BITMAPS_SIZE, bytenr);
+	close(fd);
+	if (ret < WRITE_INTENT_BITMAPS_SIZE) {
+		error("failed to read write intent bitmap from %s", dev);
+		return 1;
+	}
+
+	if (!force && wi_super_magic((struct write_intent_super *)buf) !=
+		WRITE_INTENT_SUPER_MAGIC) {
+		error("no valid write intent super found");
+		return 1;
+	}
+	ocf.filename = dev;
+	fs_info = open_ctree_fs_info(&ocf);
+	if (!fs_info) {
+		/* -a|--all needs to open the fs to find all devces. */
+		if (all || !force) {
+			error("can not open btrfs on %s", ocf.filename);
+			return 1;
+		}
+		/* Forced dump is still fine. */
+		btrfs_print_write_intent(buf);
+		return 0;
+	}
+
+	/* Basic checks, making sure the fs has bitmaps. */
+	if (!force) {
+		if (!btrfs_fs_compat_ro(fs_info, WRITE_INTENT_BITMAP)) {
+			error("no WRITE_INTENT_BITMAP feature");
+			ret = -EINVAL;
+			goto out;
+		}
+		if (fs_info->csum_type != wi_super_csum_type(
+				(struct write_intent_super *)buf)) {
+			error(
+		"mismatched csum type, write intent bitmap has %u fs has %u",
+			      wi_super_csum_type((struct write_intent_super *)buf),
+			      fs_info->csum_type);
+			ret = -EINVAL;
+			goto out;
+		}
+	}
+	if (all) {
+		struct btrfs_device *dev;
+
+		list_for_each_entry(dev, &fs_info->fs_devices->devices, dev_list) {
+			printf("devid %llu:\n", dev->devid);
+			btrfs_print_write_intent(buf);
+		}
+		ret = 0;
+		goto out;
+	}
+	btrfs_print_write_intent(buf);
+out:
+	close_ctree(fs_info->tree_root);
+	return !!ret;
+}
+
+DEFINE_SIMPLE_COMMAND(inspect_dump_write_intent, "dump-write-intent");
diff --git a/cmds/inspect.c b/cmds/inspect.c
index 1534f2040f4e..a5c1d289d84f 100644
--- a/cmds/inspect.c
+++ b/cmds/inspect.c
@@ -695,6 +695,7 @@ static const struct cmd_group inspect_cmd_group = {
 		&cmd_struct_inspect_dump_tree,
 		&cmd_struct_inspect_dump_super,
 		&cmd_struct_inspect_tree_stats,
+		&cmd_struct_inspect_dump_write_intent,
 		NULL
 	}
 };
diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index 55875a7bc2d3..105ef2d5b072 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -26,6 +26,7 @@
 #include "kernel-shared/disk-io.h"
 #include "kernel-shared/print-tree.h"
 #include "kernel-shared/volumes.h"
+#include "kernel-shared/write-intent.h"
 #include "common/utils.h"
 
 static void print_dir_item_type(struct extent_buffer *eb,
@@ -1934,6 +1935,25 @@ static void print_backup_roots(struct btrfs_super_block *sb)
 	}
 }
 
+#define DEF_WRITE_INTENT_FLAG_ENTRY(bit_name)			\
+	{WRITE_INTENT_FLAGS_##bit_name, #bit_name}
+
+static struct readable_flag_entry write_intent_flags_array[] = {
+	DEF_WRITE_INTENT_FLAG_ENTRY(TARGET_RAID56),
+	DEF_WRITE_INTENT_FLAG_ENTRY(INTERNAL),
+	DEF_WRITE_INTENT_FLAG_ENTRY(BYTENR_LOGICAL),
+};
+
+static const int write_intent_flags_num = sizeof(write_intent_flags_array) /
+					sizeof(struct readable_flag_entry);
+
+static void print_readable_write_intent_flag(u64 flag)
+{
+	return __print_readable_flag(flag, write_intent_flags_array,
+			write_intent_flags_num,
+			WRITE_INTENT_FLAGS_SUPPORTED);
+}
+
 void btrfs_print_superblock(struct btrfs_super_block *sb, int full)
 {
 	int i;
@@ -2100,3 +2120,76 @@ void btrfs_print_superblock(struct btrfs_super_block *sb, int full)
 		print_backup_roots(sb);
 	}
 }
+
+void btrfs_print_write_intent(const u8 *buf)
+{
+	struct write_intent_super *wis = (struct write_intent_super *)buf;
+	struct write_intent_entry *wie;
+	bool csum_match;
+	u16 csum_type = wi_super_csum_type(wis);
+	int csum_size;
+	int cur = 0;
+	char uuid_buf[BTRFS_UUID_UNPARSED_SIZE];
+	u8 result[BTRFS_CSUM_SIZE] = { 0 };
+	char *s;
+	int i;
+
+	if (is_valid_csum_type(csum_type)) {
+		csum_size = btrfs_csum_type_size(csum_type);
+		btrfs_csum_data(NULL, csum_type, buf + BTRFS_CSUM_SIZE, result,
+			WRITE_INTENT_BITMAPS_SIZE - BTRFS_CSUM_SIZE);
+		csum_match = !memcmp(result, buf, csum_size);
+	} else {
+		csum_size = BTRFS_CSUM_SIZE;
+		csum_match = false;
+	}
+
+	printf("csum_type\t\t%hu (", csum_type);
+	if (!is_valid_csum_type(csum_type)) {
+		printf("INVALID");
+	} else {
+		printf("%s", btrfs_super_csum_name(csum_type));
+	}
+	printf(")\n");
+	printf("csum\t\t\t0x");
+	for (i = 0; i < csum_size; i++)
+		printf("%02x", wis->csum[i]);
+	if (csum_match)
+		printf(" [match]");
+	else
+		printf(" [DON'T MATCH]");
+	putchar('\n');
+	printf("magic\t\t\t");
+	s = (char *) &wis->magic;
+	for (i = 0; i < 8; i++)
+		putchar(isprint(s[i]) ? s[i] : '.');
+	if (wi_super_magic(wis) == WRITE_INTENT_SUPER_MAGIC)
+		printf(" [match]\n");
+	else
+		printf(" [DON't MATCH]\n");
+
+	uuid_unparse(wis->fsid, uuid_buf);
+	printf("fsid\t\t\t%s\n", uuid_buf);
+	printf("flags\t\t\t0x%llx\n", wi_super_flags(wis));
+	print_readable_write_intent_flag(wi_super_flags(wis));
+	printf("events\t\t\t%llu\n", wi_super_events(wis));
+	printf("size\t\t\t%llu\n", wi_super_size(wis));
+	printf("blocksize\t\t%u\n", wi_super_blocksize(wis));
+	printf("nr_entries\t\t%llu\n", wi_super_nr_entries(wis));
+
+	for (cur = sizeof(*wis), i = 0; cur < WRITE_INTENT_BITMAPS_SIZE;
+	     cur += sizeof(*wie), i++) {
+		u64 bytenr;
+
+		wie = (struct write_intent_entry *)(buf + cur);
+
+		bytenr = wi_entry_bytenr(wie);
+
+		/* Last one. */
+		if (bytenr == 0)
+			break;
+		printf("entry %d, bytenr %llu, bitmap 0x%08x%08x\n",
+			i, bytenr, wie_get_bitmap0(wie),
+			wie_get_bitmap1(wie));
+	}
+}
diff --git a/kernel-shared/print-tree.h b/kernel-shared/print-tree.h
index 80fb6ef75ff5..5ed398b15be5 100644
--- a/kernel-shared/print-tree.h
+++ b/kernel-shared/print-tree.h
@@ -42,5 +42,6 @@ void print_extent_item(struct extent_buffer *eb, int slot, int metadata);
 void print_objectid(FILE *stream, u64 objectid, u8 type);
 void print_key_type(FILE *stream, u64 objectid, u8 type);
 void btrfs_print_superblock(struct btrfs_super_block *sb, int full);
+void btrfs_print_write_intent(const u8 *buf);
 
 #endif
-- 
2.36.1


^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-07-05  7:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-05  7:37 [PATCH 0/8] btrfs-progs: add support for write-intent bitmaps Qu Wenruo
2022-07-05  7:37 ` [PATCH 1/8] btrfs-progs: introduce a new compat RO flag, EXTRA_SUPER_RESERVED Qu Wenruo
2022-07-05  7:37 ` [PATCH 2/8] btrfs-progs: mkfs: add support for extra-super-reserved runtime flag Qu Wenruo
2022-07-05  7:37 ` [PATCH 3/8] btrfs-progs: print-tree: remove duplicated definition for compat RO flags Qu Wenruo
2022-07-05  7:37 ` [PATCH 4/8] btrfs-progs: print-tree: support btrfs_super_block::reserved_bytes Qu Wenruo
2022-07-05  7:37 ` [PATCH 5/8] btrfs-progs: check: add extra warning for dev extents inside the reserved range Qu Wenruo
2022-07-05  7:37 ` [PATCH 6/8] btrfs-progs: introduce the experimental compat RO flag, WRITE_INTENT_BITMAP Qu Wenruo
2022-07-05  7:37 ` [PATCH 7/8] btrfs-progs: introduce the on-disk format of btrfs write intent bitmaps Qu Wenruo
2022-07-05  7:37 ` [PATCH 8/8] btrfs-progs: cmds/inspect: add the ability to dump " Qu Wenruo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).