ref: eef0fe67ee4bb8c254f0f9e61c24ef5d34d05a4f
dir: /used.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" #include "extents.h" /* go through all the blocks and write out all the used block numbers to be used by the checker Starting from root, walk down each dentry printing out the linked blocks with invalid tags */ int debug = 0; char *devfile = nil; void walkdentry(u64 blkno); int checkblock(u64 blkno, s16 tag, u64 qpath); static void usage(void) { fprint(2, "usage: used [-D ] fsfile\n"); exits("usage"); } void main(int argc, char *argv[]) { u64 size; ARGBEGIN{ default: usage(); case 'D': debug++; break; }ARGEND if(argc != 1) usage(); devfile = argv[0]; if(devfile == nil) sysfatal("no disk file"); if (access(devfile, AREAD) == -1) sysfatal("%s cannot access device", devfile); size = devinit(devfile); if(size == 0) panic("null size %s", devfile); if(debug) print("%s %llud bytes %llud blocks\n", devfile, size, size/Rawblocksize); checkblock(Bmagicb, Tmagic, Qpmagic); walkdentry(Broot); exits(0); } int checkvalid(u64 blkno, Tag *t, s16 tagtype, u64 qpath) { if(t->type != tagtype || t->path != qpath || t->dirty != 0){ /* if(debug) */ fprint(2, "checkblock invalid %llud tag/path expected %s/%llud actual %s/%llud dirty %d\n", blkno, tagnames[tagtype], qpath, tagnames[t->type], t->path, t->dirty); fprint(2, "used: %llud\n", blkno); return 0; } if(debug) print("blkno %llud tag %s\n", blkno, tagnames[t->type]); print("%llud\n", blkno); return 1; } int checkblock(u64 blkno, s16 tag, u64 qpath) { u8 buf[Rawblocksize]; Tag *t; devread(blkno, buf); t = (Tag*)buf; return checkvalid(blkno, t, tag, qpath); } void walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath) { u8 buf[Rawblocksize], *cbuf; Tag *t, *ct; u64 cblkno, *bufa; int i; devread(blkno, buf); t = (Tag*)buf; if(checkvalid(blkno, t, tag, qpath)){ if(t->type == Tind0){ bufa = (u64*)(buf+sizeof(Tag)); for(i = 0; i<Nindperblock; i++){ cblkno = bufa[i]; if(cblkno == 0) return; cbuf = malloc(Rawblocksize); devread(cblkno, cbuf); ct = (Tag*)cbuf; if(ct->type == Tdentry && ct->type == bottomtag) walkdentry(cblkno); else checkvalid(cblkno, ct, bottomtag, qpath); free(cbuf); } }else{ bufa = (u64*)(buf+sizeof(Tag)); cbuf = malloc(Rawblocksize); for(i = 0; i<Nindperblock; i++){ cblkno = bufa[i]; if(cblkno == 0) return; devread(cblkno, cbuf); /* check tag */ walkindir(cblkno, tag-1, bottomtag, qpath); } free(cbuf); } } return; } void walkdentry(u64 blkno) { u8 buf[Rawblocksize], *cbuf; Dentry *d; Tag *t, *ct; u64 cblkno; int i; u8 isdir; devread(blkno, buf); t = (Tag*)buf; d = (Dentry*)(buf+sizeof(Tag)); isdir = (d->mode & DMDIR) > 0; if(debug) print("walkdentry %llud tag %s name %s d->qid.path %llud\n", blkno, tagnames[t->type], d->name, d->qid.path); if(t->type != Tdentry || t->path != d->qid.path){ if(debug) print("walkdentry invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[Tdentry], d->qid.path, tagnames[t->type], t->path); fprint(2, "%llud\n", blkno); }else print("%llud\n", blkno); /* do not list the data blocks used by /adm/frees as they are considered to be free blocks */ if(blkno == Bdfrees) return; for(i = 0; i<Ndblock; i++){ cblkno = d->dblocks[i]; if(cblkno == 0) return; cbuf = malloc(Rawblocksize); devread(cblkno, cbuf); ct = (Tag*)cbuf; if(isdir) walkdentry(cblkno); else checkvalid(cblkno, ct, Tdata, d->qid.path); free(cbuf); } cbuf = malloc(Rawblocksize); for(i = 0; i<Niblock; i++){ cblkno = d->iblocks[i]; if(cblkno == 0) return; devread(cblkno, cbuf); ct = (Tag*)cbuf; if(ct->type == Tind0+i){ walkindir(cblkno, Tind0+i, isdir ? Tdentry : Tdata, d->qid.path); }else{ fprint(2, "invalid indir tag %llud\n", cblkno); fprint(2, "%llud\n", cblkno); } } free(cbuf); return; }