ocfs2-tools/0002-dx_dirs-debugfs.ocfs2-support.patch

455 lines
12 KiB
Diff

From b891260ad1500f3f2c0562d4376307b18bc4a9f4 Mon Sep 17 00:00:00 2001
From: Mark Fasheh <mfasheh@suse.com>
Date: Sun, 11 Apr 2010 16:09:59 +0800
Subject: [PATCH 02/30] dx_dirs: debugfs.ocfs2 support
This adds a full set of functionality to debugfs.ocfs2 so that we can
visualize and debug indexed directories. Aside
from updates to other commands to dump newly added/used fields in old
structures, we get the following debugfs.ocfs2 commands:
dx_space - Show all entries in the free list
dx_dump - Show the directory index (including root block)
dx_leaf - Show a single directory index leaf block
dx_root - Show directory index root block, as well as any extent blocks
for non-inline dx_roots.
[modified the patch for code rebase and cleanup -- Coly Li]
Signed-off-by: Mark Fasheh <mfasheh@suse.com>
Signed-off-by: Coly Li <coly.li@suse.de>
---
debugfs.ocfs2/commands.c | 173 ++++++++++++++++++++++++++++++++++++++++++
debugfs.ocfs2/dump.c | 164 ++++++++++++++++++++++++++++++++++++++--
debugfs.ocfs2/include/dump.h | 5 +
3 files changed, 335 insertions(+), 7 deletions(-)
diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 1c19ab4..04e56b4 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -77,6 +77,10 @@ static void do_dirblocks(char **args);
static void do_xattr(char **args);
static void do_frag(char **args);
static void do_refcount(char **args);
+static void do_dx_root(char **args);
+static void do_dx_leaf(char **args);
+static void do_dx_dump(char **args);
+static void do_dx_space(char **args);
dbgfs_gbls gbls;
@@ -116,6 +120,10 @@ static Command commands[] = {
{ "dirblocks", do_dirblocks },
{ "frag", do_frag },
{ "refcount", do_refcount },
+ { "dx_root", do_dx_root },
+ { "dx_leaf", do_dx_leaf },
+ { "dx_dump", do_dx_dump },
+ { "dx_space", do_dx_space },
};
/*
@@ -842,6 +850,10 @@ static void do_help (char **args)
printf ("dlm_locks [-f <file>] [-l] lockname\t\t\tShow live dlm locking state\n");
printf ("dump [-p] <filespec> <outfile>\t\tDumps file to outfile on a mounted fs\n");
printf ("dirblocks <filespec>\t\t\tDump directory blocks\n");
+ printf ("dx_space <filespec>\t\t\tDump directory free space list\n");
+ printf ("dx_dump <blkno>\t\t\tShow directory index information\n");
+ printf ("dx_leaf <blkno>\t\t\tShow directory index leaf block only\n");
+ printf ("dx_root <blkno>\t\t\tShow directory index root block only\n");
printf ("encode <filespec>\t\t\tShow lock name\n");
printf ("extent <block#>\t\t\t\tShow extent block\n");
printf ("findpath <block#>\t\t\tList one pathname of the inode/lockname\n");
@@ -1316,6 +1328,167 @@ static void do_dirblocks (char **args)
}
/*
+ * do_dx_root()
+ *
+ */
+static void do_dx_root (char **args)
+{
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inodestr_args(args, 1, &blkno) != 1)
+ return;
+
+ buf = gbls.blockbuf;
+ out = open_pager(gbls.interactive);
+
+ ret = ocfs2_read_dx_root(gbls.fs, blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir root "
+ "block %"PRIu64"", blkno);
+ close_pager (out);
+ return;
+ }
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ dump_dx_root(out, dx_root);
+ if (!(dx_root->dr_flags & OCFS2_DX_FLAG_INLINE))
+ traverse_extents(gbls.fs, &dx_root->dr_list, out);
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_leaf()
+ *
+ */
+static void do_dx_leaf (char **args)
+{
+ struct ocfs2_dx_leaf *dx_leaf;
+ uint64_t blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inodestr_args(args, 1, &blkno) != 1)
+ return;
+
+ buf = gbls.blockbuf;
+ out = open_pager(gbls.interactive);
+
+ ret = ocfs2_read_dx_leaf(gbls.fs, blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir leaf "
+ "block %"PRIu64"", blkno);
+ close_pager (out);
+ return;
+ }
+
+ dx_leaf = (struct ocfs2_dx_leaf *)buf;
+ dump_dx_leaf(out, dx_leaf);
+
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_dump()
+ *
+ */
+static void do_dx_dump (char **args)
+{
+ struct ocfs2_dinode *inode;
+ uint64_t ino_blkno;
+ char *buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inode_args(args, &ino_blkno))
+ return;
+
+ out = open_pager(gbls.interactive);
+
+ buf = gbls.blockbuf;
+ ret = ocfs2_read_inode(gbls.fs, ino_blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading inode %"PRIu64"",
+ ino_blkno);
+ close_pager (out);
+ return ;
+ }
+
+ inode = (struct ocfs2_dinode *)buf;
+
+ dump_dx_entries(out, inode);
+
+ close_pager(out);
+
+ return;
+}
+
+/*
+ * do_dx_space()
+ *
+ */
+static void do_dx_space (char **args)
+{
+ struct ocfs2_dinode *inode;
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t ino_blkno, dx_blkno;
+ char *buf = NULL, *dx_root_buf = NULL;
+ FILE *out;
+ errcode_t ret = 0;
+
+ if (process_inode_args(args, &ino_blkno))
+ return;
+
+ out = open_pager(gbls.interactive);
+
+ buf = gbls.blockbuf;
+ ret = ocfs2_read_inode(gbls.fs, ino_blkno, buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading inode %"PRIu64"",
+ ino_blkno);
+ goto out;
+ }
+
+ inode = (struct ocfs2_dinode *)buf;
+ if (!(ocfs2_dir_indexed(inode))) {
+ fprintf(out, "Inode %"PRIu64" is not indexed\n", ino_blkno);
+ goto out;
+ }
+
+ ret = ocfs2_malloc_block(gbls.fs->fs_io, &dx_root_buf);
+ if (ret) {
+ goto out;
+ }
+
+ dx_blkno = (uint64_t) inode->i_dx_root;
+
+ ret = ocfs2_read_dx_root(gbls.fs, dx_blkno, dx_root_buf);
+ if (ret) {
+ com_err(args[0], ret, "while reading dx dir root "
+ "block %"PRIu64"", dx_blkno);
+ goto out;
+ }
+
+ dx_root = (struct ocfs2_dx_root_block *)dx_root_buf;
+
+ dump_dx_space(out, inode, dx_root);
+out:
+ close_pager(out);
+ if (dx_root_buf)
+ ocfs2_free(&dx_root_buf);
+
+ return;
+}
+
+/*
* do_extent()
*
*/
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 7880991..2e887ce 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -99,6 +99,9 @@ void dump_super_block(FILE *out, struct ocfs2_super_block *sb)
fprintf(out, "%02X", sb->s_uuid[i]);
fprintf(out, "\n");
fprintf(out, "\tHash: %u (0x%x)\n", sb->s_uuid_hash, sb->s_uuid_hash);
+ for (i = 0; i < 3; i++)
+ fprintf(out, "\tDX Seed[%d]: 0x%08x\n", i, sb->s_dx_seed[i]);
+
if (ocfs2_userspace_stack(sb))
fprintf(out,
"\tCluster stack: %s\n"
@@ -315,6 +318,9 @@ void dump_inode(FILE *out, struct ocfs2_dinode *in)
if (in->i_dyn_features & OCFS2_INLINE_DATA_FL) {
fprintf(out, "\tInline Data Max: %u\n",
in->id2.i_data.id_count);
+ } else if (in->i_dyn_features & OCFS2_INDEXED_DIR_FL) {
+ fprintf(out, "\tIndexed Tree Root: %"PRIu64"\n",
+ (uint64_t)in->i_dx_root);
}
if (flags)
@@ -490,6 +496,21 @@ int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
}
/*
+ * dump_dir_trailer()
+ */
+static void dump_dir_trailer(FILE *out, struct ocfs2_dir_block_trailer *trailer)
+{
+ fprintf(out,
+ "\tTrailer Block: %-15"PRIu64" Inode: %-15"PRIu64" rec_len: %-4u\n",
+ trailer->db_blkno, trailer->db_parent_dinode,
+ trailer->db_compat_rec_len);
+ fprintf(out,
+ "\tLargest hole: %u Next in list: %-15"PRIu64"\n",
+ trailer->db_free_rec_len, trailer->db_free_next);
+ dump_block_check(out, &trailer->db_check);
+}
+
+/*
* dump_dir_block()
*
*/
@@ -507,13 +528,9 @@ void dump_dir_block(FILE *out, char *buf)
};
if (!strncmp((char *)trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE,
- sizeof(trailer->db_signature))) {
- fprintf(out,
- "\tTrailer Block: %-15"PRIu64" Inode: %-15"PRIu64" rec_len: %-4u\n",
- trailer->db_blkno, trailer->db_parent_dinode,
- trailer->db_compat_rec_len);
- dump_block_check(out, &trailer->db_check);
- } else
+ sizeof(trailer->db_signature)))
+ dump_dir_trailer(out, trailer);
+ else
end = gbls.fs->fs_blocksize;
fprintf(out, "\tEntries:\n");
@@ -533,6 +550,139 @@ void dump_dir_block(FILE *out, char *buf)
}
}
+static void dump_dx_entry(FILE *out, int i, struct ocfs2_dx_entry *dx_entry)
+{
+ fprintf(out, "\t %-2d (0x%08x 0x%08x) %-13"PRIu64"\n",
+ i, dx_entry->dx_major_hash, dx_entry->dx_minor_hash,
+ (uint64_t)dx_entry->dx_dirent_blk);
+}
+
+static void dump_dx_entry_list(FILE *out, struct ocfs2_dx_entry_list *dl_list,
+ int traverse)
+{
+ int i;
+
+ fprintf(out, "\tCount: %u Num Used: %u\n",
+ dl_list->de_count, dl_list->de_num_used);
+
+ if (traverse) {
+ fprintf(out, "\t## %-11s %-13s\n", "Hash (Major Minor)",
+ "Dir Block#");
+
+ for (i = 0; i < dl_list->de_num_used; i++)
+ dump_dx_entry(out, i, &dl_list->de_entries[i]);
+ }
+}
+
+void dump_dx_root(FILE *out, struct ocfs2_dx_root_block *dr)
+{
+ char tmp_str[30];
+ GString *flags = NULL;
+
+ flags = g_string_new(NULL);
+ if (dr->dr_flags & OCFS2_DX_FLAG_INLINE)
+ g_string_append(flags, "Inline ");
+
+ fprintf(out, "\tDir Index Root: %"PRIu64" FS Generation: %u (0x%x)\n",
+ (uint64_t)dr->dr_blkno, dr->dr_fs_generation,
+ dr->dr_fs_generation);
+
+ fprintf(out, "\tClusters: %u Last Extblk: %"PRIu64" "
+ "Dir Inode: %"PRIu64"\n",
+ dr->dr_clusters, (uint64_t)dr->dr_last_eb_blk,
+ (uint64_t)dr->dr_dir_blkno);
+
+ if (dr->dr_suballoc_slot == (uint16_t)OCFS2_INVALID_SLOT)
+ strcpy(tmp_str, "Global");
+ else
+ sprintf(tmp_str, "%d", dr->dr_suballoc_slot);
+ fprintf(out, "\tSub Alloc Slot: %s Sub Alloc Bit: %u "
+ "Flags: (0x%x) %s\n",
+ tmp_str, dr->dr_suballoc_bit, dr->dr_flags, flags->str);
+
+ dump_block_check(out, &dr->dr_check);
+
+ if (dr->dr_flags & OCFS2_DX_FLAG_INLINE)
+ dump_dx_entry_list(out, &dr->dr_entries, 0);
+
+ if (flags)
+ g_string_free(flags, 1);
+}
+
+void dump_dx_leaf (FILE *out, struct ocfs2_dx_leaf *dx_leaf)
+{
+ fprintf(out, "\tDir Index Leaf: %"PRIu64" FS Generation: %u (0x%x)\n",
+ (uint64_t)dx_leaf->dl_blkno, dx_leaf->dl_fs_generation,
+ dx_leaf->dl_fs_generation);
+ dump_block_check(out, &dx_leaf->dl_check);
+
+ dump_dx_entry_list(out, &dx_leaf->dl_list, 1);
+}
+
+static int entries_iter(ocfs2_filesys *fs,
+ struct ocfs2_dx_entry_list *entry_list,
+ struct ocfs2_dx_root_block *dx_root,
+ struct ocfs2_dx_leaf *dx_leaf,
+ void *priv_data)
+{
+ FILE *out = priv_data;
+
+ if (dx_leaf) {
+ dump_dx_leaf(out, dx_leaf);
+ return 0;
+ }
+
+ /* Inline entries. Dump the list directly. */
+ dump_dx_entry_list(out, entry_list, 1);
+
+ return 0;
+}
+
+void dump_dx_entries(FILE *out, struct ocfs2_dinode *inode)
+{
+ struct ocfs2_dx_root_block *dx_root;
+ uint64_t dx_blkno;
+ char *buf = NULL;
+ errcode_t ret = 0;
+
+ if (ocfs2_malloc_block(gbls.fs->fs_io, &buf))
+ return;
+
+ if (!(ocfs2_dir_indexed(inode)))
+ return;
+
+ dx_blkno = (uint64_t) inode->i_dx_root;
+
+ ret = ocfs2_read_dx_root(gbls.fs, dx_blkno, buf);
+ if (ret)
+ return;
+
+ dx_root = (struct ocfs2_dx_root_block *)buf;
+ dump_dx_root(out, dx_root);
+
+ ocfs2_dx_entries_iterate(gbls.fs, inode, 0, entries_iter, out);
+ return;
+}
+
+static int dx_space_iter(ocfs2_filesys *fs,
+ uint64_t blkno,
+ struct ocfs2_dir_block_trailer *trailer,
+ char *dirblock,
+ void *priv_data)
+{
+ FILE *out = priv_data;
+
+ dump_dir_trailer(out, trailer);
+
+ return 0;
+}
+
+void dump_dx_space(FILE *out, struct ocfs2_dinode *inode,
+ struct ocfs2_dx_root_block *dx_root)
+{
+ ocfs2_dx_frees_iterate(gbls.fs, inode, dx_root, 0, dx_space_iter, out);
+}
+
/*
* dump_jbd_header()
*
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index cb677c9..79b10b3 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -52,7 +52,12 @@ void dump_extent_block (FILE *out, struct ocfs2_extent_block *blk);
void dump_group_descriptor (FILE *out, struct ocfs2_group_desc *grp, int index);
int dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
char *buf, void *priv_data);
+void dump_dx_root (FILE *out, struct ocfs2_dx_root_block *dx_root);
+void dump_dx_leaf (FILE *out, struct ocfs2_dx_leaf *dx_leaf);
void dump_dir_block(FILE *out, char *buf);
+void dump_dx_entries(FILE *out, struct ocfs2_dinode *inode);
+void dump_dx_space(FILE *out, struct ocfs2_dinode *inode,
+ struct ocfs2_dx_root_block *dx_root);
void dump_jbd_header (FILE *out, journal_header_t *header);
void dump_jbd_superblock (FILE *out, journal_superblock_t *jsb);
void dump_jbd_block (FILE *out, journal_superblock_t *jsb,
--
1.7.0.2