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

Rodney W. Grimes freebsd at pdx.rh.CN85.dnsmgr.net
Fri Feb 9 20:49:10 UTC 2018


[ Charset UTF-8 unsupported, converting... ]
> 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.

Cant this be done with fsdb blocks command?

> 
> 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;
> +}
> 
> 

-- 
Rod Grimes                                                 rgrimes at freebsd.org


More information about the svn-src-head mailing list