void cmd_start(void) { superok(cur_fs->dev, superaddr(cur_fs->dev), 0); wunlock(&mainlock); print("kfs: file system started\n"); }
void cmd_halt(void) { wlock(&mainlock); syncall(); superok(cur_fs->dev, superaddr(cur_fs->dev), 1); print("kfs: file system halted\n"); }
/* * 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); }
long qidpathgen(Device *dev) { Iobuf *p; Superb *sb; long path; p = getbuf(*dev, superaddr((*dev)), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("newqid: super block"); sb = (Superb*)p->iobuf; sb->qidgen++; path = sb->qidgen; putbuf(p); return path; }
long balloc(Device dev, int tag, long qid) { Iobuf *bp, *p; Superb *sb; long a; int n; p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("balloc: super block"); sb = (Superb*)p->iobuf; loop: n = --sb->fbuf.nfree; sb->tfree--; if(n < 0 || n >= FEPERBUF) panic("balloc: bad freelist"); a = sb->fbuf.free[n]; if(n <= 0) { if(a == 0) { sb->tfree = 0; sb->fbuf.nfree = 1; if(devgrow(dev, sb)) goto loop; putbuf(p); return 0; } bp = getbuf(dev, a, Bread); if(!bp || checktag(bp, Tfree, QPNONE)) { if(bp) putbuf(bp); putbuf(p); return 0; } memmove(&sb->fbuf, bp->iobuf, (FEPERBUF+1)*sizeof(long)); putbuf(bp); } bp = getbuf(dev, a, Bmod); memset(bp->iobuf, 0, RBUFSIZE); settag(bp, tag, qid); if(tag == Tind1 || tag == Tind2 || tag == Tdir) bp->flags |= Bimm; putbuf(bp); putbuf(p); return a; }
Qid newqid(Device dev) { Iobuf *p; Superb *sb; Qid qid; p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("newqid: super block"); sb = (Superb*)p->iobuf; sb->qidgen++; qid.path = sb->qidgen; qid.vers = 0; qid.type = 0; putbuf(p); return qid; }
void bfree(Device dev, long addr, int d) { Iobuf *p; long a; int i; if(!addr) return; if(d > 0) { d--; p = getbuf(dev, addr, Bread); if(p) { for(i=INDPERBUF-1; i>=0; i--) { a = ((long*)p->iobuf)[i]; bfree(dev, a, d); } putbuf(p); } } /* * 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(nofree(dev, addr)) return; p = getbuf(dev, superaddr(dev), Bread|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) panic("bfree: super block"); addfree(dev, addr, (Superb*)p->iobuf); putbuf(p); }
void main(int argc, char *argv[]) { Filsys *fs; int ream, fsok; int newbufsize, nocheck; char buf[NAMELEN]; int pid, ctl; progname = "kfs"; procname = "init"; /* * insulate from invoker's environment and keep it from swapping */ rfork(RFNAMEG|RFNOTEG|RFREND); confinit(); sfd = -1; ream = 0; newbufsize = 0; nocheck = 0; wrenfile = "/dev/sdC0/fs"; pid = getpid(); snprint(buf, sizeof buf, "/proc/%d/ctl", pid); ctl = open(buf, OWRITE); fprint(ctl, "noswap\n"); close(ctl); buf[0] = '\0'; ARGBEGIN{ case 'b': newbufsize = atol(ARGF()); break; case 'c': nocheck = 1; break; case 'f': wrenfile = ARGF(); break; case 'm': nwren = atol(ARGF()); break; case 'n': strncpy(buf, ARGF(), NAMELEN-1); buf[NAMELEN-1] = '\0'; break; case 'p': cmdmode = atol(ARGF()); break; case 'r': ream = 1; break; case 's': sfd = 0; rfd = dup(1, -1); close(1); if(open("/dev/cons", OWRITE) < 0) open("#c/cons", OWRITE); break; case 'B': conf.niobuf = strtoul(ARGF(), 0, 0); break; case 'C': chat = 1; break; default: usage(); }ARGEND if(argc != 0) usage(); cmdfd = 2; if (access(wrenfile, AREAD|AWRITE) == -1) sysfatal("%s cannot access device", wrenfile); formatinit(); sublockinit(); if(buf[0]) sprint(service, "kfs.%s", buf); else strcpy(service, "kfs"); chan = chaninit(service); consinit(); tlocks = ialloc(NTLOCK * sizeof *tlocks); uid = ialloc(conf.nuid * sizeof(*uid)); uidspace = ialloc(conf.uidspace * sizeof(*uidspace)); gidspace = ialloc(conf.gidspace * sizeof(*gidspace)); /* * init global locks */ wlock(&mainlock); wunlock(&mainlock); /* * init the file system, ream it if needed, and get the block sizes */ ream = fsinit(ream, newbufsize); iobufinit(); for(fs=filesys; fs->name; fs++) if(fs->flags & FREAM){ /* set by fsinit if reamed */ ream++; rootream(fs->dev, getraddr(fs->dev)); superream(fs->dev, superaddr(fs->dev)); } boottime = time(nil); consserve(); fsok = superok(filesys[0].dev, superaddr(filesys[0].dev), 0); if(!nocheck && !ream && !fsok) cmd_exec("check fq"); startproc(forkserve, "srv"); startproc(syncproc, "sync"); exits(0); }
Off bufalloc(Device *dev, int tag, int32_t qid, int uid) { Iobuf *bp, *p; Superb *sb; Off a, n; p = getbuf(dev, superaddr(dev), Brd|Bmod); if(!p || checktag(p, Tsuper, QPSUPER)) { print("bufalloc: super block\n"); if(p) putbuf(p); return 0; } sb = (Superb*)p->iobuf; loop: n = --sb->fbuf.nfree; sb->tfree--; if(n < 0 || n >= FEPERBUF) { print("bufalloc: %Z: bad freelist\n", dev); n = 0; sb->fbuf.free[0] = 0; } a = sb->fbuf.free[n]; if(n <= 0) { if(a == 0) { sb->tfree = 0; sb->fbuf.nfree = 1; if(dev->type == Devcw) { n = uid; if(n < 0 || n >= nelem(growacct)) n = 0; growacct[n]++; if(cwgrow(dev, sb, uid)) goto loop; } putbuf(p); print("fs %Z full uid=%d\n", dev, uid); return 0; } bp = getbuf(dev, a, Brd); if(!bp || checktag(bp, Tfree, QPNONE)) { if(bp) putbuf(bp); putbuf(p); return 0; } sb->fbuf = *(Fbuf*)bp->iobuf; putbuf(bp); } bp = getbuf(dev, a, Bmod); memset(bp->iobuf, 0, RBUFSIZE); settag(bp, tag, qid); if(tag == Tind1 || tag == Tind2 || #ifndef COMPAT32 tag == Tind3 || tag == Tind4 || /* add more Tind tags here ... */ #endif tag == Tdir) bp->flags |= Bimm; putbuf(bp); putbuf(p); return a; }
void check(Filsys *fs, long flag) { Iobuf *p; Superb *sb; Dentry *d; long raddr; long nqid; wlock(&mainlock); dev = fs->dev; flags = flag; fence = fencebase; sizname = 4000; name = zalloc(sizname); sizname -= NAMELEN+10; /* for safety */ sbaddr = superaddr(dev); raddr = getraddr(dev); p = xtag(sbaddr, Tsuper, QPSUPER); if(!p){ cprint("bad superblock\n"); goto out; } sb = (Superb*)p->iobuf; fstart = 1; fsize = sb->fsize; sizabits = (fsize-fstart + 7)/8; abits = zalloc(sizabits); nqid = sb->qidgen+100; /* not as much of a botch */ if(nqid > 1024*1024*8) nqid = 1024*1024*8; if(nqid < 64*1024) nqid = 64*1024; sizqbits = (nqid+7)/8; qbits = zalloc(sizqbits); mod = 0; nfree = 0; nfdup = 0; nused = 0; nbad = 0; ndup = 0; nqbad = 0; depth = 0; maxdepth = 0; if(flags & Ctouch) { oldblock = fsize/DSIZE; oldblock *= DSIZE; if(oldblock < 0) oldblock = 0; cprint("oldblock = %ld\n", oldblock); } if(amark(sbaddr)) {} if(cwflag) { if(amark(sb->roraddr)) {} if(amark(sb->next)) {} } if(!(flags & Cquiet)) cprint("checking file system: %s\n", fs->name); nfiles = 0; maxq = 0; d = maked(raddr, 0, QPROOT); if(d) { if(amark(raddr)) {} if(fsck(d)) modd(raddr, 0, d); depth--; fence -= sizeof(Dentry); if(depth) cprint("depth not zero on return\n"); } if(flags & Cfree) { mkfreelist(sb); sb->qidgen = maxq; settag(p, Tsuper, QPNONE); } if(sb->qidgen < maxq) cprint("qid generator low path=%ld maxq=%ld\n", sb->qidgen, maxq); if(!(flags & Cfree)) ckfreelist(sb); if(mod) { cprint("file system was modified\n"); settag(p, Tsuper, QPNONE); } if(!(flags & Cquiet)){ cprint("%8ld files\n", nfiles); cprint("%8ld blocks in the file system\n", fsize-fstart); cprint("%8ld used blocks\n", nused); cprint("%8ld free blocks\n", sb->tfree); } if(!(flags & Cfree)){ if(nfree != sb->tfree) cprint("%8ld free blocks found\n", nfree); if(nfdup) cprint("%8ld blocks duplicated in the free list\n", nfdup); if(fsize-fstart-nused-nfree) cprint("%8ld missing blocks\n", fsize-fstart-nused-nfree); } if(ndup) cprint("%8ld address duplications\n", ndup); if(nbad) cprint("%8ld bad block addresses\n", nbad); if(nqbad) cprint("%8ld bad qids\n", nqbad); if(!(flags & Cquiet)) cprint("%8ld maximum qid path\n", maxq); missing(); out: if(p) putbuf(p); free(abits); free(name); free(qbits); wunlock(&mainlock); }