diff mbox series

[1/2] btrfs-progs: print-tree: add support for dev-replace item

Message ID 3eaa8778997bbdeca22105303586caeba4ab414c.1717299366.git.wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: btrfstune: fix false alerts on dev-replace when changing csum | expand

Commit Message

Qu Wenruo June 2, 2024, 3:45 a.m. UTC
This is inspired by a recent bug that csum change doesn't detect
finished dev-replace.

At the time of that csum change patch, there is no print-tree to
show the content of btrfs_dev_replace_item thus contributes to the bug.

This patch adds the new output for btrfs_dev_replace_item, and the
example looks like this:

	item 1 key (0 DEV_REPLACE 0) itemoff 16171 itemsize 72
		src devid -1 cursor left 1179648000 cursor right 1179648000 mode ALWAYS
		state FINISHED write errors 0 uncorrectable read errors 0
		start time 1717282771 (2024-06-02 08:29:31)
		stop time 1717282771 (2024-06-02 08:29:31)

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

Patch

diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index a4ddbb2ae9cb..a9a4abaa2456 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -36,6 +36,7 @@ 
 #include "common/defs.h"
 #include "common/internal.h"
 #include "common/messages.h"
+#include "uapi/btrfs.h"
 
 static void print_dir_item_type(struct extent_buffer *eb,
                                 struct btrfs_dir_item *di)
@@ -1389,6 +1390,81 @@  static void print_header_info(struct extent_buffer *eb, unsigned int mode)
 	fflush(stdout);
 }
 
+#define DEV_REPLACE_STRING_LEN		64
+#define DEV_REPLACE_MODE_ENTRY(dest, name)				\
+	case BTRFS_DEV_REPLACE_ITEM_CONT_READING_FROM_SRCDEV_MODE_##name: \
+		strncpy((dest), #name, DEV_REPLACE_STRING_LEN);		\
+		break;
+
+static void replace_mode_to_str(u64 flags, char *ret)
+{
+	ret[0] = '\0';
+	switch(flags) {
+	DEV_REPLACE_MODE_ENTRY(ret, ALWAYS);
+	DEV_REPLACE_MODE_ENTRY(ret, AVOID);
+	default:
+		snprintf(ret, DEV_REPLACE_STRING_LEN, "unknown value(%llu)",
+			 flags);
+	}
+}
+#undef DEV_REPLACE_MODE_ENTRY
+
+#define DEV_REPLACE_STATE_ENTRY(dest, name)				\
+	case BTRFS_IOCTL_DEV_REPLACE_STATE_##name:			\
+		strncpy((dest), #name, DEV_REPLACE_STRING_LEN);		\
+		break;
+
+static void replace_state_to_str(u64 flags, char *ret)
+{
+	ret[0] = '\0';
+	switch(flags) {
+	DEV_REPLACE_STATE_ENTRY(ret, NEVER_STARTED);
+	DEV_REPLACE_STATE_ENTRY(ret, FINISHED);
+	DEV_REPLACE_STATE_ENTRY(ret, CANCELED);
+	DEV_REPLACE_STATE_ENTRY(ret, STARTED);
+	DEV_REPLACE_STATE_ENTRY(ret, SUSPENDED);
+	default:
+		snprintf(ret, DEV_REPLACE_STRING_LEN, "unknown value(%llu)",
+			 flags);
+	}
+}
+#undef DEV_REPLACE_STATE_ENTRY
+
+static void print_u64_timespec(u64 timespec, const char *prefix)
+{
+	char time_str[256];
+	struct tm tm;
+	time_t time = timespec;
+
+	localtime_r(&time, &tm);
+	strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &tm);
+	printf("%s%llu (%s)\n", prefix, timespec, time_str);
+}
+
+static void print_dev_replace_item(struct extent_buffer *eb,
+				   struct btrfs_dev_replace_item *ptr)
+{
+	char mode_str[DEV_REPLACE_STRING_LEN] = { 0 };
+	char state_str[DEV_REPLACE_STRING_LEN] = { 0 };
+
+	replace_mode_to_str(
+			btrfs_dev_replace_cont_reading_from_srcdev_mode(eb, ptr),
+			mode_str);
+	replace_state_to_str(
+			btrfs_dev_replace_replace_state(eb, ptr),
+			state_str);
+	printf("\t\tsrc devid %lld cursor left %llu cursor right %llu mode %s\n",
+		btrfs_dev_replace_src_devid(eb, ptr),
+		btrfs_dev_replace_cursor_left(eb, ptr),
+		btrfs_dev_replace_cursor_right(eb, ptr),
+		mode_str);
+	printf("\t\tstate %s write errors %llu uncorrectable read errors %llu\n",
+		state_str, btrfs_dev_replace_num_write_errors(eb, ptr),
+		btrfs_dev_replace_num_uncorrectable_read_errors(eb, ptr));
+	print_u64_timespec(btrfs_dev_replace_time_started(eb, ptr), "\t\tstart time ");
+	print_u64_timespec(btrfs_dev_replace_time_started(eb, ptr), "\t\tstop time ");
+}
+
 void __btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode)
 {
 	struct btrfs_disk_key disk_key;
@@ -1563,6 +1639,9 @@  void __btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode)
 		case BTRFS_RAID_STRIPE_KEY:
 			print_raid_stripe_key(eb, item_size, ptr);
 			break;
+		case BTRFS_DEV_REPLACE_KEY:
+			print_dev_replace_item(eb, ptr);
+			break;
 		};
 		fflush(stdout);
 	}