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-all
mailing list