[Ocfs2-tools-devel] [PATCH 6/6] debugfs.ocfs2: Print dirblocks as a whole.

Joel Becker Joel.Becker at oracle.com
Fri Jan 9 16:18:20 PST 2009


Let's print whole dirblocks, not just trailers.  The 'dir_trailers'
command becomes 'dirblocks'.  As a bonus, 'logdump' can now dump
dirblocks it detects via the trailer.

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 debugfs.ocfs2/commands.c     |   71 ++++++++++++++++++++++++++----------------
 debugfs.ocfs2/dump.c         |   65 ++++++++++++++++++++++++++++++--------
 debugfs.ocfs2/include/dump.h |    8 +++--
 debugfs.ocfs2/journal.c      |   20 ++++++++---
 4 files changed, 114 insertions(+), 50 deletions(-)

diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 7aaa840..7f2e4bc 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -73,7 +73,7 @@ static void do_bmap (char **args);
 static void do_icheck (char **args);
 static void do_dlm_locks (char **args);
 static void do_controld(char **args);
-static void do_dir_trailers(char **args);
+static void do_dirblocks(char **args);
 
 dbgfs_gbls gbls;
 
@@ -109,7 +109,7 @@ static Command commands[] = {
 	{ "stats",	do_stats },
 	{ "encode",	do_encode_lockres },
 	{ "decode",	do_decode_lockres },
-	{ "dir_trailers",	do_dir_trailers },
+	{ "dirblocks",	do_dirblocks },
 };
 
 /*
@@ -835,7 +835,7 @@ static void do_help (char **args)
 	printf ("decode <lockname#> ...\t\t\tDecode block#(s) from the lockname(s)\n");
 	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 ("dir_trailers <filespec>\t\t\tDump directory block trailers\n");
+	printf ("dirblocks <filespec>\t\t\tDump directory blocks\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");
@@ -1239,53 +1239,70 @@ static void do_group (char **args)
 	return ;
 }
 
+static int dirblocks_proxy(ocfs2_filesys *fs, uint64_t blkno,
+			   uint64_t bcount, uint16_t ext_flags,
+			   void *priv_data)
+{
+	errcode_t ret;
+	struct dirblocks_walk *ctxt = priv_data;
+
+	ret = ocfs2_read_dir_block(fs, ctxt->di, blkno, ctxt->buf);
+	if (!ret) {
+		fprintf(ctxt->out, "\tDirbloc: %"PRIu64"\n", blkno);
+		dump_dir_block(ctxt->out, ctxt->buf);
+	} else
+		com_err(gbls.cmd, ret,
+			"while reading dirblock %"PRIu64" on inode "
+			"%"PRIu64"\n",
+			blkno, ctxt->di->i_blkno);
+	return 0;
+}
+
 /*
- * do_dir_trailers()
+ * do_dirblocks()
  *
  */
-static void do_dir_trailers (char **args)
+static void do_dirblocks (char **args)
 {
-	struct ocfs2_dinode *inode;
 	uint64_t ino_blkno;
-	char *buf = NULL;
-	FILE *out;
 	errcode_t ret = 0;
-	struct dir_trailer_walk ctxt;
+	struct dirblocks_walk ctxt = {
+		.fs = gbls.fs,
+	};
 
 	if (process_inode_args(args, &ino_blkno))
 		return;
 
-	out = open_pager(gbls.interactive);
-
-	ctxt.fs = gbls.fs;
-	ctxt.out = out;
+	ret = ocfs2_check_directory(gbls.fs, ino_blkno);
+	if (ret) {
+		com_err(args[0], ret, "while checking directory at "
+			"block %"PRIu64"", ino_blkno);
+		return;
+	}
 
-	buf = gbls.blockbuf;
-	ret = ocfs2_read_inode(gbls.fs, ino_blkno, buf);
+	ret = ocfs2_read_inode(gbls.fs, ino_blkno, gbls.blockbuf);
 	if (ret) {
 		com_err(args[0], ret, "while reading inode %"PRIu64"",
 			ino_blkno);
-		close_pager (out);
-		return ;
+		return;
 	}
+	ctxt.di = (struct ocfs2_dinode *)gbls.blockbuf;
 
-	inode = (struct ocfs2_dinode *)buf;
-	if (!ocfs2_dir_has_trailer(gbls.fs, inode)) {
-		fprintf(out, "Inode %"PRIu64" has no trailers\n", ino_blkno);
-		close_pager (out);
+	ret = ocfs2_malloc_block(ctxt.fs->fs_io, &ctxt.buf);
+	if (ret) {
+		com_err(gbls.cmd, ret, "while allocating a block");
 		return;
 	}
 
-	ret = ocfs2_dir_iterate(gbls.fs, ino_blkno,
-				OCFS2_DIRENT_FLAG_INCLUDE_TRAILER, NULL,
-				dump_dir_trailers, (void *)&ctxt);
+	ctxt.out = open_pager(gbls.interactive);
+	ret = ocfs2_block_iterate_inode(gbls.fs, ctxt.di, 0,
+					dirblocks_proxy, &ctxt);
 	if (ret)
 		com_err(args[0], ret, "while iterating directory at "
 			"block %"PRIu64"", ino_blkno);
+	close_pager(ctxt.out);
 
-	close_pager(out);
-
-	return;
+	ocfs2_free(&ctxt.buf);
 }
 
 /*
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index f1a2560..c2af958 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -467,26 +467,48 @@ int  dump_dir_entry (struct ocfs2_dir_entry *rec, int offset, int blocksize,
 }
 
 /*
- * dump_dir_entry()
+ * dump_dir_block()
  *
  */
-int dump_dir_trailers(struct ocfs2_dir_entry *rec, int offset, int blocksize,
-		      char *buf, void *priv_data)
+void dump_dir_block(FILE *out, char *buf)
 {
-	struct dir_trailer_walk *ctxt = priv_data;
-	struct ocfs2_dir_block_trailer *trailer =
-		(struct ocfs2_dir_block_trailer *)rec;
 
-	if (ocfs2_dir_trailer_blk_off(ctxt->fs) != offset)
-		return 0;
+	struct ocfs2_dir_entry *dirent;
+	int offset = 0;
+	int end = ocfs2_dir_trailer_blk_off(gbls.fs);
+	struct ocfs2_dir_block_trailer *trailer =
+		ocfs2_dir_trailer_from_block(gbls.fs, buf);
+	list_dir_opts ls_opts = {
+		.fs	= gbls.fs,
+		.out	= out,
+	};
+
+	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
+		end = gbls.fs->fs_blocksize;
+
+	fprintf(out, "\tEntries:\n");
+	while (offset < end) {
+		dirent = (struct ocfs2_dir_entry *) (buf + offset);
+		if (((offset + dirent->rec_len) > end) ||
+		    (dirent->rec_len < 8) ||
+		    ((dirent->rec_len % 4) != 0) ||
+		    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
+			/* Corrupted */
+			return;
+		}
 
-	fprintf(ctxt->out,
-                "\tDirblock: %-15"PRIu64" Inode: %-15"PRIu64" rec_len: %-4u\n",
-                trailer->db_blkno, trailer->db_parent_dinode,
-                trailer->db_compat_rec_len);
-        dump_block_check(ctxt->out, &trailer->db_check);
+		dump_dir_entry(dirent, offset, gbls.fs->fs_blocksize, NULL,
+			       &ls_opts);
+		offset += dirent->rec_len;
+	}
 
-	return 0;
 }
 
 /*
@@ -645,6 +667,8 @@ void dump_jbd_block (FILE *out, journal_superblock_t *jsb,
 void dump_jbd_metadata (FILE *out, enum dump_block_type type, char *buf,
 			uint64_t blknum)
 {
+	struct ocfs2_dir_block_trailer *trailer;
+
 	fprintf (out, "\tBlock %"PRIu64": ", blknum);
 	switch (type) {
 	case DUMP_BLOCK_INODE:
@@ -665,6 +689,19 @@ void dump_jbd_metadata (FILE *out, enum dump_block_type type, char *buf,
 		dump_group_descriptor (out, (struct ocfs2_group_desc *)buf, 0);
 		fprintf (out, "\n");
 		break;
+	case DUMP_BLOCK_DIR_BLOCK:
+		fprintf(out, "Dirblock\n");
+		/*
+		 * We know there's a trailer, because that's how it
+		 * was detected
+		 */
+		ocfs2_swap_dir_entries_to_cpu(buf,
+					      ocfs2_dir_trailer_blk_off(gbls.fs));
+		trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf);
+		ocfs2_swap_dir_trailer(trailer);
+		dump_dir_block(out, buf);
+		fprintf (out, "\n");
+		break;
 	default:
 		fprintf (out, "TODO\n\n");
 		break;
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index db49dfb..f9ccb27 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -25,6 +25,7 @@ enum dump_block_type {
 	DUMP_BLOCK_INODE,
 	DUMP_BLOCK_EXTENT_BLOCK,
 	DUMP_BLOCK_GROUP_DESCRIPTOR,
+	DUMP_BLOCK_DIR_BLOCK,
 };
 
 typedef struct _list_dir_opts {
@@ -34,9 +35,11 @@ typedef struct _list_dir_opts {
 	char *buf;
 } list_dir_opts;
 
-struct dir_trailer_walk {
+struct dirblocks_walk {
 	ocfs2_filesys *fs;
 	FILE *out;
+	struct ocfs2_dinode *di;
+	char *buf;
 };
 
 void dump_super_block (FILE *out, struct ocfs2_super_block *sb);
@@ -49,8 +52,7 @@ 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);
-int dump_dir_trailers(struct ocfs2_dir_entry *rec, int offset, int blocksize,
-		      char *buf, void *priv_data);
+void dump_dir_block(FILE *out, char *buf);
 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,
diff --git a/debugfs.ocfs2/journal.c b/debugfs.ocfs2/journal.c
index 4b447fd..0343d77 100644
--- a/debugfs.ocfs2/journal.c
+++ b/debugfs.ocfs2/journal.c
@@ -166,29 +166,37 @@ static enum dump_block_type detect_block (char *buf)
 	struct ocfs2_dinode *inode;
 	struct ocfs2_extent_block *extent;
 	struct ocfs2_group_desc *group;
+	struct ocfs2_dir_block_trailer *trailer;
 	enum dump_block_type ret = DUMP_BLOCK_UNKNOWN;
 
 	inode = (struct ocfs2_dinode *)buf;
-	if (!memcmp(inode->i_signature, OCFS2_INODE_SIGNATURE,
-		    sizeof(OCFS2_INODE_SIGNATURE))) {
+	if (!strncmp((char *)inode->i_signature, OCFS2_INODE_SIGNATURE,
+		     sizeof(inode->i_signature))) {
 		ret = DUMP_BLOCK_INODE;
 		goto bail;
 	}
 
 	extent = (struct ocfs2_extent_block *)buf;
-	if (!memcmp(extent->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE,
-		    sizeof(OCFS2_EXTENT_BLOCK_SIGNATURE))) {
+	if (!strncmp((char *)extent->h_signature, OCFS2_EXTENT_BLOCK_SIGNATURE,
+		     sizeof(extent->h_signature))) {
 		ret = DUMP_BLOCK_EXTENT_BLOCK;
 		goto bail;
 	}
 
 	group = (struct ocfs2_group_desc *)buf;
-	if (!memcmp(group->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
-		    sizeof(OCFS2_GROUP_DESC_SIGNATURE))) {
+	if (!strncmp((char *)group->bg_signature, OCFS2_GROUP_DESC_SIGNATURE,
+		     sizeof(group->bg_signature))) {
 		ret = DUMP_BLOCK_GROUP_DESCRIPTOR;
 		goto bail;
 	}
 
+	trailer = ocfs2_dir_trailer_from_block(gbls.fs, buf);
+	if (!strncmp((char *)trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE,
+		     sizeof(trailer->db_signature))) {
+		ret = DUMP_BLOCK_DIR_BLOCK;
+		goto bail;
+	}
+
 bail:
 	return ret;
 }				/* detect_block */
-- 
1.5.6.5

-- 

"In the long run...we'll all be dead."
                                        -Unknown

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127



More information about the Ocfs2-tools-devel mailing list