+/* Btrfs inode flag stringification helper */
+#define STRCAT_ONE_INODE_FLAG(flags, name, empty, dst) ({ \
+ if (flags & BTRFS_INODE_##name) { \
+ if (!empty) \
+ strcat(dst, "|"); \
+ strcat(dst, #name); \
+ empty = 0; \
+ } \
+})
+
+/*
+ * Caller should ensure sizeof(*ret) >= 102: all charactors plus '|' of
+ * BTRFS_INODE_* flags
+ */
+static void inode_flags_to_str(u64 flags, char *ret)
+{
+ int empty = 1;
+
+ STRCAT_ONE_INODE_FLAG(flags, NODATASUM, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, NODATACOW, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, READONLY, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, NOCOMPRESS, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, PREALLOC, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, SYNC, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, IMMUTABLE, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, APPEND, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, NODUMP, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, NOATIME, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, DIRSYNC, empty, ret);
+ STRCAT_ONE_INODE_FLAG(flags, COMPRESS, empty, ret);
+ if (empty)
+ strcat(ret, "none");
+}
+
+static void print_inode_item(struct extent_buffer *eb,
+ struct btrfs_inode_item *ii)
+{
+ char flags_str[256];
+
+ memset(flags_str, 0, sizeof(flags_str));
+ inode_flags_to_str(btrfs_inode_flags(eb, ii), flags_str);
+ printf("\t\tgeneration %llu transid %llu size %llu nbytes %llu\n"
+ "\t\tblock group %llu mode %o links %u uid %u gid %u rdev %llu\n"
+ "\t\tsequence %llu flags 0x%llx(%s)\n",
+ (unsigned long long)btrfs_inode_generation(eb, ii),
+ (unsigned long long)btrfs_inode_transid(eb, ii),
+ (unsigned long long)btrfs_inode_size(eb, ii),
+ (unsigned long long)btrfs_inode_nbytes(eb, ii),
+ (unsigned long long)btrfs_inode_block_group(eb,ii),
+ btrfs_inode_mode(eb, ii),
+ btrfs_inode_nlink(eb, ii),
+ btrfs_inode_uid(eb, ii),
+ btrfs_inode_gid(eb, ii),
+ (unsigned long long)btrfs_inode_rdev(eb,ii),
+ (unsigned long long)btrfs_inode_flags(eb,ii),
+ (unsigned long long)btrfs_inode_sequence(eb, ii),
+ flags_str);
+ print_timespec(eb, btrfs_inode_atime(ii), "\t\tatime ", "\n");
+ print_timespec(eb, btrfs_inode_ctime(ii), "\t\tctime ", "\n");
+ print_timespec(eb, btrfs_inode_mtime(ii), "\t\tmtime ", "\n");
+ print_timespec(eb, btrfs_inode_otime(ii), "\t\totime ", "\n");
+}
+
+static void print_disk_balance_args(struct btrfs_disk_balance_args *ba)
+{
+ printf("\t\tprofiles %llu devid %llu target %llu flags %llu\n",
+ (unsigned long long)le64_to_cpu(ba->profiles),
+ (unsigned long long)le64_to_cpu(ba->devid),
+ (unsigned long long)le64_to_cpu(ba->target),
+ (unsigned long long)le64_to_cpu(ba->flags));
+ printf("\t\tusage_min %u usage_max %u pstart %llu pend %llu\n",
+ le32_to_cpu(ba->usage_min),
+ le32_to_cpu(ba->usage_max),
+ (unsigned long long)le64_to_cpu(ba->pstart),
+ (unsigned long long)le64_to_cpu(ba->pend));
+ printf("\t\tvstart %llu vend %llu limit_min %u limit_max %u\n",
+ (unsigned long long)le64_to_cpu(ba->vstart),
+ (unsigned long long)le64_to_cpu(ba->vend),
+ le32_to_cpu(ba->limit_min),
+ le32_to_cpu(ba->limit_max));
+ printf("\t\tstripes_min %u stripes_max %u\n",
+ le32_to_cpu(ba->stripes_min),
+ le32_to_cpu(ba->stripes_max));
+}
+
+static void print_balance_item(struct extent_buffer *eb,
+ struct btrfs_balance_item *bi)
+{
+ printf("\t\tbalance status flags %llu\n",
+ btrfs_balance_item_flags(eb, bi));
+
+ printf("\t\tDATA\n");
+ print_disk_balance_args(btrfs_balance_item_data(eb, bi));
+ printf("\t\tMETADATA\n");
+ print_disk_balance_args(btrfs_balance_item_meta(eb, bi));
+ printf("\t\tSYSTEM\n");
+ print_disk_balance_args(btrfs_balance_item_sys(eb, bi));
+}
+
+static void print_dev_stats(struct extent_buffer *eb,
+ struct btrfs_dev_stats_item *stats, u32 size)