ref: 285644aadb1b58735651a5068703372f8fc9adac
dir: /free.c/
#include <u.h> #include <libc.h> #include "dat.h" #include "fns.h" #include "extents.h" /* go through the contents of Bfrees and write out the list of free blocks used by reconcile.c to identify discrepancies */ Extents frees; int chatty9p = 0; char *devfile = nil; int checkdentry(u64 blkno, u8 tag, u64 qpath); void *emalloc(u32); s8 *estrdup(s8 *); void getfrees(u64 dblkno); void walkdentry(u64 blkno); void panic(char *fmt, ...); static void usage(void) { fprint(2, "usage: free [-D ] fsfile\n"); exits("usage"); } void main(int argc, char *argv[]) { u64 size; Errenv env = {0}; envpp = privalloc(); *envpp = &env; if(waserror()){ panic(0, "err stack %d: %lux %lux %lux %lux %lux %lux", env.nlabel, env.label[0][JMPBUFPC], env.label[1][JMPBUFPC], env.label[2][JMPBUFPC], env.label[3][JMPBUFPC], env.label[4][JMPBUFPC], env.label[5][JMPBUFPC]); } ARGBEGIN{ default: usage(); case 'D': chatty9p++; 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(chatty9p) print("%s %llud bytes %llud blocks\n", devfile, size, size/Blocksize); checkdentry(Bdfrees, Tdentry, Qpfrees); initextents(&frees, "frees", 0, 0, 2, nil, fprint, panic, emalloc); getfrees(Bdfrees); showextents(1, "", &frees); // showblocknos(1, &frees); close(devfd); exits(0); } int checkvalid(u64 blkno, u8 dtag, u64 dpath, u8 tag, u64 qpath, u16 len) { if(dtag != tag || dpath != qpath){ /* if(chatty9p) */ fprint(2, "check invalid %llud tag/path expected %s/%llud actual %s/%llud\n", blkno, tagnames[tag], qpath, tagnames[dtag], dpath); fprint(2, "free: %llud\n", blkno); return 0; } if(chatty9p) print("%llud %d\n", blkno, len); return 1; } int checkdentry(u64 blkno, u8 tag, u64 qpath) { u8 buf[Blocksize]; Dentry *t; devread(blkno, buf, 1); t = (Dentry*)buf; return checkvalid(blkno, t->tag, t->path, tag, qpath, 1); } void loadfreeextents(u64 blkno) { s8 *buf; buf = emalloc(Maxdatablockunits*Blocksize); devread(blkno, buf, 1); devread(blkno, buf, ((Data*)buf)->len); loadextents(&frees, (s8*)((Data*)buf)->buf, ((Data*)buf)->len*Blocksize -Ddataidssize); free(buf); } void walkindir(u64 blkno, u16 tag, u16 bottomtag, u64 qpath) { u8 buf[Blocksize]; Indirect *t; u64 cblkno; int i; devread(blkno, buf, 1); t = (Indirect*)buf; if(checkvalid(blkno, t->tagi, t->pathi, tag, qpath, 1)){ if(t->tagi == Tind0){ for(i = 0; i<Nindperblock; i++){ cblkno = t->bufa[i]; if(cblkno == 0) return; loadfreeextents(cblkno); } }else{ for(i = 0; i<Nindperblock; i++){ cblkno = t->bufa[i]; if(cblkno == 0) return; /* check tag */ walkindir(cblkno, tag-1, bottomtag, qpath); } } } } void getfrees(u64 dblkno) { u64 size; u8 buf[Blocksize]; Dentry *d; u64 cblkno; int i; devread(dblkno, buf, 1); d = (Dentry*)buf; size = d->size; if(size == 0) return; if(d->size <= Ddatasize){ loadextents(&frees, d->buf, d->size); return; } if(checkvalid(dblkno, d->tag, d->path, Tdentry, Qpfrees, 1)){ for(i = 0; i<Ndblock; i++){ cblkno = d->dblocks[i]; if(cblkno == 0) return; loadfreeextents(cblkno); } for(i = Tind0; i<Niblock+Tind0; i++){ cblkno = d->iblocks[i]; if(cblkno == 0) return; walkindir(cblkno, i, Tdata, Qpfrees); } } }