[Ocfs2-tools-devel] debugfs.ocfs2 bmap command

tao.ma tao.ma at oracle.com
Mon Aug 28 00:45:32 PDT 2006


Hi,
    I have seen the code. And write some comments.
    Please Mark, Joel & Sunil rectify it if there is something wrong. :)
GONG Jie wrote:

>Hi, all
>
>I have added the ``bmap'' command to debugfs.ocfs2.  Enclosed please find the 
>patch.
>
>  
>
>------------------------------------------------------------------------
>
>Index: debugfs.ocfs2/commands.c
>===================================================================
>--- debugfs.ocfs2/commands.c	(revision 1229)
>+++ debugfs.ocfs2/commands.c	(working copy)
>@@ -65,10 +65,12 @@ static void do_encode_lockres (char **ar
> static void do_decode_lockres (char **args);
> static void do_locate (char **args);
> static void do_fs_locks (char **args);
>+static void do_bmap (char **args);
> 
> dbgfs_gbls gbls;
> 
> static Command commands[] = {
>+	{ "bmap",	do_bmap },
> 	{ "cat",	do_cat },
> 	{ "cd",		do_cd },
> 	{ "chroot",	do_chroot },
>@@ -95,7 +97,7 @@ static Command commands[] = {
> 	{ "stat",	do_stat },
> 	{ "stats",	do_stats },
> 	{ "encode",	do_encode_lockres },
>-	{ "decode",	do_decode_lockres }
>+	{ "decode",	do_decode_lockres },
> };
> 
> /*
>@@ -402,6 +404,48 @@ bail:
> 	return ret;
> }
> 
>+/*
>+ * dump_logical_blkno()
>+ *
>+ */
>+static errcode_t dump_logical_blkno(ocfs2_filesys *fs, struct ocfs2_extent_list *el,
>+	uint64_t loglblkno, FILE *out)
>  
>
As far as I know, for a file's extent record, it is stored in numbers of 
cluster, not of block.  So rec->e_clusters is the size of clusters and 
you can't just use loglblkno -= rec->e_clusters. See 
ocfs2_clusters_to_blocks or ocfs2_blocks_to_clusters for how to transfer 
between them.
So you may first find the start blkno of the cluster which your logical 
blkno belongs to and then add the offset of this blkno in that cluster 
for the real blkno.

>+{
>+	struct ocfs2_extent_block *eb;
>+	struct ocfs2_extent_rec *rec;
>+	errcode_t ret = 0;
>+	char *buf = NULL;
>+	int i;
>+
>+	for (i = 0; i < el->l_next_free_rec; ++i) {
>+		rec = &(el->l_recs[i]);
>+		if (loglblkno < rec->e_clusters) {
>+			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 = dump_logical_blkno(fs, &(eb->h_list), loglblkno, out);
>+			} else
>+				fprintf(out, "%"PRIu64"\n", rec->e_blkno + loglblkno);
>+			goto bail;
>+		} else
>+			loglblkno -= rec->e_clusters;
>+	}
>+	fprintf(out, "0\n");
>+
>+bail:
>+	if (buf)
>+		ocfs2_free(&buf);
>+	return ret;
>+}
>+
> 
> /*
>  * do_open()
>@@ -601,6 +645,7 @@ static void do_ls (char **args)
>  */
> static void do_help (char **args)
> {
>+	printf ("bmap <filespec> <logical_blk>\t\tCalculate the logical->physical block mapping for an inode\n");
> 	printf ("cat <filespec>\t\t\t\tPrints file on stdout\n");
> 	printf ("cd <filespec>\t\t\t\tChange directory\n");
> 	printf ("chroot <filespec>\t\t\tChange root\n");
>@@ -1211,3 +1256,75 @@ static void do_fs_locks(char **args)
> 	dump_fs_locks(gbls.fs->uuid_str, out, dump_lvbs);
> 	close_pager(out);
> }
>+
>+/*
>+ * do_bmap()
>+ *
>+ */
>+static void do_bmap(char **args)
>+{
>+	struct ocfs2_dinode *inode;
>+	const char *bmap_usage = "usage: bmap <filespec> <logical_blk>";
>+	uint64_t blkno;
>+	uint64_t loglblkno;
>+	char *endptr;
>+	char *buf = NULL;
>+	FILE *out;
>+	errcode_t ret = 1;
>+ 
>+	if (check_device_open())
>+		return;
>+
>+	if (!args[1]) {
>+		fprintf(stderr, "usage: %s\n", bmap_usage);
>+		return;
>+	}
>+
>+	if (!args[1] || !args[2]) {
>+		fprintf(stderr, "usage: %s\n", bmap_usage);
>+		return;
>+	}
>+
>+	ret = string_to_inode(gbls.fs, gbls.root_blkno, gbls.cwd_blkno,
>+		args[1], &blkno);
>+	if (ret) {
>+		com_err(args[0], ret, "'%s'", args[1]);
>+		return;
>+	}
>+
>+	if (blkno >= gbls.max_blocks) {
>+		fprintf(stderr, "%s: Block number is larger than volume size\n",
>+			args[0]);
>+		return;
>+	}
>+
>+	loglblkno = strtoul(args[2], &endptr, 0);
>+	if (*endptr) {
>+		fprintf(stderr, "%s: Invalid logical block number\n", args[0]);
>+		return;
>+	}
>+ 
>+	buf = gbls.blockbuf;
>+	ret = ocfs2_read_inode(gbls.fs, blkno, buf);
>+	if (ret) {
>+		com_err(args[0], ret, " ");
>+		return ;
>+	}
>+ 
>+	inode = (struct ocfs2_dinode *)buf;
>+ 
>+	out = open_pager(gbls.interactive);
>+ 
>+	if ((inode->i_flags & (OCFS2_LOCAL_ALLOC_FL | OCFS2_CHAIN_FL | OCFS2_DEALLOC_FL))
>+		|| S_ISLNK(inode->i_mode) && !inode->i_clusters)
>+		fprintf(out, "0\n");
>+	else
>  
>
You may check whether this inode has the logical blkno that user has 
input here. So if a user input a large blkno that exceed the file size, 
you don't need to go through the whole file's extent list. See 
inode->i_clusters.

>+		dump_logical_blkno(gbls.fs, &(inode->id2.i_list), loglblkno, out);
>+ 
>+	if (ret)
>+		com_err(args[0], ret, " ");
>+ 
>+	close_pager(out);
>+ 
>+	return ;
>+}
>  
>
>------------------------------------------------------------------------
>
>_______________________________________________
>Ocfs2-tools-devel mailing list
>Ocfs2-tools-devel at oss.oracle.com
>http://oss.oracle.com/mailman/listinfo/ocfs2-tools-devel
>  
>


-- 
* **     Tao Ma
*     Member of Techincal Staff *

Oracle Asia Development Center
Emerging Technology & Solution Development
*
Tel:        +86 10 8278 6026
Mobile:   +86 13701237602         
URL:       OADC Intranet <http://cdc.oraclecorp.com/>, Oracle.com/cdc 
<http://www.oracle.com/cdc/>



More information about the Ocfs2-tools-devel mailing list