[Ocfs2-tools-devel] [PATCH] debugfs.ocfs2: Add 'frag' command

Mark Fasheh mfasheh at suse.com
Thu Aug 6 13:54:02 PDT 2009


This patch adds a new debugfs.ocfs2 command, 'frag' which will calculate the
ratio of extents to clusters in an inodes data btree. This can be used to
get a semi-accurate idea of an inodes data fragmentation level.

Signed-off-by: Mark Fasheh <mfasheh at suse.com>
---
 debugfs.ocfs2/commands.c     |   97 ++++++++++++++++++++++++++++++++++++++++++
 debugfs.ocfs2/dump.c         |   14 ++++++
 debugfs.ocfs2/include/dump.h |    2 +
 3 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/debugfs.ocfs2/commands.c b/debugfs.ocfs2/commands.c
index 143fc96..08ded82 100644
--- a/debugfs.ocfs2/commands.c
+++ b/debugfs.ocfs2/commands.c
@@ -75,6 +75,7 @@ static void do_dlm_locks (char **args);
 static void do_controld(char **args);
 static void do_dirblocks(char **args);
 static void do_xattr(char **args);
+static void do_frag(char **args);
 
 dbgfs_gbls gbls;
 
@@ -112,6 +113,7 @@ static Command commands[] = {
 	{ "encode",	do_encode_lockres },
 	{ "decode",	do_decode_lockres },
 	{ "dirblocks",	do_dirblocks },
+	{ "frag",	do_frag },
 };
 
 /*
@@ -858,6 +860,7 @@ static void do_help (char **args)
 	printf ("stat <filespec>\t\t\t\tShow inode\n");
 	printf ("stats [-h]\t\t\t\tShow superblock\n");
 	printf ("xattr [-v] <filespec>\t\t\tShow Extended Attributes\n");
+	printf ("frag <filespec>\t\t\tShow inode extents / clusters ratio\n");
 }
 
 /*
@@ -1841,3 +1844,97 @@ static void do_xattr(char **args)
 
 	return ;
 }
+
+static errcode_t calc_num_extents(ocfs2_filesys *fs,
+				  struct ocfs2_extent_list *el,
+				  uint32_t *ne)
+{
+	struct ocfs2_extent_block *eb;
+	struct ocfs2_extent_rec *rec;
+	errcode_t ret = 0;
+	char *buf = NULL;
+	int i;
+	uint32_t clusters;
+	uint32_t extents = 0;
+
+	*ne = 0;
+
+	for (i = 0; i < el->l_next_free_rec; ++i) {
+		rec = &(el->l_recs[i]);
+		clusters = ocfs2_rec_clusters(el->l_tree_depth, rec);
+
+		/*
+		 * In a unsuccessful insertion, we may shift a tree
+		 * add a new branch for it and do no insertion. So we
+		 * may meet a extent block which have
+		 * clusters == 0, this should only be happen
+		 * in the last extent rec. */
+		if (!clusters && i == el->l_next_free_rec - 1)
+			break;
+
+		extents = 1;
+
+		if (el->l_tree_depth) {
+			ret = ocfs2_malloc_block(gbls.fs->fs_io, &buf);
+			if (ret)
+				goto bail;
+
+			ret = ocfs2_read_extent_block(fs, rec->e_blkno, buf);
+			if (ret)
+				goto bail;
+
+			eb = (struct ocfs2_extent_block *)buf;
+
+			ret = calc_num_extents(fs, &(eb->h_list), &extents);
+			if (ret)
+				goto bail;
+
+		}		
+
+		*ne = *ne + extents;
+	}
+
+bail:
+	if (buf)
+		ocfs2_free(&buf);
+	return ret;
+}
+
+static void do_frag(char **args)
+{
+	struct ocfs2_dinode *inode;
+	uint64_t blkno;
+	char *buf = NULL;
+	FILE *out;
+	errcode_t ret = 0;
+	uint32_t clusters;
+	uint32_t extents = 0;
+
+	if (process_inode_args(args, &blkno))
+		return;
+
+	buf = gbls.blockbuf;
+	ret = ocfs2_read_inode(gbls.fs, blkno, buf);
+	if (ret) {
+		com_err(args[0], ret, "while reading inode %"PRIu64"", blkno);
+		return ;
+	}
+
+	inode = (struct ocfs2_dinode *)buf;
+
+	out = open_pager(gbls.interactive);
+
+	clusters = inode->i_clusters;
+	if (!(inode->i_dyn_features & OCFS2_INLINE_DATA_FL))
+		ret = calc_num_extents(gbls.fs, &(inode->id2.i_list), &extents);
+
+	dump_frag(out, inode->i_blkno, clusters, extents);
+
+	if (ret)
+		com_err(args[0], ret, "while traversing inode at block "
+			"%"PRIu64, blkno);
+
+	close_pager(out);
+
+	return ;
+}
diff --git a/debugfs.ocfs2/dump.c b/debugfs.ocfs2/dump.c
index 17f58e9..f69f8bd 100644
--- a/debugfs.ocfs2/dump.c
+++ b/debugfs.ocfs2/dump.c
@@ -1011,3 +1011,17 @@ uint32_t dump_xattr_ibody(FILE *out, ocfs2_filesys *fs,
 		return 0;
 	}
 }
+
+void dump_frag(FILE *out, uint64_t ino, uint32_t clusters,
+	       uint32_t extents)
+{
+	float frag_level = 0;
+
+	if (clusters > 1 && extents) {
+		float e = extents, c = clusters;
+		frag_level = 100 * (e / c);
+	}
+
+	fprintf(out, "Inode: %"PRIu64"\t%% fragmented: %.2f\tclusters:"
+		" %u\textents: %u\n", ino, frag_level, clusters, extents);
+}
diff --git a/debugfs.ocfs2/include/dump.h b/debugfs.ocfs2/include/dump.h
index 0abccbc..8cd9a97 100644
--- a/debugfs.ocfs2/include/dump.h
+++ b/debugfs.ocfs2/include/dump.h
@@ -76,5 +76,7 @@ errcode_t dump_xattr_block(FILE *out, ocfs2_filesys *fs,
 			   uint32_t *xattrs_block,
 			   uint64_t *xattrs_bucket,
 			   int verbose);
+void dump_frag(FILE *out, uint64_t ino, uint32_t clusters,
+	       uint32_t extents);
 
 #endif		/* __DUMP_H__ */
-- 
1.5.6




More information about the Ocfs2-tools-devel mailing list