/* * Attempt to acquire the lease. * Return 1 if succedded, 0 if not , and < 0 on errors. */ int acquire(int fd, off_t offset, char *id, int busyloop, long long *ts) { char curr[taglen+1] = "", last[taglen+1] = "", tag[taglen+1] = ""; long backoff_usec = (lease_ms + 6 * op_max_ms) * 1000; long contend_usec = (2 * op_max_ms) * 1000; char dummyid[idlen+1]; if (readtag(fd, offset, curr, 1) < 0) return -errno; settag(last, freetag); do { DEBUG("restart: curr tag is '%s'", curr); if (!sametag(curr, last) && !isfree(curr)) do { DEBUG("backoff: curr tag is '%s'", curr); settag(last, curr); usleep(backoff_usec); if (readtag(fd, offset, curr, 1) < 0) return -errno; } while (busyloop && !sametag(curr, last) && !isfree(curr)); if (!sametag(curr, last) && !isfree(curr)) { DEBUG("fail: curr tag is '%s'", curr); return 0; } DEBUG("contend: curr tag is '%s'", curr); if (writetimestamp(fd, offset, id, tag, ts) < 0) { DEBUG("lost (writetimestamp failed) : curr tag is %s", curr); return -errno; } usleep(contend_usec); if (readtag(fd, offset, curr, 1) < 0) { DEBUG("lost (readtag failed) : curr tag is %s", curr); return -errno; } } while (busyloop && !sametag(curr, tag)); if (busyloop || sametag(curr, tag)) { DEBUG("won : curr tag is %s", curr); querytag(curr, dummyid, ts); return renew(fd, offset, id, ts); } DEBUG("lost : curr tag is %s\n our tag is %s", curr, tag); return 0; }
int doclri(File *f) { Iobuf *p, *p1; Dentry *d, *d1; int err; err = 0; p = 0; p1 = 0; if(f->fs->dev->type == Devro) { err = Eronly; goto out; } /* * check on parent directory of file to be deleted */ if(f->wpath == 0 || f->wpath->addr == f->addr) { err = Ephase; goto out; } p1 = getbuf(f->fs->dev, f->wpath->addr, Brd); d1 = getdir(p1, f->wpath->slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { err = Ephase; goto out; } accessdir(p1, d1, FWRITE, 0); putbuf(p1); p1 = 0; /* * check on file to be deleted */ p = getbuf(f->fs->dev, f->addr, Brd); d = getdir(p, f->slot); /* * do it */ memset(d, 0, sizeof(Dentry)); settag(p, Tdir, QPNONE); freewp(f->wpath); freefp(f); out: if(p1) putbuf(p1); if(p) putbuf(p); return err; }
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; }
void superream(Device dev, long addr) { Iobuf *p; Superb *s; long i; p = getbuf(dev, addr, Bmod|Bimm); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tsuper, QPSUPER); s = (Superb*)p->iobuf; s->fstart = 1; s->fsize = devsize(dev); s->fbuf.nfree = 1; s->qidgen = 10; for(i=s->fsize-1; i>=addr+2; i--) addfree(dev, i, s); putbuf(p); }
void rootream(Device dev, long addr) { Iobuf *p; Dentry *d; p = getbuf(dev, addr, Bmod|Bimm); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tdir, QPROOT); d = getdir(p, 0); strcpy(d->name, "/"); d->uid = -1; d->gid = -1; d->mode = DALLOC | DDIR | ((DREAD|DWRITE|DEXEC) << 6) | ((DREAD|DWRITE|DEXEC) << 3) | ((DREAD|DWRITE|DEXEC) << 0); d->qid = QID9P1(QPROOT|QPDIR,0); d->atime = time(0); d->mtime = d->atime; putbuf(p); }
void fwormream(Device *d) { Iobuf *p; Device *fdev; Off a, b; print("fworm ream\n"); devinit(d); fdev = FDEV(d); a = fwormsize(d); b = devsize(fdev); print("\tfwsize = %lld\n", (Wideoff)a); print("\tbwsize = %lld\n", (Wideoff)b-a); for(; a < b; a++) { p = getbuf(fdev, a, Bmod|Bres); if(!p) panic("fworm: init"); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tvirgo, a); putbuf(p); } }
void addfree(Device *dev, Off addr, Superb *sb) { int n; Iobuf *p; n = sb->fbuf.nfree; if(n < 0 || n > FEPERBUF) panic("addfree: bad freelist"); if(n >= FEPERBUF) { p = getbuf(dev, addr, Bmod|Bimm); if(p == 0) panic("addfree: getbuf"); *(Fbuf*)p->iobuf = sb->fbuf; settag(p, Tfree, QPNONE); putbuf(p); n = 0; } sb->fbuf.free[n++] = addr; sb->fbuf.nfree = n; sb->tfree++; if(addr >= sb->fsize) sb->fsize = addr+1; }
/** * anchor_load: load anchor table * * @param[in] path path name */ void anchor_load(const char *path) { int db, current_fid; /* Get fid of the path */ { const char *p = path2fid(path); if (p == NULL) die("anchor_load: internal error. file '%s' not found in GPATH.", path); current_fid = atoi(p); } FIRST = LAST = 0; end = CURRENT = NULL; if (vb == NULL) vb = varray_open(sizeof(struct anchor), 1000); else varray_reset(vb); for (db = GTAGS; db < GTAGLIM; db++) { XARGS *xp; char *ctags_xid; if ((xp = anchor_input[db]) == NULL) continue; /* * Read from input stream until it reaches end of file * or the line of another file appears. */ while ((ctags_xid = xargs_read(xp)) != NULL) { SPLIT ptable; struct anchor *a; int type, fid; const char *ctags_x = parse_xid(ctags_xid, NULL, &fid); /* * It is the following file. */ if (current_fid != fid) { xargs_unread(xp); break; } if (split(ctags_x, 4, &ptable) < 4) { recover(&ptable); die("too small number of parts in anchor_load().\n'%s'", ctags_x); } if (db == GTAGS) { char *p = ptable.part[PART_LINE].start; for (; *p && isspace((unsigned char)*p); p++) ; if (!*p) { recover(&ptable); die("The output of parser is illegal.\n%s", ctags_x); } /* * Function header is applied only to the anchor whoes type is 'D'. * (D: function, M: macro, T: type) */ type = 'T'; if (*p == '#') type = 'M'; else if (locatestring(p, "typedef", MATCH_AT_FIRST)) type = 'T'; else if ((p = locatestring(p, ptable.part[PART_TAG].start, MATCH_FIRST)) != NULL) { /* skip a tag and the following blanks */ p += strlen(ptable.part[PART_TAG].start); for (; *p && isspace((unsigned char)*p); p++) ; if (*p == '(') type = 'D'; } } else if (db == GRTAGS) type = 'R'; else type = 'Y'; /* allocate an entry */ a = varray_append(vb); a->lineno = atoi(ptable.part[PART_LNO].start); a->type = type; a->done = 0; settag(a, ptable.part[PART_TAG].start); recover(&ptable); } if (ctags_xid == NULL) { xargs_close(anchor_input[db]); anchor_input[db] = NULL; } } if (vb->length == 0) { table = NULL; } else { int i, used = vb->length; /* * Sort by lineno. */ table = varray_assign(vb, 0, 0); qsort(table, used, sizeof(struct anchor), cmp); /* * Setup some lineno. */ for (i = 0; i < used; i++) if (table[i].type == 'D') break; if (i < used) FIRST = table[i].lineno; for (i = used - 1; i >= 0; i--) if (table[i].type == 'D') break; if (i >= 0) LAST = table[i].lineno; } /* * Setup loop range. */ start = table; curp = NULL; end = &table[vb->length]; /* anchor_dump(stderr, 0);*/ }
void sysinit(void) { int error; char *cp, *ep; Device *d; Filsys *fs; Fspar *fsp; Iobuf *p; cons.chan = fs_chaninit(Devcon, 1, 0); start: /* * part 1 -- read the config file */ devnone = iconfig("n"); cp = nvrgetconfig(); print("config %s\n", cp); confdev = d = iconfig(cp); devinit(d); if(f.newconf) { p = getbuf(d, 0, Bmod); memset(p->iobuf, 0, RBUFSIZE); settag(p, Tconfig, 0); } else p = getbuf(d, 0, Brd|Bmod); if(!p || checktag(p, Tconfig, 0)) panic("config io"); mergeconf(p); if (resetparams) { for (fsp = fspar; fsp->name != nil; fsp++) fsp->declared = 0; resetparams = 0; } for (fsp = fspar; fsp->name != nil; fsp++) { /* supply defaults from this cwfs instance */ if (fsp->declared == 0) { fsp->declared = fsp->actual; f.modconf = 1; } /* warn if declared value is not our compiled-in value */ if (fsp->declared != fsp->actual) print("warning: config %s %ld != compiled-in %ld\n", fsp->name, fsp->declared, fsp->actual); } if(f.modconf) { memset(p->iobuf, 0, BUFSIZE); p->flags |= Bmod|Bimm; cp = p->iobuf; ep = p->iobuf + RBUFSIZE - 1; if(service[0]) cp = seprint(cp, ep, "service %s\n", service); for(fs=filsys; fs->name; fs++) if(fs->conf && fs->conf[0] != '\0') cp = seprint(cp, ep, "filsys %s %s\n", fs->name, fs->conf); for (fsp = fspar; fsp->name != nil; fsp++) cp = seprint(cp, ep, "%s %ld\n", fsp->name, fsp->declared); putbuf(p); f.modconf = f.newconf = 0; print("config block written\n"); goto start; } putbuf(p); print("service %s\n", service); loop: /* * part 2 -- squeeze out the deleted filesystems */ for(fs=filsys; fs->name; fs++) if(fs->conf == nil || fs->conf[0] == '\0') { for(; fs->name; fs++) *fs = *(fs+1); goto loop; } if(filsys[0].name == nil) panic("no filsys"); /* * part 3 -- compile the device expression */ error = 0; for(fs=filsys; fs->name; fs++) { print("filsys %s %s\n", fs->name, fs->conf); fs->dev = iconfig(fs->conf); if(f.error) { error = 1; continue; } } if(error) panic("fs config"); /* * part 4 -- initialize the devices */ for(fs=filsys; fs->name; fs++) { delay(3000); print("sysinit: %s\n", fs->name); if(fs->flags & FREAM) devream(fs->dev, 1); if(fs->flags & FRECOVER) devrecover(fs->dev); devinit(fs->dev); } /* * part 5 -- optionally copy devices or worms */ if (copyworm) { dowormcopy(); /* can return if user quits early */ panic("copyworm bailed out!"); } if (copydev) if (dodevcopy() < 0) panic("copydev failed!"); else panic("copydev done."); }
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; }
int doremove(File *f, int iscon) { Iobuf *p, *p1; Dentry *d, *d1; int32_t addr; int slot, err; p = 0; p1 = 0; if(isro(f->fs->dev) || (f->cp != cons.chan && writegroup && !ingroup(f->uid, writegroup))) { err = Eronly; goto out; } /* * check on parent directory of file to be deleted */ if(f->wpath == 0 || f->wpath->addr == f->addr) { err = Ephase; goto out; } p1 = getbuf(f->fs->dev, f->wpath->addr, Bread); d1 = getdir(p1, f->wpath->slot); if(!d1 || checktag(p1, Tdir, QPNONE) || !(d1->mode & DALLOC)) { err = Ephase; goto out; } if(!iscon && iaccess(f, d1, DWRITE)) { err = Eaccess; goto out; } accessdir(p1, d1, FWRITE); putbuf(p1); p1 = 0; /* * check on file to be deleted */ p = getbuf(f->fs->dev, f->addr, Bread); d = getdir(p, f->slot); if(!d || checktag(p, Tdir, QPNONE) || !(d->mode & DALLOC)) { err = Ealloc; goto out; } if(err = mkqidcmp(&f->qid, d)) goto out; /* * if deleting a directory, make sure it is empty */ if((d->mode & DDIR)) for(addr=0;; addr++) { p1 = dnodebuf(p, d, addr, 0); if(!p1) break; if(checktag(p1, Tdir, d->qid.path)) { err = Ephase; goto out; } for(slot=0; slot<DIRPERBUF; slot++) { d1 = getdir(p1, slot); if(!(d1->mode & DALLOC)) continue; err = Eempty; goto out; } putbuf(p1); } /* * do it */ dtrunc(p, d); memset(d, 0, sizeof(Dentry)); settag(p, Tdir, QPNONE); out: if(p1) putbuf(p1); if(p) putbuf(p); return err; }
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); }