Date: Fri, 9 Feb 2018 12:49:01 -0800 (PST) From: "Rodney W. Grimes" <freebsd@pdx.rh.CN85.dnsmgr.net> To: Kirk McKusick <mckusick@freebsd.org> Cc: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r329076 - in head/tools/diag: . prtblknos Message-ID: <201802092049.w19Kn152032218@pdx.rh.CN85.dnsmgr.net> In-Reply-To: <201802091910.w19JAksQ018424@repo.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
[ 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@freebsd.org
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802092049.w19Kn152032218>