static int srvFd(char* name, int mode, int fd, char** mntpnt) { int n, srvfd; char *p, buf[10]; /* * Drop a file descriptor with given name and mode into /srv. * Create with ORCLOSE and don't close srvfd so it will be removed * automatically on process exit. */ p = smprint("/srv/%s", name); if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){ vtMemFree(p); p = smprint("#s/%s", name); if((srvfd = create(p, ORCLOSE|OWRITE, mode)) < 0){ vtSetError("create %s: %r", p); vtMemFree(p); return -1; } } n = snprint(buf, sizeof(buf), "%d", fd); if(write(srvfd, buf, n) < 0){ close(srvfd); vtSetError("write %s: %r", p); vtMemFree(p); return -1; } *mntpnt = p; return srvfd; }
void deeClose(DirEntryEnum *dee) { int i; if(dee == nil) return; for(i=dee->i; i<dee->n; i++) deCleanup(dee->buf+i); vtMemFree(dee->buf); fileDecRef(dee->file); vtMemFree(dee); }
void deCleanup(DirEntry *dir) { vtMemFree(dir->elem); dir->elem = nil; vtMemFree(dir->uid); dir->uid = nil; vtMemFree(dir->gid); dir->gid = nil; vtMemFree(dir->mid); dir->mid = nil; }
static void fidFree(Fid* fid) { if(fid->file != nil){ fileDecRef(fid->file); fid->file = nil; } if(fid->db != nil){ dirBufFree(fid->db); fid->db = nil; } fidUnlock(fid); if(fid->uid != nil){ vtMemFree(fid->uid); fid->uid = nil; } if(fid->uname != nil){ vtMemFree(fid->uname); fid->uname = nil; } if(fid->excl != nil) exclFree(fid); if(fid->rpc != nil){ close(fid->rpc->afd); auth_freerpc(fid->rpc); fid->rpc = nil; } if(fid->fsys != nil){ fsysPut(fid->fsys); fid->fsys = nil; } if(fid->cuname != nil){ vtMemFree(fid->cuname); fid->cuname = nil; } vtLock(fbox.lock); fbox.inuse--; if(fbox.nfree < 10){ fid->hash = fbox.free; fbox.free = fid; fbox.nfree++; } else{ vtLockFree(fid->alock); vtLockFree(fid->lock); vtMemFree(fid); } vtUnlock(fbox.lock); }
void vtDetach(void) { Thread *p; p = *vtRock; assert(p != nil); p->ref--; if(p->ref == 0) { vtMemFree(p->error); vtMemFree(p); *vtRock = nil; } }
/* * Fsck that MetaBlock has reasonable header, sorted entries, */ static int chkMetaBlock(MetaBlock *mb) { MetaChunk *mc; int oo, o, n, i; uchar *p; mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk)); p = mb->buf + MetaHeaderSize; for(i = 0; i < mb->nindex; i++){ mc[i].offset = p[0]<<8 | p[1]; mc[i].size = p[2]<<8 | p[3]; mc[i].index = i; p += MetaIndexSize; } qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp); /* check block looks ok */ oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; o = oo; n = 0; for(i = 0; i < mb->nindex; i++){ o = mc[i].offset; n = mc[i].size; if(o < oo) goto Err; oo += n; } if(o+n > mb->size || mb->size - oo != mb->free) goto Err; vtMemFree(mc); return 1; Err: if(0){ fprint(2, "metaChunks failed!\n"); oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; for(i=0; i<mb->nindex; i++){ fprint(2, "\t%d: %d %d\n", i, mc[i].offset, mc[i].offset + mc[i].size); oo += mc[i].size; } fprint(2, "\tused=%d size=%d free=%d free2=%d\n", oo, mb->size, mb->free, mb->size - oo); } vtMemFree(mc); return 0; }
int fileMetaFlush(File *f, int rec) { File **kids, *p; int nkids; int i, rv; fileMetaLock(f); rv = fileMetaFlush2(f, nil); fileMetaUnlock(f); if(!rec || !fileIsDir(f)) return rv; if(!fileLock(f)) return rv; nkids = 0; for(p=f->down; p; p=p->next) nkids++; kids = vtMemAlloc(nkids*sizeof(File*)); i = 0; for(p=f->down; p; p=p->next){ kids[i++] = p; p->ref++; } fileUnlock(f); for(i=0; i<nkids; i++){ rv |= fileMetaFlush(kids[i], 1); fileDecRef(kids[i]); } vtMemFree(kids); return rv; }
static Packet * vtRPC(VtSession *z, int op, Packet *p) { uint8_t *hdr, buf[2]; char *err; if(z == nil){ vtSetError(ENotConnected); return nil; } /* * single threaded for the momment */ vtLock(z->lk); if(z->cstate != VtStateConnected){ vtSetError(ENotConnected); goto Err; } hdr = packetHeader(p, 2); hdr[0] = op; /* op */ hdr[1] = 0; /* tid */ vtDebug(z, "client send: "); vtDebugMesg(z, p, "\n"); if(!vtSendPacket(z, p)) { p = nil; goto Err; } p = vtRecvPacket(z); if(p == nil) goto Err; vtDebug(z, "client recv: "); vtDebugMesg(z, p, "\n"); if(!packetConsume(p, buf, 2)) goto Err; if(buf[0] == VtRError) { if(!vtGetString(p, &err)) { vtSetError(EProtocolBotch); goto Err; } vtSetError(err); vtMemFree(err); packetFree(p); vtUnlock(z->lk); return nil; } if(buf[0] != op+1 || buf[1] != 0) { vtSetError(EProtocolBotch); goto Err; } vtUnlock(z->lk); return p; Err: vtDebug(z, "vtRPC failed: %s\n", vtGetError()); if(p != nil) packetFree(p); vtUnlock(z->lk); vtDisconnect(z, 1); return nil; }
void vtRendezFree(VtRendez *q) { if(q == nil) return; assert(q->wfirst == nil); vtMemFree(q); }
uchar * mbAlloc(MetaBlock *mb, int n) { int i, o; MetaChunk *mc; /* off the end */ if(mb->maxsize - mb->size >= n) return mb->buf + mb->size; /* check if possible */ if(mb->maxsize - mb->size + mb->free < n) return nil; mc = metaChunks(mb); if(mc == nil){ fprint(2, "mbAlloc: metaChunks failed: %r\n"); return nil; } /* look for hole */ o = MetaHeaderSize + mb->maxindex*MetaIndexSize; for(i=0; i<mb->nindex; i++){ if(mc[i].offset - o >= n){ vtMemFree(mc); return mb->buf + o; } o = mc[i].offset + mc[i].size; } if(mb->maxsize - o >= n){ vtMemFree(mc); return mb->buf + o; } /* compact and return off the end */ mbCompact(mb, mc); vtMemFree(mc); if(mb->maxsize - mb->size < n){ vtSetError(EBadMeta); return nil; } return mb->buf + mb->size; }
static void srvFree(Srv* srv) { if(srv->prev != nil) srv->prev->next = srv->next; else sbox.head = srv->next; if(srv->next != nil) srv->next->prev = srv->prev; else sbox.tail = srv->prev; if(srv->srvfd != -1) close(srv->srvfd); vtMemFree(srv->service); vtMemFree(srv->mntpnt); vtMemFree(srv); }
static void snapClose(Snap *s) { if(s == nil) return; periodicKill(s->tick); vtMemFree(s); }
void vtSha1Free(VtSha1 *s) { if(s == nil) return; if(s->s != nil) free(s->s); vtMemFree(s); }
static void lstnFree(Lstn* lstn) { vtLock(lbox.lock); if(lstn->prev != nil) lstn->prev->next = lstn->next; else lbox.head = lstn->next; if(lstn->next != nil) lstn->next->prev = lstn->prev; else lbox.tail = lstn->prev; vtUnlock(lbox.lock); if(lstn->afd != -1) close(lstn->afd); vtMemFree(lstn->address); vtMemFree(lstn); }
void vtLockFree(VtLock *p) { if(p == nil) return; assert(p->writer == nil); assert(p->readers == 0); assert(p->qfirst == nil); vtMemFree(p); }
static int _groupRemMember(Ubox* box, User* g, char* member) { int i; if(_userByUname(box, member) == nil) return 0; for(i = 0; i < g->ngroup; i++){ if(strcmp(g->group[i], member) == 0) break; } if(i >= g->ngroup){ if(strcmp(g->uname, member) == 0) vtSetError("uname: '%s' always in own group", member); else vtSetError("uname: '%s' not in group '%s'", member, g->uname); return 0; } vtMemFree(g->group[i]); box->len -= strlen(member); if(g->ngroup > 1) box->len--; g->ngroup--; switch(g->ngroup){ case 0: vtMemFree(g->group); g->group = nil; break; default: for(; i < g->ngroup; i++) g->group[i] = g->group[i+1]; g->group[i] = nil; /* prevent accidents */ g->group = vtMemRealloc(g->group, g->ngroup * sizeof(char*)); break; } return 1; }
static void uboxFree(Ubox* box) { User *next, *u; for(u = box->head; u != nil; u = next){ next = u->next; userFree(u); } vtMemFree(box); }
void vtFree(VtSession *z) { if(z == nil) return; vtLockFree(z->lk); vtSha1Free(z->inHash); vtLockFree(z->inLock); packetFree(z->part); vtSha1Free(z->outHash); vtLockFree(z->outLock); vtMemFree(z->uid); vtMemFree(z->sid); vtMemFree(z->vtbl); memset(z, 0, sizeof(VtSession)); z->fd = -1; vtMemFree(z); }
static void fileFree(File *f) { sourceClose(f->source); vtLockFree(f->lk); sourceClose(f->msource); deCleanup(&f->dir); memset(f, ~0, sizeof(File)); vtMemFree(f); }
int vtHello(VtSession *z) { Packet *p; uint8_t buf[10]; char *sid; int crypto, codec; sid = nil; p = packetAlloc(); if(!vtAddString(p, vtGetVersion(z))) goto Err; if(!vtAddString(p, vtGetUid(z))) goto Err; buf[0] = vtGetCryptoStrength(z); buf[1] = 0; buf[2] = 0; packetAppend(p, buf, 3); p = vtRPC(z, VtQHello, p); if(p == nil) return 0; if(!vtGetString(p, &sid)) goto Err; if(!packetConsume(p, buf, 2)) goto Err; if(packetSize(p) != 0) { vtSetError(EProtocolBotch); goto Err; } crypto = buf[0]; codec = buf[1]; USED(crypto); USED(codec); packetFree(p); vtLock(z->lk); z->sid = sid; z->auth.state = VtAuthOK; vtSha1Free(z->inHash); z->inHash = nil; vtSha1Free(z->outHash); z->outHash = nil; vtUnlock(z->lk); return 1; Err: packetFree(p); vtMemFree(sid); return 0; }
void fsClose(Fs *fs) { vtRLock(fs->elk); periodicKill(fs->metaFlush); snapClose(fs->snap); if(fs->file){ fileMetaFlush(fs->file, 0); if(!fileDecRef(fs->file)) vtFatal("fsClose: files still in use: %r\n"); } fs->file = nil; sourceClose(fs->source); cacheFree(fs->cache); if(fs->arch) archFree(fs->arch); vtMemFree(fs->name); vtRUnlock(fs->elk); vtLockFree(fs->elk); memset(fs, ~0, sizeof(Fs)); vtMemFree(fs); }
static int deeFill(DirEntryEnum *dee) { int i, n; Source *meta, *source; MetaBlock mb; MetaEntry me; File *f; Block *b; DirEntry *de; /* clean up first */ for(i=dee->i; i<dee->n; i++) deCleanup(dee->buf+i); vtMemFree(dee->buf); dee->buf = nil; dee->i = 0; dee->n = 0; f = dee->file; source = f->source; meta = f->msource; b = sourceBlock(meta, dee->boff, OReadOnly); if(b == nil) goto Err; if(!mbUnpack(&mb, b->data, meta->dsize)) goto Err; n = mb.nindex; dee->buf = vtMemAlloc(n * sizeof(DirEntry)); for(i=0; i<n; i++){ de = dee->buf + i; meUnpack(&me, &mb, i); if(!deUnpack(de, &me)) goto Err; dee->n++; if(!(de->mode & ModeDir)) if(!dirEntrySize(source, de->entry, de->gen, &de->size)) goto Err; } dee->boff++; blockPut(b); return 1; Err: blockPut(b); return 0; }
/* * Walk through all the blocks in the write buffer. * Then we can look for ones we missed -- those are leaks. */ static void checkEpochs(Fsck *chk) { u32int e; uint nb; nb = chk->nblocks; chk->amap = vtMemAllocZ(nb/8+1); chk->emap = vtMemAllocZ(nb/8+1); chk->xmap = vtMemAllocZ(nb/8+1); chk->errmap = vtMemAllocZ(nb/8+1); for(e = chk->fs->ehi; e >= chk->fs->elo; e--){ memset(chk->emap, 0, chk->nblocks/8+1); memset(chk->xmap, 0, chk->nblocks/8+1); checkEpoch(chk, e); } checkLeak(chk); vtMemFree(chk->amap); vtMemFree(chk->emap); vtMemFree(chk->xmap); vtMemFree(chk->errmap); }
void archFree(Arch *a) { /* kill slave */ vtLock(a->lk); a->die = vtRendezAlloc(a->lk); vtWakeup(a->starve); while(a->ref > 1) vtSleep(a->die); vtUnlock(a->lk); vtRendezFree(a->starve); vtRendezFree(a->die); vtLockFree(a->lk); vtMemFree(a); }
static MetaChunk * metaChunks(MetaBlock *mb) { MetaChunk *mc; int oo, o, n, i; uchar *p; mc = vtMemAlloc(mb->nindex*sizeof(MetaChunk)); p = mb->buf + MetaHeaderSize; for(i = 0; i<mb->nindex; i++){ mc[i].offset = U16GET(p); mc[i].size = U16GET(p+2); mc[i].index = i; p += MetaIndexSize; } qsort(mc, mb->nindex, sizeof(MetaChunk), offsetCmp); /* check block looks ok */ oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; o = oo; n = 0; for(i=0; i<mb->nindex; i++){ o = mc[i].offset; n = mc[i].size; if(o < oo) goto Err; oo += n; } if(o+n > mb->size) goto Err; if(mb->size - oo != mb->free) goto Err; return mc; Err: fprint(2, "metaChunks failed!\n"); oo = MetaHeaderSize + mb->maxindex*MetaIndexSize; for(i=0; i<mb->nindex; i++){ fprint(2, "\t%d: %d %d\n", i, mc[i].offset, mc[i].offset + mc[i].size); oo += mc[i].size; } fprint(2, "\tused=%d size=%d free=%d free2=%d\n", oo, mb->size, mb->free, mb->size - oo); vtSetError(EBadMeta); vtMemFree(mc); return nil; }
/* return number of directory entries remaining */ static int fsRsearch1(File *f, char *s) { int n, r; DirEntry de; DirEntryEnum *dee; File *ff; char *t; dee = deeOpen(f); if(dee == nil) return 0; n = 0; for(;;){ r = deeRead(dee, &de); if(r <= 0) break; n++; if(de.mode & ModeSnapshot){ if((ff = fileWalk(f, de.elem)) != nil) fileDecRef(ff); else if(strcmp(vtGetError(), ESnapOld) == 0){ if(fileClri(f, de.elem, "adm")) n--; } } else if(de.mode & ModeDir){ if((ff = fileWalk(f, de.elem)) != nil){ t = smprint("%s/%s", s, de.elem); if(fsRsearch1(ff, t) == 0) if(fileRemove(ff, "adm")) n--; vtMemFree(t); fileDecRef(ff); } } deCleanup(&de); if(r < 0) break; } deeClose(dee); return n; }
static int fsEsearch1(File *f, char *path, uint32_t savetime, uint32_t *plo) { int n, r; DirEntry de; DirEntryEnum *dee; File *ff; Entry e, ee; char *t; dee = deeOpen(f); if(dee == nil) return 0; n = 0; for(;;){ r = deeRead(dee, &de); if(r <= 0) break; if(de.mode & ModeSnapshot){ if((ff = fileWalk(f, de.elem)) != nil){ if(fileGetSources(ff, &e, &ee)) if(de.mtime >= savetime && e.snap != 0) if(e.snap < *plo) *plo = e.snap; fileDecRef(ff); } } else if(de.mode & ModeDir){ if((ff = fileWalk(f, de.elem)) != nil){ t = smprint("%s/%s", path, de.elem); n += fsEsearch1(ff, t, savetime, plo); vtMemFree(t); fileDecRef(ff); } } deCleanup(&de); if(r < 0) break; } deeClose(dee); return n; }
void sourceClose(Source *r) { if(r == nil) return; vtLock(r->lk); r->ref--; if(r->ref) { vtUnlock(r->lk); return; } assert(r->ref == 0); vtUnlock(r->lk); if(r->parent) sourceClose(r->parent); vtLockFree(r->lk); memset(r, ~0, sizeof(*r)); vtMemFree(r); }
char* vtSetError(char* fmt, ...) { Thread *p; char *s; va_list args; p = threadLookup(); va_start(args, fmt); s = vsmprint(fmt, args); vtMemFree(p->error); p->error = s; va_end(args); if(ERROR) fprint(2, "vtSetError: %s\n", p->error); werrstr("%s", p->error); return p->error; }
void fsCheck(Fsck *chk) { Block *b; Super super; checkInit(chk); b = superGet(chk->cache, &super); if(b == nil){ chk->print("could not load super block: %R"); return; } blockPut(b); chk->hint = super.active; checkEpochs(chk); chk->smap = vtMemAllocZ(chk->nblocks/8+1); checkDirs(chk); vtMemFree(chk->smap); }