Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

map block # to inode in fsdb

3 views
Skip to first unread message

Manuel Bouyer

unread,
Apr 17, 2003, 4:54:11 PM4/17/03
to

--h31gzZEtNLTqOjlF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
As I got a disk wich developed bad blocks, I've got the need (like other
peoples in the same situation) to find the files owning these blocks.
So I added a findblk command to fsdb, which maps a disk block back to
the inode (or range of inodes if it's an inode block). As this needs to
look at all the inodes of the filesystem, this can be quite long, so
you can specify multiple blocks numbers in the same findblk command.
The output looks like:
fsdb (inum: 2)> findblk 64 96 2176
block 64: inode block (0-64)
2176: data block of inode 2
block 96: inode block (128-192)

The attached patch is against 1.6.1. I'll port it to current (which I guess
is a bit different because of UFS2) after getting comments, improvements,
etc ..

--
Manuel Bouyer, LIP6, Universite Paris VI. Manuel...@lip6.fr
NetBSD: 24 ans d'experience feront toujours la difference
--

--h31gzZEtNLTqOjlF
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="diff.fsdb"

? fsdb
? fsdb.cat8
Index: fsdb.8
===================================================================
RCS file: /cvsroot/src/sbin/fsdb/fsdb.8,v
retrieving revision 1.13
diff -u -r1.13 fsdb.8
--- fsdb.8 2002/02/08 01:30:43 1.13
+++ fsdb.8 2003/04/17 20:52:17
@@ -128,6 +128,10 @@
.Pp
.It Cm blks
List the current inode's blocks numbers.
+.It Cm findblk Ar disk block number ...
+Find the inode(s) owning the specifed disk block(s) number(s).
+Note that these are not absolute disk blocks numbers, but offsets from the
+start or the partition.
.Pp
.It Cm rm Ar name
.It Cm del Ar name
Index: fsdb.c
===================================================================
RCS file: /cvsroot/src/sbin/fsdb/fsdb.c,v
retrieving revision 1.20
diff -u -r1.20 fsdb.c
--- fsdb.c 2002/03/18 20:04:49 1.20
+++ fsdb.c 2003/04/17 20:52:18
@@ -79,6 +79,10 @@
static int dotime __P((char *, int32_t *, int32_t *));
static void print_blks __P((ufs_daddr_t *buf, int size, int *blknum));
static void print_indirblks __P((daddr_t blk, int ind_level, int *blknum));
+static int compare_blk __P((ufs_daddr_t *, ufs_daddr_t));
+static int founddatablk __P((ufs_daddr_t));
+static int find_blks __P((ufs_daddr_t *buf, int size, ufs_daddr_t *blknum));
+static int find_indirblks __P((daddr_t blk, int ind_level, ufs_daddr_t *blknum));

int returntosingle = 0;
struct dinode *curinode;
@@ -154,6 +158,7 @@
CMDFUNC(quit); /* quit */
CMDFUNC(ls); /* list directory */
CMDFUNC(blks); /* list blocks */
+CMDFUNC(findblk); /* find block */
CMDFUNC(rm); /* remove name */
CMDFUNC(ln); /* add name */
CMDFUNC(newtype); /* change type */
@@ -185,6 +190,7 @@
{"linkcount", "Set link count to COUNT", 2, 2, linkcount},
{"ls", "List current inode as directory", 1, 1, ls},
{"blks", "List current inode's data blocks", 1, 1, blks},
+ {"findblk", "Find inode owning disk block(s)", 2, 33, findblk},
{"rm", "Remove NAME from current inode directory", 2, 2, rm},
{"del", "Remove NAME from current inode directory", 2, 2, rm},
{"ln", "Hardlink INO into current inode directory as NAME", 3, 3, ln},
@@ -457,12 +463,158 @@
print_blks(curinode->di_db, NDADDR, &blkno);
for (i = 0; i < NIADDR; i++) {
if (curinode->di_ib[i] != 0)
- print_indirblks(iswap32(curinode->di_ib[i]), i,
- &blkno);
+ print_indirblks(iswap32(curinode->di_ib[i]), i, &blkno);
}
return 0;
}

+static int findblk_numtofind;
+CMDFUNCSTART(findblk)
+{
+ ino_t inum;
+ ufs_daddr_t *wantedblk;
+ int i;
+
+ ocurrent = curinum;
+ wantedblk = malloc(sizeof(ufs_daddr_t) * (argc - 1));
+ if (wantedblk == NULL) {
+ perror("malloc");
+ return 1;
+ }
+ memset(wantedblk, 0, sizeof(ufs_daddr_t) * (argc - 1));
+ for (i = 1; i < argc; i++)
+ wantedblk[i - 1] = dbtofsb(sblock, strtoull(argv[i], NULL, 0));
+ findblk_numtofind = argc - 1;
+ for (inum = 2; inum < sblock->fs_ipg * sblock->fs_ncg ; inum++)
+ {
+ if (compare_blk(wantedblk, ino_to_fsba(sblock, inum))) {
+ printf("block %llu: inode block (%d-%d)\n",
+ (unsigned long long)fsbtodb(sblock,
+ ino_to_fsba(sblock, inum)),
+ (inum / INOPB(sblock)) * INOPB(sblock),
+ (inum / INOPB(sblock) + 1) * INOPB(sblock));
+ findblk_numtofind--;
+ if (findblk_numtofind == 0)
+ goto end;
+ }
+ curinum = inum;
+ curinode = ginode(inum);
+ switch (iswap16(curinode->di_mode) & IFMT) {
+ case IFDIR:
+ case IFREG:
+ break;
+ case IFLNK:
+ if (iswap64(curinode->di_size) > 0 &&
+ iswap64(curinode->di_size) < MAXSYMLINKLEN &&
+ curinode->di_blocks == 0)
+ continue;
+ else
+ break;
+ default:
+ continue;
+ }
+ if (find_blks(curinode->di_db, NDADDR, wantedblk)) {
+ goto end;
+ }
+ for (i = 0; i < NIADDR; i++) {
+ if (compare_blk(wantedblk,
+ iswap32(curinode->di_ib[i]))) {
+ if (founddatablk(iswap32(curinode->di_ib[i])))
+ goto end;
+ }
+ if (curinode->di_ib[i] != 0)
+ if (find_indirblks(iswap32(curinode->di_ib[i]),
+ i, wantedblk)) {
+ goto end;
+ }
+ }
+ }
+end:
+ free(wantedblk);
+ curinum = ocurrent;
+ curinode = ginode(curinum);
+ return 0;
+}
+
+static int
+compare_blk(wantedblk, curblk)
+ ufs_daddr_t *wantedblk;
+ ufs_daddr_t curblk;
+{
+ int i;
+ for (i = 0; i < 32; i++) {
+ if (wantedblk[i] != 0 && wantedblk[i] == curblk) {
+ wantedblk[i] = 0;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+founddatablk(blk)
+ ufs_daddr_t blk;
+{
+ printf("%llu: data block of inode %d\n",
+ (unsigned long long)fsbtodb(sblock, blk), curinum);
+ findblk_numtofind--;
+ if (findblk_numtofind == 0)
+ return 1;
+ return 0;
+}
+
+static int
+find_blks(buf, size, wantedblk)
+ ufs_daddr_t *buf;
+ int size;
+ ufs_daddr_t *wantedblk;
+
+{
+ int blk;
+ for(blk = 0; blk < size; blk++) {
+ if (buf[blk] == 0)
+ continue;
+ if (compare_blk(wantedblk, iswap32(buf[blk]))) {
+ if (founddatablk(iswap32(buf[blk])))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int
+find_indirblks(blk, ind_level, wantedblk)
+ daddr_t blk;
+ int ind_level;
+ ufs_daddr_t *wantedblk;
+{
+#define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
+ daddr_t idblk[MAXNINDIR];
+ int i;
+
+ bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
+ (int)sblock->fs_bsize);
+ if (ind_level <= 0) {
+ if (find_blks(idblk,
+ sblock->fs_bsize / sizeof(daddr_t), wantedblk))
+ return 1;
+ } else {
+ ind_level--;
+ for (i = 0; i < sblock->fs_bsize / sizeof(daddr_t); i++) {
+ if (compare_blk(wantedblk, iswap32(idblk[i]))) {
+ if (founddatablk(iswap32(idblk[i])))
+ return 1;
+ }
+ if(idblk[i] != 0)
+ if (find_indirblks(iswap32(idblk[i]),
+ ind_level, wantedblk))
+ return 1;
+ }
+ }
+#undef MAXNINDIR
+ return 0;
+}
+
static void
print_blks(buf, size, blknum)
ufs_daddr_t *buf;
@@ -493,7 +645,7 @@
}

static void
-print_indirblks(blk,ind_level, blknum)
+print_indirblks(blk, ind_level, blknum)
daddr_t blk;
int ind_level;
int *blknum;
@@ -501,7 +653,7 @@
#define MAXNINDIR (MAXBSIZE / sizeof(daddr_t))
daddr_t idblk[MAXNINDIR];
int i;
-
+
printf("Indirect block %d (level %d):\n", blk, ind_level+1);
bread(fsreadfd, (char *)idblk, fsbtodb(sblock, blk),
(int)sblock->fs_bsize);

--h31gzZEtNLTqOjlF--

Frank van der Linden

unread,
Apr 19, 2003, 9:36:29 AM4/19/03
to
On Thu, Apr 17, 2003 at 10:53:47PM +0200, Manuel Bouyer wrote:
> The attached patch is against 1.6.1. I'll port it to current (which I guess
> is a bit different because of UFS2) after getting comments, improvements,
> etc ..

Looks ok. For -current, please don't use ufs_daddr_t, use explicit
types for on-disk structures. Also, you're using sizeof (daddr_t) for
a diskblock search, which will be a problem; you need to use explicit
types there as well (and split up the cases for 32 vs. 64 bit block
values).

- Frank

0 new messages