📄 9fsys.c
字号:
l = b->l; consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n", argc==6 ? "old: " : "", addr, l.type, l.state, l.epoch, l.epochClose, l.tag); if(argc == 6){ if(strcmp(argv[1], "-") != 0) l.type = atoi(argv[1]); if(strcmp(argv[2], "-") != 0) l.state = atoi(argv[2]); if(strcmp(argv[3], "-") != 0) l.epoch = strtoul(argv[3], 0, 0); if(strcmp(argv[4], "-") != 0) l.epochClose = strtoul(argv[4], 0, 0); if(strcmp(argv[5], "-") != 0) l.tag = strtoul(argv[5], 0, 0); consPrint("new: label %#ux %ud %ud %ud %ud %#x\n", addr, l.type, l.state, l.epoch, l.epochClose, l.tag); bb = _blockSetLabel(b, &l); if(bb == nil) goto Out1; n = 0; for(;;){ if(blockWrite(bb)){ while(bb->iostate != BioClean){ assert(bb->iostate == BioWriting); vtSleep(bb->ioready); } break; } consPrint("blockWrite: %R\n"); if(n++ >= 5){ consPrint("giving up\n"); break; } sleep(5*1000); } blockPut(bb); } r = 1;Out1: blockPut(b);Out0: vtRUnlock(fs->elk); return r;}/* * Inspect and edit the blocks on disk. */static intfsysBlock(Fsys* fsys, int argc, char* argv[]){ Fs *fs; char *s; Block *b; uchar *buf; u32int addr; int c, count, i, offset; char *usage = "usage: [fsys name] block addr offset [count [data]]"; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc < 2 || argc > 4) return cliError(usage); fs = fsys->fs; addr = strtoul(argv[0], 0, 0); offset = strtoul(argv[1], 0, 0); if(offset < 0 || offset >= fs->blockSize){ vtSetError("bad offset"); return 0; } if(argc > 2) count = strtoul(argv[2], 0, 0); else count = 100000000; if(offset+count > fs->blockSize) count = fs->blockSize - count; vtRLock(fs->elk); b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); if(b == nil){ vtSetError("cacheLocal %#ux: %R", addr); vtRUnlock(fs->elk); return 0; } consPrint("\t%sblock %#ux %ud %ud %.*H\n", argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset); if(argc == 4){ s = argv[3]; if(strlen(s) != 2*count){ vtSetError("bad data count"); goto Out; } buf = vtMemAllocZ(count); for(i = 0; i < count*2; i++){ if(s[i] >= '0' && s[i] <= '9') c = s[i] - '0'; else if(s[i] >= 'a' && s[i] <= 'f') c = s[i] - 'a' + 10; else if(s[i] >= 'A' && s[i] <= 'F') c = s[i] - 'A' + 10; else{ vtSetError("bad hex"); vtMemFree(buf); goto Out; } if((i & 1) == 0) c <<= 4; buf[i>>1] |= c; } memmove(b->data+offset, buf, count); consPrint("\tnew: block %#ux %ud %ud %.*H\n", addr, offset, count, count, b->data+offset); blockDirty(b); }Out: blockPut(b); vtRUnlock(fs->elk); return 1;}/* * Free a disk block. */static intfsysBfree(Fsys* fsys, int argc, char* argv[]){ Fs *fs; Label l; char *p; Block *b; u32int addr; char *usage = "usage: [fsys name] bfree addr ..."; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc == 0) return cliError(usage); fs = fsys->fs; vtRLock(fs->elk); while(argc > 0){ addr = strtoul(argv[0], &p, 0); if(*p != '\0'){ consPrint("bad address - '%s'\n", addr); /* syntax error; let's stop */ vtRUnlock(fs->elk); return 0; } b = cacheLocal(fs->cache, PartData, addr, OReadOnly); if(b == nil){ consPrint("loading %#ux: %R\n", addr); continue; } l = b->l; if(l.state == BsFree) consPrint("%#ux is already free\n", addr); else{ consPrint("label %#ux %ud %ud %ud %ud %#x\n", addr, l.type, l.state, l.epoch, l.epochClose, l.tag); l.state = BsFree; l.type = BtMax; l.tag = 0; l.epoch = 0; l.epochClose = 0; if(!blockSetLabel(b, &l, 0)) consPrint("freeing %#ux: %R\n", addr); } blockPut(b); argc--; argv++; } vtRUnlock(fs->elk); return 1;}static intfsysDf(Fsys *fsys, int argc, char* argv[]){ char *usage = "usage: [fsys name] df"; u32int used, tot, bsize; Fs *fs; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc != 0) return cliError(usage); fs = fsys->fs; cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize); consPrint("\t%s: %,llud used + %,llud free = %,llud (%ud%% used)\n", fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize, tot*(vlong)bsize, used*100/tot); return 1;}/* * Zero an entry or a pointer. */static intfsysClrep(Fsys* fsys, int argc, char* argv[], int ch){ Fs *fs; Entry e; Block *b; u32int addr; int i, max, offset, sz; uchar zero[VtEntrySize]; char *usage = "usage: [fsys name] clr%c addr offset ..."; ARGBEGIN{ default: return cliError(usage, ch); }ARGEND if(argc < 2) return cliError(usage, ch); fs = fsys->fs; vtRLock(fsys->fs->elk); addr = strtoul(argv[0], 0, 0); b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); if(b == nil){ vtSetError("cacheLocal %#ux: %R", addr); Err: vtRUnlock(fsys->fs->elk); return 0; } switch(ch){ default: vtSetError("clrep"); goto Err; case 'e': if(b->l.type != BtDir){ vtSetError("wrong block type"); goto Err; } sz = VtEntrySize; memset(&e, 0, sizeof e); entryPack(&e, zero, 0); break; case 'p': if(b->l.type == BtDir || b->l.type == BtData){ vtSetError("wrong block type"); goto Err; } sz = VtScoreSize; memmove(zero, vtZeroScore, VtScoreSize); break; } max = fs->blockSize/sz; for(i = 1; i < argc; i++){ offset = atoi(argv[i]); if(offset >= max){ consPrint("\toffset %d too large (>= %d)\n", i, max); continue; } consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz); memmove(b->data+offset*sz, zero, sz); } blockDirty(b); blockPut(b); vtRUnlock(fsys->fs->elk); return 1;}static intfsysClre(Fsys* fsys, int argc, char* argv[]){ return fsysClrep(fsys, argc, argv, 'e');}static intfsysClrp(Fsys* fsys, int argc, char* argv[]){ return fsysClrep(fsys, argc, argv, 'p');}static intfsysEsearch1(File* f, char* s, u32int elo){ 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){ consPrint("\tdeeRead %s/%s: %R\n", s, de.elem); break; } if(r == 0) break; if(de.mode & ModeSnapshot){ if((ff = fileWalk(f, de.elem)) == nil) consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); else{ if(!fileGetSources(ff, &e, &ee)) consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem); else if(e.snap != 0 && e.snap < elo){ consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem); n++; } fileDecRef(ff); } } else if(de.mode & ModeDir){ if((ff = fileWalk(f, de.elem)) == nil) consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); else{ t = smprint("%s/%s", s, de.elem); n += fsysEsearch1(ff, t, elo); vtMemFree(t); fileDecRef(ff); } } deCleanup(&de); if(r < 0) break; } deeClose(dee); return n;}static intfsysEsearch(Fs* fs, char* path, u32int elo){ int n; File *f; DirEntry de; f = fileOpen(fs, path); if(f == nil) return 0; if(!fileGetDir(f, &de)){ consPrint("\tfileGetDir %s failed: %R\n", path); fileDecRef(f); return 0; } if((de.mode & ModeDir) == 0){ fileDecRef(f); deCleanup(&de); return 0; } deCleanup(&de); n = fsysEsearch1(f, path, elo); fileDecRef(f); return n;}static intfsysEpoch(Fsys* fsys, int argc, char* argv[]){ Fs *fs; int force, n, remove; u32int low, old; char *usage = "usage: [fsys name] epoch [[-ry] low]"; force = 0; remove = 0; ARGBEGIN{ case 'y': force = 1; break; case 'r': remove = 1; break; default: return cliError(usage); }ARGEND if(argc > 1) return cliError(usage); if(argc > 0) low = strtoul(argv[0], 0, 0); else low = ~(u32int)0; if(low == 0) return cliError("low epoch cannot be zero"); fs = fsys->fs; vtRLock(fs->elk); consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi); n = fsysEsearch(fsys->fs, "/archive", low); n += fsysEsearch(fsys->fs, "/snapshot", low); consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low); vtRUnlock(fs->elk); /* * There's a small race here -- a new snapshot with epoch < low might * get introduced now that we unlocked fs->elk. Low has to * be <= fs->ehi. Of course, in order for this to happen low has * to be equal to the current fs->ehi _and_ a snapshot has to * run right now. This is a small enough window that I don't care. */ if(n != 0 && !force){ consPrint("\tnot setting low epoch\n"); return 1; } old = fs->elo; if(!fsEpochLow(fs, low)) consPrint("\tfsEpochLow: %R\n"); else{ consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old); consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo); if(fs->elo < low) consPrint("\twarning: new low epoch < old low epoch\n"); if(force && remove) fsSnapshotRemove(fs); } return 1;}static intfsysCreate(Fsys* fsys, int argc, char* argv[]){ int r; ulong mode; char *elem, *p, *path; char *usage = "usage: [fsys name] create path uid gid perm"; DirEntry de; File *file, *parent; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc != 4) return cliError(usage); if(!fsysParseMode(argv[3], &mode)) return cliError(usage); if(mode&ModeSnapshot) return cliError("create - cannot create with snapshot bit set"); if(strcmp(argv[1], uidnoworld) == 0) return cliError("permission denied"); vtRLock(fsys->fs->elk); path = vtStrDup(argv[0]); if((p = strrchr(path, '/')) != nil){ *p++ = '\0'; elem = p; p = path; if(*p == '\0') p = "/"; } else{ p = "/"; elem = path; } r = 0; if((parent = fileOpen(fsys->fs, p)) == nil) goto out; file = fileCreate(parent, elem, mode, argv[1]); fileDecRef(parent); if(file == nil){ vtSetError("create %s/%s: %R", p, elem); goto out; } if(!fileGetDir(file, &de)){ vtSetError("stat failed after create: %R"); goto out1; } if(strcmp(de.gid, argv[2]) != 0){ vtMemFree(de.gid); de.gid = vtStrDup(argv[2]); if(!fileSetDir(file, &de, argv[1])){ vtSetError("wstat failed after create: %R"); goto out2; } } r = 1;out2: deCleanup(&de);out1: fileDecRef(file);out: vtMemFree(path); vtRUnlock(fsys->fs->elk); return r;}static voidfsysPrintStat(char *prefix, char *file, DirEntry *de){ char buf[64]; if(prefix == nil) prefix = ""; consPrint("%sstat %q %q %q %q %s %llud\n", prefix, file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);}static intfsysStat(Fsys* fsys, int argc, char* argv[]){ int i; File *f; DirEntry de; char *usage = "usage: [fsys name] stat files..."; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc == 0) return cliError(usage); vtRLock(fsys->fs->elk); for(i=0; i<argc; i++){ if((f = fileOpen(fsys->fs, argv[i])) == nil){ consPrint("%s: %R\n"); continue; } if(!fileGetDir(f, &de)){ consPrint("%s: %R\n"); fileDecRef(f); continue; } fsysPrintStat("\t", argv[i], &de); deCleanup(&de); fileDecRef(f); } vtRUnlock(fsys->fs->elk); return 1;}static intfsysWstat(Fsys *fsys, int argc, char* argv[]){ File *f; char *p; DirEntry de; char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n" "\tuse - for any field to mean don't change"; ARGBEGIN{ default: return cliError(usage); }ARGEND if(argc != 6) return cliError(usage); vtRLock(fsys->fs->elk); if((f = fileOpen(fsys->fs, argv[0])) == nil){ vtSetError("console wstat - walk - %R"); vtRUnlock(fsys->fs->elk); return 0; } if(!fileGetDir(f, &de)){ vtSetError("console wstat - stat - %R"); fileDecRef(f); vtRUnlock(fsys->fs->elk); return 0; } fsysPrintStat("\told: w", argv[0], &de); if(strcmp(argv[1], "-") != 0){ if(!validFileName(argv[1])){ vtSetError("console wstat - bad elem");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -