From owner-svn-src-head@freebsd.org Fri Feb 9 19:10:47 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 1B65DF1C47E; Fri, 9 Feb 2018 19:10:47 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id BFFEB73A1E; Fri, 9 Feb 2018 19:10:46 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id BB044D9C; Fri, 9 Feb 2018 19:10:46 +0000 (UTC) (envelope-from mckusick@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w19JAkkE018428; Fri, 9 Feb 2018 19:10:46 GMT (envelope-from mckusick@FreeBSD.org) Received: (from mckusick@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w19JAksQ018424; Fri, 9 Feb 2018 19:10:46 GMT (envelope-from mckusick@FreeBSD.org) Message-Id: <201802091910.w19JAksQ018424@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: mckusick set sender to mckusick@FreeBSD.org using -f From: Kirk McKusick Date: Fri, 9 Feb 2018 19:10:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r329076 - in head/tools/diag: . prtblknos X-SVN-Group: head X-SVN-Commit-Author: mckusick X-SVN-Commit-Paths: in head/tools/diag: . prtblknos X-SVN-Commit-Revision: 329076 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Feb 2018 19:10:47 -0000 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 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 +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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; +}