Tnode* initxsuper(void) { Block *b; Tnode *t; b = readBlock(PartSuper, 0); if(b == nil) return stringnode("reading super: %r"); if(!superUnpack(&super, b->data)) { blockPut(b); return stringnode("unpacking super: %r"); } blockPut(b); t = stringnode("super " "version=%#ux " "epoch=[%#ux,%#ux) " "qid=%#llux " "active=%#x " "next=%#x " "current=%#x " "last=%V " "name=%s", super.version, super.epochLow, super.epochHigh, super.qid, super.active, super.next, super.current, super.last, super.name); t->expand = xsuperexpand; return t; }
Block* superGet(Cache *c, Super* super) { Block *b; if((b = cacheLocal(c, PartSuper, 0, OReadWrite)) == nil){ fprint(2, "%s: superGet: cacheLocal failed: %R\n", argv0); return nil; } if(!superUnpack(super, b->data)){ fprint(2, "%s: superGet: superUnpack failed: %R\n", argv0); blockPut(b); return nil; } return b; }
void main(int argc, char **argv) { int fd; Header h; Super s; ARGBEGIN{ default: usage(); }ARGEND if(argc == 0 || argc > 2) usage(); if((fd = open(argv[0], argc==2 ? ORDWR : OREAD)) < 0) sysfatal("open %s: %r", argv[0]); if(pread(fd, buf, HeaderSize, HeaderOffset) != HeaderSize) sysfatal("reading header: %r"); if(!headerUnpack(&h, buf)) sysfatal("unpacking header: %r"); if(pread(fd, buf, h.blockSize, (vlong)h.super*h.blockSize) != h.blockSize) sysfatal("reading super block: %r"); if(!superUnpack(&s, buf)) sysfatal("unpacking super block: %r"); print("epoch %d\n", s.epochLow); if(argc == 2){ s.epochLow = strtoul(argv[1], 0, 0); superPack(&s, buf); if(pwrite(fd, buf, h.blockSize, (vlong)h.super*h.blockSize) != h.blockSize) sysfatal("writing super block: %r"); } exits(0); }
Fs * fsOpen(char *file, VtSession *z, int32_t ncache, int mode) { int fd, m; uint8_t oscore[VtScoreSize]; Block *b, *bs; Disk *disk; Fs *fs; Super super; switch(mode){ default: vtSetError(EBadMode); return nil; case OReadOnly: m = OREAD; break; case OReadWrite: m = ORDWR; break; } fd = open(file, m); if(fd < 0){ vtSetError("open %s: %r", file); return nil; } bwatchInit(); disk = diskAlloc(fd); if(disk == nil){ vtSetError("diskAlloc: %R"); close(fd); return nil; } fs = vtMemAllocZ(sizeof(Fs)); fs->mode = mode; fs->name = vtStrDup(file); fs->blockSize = diskBlockSize(disk); fs->elk = vtLockAlloc(); fs->cache = cacheAlloc(disk, z, ncache, mode); if(mode == OReadWrite && z) fs->arch = archInit(fs->cache, disk, fs, z); fs->z = z; b = cacheLocal(fs->cache, PartSuper, 0, mode); if(b == nil) goto Err; if(!superUnpack(&super, b->data)){ blockPut(b); vtSetError("bad super block"); goto Err; } blockPut(b); fs->ehi = super.epochHigh; fs->elo = super.epochLow; //fprint(2, "%s: fs->ehi %d fs->elo %d active=%d\n", argv0, fs->ehi, fs->elo, super.active); fs->source = sourceRoot(fs, super.active, mode); if(fs->source == nil){ /* * Perhaps it failed because the block is copy-on-write. * Do the copy and try again. */ if(mode == OReadOnly || strcmp(vtGetError(), EBadRoot) != 0) goto Err; b = cacheLocalData(fs->cache, super.active, BtDir, RootTag, OReadWrite, 0); if(b == nil){ vtSetError("cacheLocalData: %R"); goto Err; } if(b->l.epoch == fs->ehi){ blockPut(b); vtSetError("bad root source block"); goto Err; } b = blockCopy(b, RootTag, fs->ehi, fs->elo); if(b == nil) goto Err; localToGlobal(super.active, oscore); super.active = b->addr; bs = cacheLocal(fs->cache, PartSuper, 0, OReadWrite); if(bs == nil){ blockPut(b); vtSetError("cacheLocal: %R"); goto Err; } superPack(&super, bs->data); blockDependency(bs, b, 0, oscore, nil); blockPut(b); blockDirty(bs); blockRemoveLink(bs, globalToLocal(oscore), BtDir, RootTag, 0); blockPut(bs); fs->source = sourceRoot(fs, super.active, mode); if(fs->source == nil){ vtSetError("sourceRoot: %R"); goto Err; } } //fprint(2, "%s: got fs source\n", argv0); vtRLock(fs->elk); fs->file = fileRoot(fs->source); fs->source->file = fs->file; /* point back */ vtRUnlock(fs->elk); if(fs->file == nil){ vtSetError("fileRoot: %R"); goto Err; } //fprint(2, "%s: got file root\n", argv0); if(mode == OReadWrite){ fs->metaFlush = periodicAlloc(fsMetaFlush, fs, 1000); fs->snap = snapInit(fs); } return fs; Err: fprint(2, "%s: fsOpen error\n", argv0); fsClose(fs); return nil; }