svn commit: r329076 - in head/tools/diag: . prtblknos

Kirk McKusick mckusick at FreeBSD.org
Fri Feb 9 19:10:47 UTC 2018


Author: mckusick
Date: Fri Feb  9 19:10:46 2018
New Revision: 329076
URL: https://svnweb.freebsd.org/changeset/base/329076

Log:
  This is a little C-program that can be used to print out the list
  of blocks used by a requested list of inodes.
  
  For example, to list the blocks referenced by your kernel:
  
  guest_12 % df /
  Filesystem      1K-blocks     Used   Avail Capacity  Mounted on
  /dev/gpt/rootfs  20307196 10707336 7975288    57%    /
  
  guest_12 % ls -i /boot/kernel/kernel
  160603 /boot/kernel/kernel
  
  guest_12 % ./prtblknos /dev/gpt/rootfs 160603
  160603:	lbn 0-7 blkno 3217584-3217647
  	lbn 8-11 blkno 3217864-3217895 distance 216
  First-level indirect, blkno 3217896-3217903 distance 0
  	lbn 12-19 blkno 3217904-3217967 distance 8
  	lbn 20-75 blkno 3251816-3252263 distance 33848
  	lbn 76-83 blkno 3252368-3252431 distance 104
  	lbn 84-91 blkno 3252464-3252527 distance 32
  	lbn 92-852 blkno 3252896-3258983 distance 368
  
  Each contiguous range of blocks is printed on a line.
  The distance metric is the size of the gap from the end of the
  previous set of blocks to the beginning of the next set of blocks.
  Short distances are desirable.

Added:
  head/tools/diag/prtblknos/
  head/tools/diag/prtblknos/Makefile   (contents, props changed)
  head/tools/diag/prtblknos/README   (contents, props changed)
  head/tools/diag/prtblknos/prtblknos.c   (contents, props changed)
Modified:
  head/tools/diag/README

Modified: head/tools/diag/README
==============================================================================
--- head/tools/diag/README	Fri Feb  9 18:47:00 2018	(r329075)
+++ head/tools/diag/README	Fri Feb  9 19:10:46 2018	(r329076)
@@ -11,4 +11,4 @@ Please make a subdir per program, and add a brief desc
 dumpvfscache	program that can be used to examine the contents of the vfs
 		name cache.
 localeck	check for invalid/incomplete locales 
-
+prtblknos	Print out the blocks used by each inode in the list

Added: head/tools/diag/prtblknos/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/diag/prtblknos/Makefile	Fri Feb  9 19:10:46 2018	(r329076)
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG=	prtblknos
+
+MAN=
+
+test:	${PROG}
+	./${PROG} > a
+
+.include <bsd.prog.mk>

Added: head/tools/diag/prtblknos/README
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/diag/prtblknos/README	Fri Feb  9 19:10:46 2018	(r329076)
@@ -0,0 +1,31 @@
+# $FreeBSD$
+
+This is a little C-program that can be used to print out the list
+of blocks used by a requested list of inodes.
+
+For example, to list the blocks referenced by your kernel:
+
+guest_12 % df /
+Filesystem      1K-blocks     Used   Avail Capacity  Mounted on
+/dev/gpt/rootfs  20307196 10707336 7975288    57%    /
+
+guest_12 % ls -i /boot/kernel/kernel
+160603 /boot/kernel/kernel
+
+guest_12 % ./prtblknos /dev/gpt/rootfs 160603
+160603:	lbn 0-7 blkno 3217584-3217647
+	lbn 8-11 blkno 3217864-3217895 distance 216
+First-level indirect, blkno 3217896-3217903 distance 0
+	lbn 12-19 blkno 3217904-3217967 distance 8
+	lbn 20-75 blkno 3251816-3252263 distance 33848
+	lbn 76-83 blkno 3252368-3252431 distance 104
+	lbn 84-91 blkno 3252464-3252527 distance 32
+	lbn 92-852 blkno 3252896-3258983 distance 368
+
+Each contiguous range of blocks is printed on a line.
+The distance metric is the size of the gap from the end of the
+previous set of blocks to the beginning of the next set of blocks.
+Short distances are desirable.
+
+	Marshall Kirk McKusick
+	January 19, 2018

Added: head/tools/diag/prtblknos/prtblknos.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/diag/prtblknos/prtblknos.c	Fri Feb  9 19:10:46 2018	(r329076)
@@ -0,0 +1,314 @@
+/*
+ * Copyright (c) 1998, 2003, 2013, 2018 Marshall Kirk McKusick.
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MARSHALL KIRK MCKUSICK ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL MARSHALL KIRK MCKUSICK BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/disklabel.h>
+#include <sys/time.h>
+
+#include <ufs/ufs/dinode.h>
+#include <ufs/ffs/fs.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+union dinode {
+	struct ufs1_dinode *dp1;
+	struct ufs2_dinode *dp2;
+};
+struct fs *sbp;
+char *fsname;
+int fd;
+
+void indirprt(int level, int blksperindir, int lbn, ufs2_daddr_t blkno,
+	int lastlbn);
+void printblk(int lbn, ufs2_daddr_t blkno, int numblks, int lastlbn);
+
+/* 
+ * Possible superblock locations ordered from most to least likely.
+ */
+static int sblock_try[] = SBLOCKSEARCH;
+
+int
+main(argc, argv)
+	int argc;
+	char *argv[];
+{
+	int i, len, lbn, frags, inonum, numblks, blksperindir;
+	char sblock[SBLOCKSIZE], ibuf[MAXBSIZE];
+	ufs2_daddr_t blkno;
+	off_t size, offset;
+	union dinode dp;
+
+	if (argc < 3) {
+		(void)fprintf(stderr,"usage: prtblknos filesystem inode ...\n");
+		exit(1);
+	}
+
+	fsname = *++argv;
+
+	/* get the superblock. */
+	if ((fd = open(fsname, O_RDONLY, 0)) < 0)
+		err(1, "%s", fsname);
+	for (i = 0; sblock_try[i] != -1; i++) {
+		if (lseek(fd, sblock_try[i], SEEK_SET) < 0)
+			err(1, "lseek: %s", fsname);
+		if (read(fd, sblock, (long)SBLOCKSIZE) != SBLOCKSIZE)
+			err(1, "can't read superblock: %s", fsname);
+		sbp = (struct fs *)sblock;
+		if ((sbp->fs_magic == FS_UFS1_MAGIC ||
+		     (sbp->fs_magic == FS_UFS2_MAGIC &&
+		      sbp->fs_sblockloc == sblock_try[i])) &&
+		    sbp->fs_bsize <= MAXBSIZE &&
+		    sbp->fs_bsize >= sizeof(struct fs))
+			break;
+	}
+	if (sblock_try[i] == -1)
+		errx(1, "Cannot find file system superblock\n");
+
+	/* remaining arguments are inode numbers. */
+	while (*++argv) {
+		/* get the inode number. */
+		if ((inonum = atoi(*argv)) <= 0)
+			errx(1, "%s is not a valid inode number", *argv);
+		(void)printf("%d:", inonum);
+
+		/* read in the appropriate block. */
+		offset = ino_to_fsba(sbp, inonum);	/* inode to fs blk */
+		offset = fsbtodb(sbp, offset);		/* fs blk disk blk */
+		offset *= DEV_BSIZE;			/* disk blk to bytes */
+
+		/* seek and read the block */
+		if (lseek(fd, offset, SEEK_SET) < 0)
+			err(1, "%s", fsname);
+		if (read(fd, ibuf, sbp->fs_bsize) != sbp->fs_bsize)
+			err(1, "%s", fsname);
+
+		/* get the inode within the block. */
+		if (sbp->fs_magic == FS_UFS1_MAGIC) {
+			dp.dp1 = &((struct ufs1_dinode *)(ibuf))
+			    [ino_to_fsbo(sbp, inonum)];
+			size = dp.dp1->di_size;
+		} else {
+			dp.dp2 = &((struct ufs2_dinode *)(ibuf))
+			    [ino_to_fsbo(sbp, inonum)];
+			size = dp.dp2->di_size;
+		}
+
+		numblks = howmany(size, sbp->fs_bsize);
+		if (numblks == 0) {
+			printf(" empty file\n");
+			continue;
+		}
+		len = numblks < UFS_NDADDR ? numblks : UFS_NDADDR;
+		for (i = 0; i < len; i++) {
+			if (i < numblks - 1)
+				frags = sbp->fs_frag;
+			else
+				frags = howmany(size % sbp->fs_bsize,
+						  sbp->fs_fsize);
+			if (sbp->fs_magic == FS_UFS1_MAGIC)
+				blkno = dp.dp1->di_db[i];
+			else
+				blkno = dp.dp2->di_db[i];
+			printblk(i, blkno, frags, numblks);
+		}
+
+		blksperindir = 1;
+		len = numblks - UFS_NDADDR;
+		lbn = UFS_NDADDR;
+		for (i = 0; len > 0 && i < UFS_NIADDR; i++) {
+			if (sbp->fs_magic == FS_UFS1_MAGIC)
+				blkno = dp.dp1->di_ib[i];
+			else
+				blkno = dp.dp2->di_ib[i];
+			indirprt(i, blksperindir, lbn, blkno, numblks);
+			blksperindir *= NINDIR(sbp);
+			lbn += blksperindir;
+			len -= blksperindir;
+		}
+
+		/* dummy print to flush out last extent */
+		printblk(numblks, 0, frags, 0);
+	}
+	(void)close(fd);
+	exit(0);
+}
+
+void
+indirprt(level, blksperindir, lbn, blkno, lastlbn)
+	int level;
+	int blksperindir;
+	int lbn;
+	ufs2_daddr_t blkno;
+	int lastlbn;
+{
+	char indir[MAXBSIZE];
+	off_t offset;
+	int i, last;
+
+	printblk(lbn, blkno, sbp->fs_frag, -level);
+	/* read in the indirect block. */
+	offset = fsbtodb(sbp, blkno);		/* fs blk disk blk */
+	offset *= DEV_BSIZE;			/* disk blk to bytes */
+	if (lseek(fd, offset, SEEK_SET) < 0)
+		err(1, "%s", fsname);
+	if (read(fd, indir, sbp->fs_bsize) != sbp->fs_bsize)
+		err(1, "%s", fsname);
+	last = howmany(lastlbn - lbn, blksperindir) < NINDIR(sbp) ?
+	    howmany(lastlbn - lbn, blksperindir) : NINDIR(sbp);
+	if (blksperindir == 1) {
+		for (i = 0; i < last; i++) {
+			if (sbp->fs_magic == FS_UFS1_MAGIC)
+				blkno = ((ufs1_daddr_t *)indir)[i];
+			else
+				blkno = ((ufs2_daddr_t *)indir)[i];
+			printblk(lbn + i, blkno, sbp->fs_frag, lastlbn);
+		}
+		return;
+	}
+	for (i = 0; i < last; i++) {
+		if (sbp->fs_magic == FS_UFS1_MAGIC)
+			blkno = ((ufs1_daddr_t *)indir)[i];
+		else
+			blkno = ((ufs2_daddr_t *)indir)[i];
+		indirprt(level - 1, blksperindir / NINDIR(sbp),
+		    lbn + blksperindir * i, blkno, lastlbn);
+	}
+}
+
+char *
+distance(lastblk, firstblk)
+	daddr_t lastblk;
+	daddr_t firstblk;
+{
+	daddr_t delta;
+	int firstcg, lastcg;
+	static char buf[100];
+
+	if (lastblk == 0)
+		return ("");
+	delta = firstblk - lastblk - 1;
+	firstcg = dtog(sbp, firstblk);
+	lastcg = dtog(sbp, lastblk);
+	if (firstcg == lastcg) {
+		snprintf(buf, 100, " distance %jd", (intmax_t)delta);
+		return (&buf[0]);
+	}
+	snprintf(buf, 100, " cg %d blk %jd to cg %d blk %jd",
+	    lastcg, dtogd(sbp, lastblk), firstcg, dtogd(sbp, firstblk));
+	return (&buf[0]);
+}
+	
+
+char *indirname[UFS_NIADDR] = { "First", "Second", "Third" };
+
+void
+printblk(lbn, blkno, numblks, lastlbn)
+	int lbn;
+	ufs2_daddr_t blkno;
+	int numblks;
+	int lastlbn;
+{
+	static int seq;
+	static daddr_t lastindirblk, lastblk, firstblk;
+
+	if (lastlbn <= 0)
+		goto flush;
+	if (seq == 0) {
+		seq = 1;
+		firstblk = blkno;
+		return;
+	}
+	if (lbn == 0) {
+		seq = 1;
+		lastblk = 0;
+		firstblk = blkno;
+		lastindirblk = 0;
+		return;
+	}
+	if (lbn < lastlbn && ((firstblk == 0 && blkno == 0) ||
+	    (firstblk == BLK_NOCOPY && blkno == BLK_NOCOPY) ||
+	    (firstblk == BLK_SNAP && blkno == BLK_SNAP) ||
+	    blkno == firstblk + seq * numblks)) {
+		seq++;
+		return;
+	}
+flush:
+	if (seq == 0)
+		goto prtindir;
+	if (firstblk <= BLK_SNAP) {
+		if (seq == 1)
+			printf("\tlbn %d %s\n", lbn - seq,
+			    firstblk == 0 ? "hole" :
+			    firstblk == BLK_NOCOPY ? "nocopy" :
+			    "snapblk");
+		else
+			printf("\tlbn %d-%d %s\n",
+			    lbn - seq, lbn - 1,
+			    firstblk == 0 ? "hole" :
+			    firstblk == BLK_NOCOPY ? "nocopy" :
+			    "snapblk");
+	} else if (seq == 1) {
+		if (numblks == 1)
+			printf("\tlbn %d blkno %jd%s\n", lbn - seq,
+			    (intmax_t)firstblk, distance(lastblk, firstblk));
+		else
+			printf("\tlbn %d blkno %jd-%jd%s\n", lbn - seq,
+			    (intmax_t)firstblk,
+			    (intmax_t)(firstblk + numblks - 1),
+			    distance(lastblk, firstblk));
+		lastblk = firstblk + numblks - 1;
+	} else {
+		printf("\tlbn %d-%d blkno %jd-%jd%s\n", lbn - seq, lbn - 1,
+		    (intmax_t)firstblk, (intmax_t)(firstblk +
+		    (seq - 1) * sbp->fs_frag + numblks - 1),
+		    distance(lastblk, firstblk));
+		lastblk = firstblk + (seq - 1) * sbp->fs_frag + numblks - 1;
+	}
+	if (lastlbn > 0 || blkno == 0) {
+		seq = 1;
+		firstblk = blkno;
+		return;
+	}
+prtindir:
+	if (seq != 0 && (sbp->fs_metaspace == 0 || lastindirblk == 0))
+		lastindirblk = lastblk;
+	printf("%s-level indirect, blkno %jd-%jd%s\n", indirname[-lastlbn],
+	    (intmax_t)blkno, (intmax_t)(blkno + numblks - 1),
+	    distance(lastindirblk, blkno));
+	lastindirblk = blkno + numblks - 1;
+	if (sbp->fs_metaspace == 0)
+		lastblk = lastindirblk;
+	seq = 0;
+}


More information about the svn-src-head mailing list