+ print_key_type(stdout, objectid, type);
+ switch (type) {
+ case BTRFS_QGROUP_RELATION_KEY:
+ case BTRFS_QGROUP_INFO_KEY:
+ case BTRFS_QGROUP_LIMIT_KEY:
+ printf(" %llu/%llu)", btrfs_qgroup_level(offset),
+ btrfs_qgroup_subvid(offset));
+ break;
+ case BTRFS_UUID_KEY_SUBVOL:
+ case BTRFS_UUID_KEY_RECEIVED_SUBVOL:
+ printf(" 0x%016llx)", (unsigned long long)offset);
+ break;
+
+ /*
+ * Key offsets of ROOT_ITEM point to tree root, print them in human
+ * readable format. Especially useful for trees like data/tree reloc
+ * tree, whose tree id can be negative.
+ */
+ case BTRFS_ROOT_ITEM_KEY:
+ printf(" ");
+ /*
+ * Normally offset of ROOT_ITEM should present the generation
+ * of creation time of the root.
+ * However if this is reloc tree, offset is the subvolume
+ * id of its source. Here we do extra check on this.
+ */
+ if (objectid == BTRFS_TREE_RELOC_OBJECTID)
+ print_objectid(stdout, offset, type);
+ else
+ printf("%lld", offset);
+ printf(")");
+ break;
+ default:
+ if (offset == (u64)-1)
+ printf(" -1)");
+ else
+ printf(" %llu)", (unsigned long long)offset);
+ break;
+ }
+}
+
+static void print_uuid_item(struct extent_buffer *l, unsigned long offset,
+ u32 item_size)
+{
+ if (item_size & (sizeof(u64) - 1)) {
+ printf("btrfs: uuid item with illegal size %lu!\n",
+ (unsigned long)item_size);
+ return;
+ }
+ while (item_size) {
+ __le64 subvol_id;
+
+ read_extent_buffer(l, &subvol_id, offset, sizeof(u64));
+ printf("\t\tsubvol_id %llu\n",
+ (unsigned long long)le64_to_cpu(subvol_id));
+ item_size -= sizeof(u64);
+ offset += sizeof(u64);
+ }
+}
+
+/* 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_sequence(eb, ii),
+ (unsigned long long)btrfs_inode_flags(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");