Neat! But, please define "block". Are you talking about a filesystem block 
(i.e. default 32KB on UFS2), are you talking about a disk block (which may vary 
based on the Logical Sector Size of the underlying media)?

Thanks,

Ravi (rpokala@)

-----Original Message-----
From: <owner-src-committ...@freebsd.org> on behalf of Kirk McKusick 
<mckus...@freebsd.org>
Date: 2018-02-09, Friday at 11:10
To: <src-committ...@freebsd.org>, <svn-src-...@freebsd.org>, 
<svn-src-head@freebsd.org>
Subject: svn commit: r329076 - in head/tools/diag: . prtblknos

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




_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to