linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH v5 0/2] Add subcommand that dumps file extents
@ 2021-08-22 15:01 Sidong Yang
  2021-08-22 15:01 ` [PATCH v5 1/2] btrfs-progs: export util functions about file extent items Sidong Yang
  2021-08-22 15:01 ` [PATCH v5 2/2] btrfs-progs: cmds: Add subcommand that dumps file extents Sidong Yang
  0 siblings, 2 replies; 3+ messages in thread
From: Sidong Yang @ 2021-08-22 15:01 UTC (permalink / raw)
  To: linux-btrfs, David Sterba, Qu Wenruo; +Cc: Sidong Yang

Hi, I'm want to print which device has the file_extent. but I don't know
how. Maybe it could be found by find block group in extent tree and find
devid in chunk tree again. I don't know it's good way to find it. is
there any good way to find devid?

This patch series add an subcommand in inspect-internal. It dumps file extents
of the file that user provided. For avoiding duplicated code, the patch that
export functions is in this series.

Sidong Yang (2):
  btrfs-progs: export util functions about file extent items
  btrfs-progs: cmds: Add subcommand that dumps file extents

---
v2:
 - Prints type and compression
 - Use the terms from file_extents_item like disk_bytenr not like
   "physical"
v3:
 - export util functions for removing duplication
 - change the way to loop with search ioctl
v4:
 - export COMPRESS_STR_LEN for using function safely
v5:
 - Supports json format
 - Print hole type by checking disk_bytenr
---

 Makefile                         |   2 +-
 cmds/commands.h                  |   2 +-
 cmds/inspect-dump-file-extents.c | 161 +++++++++++++++++++++++++++++++
 cmds/inspect.c                   |   1 +
 kernel-shared/print-tree.c       |  18 ++--
 kernel-shared/print-tree.h       |   5 +
 6 files changed, 178 insertions(+), 11 deletions(-)
 create mode 100644 cmds/inspect-dump-file-extents.c

-- 
2.25.1


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

* [PATCH v5 1/2] btrfs-progs: export util functions about file extent items
  2021-08-22 15:01 [RFC PATCH v5 0/2] Add subcommand that dumps file extents Sidong Yang
@ 2021-08-22 15:01 ` Sidong Yang
  2021-08-22 15:01 ` [PATCH v5 2/2] btrfs-progs: cmds: Add subcommand that dumps file extents Sidong Yang
  1 sibling, 0 replies; 3+ messages in thread
From: Sidong Yang @ 2021-08-22 15:01 UTC (permalink / raw)
  To: linux-btrfs, David Sterba, Qu Wenruo; +Cc: Sidong Yang

This patch export two functions that convert enum about file extents to
string. It can be used in other code like inspect-internal command. And
this patch also make compress_type_to_str() function more safe by using
strncpy() than strcpy().

Signed-off-by: Sidong Yang <realwakka@gmail.com>
---
 kernel-shared/print-tree.c | 18 +++++++++---------
 kernel-shared/print-tree.h |  5 +++++
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c
index e5d4b453..ce1c0ed3 100644
--- a/kernel-shared/print-tree.c
+++ b/kernel-shared/print-tree.c
@@ -338,27 +338,27 @@ static void print_uuids(struct extent_buffer *eb)
 	printf("fs uuid %s\nchunk uuid %s\n", fs_uuid, chunk_uuid);
 }
 
-static void compress_type_to_str(u8 compress_type, char *ret)
+void btrfs_compress_type_to_str(u8 compress_type, char *ret)
 {
 	switch (compress_type) {
 	case BTRFS_COMPRESS_NONE:
-		strcpy(ret, "none");
+		strncpy(ret, "none", BTRFS_COMPRESS_STR_LEN);
 		break;
 	case BTRFS_COMPRESS_ZLIB:
-		strcpy(ret, "zlib");
+		strncpy(ret, "zlib", BTRFS_COMPRESS_STR_LEN);
 		break;
 	case BTRFS_COMPRESS_LZO:
-		strcpy(ret, "lzo");
+		strncpy(ret, "lzo", BTRFS_COMPRESS_STR_LEN);
 		break;
 	case BTRFS_COMPRESS_ZSTD:
-		strcpy(ret, "zstd");
+		strncpy(ret, "zstd", BTRFS_COMPRESS_STR_LEN);
 		break;
 	default:
-		sprintf(ret, "UNKNOWN.%d", compress_type);
+		snprintf(ret, BTRFS_COMPRESS_STR_LEN, "UNKNOWN.%d", compress_type);
 	}
 }
 
-static const char* file_extent_type_to_str(u8 type)
+const char* btrfs_file_extent_type_to_str(u8 type)
 {
 	switch (type) {
 	case BTRFS_FILE_EXTENT_INLINE: return "inline";
@@ -376,12 +376,12 @@ static void print_file_extent_item(struct extent_buffer *eb,
 	unsigned char extent_type = btrfs_file_extent_type(eb, fi);
 	char compress_str[16];
 
-	compress_type_to_str(btrfs_file_extent_compression(eb, fi),
+	btrfs_compress_type_to_str(btrfs_file_extent_compression(eb, fi),
 			     compress_str);
 
 	printf("\t\tgeneration %llu type %hhu (%s)\n",
 			btrfs_file_extent_generation(eb, fi),
-			extent_type, file_extent_type_to_str(extent_type));
+			extent_type, btrfs_file_extent_type_to_str(extent_type));
 
 	if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
 		printf("\t\tinline extent data size %u ram_bytes %llu compression %hhu (%s)\n",
diff --git a/kernel-shared/print-tree.h b/kernel-shared/print-tree.h
index 80fb6ef7..3b96e89d 100644
--- a/kernel-shared/print-tree.h
+++ b/kernel-shared/print-tree.h
@@ -33,6 +33,8 @@ enum {
 	BTRFS_PRINT_TREE_DEFAULT = BTRFS_PRINT_TREE_BFS,
 };
 
+#define BTRFS_COMPRESS_STR_LEN 12
+
 void btrfs_print_tree(struct extent_buffer *eb, unsigned int mode);
 void btrfs_print_leaf(struct extent_buffer *eb, unsigned int mode);
 
@@ -43,4 +45,7 @@ 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_compress_type_to_str(u8 compress_type, char *ret);
+const char* btrfs_file_extent_type_to_str(u8 type);
+
 #endif
-- 
2.25.1


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

* [PATCH v5 2/2] btrfs-progs: cmds: Add subcommand that dumps file extents
  2021-08-22 15:01 [RFC PATCH v5 0/2] Add subcommand that dumps file extents Sidong Yang
  2021-08-22 15:01 ` [PATCH v5 1/2] btrfs-progs: export util functions about file extent items Sidong Yang
@ 2021-08-22 15:01 ` Sidong Yang
  1 sibling, 0 replies; 3+ messages in thread
From: Sidong Yang @ 2021-08-22 15:01 UTC (permalink / raw)
  To: linux-btrfs, David Sterba, Qu Wenruo; +Cc: Sidong Yang

This patch adds an subcommand in inspect-internal. It dumps file extents of
the file that user provided. It helps to show the internal information
about file extents comprise the file. It supports json format by using
formatted printing. An example is below.

{
  "__header": {
    "version": "1"
  },
  "file-extents": [
    {
      "start": "0",
      "disk_bytenr": "21651456",
      "disk_num_bytes": "4096",
      "offset": "0",
      "len": "65536",
      "compression": "zstd",
      "type": "regular"
    },
    {
      "start": "65536",
      "len": "131072",
      "compression": "none",
      "type": "hole"
    }
  ]
}

Signed-off-by: Sidong Yang <realwakka@gmail.com>
---
 Makefile                         |   2 +-
 cmds/commands.h                  |   2 +-
 cmds/inspect-dump-file-extents.c | 161 +++++++++++++++++++++++++++++++
 cmds/inspect.c                   |   1 +
 4 files changed, 164 insertions(+), 2 deletions(-)
 create mode 100644 cmds/inspect-dump-file-extents.c

diff --git a/Makefile b/Makefile
index a1cc457b..911e16de 100644
--- a/Makefile
+++ b/Makefile
@@ -156,7 +156,7 @@ cmds_objects = cmds/subvolume.o cmds/filesystem.o cmds/device.o cmds/scrub.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-tree-stats.o cmds/inspect-dump-file-extents.o cmds/filesystem-du.o \
 	       mkfs/common.o check/mode-common.o check/mode-lowmem.o
 libbtrfs_objects = common/send-stream.o common/send-utils.o kernel-lib/rbtree.o btrfs-list.o \
 		   kernel-lib/radix-tree.o common/extent-cache.o kernel-shared/extent_io.o \
diff --git a/cmds/commands.h b/cmds/commands.h
index 8fa85d6c..55de248e 100644
--- a/cmds/commands.h
+++ b/cmds/commands.h
@@ -154,5 +154,5 @@ DECLARE_COMMAND(select_super);
 DECLARE_COMMAND(dump_super);
 DECLARE_COMMAND(debug_tree);
 DECLARE_COMMAND(rescue);
-
+DECLARE_COMMAND(inspect_dump_file_extents);
 #endif
diff --git a/cmds/inspect-dump-file-extents.c b/cmds/inspect-dump-file-extents.c
new file mode 100644
index 00000000..5f5469a3
--- /dev/null
+++ b/cmds/inspect-dump-file-extents.c
@@ -0,0 +1,161 @@
+/*
+ * 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 <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#include <sys/ioctl.h>
+
+#include "common/utils.h"
+#include "common/format-output.h"
+#include "cmds/commands.h"
+#include "kernel-shared/print-tree.h"
+
+static const char * const cmd_inspect_dump_file_extents_usage[] = {
+	"btrfs inspect-internal dump-extent path",
+	"Dump file extent in a textual form",
+	NULL
+};
+
+static const struct rowspec dump_file_extents_rowspec[] = {
+	{ .key = "device", .fmt = "%s", .out_text = "device", .out_json = "device" },
+	{ .key = "type", .fmt = "%s", .out_text = "type", .out_json = "type" },
+	{ .key = "start", .fmt = "%u", .out_text = "start", .out_json = "start" },
+	{ .key = "len", .fmt = "%u", .out_text = "len", .out_json = "len" },
+	{ .key = "disk_bytenr", .fmt = "%u", .out_text = "disk_bytenr", .out_json = "disk_bytenr" },
+	{ .key = "disk_num_bytes", .fmt = "%u", .out_text = "disk_num_bytes", .out_json = "disk_num_bytes" },
+	{ .key = "offset", .fmt = "%u", .out_text = "offset", .out_json = "offset" },
+	{ .key = "compression", .fmt = "%s", .out_text = "compression", .out_json = "compression" },
+	ROWSPEC_END
+};
+
+static int cmd_inspect_dump_file_extents(const struct cmd_struct *cmd,
+										 int argc, char **argv)
+{
+	int fd;
+	struct stat statbuf;
+	struct btrfs_ioctl_ino_lookup_args lookup;
+	struct btrfs_ioctl_search_args args;
+	struct btrfs_ioctl_search_key *sk = &args.key;
+	struct btrfs_file_extent_item *extent_item;
+	struct btrfs_ioctl_search_header *header;
+	u64 start, buf_off;
+	int ret, i;
+
+	struct format_ctx fctx;
+
+	fd = open(argv[optind], O_RDONLY);
+	if (fd < 0) {
+		error("cannot open %s: %m", argv[optind]);
+		ret = 1;
+		goto out;
+	}
+
+	if (fstat(fd, &statbuf) < 0) {
+		error("failed to fstat %s: %m", argv[optind]);
+		ret = 1;
+		goto out;
+	}
+
+	lookup.treeid = 0;
+	lookup.objectid = BTRFS_FIRST_FREE_OBJECTID;
+
+	if (ioctl(fd, BTRFS_IOC_INO_LOOKUP, &lookup) < 0) {
+		error("failed to lookup inode %s: %m", argv[optind]);
+		ret = 1;
+		goto out;
+	}
+
+	sk->tree_id = lookup.treeid;
+	sk->min_objectid = statbuf.st_ino;
+	sk->max_objectid = statbuf.st_ino;
+	sk->min_offset = 0;
+	sk->max_offset = UINT64_MAX;
+	sk->min_transid = 0;
+	sk->max_transid = UINT64_MAX;
+	sk->min_type = sk->max_type = BTRFS_EXTENT_DATA_KEY;
+	sk->nr_items = UINT32_MAX;
+
+again:
+	if (ioctl(fd, BTRFS_IOC_TREE_SEARCH, &args)) {
+		error("failed to search tree ioctl %s: %m", argv[optind]);
+		ret = 1;
+		goto out;
+	}
+
+	buf_off = 0;
+	fmt_start(&fctx, dump_file_extents_rowspec, 24, 0);
+	fmt_print_start_group(&fctx, "file-extents", JSON_TYPE_ARRAY);
+	for(i=0; i<sk->nr_items; ++i) {
+		header = (struct btrfs_ioctl_search_header *)(args.buf + buf_off);
+
+		if (btrfs_search_header_type(header) == BTRFS_EXTENT_DATA_KEY) {
+			u64 len, disk_bytenr, disk_num_bytes, offset;
+			const char *type_str;
+			char compress_str[BTRFS_COMPRESS_STR_LEN];
+
+			extent_item = (struct btrfs_file_extent_item *)(header + 1);
+			fmt_print_start_group(&fctx, NULL, JSON_TYPE_MAP);
+
+			start = btrfs_search_header_offset(header);
+			fmt_print(&fctx, "start", start);
+			type_str = btrfs_file_extent_type_to_str(extent_item->type);
+			btrfs_compress_type_to_str(extent_item->compression, compress_str);
+
+			switch (extent_item->type) {
+			case BTRFS_FILE_EXTENT_INLINE:
+				len = le64_to_cpu(extent_item->ram_bytes);
+				break;
+			case BTRFS_FILE_EXTENT_REG:
+			case BTRFS_FILE_EXTENT_PREALLOC:
+				len = le64_to_cpu(extent_item->num_bytes);
+				disk_bytenr = le64_to_cpu(extent_item->disk_bytenr);
+				if (disk_bytenr) {
+					disk_num_bytes = le64_to_cpu(extent_item->disk_num_bytes);
+					offset = le64_to_cpu(extent_item->offset);
+					fmt_print(&fctx, "disk_bytenr", disk_bytenr);
+					fmt_print(&fctx, "disk_num_bytes", disk_num_bytes);
+					fmt_print(&fctx, "offset", offset);
+
+				} else {
+					type_str = "hole";
+				}
+				break;
+			}
+
+			fmt_print(&fctx, "len", len);
+			fmt_print(&fctx, "compression", compress_str);
+			fmt_print(&fctx, "type", type_str);
+			fmt_print_end_group(&fctx, NULL);
+		}
+		buf_off += sizeof(*header) + btrfs_search_header_len(header);
+	}
+	fmt_print_end_group(&fctx, "file-extents");
+	fmt_end(&fctx);
+
+	if (sk->nr_items > 512) {
+		sk->nr_items = UINT32_MAX;
+		sk->min_offset = start + 1;
+		goto again;
+	}
+	ret = 0;
+out:
+	close(fd);
+	return ret;
+}
+
+DEFINE_COMMAND_WITH_FLAGS(inspect_dump_file_extents, "dump-file-extents", CMD_FORMAT_JSON);
diff --git a/cmds/inspect.c b/cmds/inspect.c
index 2ef5f4b6..dfb0e27b 100644
--- a/cmds/inspect.c
+++ b/cmds/inspect.c
@@ -696,6 +696,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_file_extents,
 		NULL
 	}
 };
-- 
2.25.1


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

end of thread, other threads:[~2021-08-22 15:02 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-22 15:01 [RFC PATCH v5 0/2] Add subcommand that dumps file extents Sidong Yang
2021-08-22 15:01 ` [PATCH v5 1/2] btrfs-progs: export util functions about file extent items Sidong Yang
2021-08-22 15:01 ` [PATCH v5 2/2] btrfs-progs: cmds: Add subcommand that dumps file extents Sidong Yang

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