int checktag(Iobuf *p, int tag, Off qpath) { Tag *t; static Off lastaddr; t = (Tag*)(p->iobuf+BUFSIZE); if(t->tag != tag) { if(p->flags & Bmod) { print("\ttag = %d/%llu; expected %lld/%d -- not flushed\n", t->tag, (Wideoff)t->path, (Wideoff)qpath, tag); return 2; } if(p->dev != nil && p->dev->type == Devcw) cwfree(p->dev, p->addr); if(p->addr != lastaddr) print("\ttag = %G/%llu; expected %G/%lld -- flushed (%lld)\n", t->tag, (Wideoff)t->path, tag, (Wideoff)qpath, (Wideoff)p->addr); lastaddr = p->addr; p->dev = devnone; p->addr = -1; p->flags = 0; return 2; } if(qpath != QPNONE) { if((qpath ^ t->path) & ~QPDIR) { if(1 || CHAT(0)) print("\ttag/path = %llu; expected %d/%llux\n", (Wideoff)t->path, tag, (Wideoff)qpath); return 0; } } return 0; }
/* * free the block at `addr' on dev. * if it's an indirect block (d [depth] > 0), * first recursively free all the blocks it names. * * ts->relblk is the block number within the file of this * block (or the first data block eventually pointed to via * this indirect block). */ void buffree(Device *dev, Off addr, int d, Truncstate *ts) { Iobuf *p; Off a; int i, pastlast; if(!addr) return; pastlast = (ts == nil? 1: ts->pastlast); /* * if this is an indirect block, recurse and free any * suitable blocks within it (possibly via further indirect blocks). */ if(d > 0) { d--; p = getbuf(dev, addr, Brd); if(p) { if (ts == nil) /* common case: create */ for(i=INDPERBUF-1; i>=0; i--) { a = ((Off *)p->iobuf)[i]; buffree(dev, a, d, nil); } else /* wstat truncation */ for (i = 0; i < INDPERBUF; i++) truncfree(ts, dev, d, p, i); putbuf(p); } } if (!pastlast) return; /* * having zeroed the pointer to this block, add it to the free list. * stop outstanding i/o */ p = getbuf(dev, addr, Bprobe); if(p) { p->flags &= ~(Bmod|Bimm); putbuf(p); } /* * dont put written worm * blocks into free list */ if(dev->type == Devcw) { i = cwfree(dev, addr); if(i) return; } p = getbuf(dev, superaddr(dev), Brd|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("buffree: super block"); addfree(dev, addr, (Superb*)p->iobuf); putbuf(p); }