15e96a66cSDavid du Colombier #include "stdinc.h" 2b8a11165SDavid du Colombier #include <bio.h> 35e96a66cSDavid du Colombier #include "dat.h" 45e96a66cSDavid du Colombier #include "fns.h" 55e96a66cSDavid du Colombier #include "9.h" 65e96a66cSDavid du Colombier 75e96a66cSDavid du Colombier typedef struct Fsys Fsys; 85e96a66cSDavid du Colombier 97abd426fSDavid du Colombier struct Fsys { 105e96a66cSDavid du Colombier VtLock* lock; 115e96a66cSDavid du Colombier 120c6300e7SDavid du Colombier char* name; /* copy here & Fs to ease error reporting */ 135e96a66cSDavid du Colombier char* dev; 145e96a66cSDavid du Colombier char* venti; 155e96a66cSDavid du Colombier 165e96a66cSDavid du Colombier Fs* fs; 175e96a66cSDavid du Colombier VtSession* session; 185e96a66cSDavid du Colombier int ref; 195e96a66cSDavid du Colombier 205e96a66cSDavid du Colombier int noauth; 215e96a66cSDavid du Colombier int noperm; 225e96a66cSDavid du Colombier int wstatallow; 235e96a66cSDavid du Colombier 245e96a66cSDavid du Colombier Fsys* next; 257abd426fSDavid du Colombier }; 265e96a66cSDavid du Colombier 27b8a11165SDavid du Colombier int mempcnt; /* from fossil.c */ 28b8a11165SDavid du Colombier 29b8a11165SDavid du Colombier int fsGetBlockSize(Fs *fs); 30b8a11165SDavid du Colombier 315e96a66cSDavid du Colombier static struct { 325e96a66cSDavid du Colombier VtLock* lock; 335e96a66cSDavid du Colombier Fsys* head; 345e96a66cSDavid du Colombier Fsys* tail; 355e96a66cSDavid du Colombier 365e96a66cSDavid du Colombier char* curfsys; 375e96a66cSDavid du Colombier } sbox; 385e96a66cSDavid du Colombier 395e96a66cSDavid du Colombier static char *_argv0; 405e96a66cSDavid du Colombier #define argv0 _argv0 415e96a66cSDavid du Colombier 4281cf8742SDavid du Colombier static char FsysAll[] = "all"; 4381cf8742SDavid du Colombier 445e96a66cSDavid du Colombier static char EFsysBusy[] = "fsys: '%s' busy"; 455e96a66cSDavid du Colombier static char EFsysExists[] = "fsys: '%s' already exists"; 465e96a66cSDavid du Colombier static char EFsysNoCurrent[] = "fsys: no current fsys"; 475e96a66cSDavid du Colombier static char EFsysNotFound[] = "fsys: '%s' not found"; 485e96a66cSDavid du Colombier static char EFsysNotOpen[] = "fsys: '%s' not open"; 495e96a66cSDavid du Colombier 50ea58ad6fSDavid du Colombier static char * 51ea58ad6fSDavid du Colombier ventihost(char *host) 52ea58ad6fSDavid du Colombier { 53ea58ad6fSDavid du Colombier if(host != nil) 54*1bdadbfaSDavid du Colombier return vtStrDup(host); 55ea58ad6fSDavid du Colombier host = getenv("venti"); 56ea58ad6fSDavid du Colombier if(host == nil) 57*1bdadbfaSDavid du Colombier host = vtStrDup("$venti"); 58ea58ad6fSDavid du Colombier return host; 59ea58ad6fSDavid du Colombier } 60ea58ad6fSDavid du Colombier 61ea58ad6fSDavid du Colombier static void 62ea58ad6fSDavid du Colombier prventihost(char *host) 63ea58ad6fSDavid du Colombier { 64ea58ad6fSDavid du Colombier char *vh; 65ea58ad6fSDavid du Colombier 66ea58ad6fSDavid du Colombier vh = ventihost(host); 67ea58ad6fSDavid du Colombier fprint(2, "%s: dialing venti at %s\n", 68ea58ad6fSDavid du Colombier argv0, netmkaddr(vh, 0, "venti")); 69ea58ad6fSDavid du Colombier free(vh); 70ea58ad6fSDavid du Colombier } 71ea58ad6fSDavid du Colombier 72ea58ad6fSDavid du Colombier static VtSession * 73ea58ad6fSDavid du Colombier myDial(char *host, int canfail) 74ea58ad6fSDavid du Colombier { 75ea58ad6fSDavid du Colombier prventihost(host); 76ea58ad6fSDavid du Colombier return vtDial(host, canfail); 77ea58ad6fSDavid du Colombier } 78ea58ad6fSDavid du Colombier 79ea58ad6fSDavid du Colombier static int 80ea58ad6fSDavid du Colombier myRedial(VtSession *z, char *host) 81ea58ad6fSDavid du Colombier { 82ea58ad6fSDavid du Colombier prventihost(host); 83ea58ad6fSDavid du Colombier return vtRedial(z, host); 84ea58ad6fSDavid du Colombier } 85ea58ad6fSDavid du Colombier 865e96a66cSDavid du Colombier static Fsys* 875e96a66cSDavid du Colombier _fsysGet(char* name) 885e96a66cSDavid du Colombier { 895e96a66cSDavid du Colombier Fsys *fsys; 905e96a66cSDavid du Colombier 915e96a66cSDavid du Colombier if(name == nil || name[0] == '\0') 925e96a66cSDavid du Colombier name = "main"; 935e96a66cSDavid du Colombier 945e96a66cSDavid du Colombier vtRLock(sbox.lock); 955e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 965e96a66cSDavid du Colombier if(strcmp(name, fsys->name) == 0){ 975e96a66cSDavid du Colombier fsys->ref++; 985e96a66cSDavid du Colombier break; 995e96a66cSDavid du Colombier } 1005e96a66cSDavid du Colombier } 101dc5a79c1SDavid du Colombier vtRUnlock(sbox.lock); 1025e96a66cSDavid du Colombier if(fsys == nil) 1035e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 1045e96a66cSDavid du Colombier return fsys; 1055e96a66cSDavid du Colombier } 1065e96a66cSDavid du Colombier 1075e96a66cSDavid du Colombier static int 1085e96a66cSDavid du Colombier cmdPrintConfig(int argc, char* argv[]) 1095e96a66cSDavid du Colombier { 1105e96a66cSDavid du Colombier Fsys *fsys; 1115e96a66cSDavid du Colombier char *usage = "usage: printconfig"; 1125e96a66cSDavid du Colombier 1135e96a66cSDavid du Colombier ARGBEGIN{ 1145e96a66cSDavid du Colombier default: 1155e96a66cSDavid du Colombier return cliError(usage); 1165e96a66cSDavid du Colombier }ARGEND 1175e96a66cSDavid du Colombier 1185e96a66cSDavid du Colombier if(argc) 1195e96a66cSDavid du Colombier return cliError(usage); 1205e96a66cSDavid du Colombier 1215e96a66cSDavid du Colombier vtRLock(sbox.lock); 1225e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 1235e96a66cSDavid du Colombier consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev); 1245e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 1250c6300e7SDavid du Colombier consPrint("\tfsys %s venti %q\n", fsys->name, 1260c6300e7SDavid du Colombier fsys->venti); 1275e96a66cSDavid du Colombier } 1285e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 1295e96a66cSDavid du Colombier return 1; 1305e96a66cSDavid du Colombier } 1315e96a66cSDavid du Colombier 1325e96a66cSDavid du Colombier Fsys* 1335e96a66cSDavid du Colombier fsysGet(char* name) 1345e96a66cSDavid du Colombier { 1355e96a66cSDavid du Colombier Fsys *fsys; 1365e96a66cSDavid du Colombier 1375e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 1385e96a66cSDavid du Colombier return nil; 1395e96a66cSDavid du Colombier 1405e96a66cSDavid du Colombier vtLock(fsys->lock); 1415e96a66cSDavid du Colombier if(fsys->fs == nil){ 1425e96a66cSDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 1435e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1445e96a66cSDavid du Colombier fsysPut(fsys); 1455e96a66cSDavid du Colombier return nil; 1465e96a66cSDavid du Colombier } 1475e96a66cSDavid du Colombier vtUnlock(fsys->lock); 1485e96a66cSDavid du Colombier 1495e96a66cSDavid du Colombier return fsys; 1505e96a66cSDavid du Colombier } 1515e96a66cSDavid du Colombier 15261201b97SDavid du Colombier char* 15361201b97SDavid du Colombier fsysGetName(Fsys* fsys) 15461201b97SDavid du Colombier { 15561201b97SDavid du Colombier return fsys->name; 15661201b97SDavid du Colombier } 15761201b97SDavid du Colombier 1585e96a66cSDavid du Colombier Fsys* 1595e96a66cSDavid du Colombier fsysIncRef(Fsys* fsys) 1605e96a66cSDavid du Colombier { 1615e96a66cSDavid du Colombier vtLock(sbox.lock); 1625e96a66cSDavid du Colombier fsys->ref++; 1635e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1645e96a66cSDavid du Colombier 1655e96a66cSDavid du Colombier return fsys; 1665e96a66cSDavid du Colombier } 1675e96a66cSDavid du Colombier 1685e96a66cSDavid du Colombier void 1695e96a66cSDavid du Colombier fsysPut(Fsys* fsys) 1705e96a66cSDavid du Colombier { 1715e96a66cSDavid du Colombier vtLock(sbox.lock); 1725e96a66cSDavid du Colombier assert(fsys->ref > 0); 1735e96a66cSDavid du Colombier fsys->ref--; 1745e96a66cSDavid du Colombier vtUnlock(sbox.lock); 1755e96a66cSDavid du Colombier } 1765e96a66cSDavid du Colombier 1775e96a66cSDavid du Colombier Fs* 1785e96a66cSDavid du Colombier fsysGetFs(Fsys* fsys) 1795e96a66cSDavid du Colombier { 1805e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 1815e96a66cSDavid du Colombier 1825e96a66cSDavid du Colombier return fsys->fs; 1835e96a66cSDavid du Colombier } 1845e96a66cSDavid du Colombier 1855e96a66cSDavid du Colombier void 1865e96a66cSDavid du Colombier fsysFsRlock(Fsys* fsys) 1875e96a66cSDavid du Colombier { 1885e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 1895e96a66cSDavid du Colombier } 1905e96a66cSDavid du Colombier 1915e96a66cSDavid du Colombier void 1925e96a66cSDavid du Colombier fsysFsRUnlock(Fsys* fsys) 1935e96a66cSDavid du Colombier { 1945e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 1955e96a66cSDavid du Colombier } 1965e96a66cSDavid du Colombier 1975e96a66cSDavid du Colombier int 1985e96a66cSDavid du Colombier fsysNoAuthCheck(Fsys* fsys) 1995e96a66cSDavid du Colombier { 2005e96a66cSDavid du Colombier return fsys->noauth; 2015e96a66cSDavid du Colombier } 2025e96a66cSDavid du Colombier 2035e96a66cSDavid du Colombier int 2045e96a66cSDavid du Colombier fsysNoPermCheck(Fsys* fsys) 2055e96a66cSDavid du Colombier { 2065e96a66cSDavid du Colombier return fsys->noperm; 2075e96a66cSDavid du Colombier } 2085e96a66cSDavid du Colombier 2095e96a66cSDavid du Colombier int 2105e96a66cSDavid du Colombier fsysWstatAllow(Fsys* fsys) 2115e96a66cSDavid du Colombier { 2125e96a66cSDavid du Colombier return fsys->wstatallow; 2135e96a66cSDavid du Colombier } 2145e96a66cSDavid du Colombier 2155e96a66cSDavid du Colombier static char modechars[] = "YUGalLdHSATs"; 2165e96a66cSDavid du Colombier static ulong modebits[] = { 2175e96a66cSDavid du Colombier ModeSticky, 2185e96a66cSDavid du Colombier ModeSetUid, 2195e96a66cSDavid du Colombier ModeSetGid, 2205e96a66cSDavid du Colombier ModeAppend, 2215e96a66cSDavid du Colombier ModeExclusive, 2225e96a66cSDavid du Colombier ModeLink, 2235e96a66cSDavid du Colombier ModeDir, 2245e96a66cSDavid du Colombier ModeHidden, 2255e96a66cSDavid du Colombier ModeSystem, 2265e96a66cSDavid du Colombier ModeArchive, 2275e96a66cSDavid du Colombier ModeTemporary, 2285e96a66cSDavid du Colombier ModeSnapshot, 2295e96a66cSDavid du Colombier 0 2305e96a66cSDavid du Colombier }; 2315e96a66cSDavid du Colombier 2325e96a66cSDavid du Colombier char* 2335e96a66cSDavid du Colombier fsysModeString(ulong mode, char *buf) 2345e96a66cSDavid du Colombier { 2355e96a66cSDavid du Colombier int i; 2365e96a66cSDavid du Colombier char *p; 2375e96a66cSDavid du Colombier 2385e96a66cSDavid du Colombier p = buf; 2395e96a66cSDavid du Colombier for(i=0; modebits[i]; i++) 2405e96a66cSDavid du Colombier if(mode & modebits[i]) 2415e96a66cSDavid du Colombier *p++ = modechars[i]; 2425e96a66cSDavid du Colombier sprint(p, "%luo", mode&0777); 2435e96a66cSDavid du Colombier return buf; 2445e96a66cSDavid du Colombier } 2455e96a66cSDavid du Colombier 2465e96a66cSDavid du Colombier int 2475e96a66cSDavid du Colombier fsysParseMode(char* s, ulong* mode) 2485e96a66cSDavid du Colombier { 2495e96a66cSDavid du Colombier ulong x, y; 2505e96a66cSDavid du Colombier char *p; 2515e96a66cSDavid du Colombier 2525e96a66cSDavid du Colombier x = 0; 2535e96a66cSDavid du Colombier for(; *s < '0' || *s > '9'; s++){ 2545e96a66cSDavid du Colombier if(*s == 0) 2555e96a66cSDavid du Colombier return 0; 2565e96a66cSDavid du Colombier p = strchr(modechars, *s); 2575e96a66cSDavid du Colombier if(p == nil) 2585e96a66cSDavid du Colombier return 0; 2595e96a66cSDavid du Colombier x |= modebits[p-modechars]; 2605e96a66cSDavid du Colombier } 2615e96a66cSDavid du Colombier y = strtoul(s, &p, 8); 2625e96a66cSDavid du Colombier if(*p != '\0' || y > 0777) 2635e96a66cSDavid du Colombier return 0; 2645e96a66cSDavid du Colombier *mode = x|y; 2655e96a66cSDavid du Colombier return 1; 2665e96a66cSDavid du Colombier } 2675e96a66cSDavid du Colombier 2685e96a66cSDavid du Colombier File* 2695e96a66cSDavid du Colombier fsysGetRoot(Fsys* fsys, char* name) 2705e96a66cSDavid du Colombier { 2715e96a66cSDavid du Colombier File *root, *sub; 2725e96a66cSDavid du Colombier 2735e96a66cSDavid du Colombier assert(fsys != nil && fsys->fs != nil); 2745e96a66cSDavid du Colombier 2755e96a66cSDavid du Colombier root = fsGetRoot(fsys->fs); 2765e96a66cSDavid du Colombier if(name == nil || strcmp(name, "") == 0) 2775e96a66cSDavid du Colombier return root; 2785e96a66cSDavid du Colombier 2795e96a66cSDavid du Colombier sub = fileWalk(root, name); 2805e96a66cSDavid du Colombier fileDecRef(root); 2815e96a66cSDavid du Colombier 2825e96a66cSDavid du Colombier return sub; 2835e96a66cSDavid du Colombier } 2845e96a66cSDavid du Colombier 2855e96a66cSDavid du Colombier static Fsys* 2865e96a66cSDavid du Colombier fsysAlloc(char* name, char* dev) 2875e96a66cSDavid du Colombier { 2885e96a66cSDavid du Colombier Fsys *fsys; 2895e96a66cSDavid du Colombier 2905e96a66cSDavid du Colombier vtLock(sbox.lock); 2915e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 2925e96a66cSDavid du Colombier if(strcmp(fsys->name, name) != 0) 2935e96a66cSDavid du Colombier continue; 2945e96a66cSDavid du Colombier vtSetError(EFsysExists, name); 2955e96a66cSDavid du Colombier vtUnlock(sbox.lock); 2965e96a66cSDavid du Colombier return nil; 2975e96a66cSDavid du Colombier } 2985e96a66cSDavid du Colombier 2995e96a66cSDavid du Colombier fsys = vtMemAllocZ(sizeof(Fsys)); 3005e96a66cSDavid du Colombier fsys->lock = vtLockAlloc(); 3015e96a66cSDavid du Colombier fsys->name = vtStrDup(name); 3025e96a66cSDavid du Colombier fsys->dev = vtStrDup(dev); 3035e96a66cSDavid du Colombier 3045e96a66cSDavid du Colombier fsys->ref = 1; 3055e96a66cSDavid du Colombier 3065e96a66cSDavid du Colombier if(sbox.tail != nil) 3075e96a66cSDavid du Colombier sbox.tail->next = fsys; 3085e96a66cSDavid du Colombier else 3095e96a66cSDavid du Colombier sbox.head = fsys; 3105e96a66cSDavid du Colombier sbox.tail = fsys; 3115e96a66cSDavid du Colombier vtUnlock(sbox.lock); 3125e96a66cSDavid du Colombier 3135e96a66cSDavid du Colombier return fsys; 3145e96a66cSDavid du Colombier } 3155e96a66cSDavid du Colombier 3165e96a66cSDavid du Colombier static int 3175e96a66cSDavid du Colombier fsysClose(Fsys* fsys, int argc, char* argv[]) 3185e96a66cSDavid du Colombier { 3195e96a66cSDavid du Colombier char *usage = "usage: [fsys name] close"; 3205e96a66cSDavid du Colombier 3215e96a66cSDavid du Colombier ARGBEGIN{ 3225e96a66cSDavid du Colombier default: 3235e96a66cSDavid du Colombier return cliError(usage); 3245e96a66cSDavid du Colombier }ARGEND 3255e96a66cSDavid du Colombier if(argc) 3265e96a66cSDavid du Colombier return cliError(usage); 3275e96a66cSDavid du Colombier 32868412abfSDavid du Colombier return cliError("close isn't working yet; halt %s and then kill fossil", 32968412abfSDavid du Colombier fsys->name); 3305e96a66cSDavid du Colombier 3315e96a66cSDavid du Colombier /* 3325e96a66cSDavid du Colombier * Oooh. This could be hard. What if fsys->ref != 1? 3335e96a66cSDavid du Colombier * Also, fsClose() either does the job or panics, can we 3345e96a66cSDavid du Colombier * gracefully detect it's still busy? 3355e96a66cSDavid du Colombier * 3365e96a66cSDavid du Colombier * More thought and care needed here. 3375e96a66cSDavid du Colombier fsClose(fsys->fs); 3385e96a66cSDavid du Colombier fsys->fs = nil; 3395e96a66cSDavid du Colombier vtClose(fsys->session); 3405e96a66cSDavid du Colombier fsys->session = nil; 3415e96a66cSDavid du Colombier 3425e96a66cSDavid du Colombier if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){ 3435e96a66cSDavid du Colombier sbox.curfsys = nil; 3445e96a66cSDavid du Colombier consPrompt(nil); 3455e96a66cSDavid du Colombier } 3465e96a66cSDavid du Colombier 3475e96a66cSDavid du Colombier return 1; 34868412abfSDavid du Colombier */ 3495e96a66cSDavid du Colombier } 3505e96a66cSDavid du Colombier 3515e96a66cSDavid du Colombier static int 3525e96a66cSDavid du Colombier fsysVac(Fsys* fsys, int argc, char* argv[]) 3535e96a66cSDavid du Colombier { 3545e96a66cSDavid du Colombier uchar score[VtScoreSize]; 3555e96a66cSDavid du Colombier char *usage = "usage: [fsys name] vac path"; 3565e96a66cSDavid du Colombier 3575e96a66cSDavid du Colombier ARGBEGIN{ 3585e96a66cSDavid du Colombier default: 3595e96a66cSDavid du Colombier return cliError(usage); 3605e96a66cSDavid du Colombier }ARGEND 3615e96a66cSDavid du Colombier if(argc != 1) 3625e96a66cSDavid du Colombier return cliError(usage); 3635e96a66cSDavid du Colombier 3645e96a66cSDavid du Colombier if(!fsVac(fsys->fs, argv[0], score)) 3655e96a66cSDavid du Colombier return 0; 3665e96a66cSDavid du Colombier 3675e96a66cSDavid du Colombier consPrint("vac:%V\n", score); 3685e96a66cSDavid du Colombier return 1; 3695e96a66cSDavid du Colombier } 3705e96a66cSDavid du Colombier 3715e96a66cSDavid du Colombier static int 3725e96a66cSDavid du Colombier fsysSnap(Fsys* fsys, int argc, char* argv[]) 3735e96a66cSDavid du Colombier { 3745e96a66cSDavid du Colombier int doarchive; 375c3c4501eSDavid du Colombier char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]"; 376c3c4501eSDavid du Colombier char *src, *dst; 3775e96a66cSDavid du Colombier 378c3c4501eSDavid du Colombier src = nil; 379c3c4501eSDavid du Colombier dst = nil; 3805e96a66cSDavid du Colombier doarchive = 0; 3815e96a66cSDavid du Colombier ARGBEGIN{ 3825e96a66cSDavid du Colombier default: 3835e96a66cSDavid du Colombier return cliError(usage); 3845e96a66cSDavid du Colombier case 'a': 3855e96a66cSDavid du Colombier doarchive = 1; 3865e96a66cSDavid du Colombier break; 387c3c4501eSDavid du Colombier case 'd': 388c3c4501eSDavid du Colombier if((dst = ARGF()) == nil) 389c3c4501eSDavid du Colombier return cliError(usage); 390c3c4501eSDavid du Colombier break; 391c3c4501eSDavid du Colombier case 's': 392c3c4501eSDavid du Colombier if((src = ARGF()) == nil) 393c3c4501eSDavid du Colombier return cliError(usage); 394c3c4501eSDavid du Colombier break; 3955e96a66cSDavid du Colombier }ARGEND 3965e96a66cSDavid du Colombier if(argc) 3975e96a66cSDavid du Colombier return cliError(usage); 3985e96a66cSDavid du Colombier 399c3c4501eSDavid du Colombier if(!fsSnapshot(fsys->fs, src, dst, doarchive)) 4005e96a66cSDavid du Colombier return 0; 4015e96a66cSDavid du Colombier 4025e96a66cSDavid du Colombier return 1; 4035e96a66cSDavid du Colombier } 4045e96a66cSDavid du Colombier 4055e96a66cSDavid du Colombier static int 406dc5a79c1SDavid du Colombier fsysSnapClean(Fsys *fsys, int argc, char* argv[]) 407dc5a79c1SDavid du Colombier { 408dc5a79c1SDavid du Colombier u32int arch, snap, life; 409dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snapclean [maxminutes]\n"; 410dc5a79c1SDavid du Colombier 411dc5a79c1SDavid du Colombier ARGBEGIN{ 412dc5a79c1SDavid du Colombier default: 413dc5a79c1SDavid du Colombier return cliError(usage); 414dc5a79c1SDavid du Colombier }ARGEND 415dc5a79c1SDavid du Colombier 416dc5a79c1SDavid du Colombier if(argc > 1) 417dc5a79c1SDavid du Colombier return cliError(usage); 418dc5a79c1SDavid du Colombier if(argc == 1) 419f83f9c78SDavid du Colombier life = atoi(argv[0]); 420dc5a79c1SDavid du Colombier else 421dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 422dc5a79c1SDavid du Colombier 423dc5a79c1SDavid du Colombier fsSnapshotCleanup(fsys->fs, life); 424dc5a79c1SDavid du Colombier return 1; 425dc5a79c1SDavid du Colombier } 426dc5a79c1SDavid du Colombier 427dc5a79c1SDavid du Colombier static int 4285e96a66cSDavid du Colombier fsysSnapTime(Fsys* fsys, int argc, char* argv[]) 4295e96a66cSDavid du Colombier { 430dc5a79c1SDavid du Colombier char buf[128], *x; 431dc5a79c1SDavid du Colombier int hh, mm, changed; 432dc5a79c1SDavid du Colombier u32int arch, snap, life; 433dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]"; 4345e96a66cSDavid du Colombier 435dc5a79c1SDavid du Colombier changed = 0; 436dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 4375e96a66cSDavid du Colombier ARGBEGIN{ 4385e96a66cSDavid du Colombier case 'a': 439dc5a79c1SDavid du Colombier changed = 1; 4405e96a66cSDavid du Colombier x = ARGF(); 4415e96a66cSDavid du Colombier if(x == nil) 4425e96a66cSDavid du Colombier return cliError(usage); 4435e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 4445e96a66cSDavid du Colombier arch = ~(u32int)0; 4455e96a66cSDavid du Colombier break; 4465e96a66cSDavid du Colombier } 4475e96a66cSDavid du Colombier if(strlen(x) != 4 || strspn(x, "0123456789") != 4) 4485e96a66cSDavid du Colombier return cliError(usage); 4495e96a66cSDavid du Colombier hh = (x[0]-'0')*10 + x[1]-'0'; 4505e96a66cSDavid du Colombier mm = (x[2]-'0')*10 + x[3]-'0'; 4515e96a66cSDavid du Colombier if(hh >= 24 || mm >= 60) 4525e96a66cSDavid du Colombier return cliError(usage); 4535e96a66cSDavid du Colombier arch = hh*60+mm; 4545e96a66cSDavid du Colombier break; 4555e96a66cSDavid du Colombier case 's': 456dc5a79c1SDavid du Colombier changed = 1; 4575e96a66cSDavid du Colombier x = ARGF(); 4585e96a66cSDavid du Colombier if(x == nil) 4595e96a66cSDavid du Colombier return cliError(usage); 4605e96a66cSDavid du Colombier if(strcmp(x, "none") == 0){ 4615e96a66cSDavid du Colombier snap = ~(u32int)0; 4625e96a66cSDavid du Colombier break; 4635e96a66cSDavid du Colombier } 4645e96a66cSDavid du Colombier snap = atoi(x); 4655e96a66cSDavid du Colombier break; 466dc5a79c1SDavid du Colombier case 't': 467dc5a79c1SDavid du Colombier changed = 1; 468dc5a79c1SDavid du Colombier x = ARGF(); 469dc5a79c1SDavid du Colombier if(x == nil) 470dc5a79c1SDavid du Colombier return cliError(usage); 471dc5a79c1SDavid du Colombier if(strcmp(x, "none") == 0){ 472dc5a79c1SDavid du Colombier life = ~(u32int)0; 473dc5a79c1SDavid du Colombier break; 474dc5a79c1SDavid du Colombier } 475dc5a79c1SDavid du Colombier life = atoi(x); 476dc5a79c1SDavid du Colombier break; 4775e96a66cSDavid du Colombier default: 4785e96a66cSDavid du Colombier return cliError(usage); 4795e96a66cSDavid du Colombier }ARGEND 4805e96a66cSDavid du Colombier if(argc > 0) 4815e96a66cSDavid du Colombier return cliError(usage); 4825e96a66cSDavid du Colombier 483dc5a79c1SDavid du Colombier if(changed){ 484dc5a79c1SDavid du Colombier snapSetTimes(fsys->fs->snap, arch, snap, life); 485dc5a79c1SDavid du Colombier return 1; 486dc5a79c1SDavid du Colombier } 487dc5a79c1SDavid du Colombier snapGetTimes(fsys->fs->snap, &arch, &snap, &life); 4885e96a66cSDavid du Colombier if(arch != ~(u32int)0) 4895e96a66cSDavid du Colombier sprint(buf, "-a %02d%02d", arch/60, arch%60); 4905e96a66cSDavid du Colombier else 4915e96a66cSDavid du Colombier sprint(buf, "-a none"); 4925e96a66cSDavid du Colombier if(snap != ~(u32int)0) 4935e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s %d", snap); 4945e96a66cSDavid du Colombier else 4955e96a66cSDavid du Colombier sprint(buf+strlen(buf), " -s none"); 496dc5a79c1SDavid du Colombier if(life != ~(u32int)0) 497dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t %ud", life); 498dc5a79c1SDavid du Colombier else 499dc5a79c1SDavid du Colombier sprint(buf+strlen(buf), " -t none"); 5005e96a66cSDavid du Colombier consPrint("\tsnaptime %s\n", buf); 5015e96a66cSDavid du Colombier return 1; 5025e96a66cSDavid du Colombier } 5035e96a66cSDavid du Colombier 5045e96a66cSDavid du Colombier static int 5055e96a66cSDavid du Colombier fsysSync(Fsys* fsys, int argc, char* argv[]) 5065e96a66cSDavid du Colombier { 5075e96a66cSDavid du Colombier char *usage = "usage: [fsys name] sync"; 5080b9a5132SDavid du Colombier int n; 5095e96a66cSDavid du Colombier 5105e96a66cSDavid du Colombier ARGBEGIN{ 5115e96a66cSDavid du Colombier default: 5125e96a66cSDavid du Colombier return cliError(usage); 5135e96a66cSDavid du Colombier }ARGEND 5145e96a66cSDavid du Colombier if(argc > 0) 5155e96a66cSDavid du Colombier return cliError(usage); 5165e96a66cSDavid du Colombier 5170b9a5132SDavid du Colombier n = cacheDirty(fsys->fs->cache); 5185e96a66cSDavid du Colombier fsSync(fsys->fs); 5190b9a5132SDavid du Colombier consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n); 52081cf8742SDavid du Colombier return 1; 52181cf8742SDavid du Colombier } 5225e96a66cSDavid du Colombier 52381cf8742SDavid du Colombier static int 52481cf8742SDavid du Colombier fsysHalt(Fsys *fsys, int argc, char* argv[]) 52581cf8742SDavid du Colombier { 52681cf8742SDavid du Colombier char *usage = "usage: [fsys name] halt"; 52781cf8742SDavid du Colombier 52881cf8742SDavid du Colombier ARGBEGIN{ 52981cf8742SDavid du Colombier default: 53081cf8742SDavid du Colombier return cliError(usage); 53181cf8742SDavid du Colombier }ARGEND 53281cf8742SDavid du Colombier if(argc > 0) 53381cf8742SDavid du Colombier return cliError(usage); 53481cf8742SDavid du Colombier 53581cf8742SDavid du Colombier fsHalt(fsys->fs); 53681cf8742SDavid du Colombier return 1; 53781cf8742SDavid du Colombier } 53881cf8742SDavid du Colombier 53981cf8742SDavid du Colombier static int 54081cf8742SDavid du Colombier fsysUnhalt(Fsys *fsys, int argc, char* argv[]) 54181cf8742SDavid du Colombier { 54281cf8742SDavid du Colombier char *usage = "usage: [fsys name] unhalt"; 54381cf8742SDavid du Colombier 54481cf8742SDavid du Colombier ARGBEGIN{ 54581cf8742SDavid du Colombier default: 54681cf8742SDavid du Colombier return cliError(usage); 54781cf8742SDavid du Colombier }ARGEND 54881cf8742SDavid du Colombier if(argc > 0) 54981cf8742SDavid du Colombier return cliError(usage); 55081cf8742SDavid du Colombier 55181cf8742SDavid du Colombier if(!fsys->fs->halted) 55281cf8742SDavid du Colombier return cliError("file system %s not halted", fsys->name); 55381cf8742SDavid du Colombier 55481cf8742SDavid du Colombier fsUnhalt(fsys->fs); 5555e96a66cSDavid du Colombier return 1; 5565e96a66cSDavid du Colombier } 5575e96a66cSDavid du Colombier 5585e96a66cSDavid du Colombier static int 5595e96a66cSDavid du Colombier fsysRemove(Fsys* fsys, int argc, char* argv[]) 5605e96a66cSDavid du Colombier { 5615e96a66cSDavid du Colombier File *file; 5625e96a66cSDavid du Colombier char *usage = "usage: [fsys name] remove path ..."; 5635e96a66cSDavid du Colombier 5645e96a66cSDavid du Colombier ARGBEGIN{ 5655e96a66cSDavid du Colombier default: 5665e96a66cSDavid du Colombier return cliError(usage); 5675e96a66cSDavid du Colombier }ARGEND 5685e96a66cSDavid du Colombier if(argc == 0) 5695e96a66cSDavid du Colombier return cliError(usage); 5705e96a66cSDavid du Colombier 5715e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 5725e96a66cSDavid du Colombier while(argc > 0){ 5735e96a66cSDavid du Colombier if((file = fileOpen(fsys->fs, argv[0])) == nil) 5745e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 5755e96a66cSDavid du Colombier else{ 5765e96a66cSDavid du Colombier if(!fileRemove(file, uidadm)) 5775e96a66cSDavid du Colombier consPrint("%s: %R\n", argv[0]); 5785e96a66cSDavid du Colombier fileDecRef(file); 5795e96a66cSDavid du Colombier } 5805e96a66cSDavid du Colombier argc--; 5815e96a66cSDavid du Colombier argv++; 5825e96a66cSDavid du Colombier } 5835e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 5845e96a66cSDavid du Colombier 5855e96a66cSDavid du Colombier return 1; 5865e96a66cSDavid du Colombier } 5875e96a66cSDavid du Colombier 5885e96a66cSDavid du Colombier static int 5895e96a66cSDavid du Colombier fsysClri(Fsys* fsys, int argc, char* argv[]) 5905e96a66cSDavid du Colombier { 5915e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clri path ..."; 5925e96a66cSDavid du Colombier 5935e96a66cSDavid du Colombier ARGBEGIN{ 5945e96a66cSDavid du Colombier default: 5955e96a66cSDavid du Colombier return cliError(usage); 5965e96a66cSDavid du Colombier }ARGEND 5975e96a66cSDavid du Colombier if(argc == 0) 5985e96a66cSDavid du Colombier return cliError(usage); 5995e96a66cSDavid du Colombier 6005e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 6015e96a66cSDavid du Colombier while(argc > 0){ 602dc5a79c1SDavid du Colombier if(!fileClriPath(fsys->fs, argv[0], uidadm)) 6035e96a66cSDavid du Colombier consPrint("clri %s: %R\n", argv[0]); 6045e96a66cSDavid du Colombier argc--; 6055e96a66cSDavid du Colombier argv++; 6065e96a66cSDavid du Colombier } 6075e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 6085e96a66cSDavid du Colombier 6095e96a66cSDavid du Colombier return 1; 6105e96a66cSDavid du Colombier } 6115e96a66cSDavid du Colombier 6125e96a66cSDavid du Colombier /* 6135e96a66cSDavid du Colombier * Inspect and edit the labels for blocks on disk. 6145e96a66cSDavid du Colombier */ 6155e96a66cSDavid du Colombier static int 6165e96a66cSDavid du Colombier fsysLabel(Fsys* fsys, int argc, char* argv[]) 6175e96a66cSDavid du Colombier { 6185e96a66cSDavid du Colombier Fs *fs; 6195e96a66cSDavid du Colombier Label l; 6205e96a66cSDavid du Colombier int n, r; 6215e96a66cSDavid du Colombier u32int addr; 6225e96a66cSDavid du Colombier Block *b, *bb; 6235e96a66cSDavid du Colombier char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]"; 6245e96a66cSDavid du Colombier 6255e96a66cSDavid du Colombier ARGBEGIN{ 6265e96a66cSDavid du Colombier default: 6275e96a66cSDavid du Colombier return cliError(usage); 6285e96a66cSDavid du Colombier }ARGEND 6295e96a66cSDavid du Colombier if(argc != 1 && argc != 6) 6305e96a66cSDavid du Colombier return cliError(usage); 6315e96a66cSDavid du Colombier 6325e96a66cSDavid du Colombier r = 0; 6335e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 6345e96a66cSDavid du Colombier 6355e96a66cSDavid du Colombier fs = fsys->fs; 6365e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 6375e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 6385e96a66cSDavid du Colombier if(b == nil) 6395e96a66cSDavid du Colombier goto Out0; 6405e96a66cSDavid du Colombier 6415e96a66cSDavid du Colombier l = b->l; 6425e96a66cSDavid du Colombier consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n", 6435e96a66cSDavid du Colombier argc==6 ? "old: " : "", addr, l.type, l.state, 6445e96a66cSDavid du Colombier l.epoch, l.epochClose, l.tag); 6455e96a66cSDavid du Colombier 6465e96a66cSDavid du Colombier if(argc == 6){ 6475e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0) 6485e96a66cSDavid du Colombier l.type = atoi(argv[1]); 6495e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0) 6505e96a66cSDavid du Colombier l.state = atoi(argv[2]); 6515e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0) 6525e96a66cSDavid du Colombier l.epoch = strtoul(argv[3], 0, 0); 6535e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0) 6545e96a66cSDavid du Colombier l.epochClose = strtoul(argv[4], 0, 0); 6555e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0) 6565e96a66cSDavid du Colombier l.tag = strtoul(argv[5], 0, 0); 6575e96a66cSDavid du Colombier 6585e96a66cSDavid du Colombier consPrint("new: label %#ux %ud %ud %ud %ud %#x\n", 6595e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 6605e96a66cSDavid du Colombier bb = _blockSetLabel(b, &l); 6615e96a66cSDavid du Colombier if(bb == nil) 6625e96a66cSDavid du Colombier goto Out1; 6635e96a66cSDavid du Colombier n = 0; 6645e96a66cSDavid du Colombier for(;;){ 6655e96a66cSDavid du Colombier if(blockWrite(bb)){ 6665e96a66cSDavid du Colombier while(bb->iostate != BioClean){ 6675e96a66cSDavid du Colombier assert(bb->iostate == BioWriting); 6685e96a66cSDavid du Colombier vtSleep(bb->ioready); 6695e96a66cSDavid du Colombier } 6705e96a66cSDavid du Colombier break; 6715e96a66cSDavid du Colombier } 6725e96a66cSDavid du Colombier consPrint("blockWrite: %R\n"); 6735e96a66cSDavid du Colombier if(n++ >= 5){ 6745e96a66cSDavid du Colombier consPrint("giving up\n"); 6755e96a66cSDavid du Colombier break; 6765e96a66cSDavid du Colombier } 6775e96a66cSDavid du Colombier sleep(5*1000); 6785e96a66cSDavid du Colombier } 6795e96a66cSDavid du Colombier blockPut(bb); 6805e96a66cSDavid du Colombier } 6815e96a66cSDavid du Colombier r = 1; 6825e96a66cSDavid du Colombier Out1: 6835e96a66cSDavid du Colombier blockPut(b); 6845e96a66cSDavid du Colombier Out0: 6855e96a66cSDavid du Colombier vtRUnlock(fs->elk); 6865e96a66cSDavid du Colombier 6875e96a66cSDavid du Colombier return r; 6885e96a66cSDavid du Colombier } 6895e96a66cSDavid du Colombier 6905e96a66cSDavid du Colombier /* 6915e96a66cSDavid du Colombier * Inspect and edit the blocks on disk. 6925e96a66cSDavid du Colombier */ 6935e96a66cSDavid du Colombier static int 6945e96a66cSDavid du Colombier fsysBlock(Fsys* fsys, int argc, char* argv[]) 6955e96a66cSDavid du Colombier { 6965e96a66cSDavid du Colombier Fs *fs; 6975e96a66cSDavid du Colombier char *s; 6985e96a66cSDavid du Colombier Block *b; 6995e96a66cSDavid du Colombier uchar *buf; 7005e96a66cSDavid du Colombier u32int addr; 7015e96a66cSDavid du Colombier int c, count, i, offset; 7025e96a66cSDavid du Colombier char *usage = "usage: [fsys name] block addr offset [count [data]]"; 7035e96a66cSDavid du Colombier 7045e96a66cSDavid du Colombier ARGBEGIN{ 7055e96a66cSDavid du Colombier default: 7065e96a66cSDavid du Colombier return cliError(usage); 7075e96a66cSDavid du Colombier }ARGEND 7085e96a66cSDavid du Colombier if(argc < 2 || argc > 4) 7095e96a66cSDavid du Colombier return cliError(usage); 7105e96a66cSDavid du Colombier 7115e96a66cSDavid du Colombier fs = fsys->fs; 7125e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 7135e96a66cSDavid du Colombier offset = strtoul(argv[1], 0, 0); 7145e96a66cSDavid du Colombier if(offset < 0 || offset >= fs->blockSize){ 7155e96a66cSDavid du Colombier vtSetError("bad offset"); 7165e96a66cSDavid du Colombier return 0; 7175e96a66cSDavid du Colombier } 7185e96a66cSDavid du Colombier if(argc > 2) 7195e96a66cSDavid du Colombier count = strtoul(argv[2], 0, 0); 7205e96a66cSDavid du Colombier else 7215e96a66cSDavid du Colombier count = 100000000; 7225e96a66cSDavid du Colombier if(offset+count > fs->blockSize) 7235e96a66cSDavid du Colombier count = fs->blockSize - count; 7245e96a66cSDavid du Colombier 7255e96a66cSDavid du Colombier vtRLock(fs->elk); 7265e96a66cSDavid du Colombier 7275e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 7285e96a66cSDavid du Colombier if(b == nil){ 7295e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 7305e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7315e96a66cSDavid du Colombier return 0; 7325e96a66cSDavid du Colombier } 7335e96a66cSDavid du Colombier 7345e96a66cSDavid du Colombier consPrint("\t%sblock %#ux %ud %ud %.*H\n", 7355e96a66cSDavid du Colombier argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset); 7365e96a66cSDavid du Colombier 7375e96a66cSDavid du Colombier if(argc == 4){ 7385e96a66cSDavid du Colombier s = argv[3]; 7395e96a66cSDavid du Colombier if(strlen(s) != 2*count){ 7405e96a66cSDavid du Colombier vtSetError("bad data count"); 7415e96a66cSDavid du Colombier goto Out; 7425e96a66cSDavid du Colombier } 7435e96a66cSDavid du Colombier buf = vtMemAllocZ(count); 7445e96a66cSDavid du Colombier for(i = 0; i < count*2; i++){ 7455e96a66cSDavid du Colombier if(s[i] >= '0' && s[i] <= '9') 7465e96a66cSDavid du Colombier c = s[i] - '0'; 7475e96a66cSDavid du Colombier else if(s[i] >= 'a' && s[i] <= 'f') 7485e96a66cSDavid du Colombier c = s[i] - 'a' + 10; 7495e96a66cSDavid du Colombier else if(s[i] >= 'A' && s[i] <= 'F') 7505e96a66cSDavid du Colombier c = s[i] - 'A' + 10; 7515e96a66cSDavid du Colombier else{ 7525e96a66cSDavid du Colombier vtSetError("bad hex"); 7535e96a66cSDavid du Colombier vtMemFree(buf); 7545e96a66cSDavid du Colombier goto Out; 7555e96a66cSDavid du Colombier } 7565e96a66cSDavid du Colombier if((i & 1) == 0) 7575e96a66cSDavid du Colombier c <<= 4; 7585e96a66cSDavid du Colombier buf[i>>1] |= c; 7595e96a66cSDavid du Colombier } 7605e96a66cSDavid du Colombier memmove(b->data+offset, buf, count); 7615e96a66cSDavid du Colombier consPrint("\tnew: block %#ux %ud %ud %.*H\n", 7625e96a66cSDavid du Colombier addr, offset, count, count, b->data+offset); 7635e96a66cSDavid du Colombier blockDirty(b); 7645e96a66cSDavid du Colombier } 7655e96a66cSDavid du Colombier 7665e96a66cSDavid du Colombier Out: 7675e96a66cSDavid du Colombier blockPut(b); 7685e96a66cSDavid du Colombier vtRUnlock(fs->elk); 7695e96a66cSDavid du Colombier 7705e96a66cSDavid du Colombier return 1; 7715e96a66cSDavid du Colombier } 7725e96a66cSDavid du Colombier 7735e96a66cSDavid du Colombier /* 7745e96a66cSDavid du Colombier * Free a disk block. 7755e96a66cSDavid du Colombier */ 7765e96a66cSDavid du Colombier static int 7775e96a66cSDavid du Colombier fsysBfree(Fsys* fsys, int argc, char* argv[]) 7785e96a66cSDavid du Colombier { 7795e96a66cSDavid du Colombier Fs *fs; 7805e96a66cSDavid du Colombier Label l; 7815e96a66cSDavid du Colombier char *p; 7825e96a66cSDavid du Colombier Block *b; 7835e96a66cSDavid du Colombier u32int addr; 7845e96a66cSDavid du Colombier char *usage = "usage: [fsys name] bfree addr ..."; 7855e96a66cSDavid du Colombier 7865e96a66cSDavid du Colombier ARGBEGIN{ 7875e96a66cSDavid du Colombier default: 7885e96a66cSDavid du Colombier return cliError(usage); 7895e96a66cSDavid du Colombier }ARGEND 7905e96a66cSDavid du Colombier if(argc == 0) 7915e96a66cSDavid du Colombier return cliError(usage); 7925e96a66cSDavid du Colombier 7935e96a66cSDavid du Colombier fs = fsys->fs; 7945e96a66cSDavid du Colombier vtRLock(fs->elk); 7955e96a66cSDavid du Colombier while(argc > 0){ 7965e96a66cSDavid du Colombier addr = strtoul(argv[0], &p, 0); 7975e96a66cSDavid du Colombier if(*p != '\0'){ 7980c6300e7SDavid du Colombier consPrint("bad address - '%ud'\n", addr); 7995e96a66cSDavid du Colombier /* syntax error; let's stop */ 8005e96a66cSDavid du Colombier vtRUnlock(fs->elk); 8015e96a66cSDavid du Colombier return 0; 8025e96a66cSDavid du Colombier } 8035e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, OReadOnly); 8045e96a66cSDavid du Colombier if(b == nil){ 8055e96a66cSDavid du Colombier consPrint("loading %#ux: %R\n", addr); 8065e96a66cSDavid du Colombier continue; 8075e96a66cSDavid du Colombier } 8085e96a66cSDavid du Colombier l = b->l; 809e569ccb5SDavid du Colombier if(l.state == BsFree) 810e569ccb5SDavid du Colombier consPrint("%#ux is already free\n", addr); 811e569ccb5SDavid du Colombier else{ 8125e96a66cSDavid du Colombier consPrint("label %#ux %ud %ud %ud %ud %#x\n", 8135e96a66cSDavid du Colombier addr, l.type, l.state, l.epoch, l.epochClose, l.tag); 8145e96a66cSDavid du Colombier l.state = BsFree; 8155e96a66cSDavid du Colombier l.type = BtMax; 8165e96a66cSDavid du Colombier l.tag = 0; 8175e96a66cSDavid du Colombier l.epoch = 0; 8185e96a66cSDavid du Colombier l.epochClose = 0; 819e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0)) 8205e96a66cSDavid du Colombier consPrint("freeing %#ux: %R\n", addr); 821e569ccb5SDavid du Colombier } 8225e96a66cSDavid du Colombier blockPut(b); 8235e96a66cSDavid du Colombier argc--; 8245e96a66cSDavid du Colombier argv++; 8255e96a66cSDavid du Colombier } 8265e96a66cSDavid du Colombier vtRUnlock(fs->elk); 8275e96a66cSDavid du Colombier 8285e96a66cSDavid du Colombier return 1; 8295e96a66cSDavid du Colombier } 8305e96a66cSDavid du Colombier 8317abd426fSDavid du Colombier static int 8327abd426fSDavid du Colombier fsysDf(Fsys *fsys, int argc, char* argv[]) 8337abd426fSDavid du Colombier { 8347abd426fSDavid du Colombier char *usage = "usage: [fsys name] df"; 8357abd426fSDavid du Colombier u32int used, tot, bsize; 8367abd426fSDavid du Colombier Fs *fs; 8377abd426fSDavid du Colombier 8387abd426fSDavid du Colombier ARGBEGIN{ 8397abd426fSDavid du Colombier default: 8407abd426fSDavid du Colombier return cliError(usage); 8417abd426fSDavid du Colombier }ARGEND 8427abd426fSDavid du Colombier if(argc != 0) 8437abd426fSDavid du Colombier return cliError(usage); 8447abd426fSDavid du Colombier 8457abd426fSDavid du Colombier fs = fsys->fs; 8467abd426fSDavid du Colombier cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize); 8470c6300e7SDavid du Colombier consPrint("\t%s: %,llud used + %,llud free = %,llud (%llud%% used)\n", 848dc5a79c1SDavid du Colombier fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize, 849208510e1SDavid du Colombier tot*(vlong)bsize, used*100LL/tot); 8507abd426fSDavid du Colombier return 1; 8517abd426fSDavid du Colombier } 8527abd426fSDavid du Colombier 8535e96a66cSDavid du Colombier /* 8545e96a66cSDavid du Colombier * Zero an entry or a pointer. 8555e96a66cSDavid du Colombier */ 8565e96a66cSDavid du Colombier static int 8575e96a66cSDavid du Colombier fsysClrep(Fsys* fsys, int argc, char* argv[], int ch) 8585e96a66cSDavid du Colombier { 8595e96a66cSDavid du Colombier Fs *fs; 8605e96a66cSDavid du Colombier Entry e; 8615e96a66cSDavid du Colombier Block *b; 8625e96a66cSDavid du Colombier u32int addr; 8635e96a66cSDavid du Colombier int i, max, offset, sz; 8645e96a66cSDavid du Colombier uchar zero[VtEntrySize]; 8655e96a66cSDavid du Colombier char *usage = "usage: [fsys name] clr%c addr offset ..."; 8665e96a66cSDavid du Colombier 8675e96a66cSDavid du Colombier ARGBEGIN{ 8685e96a66cSDavid du Colombier default: 8695e96a66cSDavid du Colombier return cliError(usage, ch); 8705e96a66cSDavid du Colombier }ARGEND 8715e96a66cSDavid du Colombier if(argc < 2) 8725e96a66cSDavid du Colombier return cliError(usage, ch); 8735e96a66cSDavid du Colombier 8745e96a66cSDavid du Colombier fs = fsys->fs; 8755e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 8765e96a66cSDavid du Colombier 8775e96a66cSDavid du Colombier addr = strtoul(argv[0], 0, 0); 8785e96a66cSDavid du Colombier b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly); 8795e96a66cSDavid du Colombier if(b == nil){ 8805e96a66cSDavid du Colombier vtSetError("cacheLocal %#ux: %R", addr); 8815e96a66cSDavid du Colombier Err: 8825e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 8835e96a66cSDavid du Colombier return 0; 8845e96a66cSDavid du Colombier } 8855e96a66cSDavid du Colombier 8865e96a66cSDavid du Colombier switch(ch){ 8875e96a66cSDavid du Colombier default: 8885e96a66cSDavid du Colombier vtSetError("clrep"); 8895e96a66cSDavid du Colombier goto Err; 8905e96a66cSDavid du Colombier case 'e': 8915e96a66cSDavid du Colombier if(b->l.type != BtDir){ 8925e96a66cSDavid du Colombier vtSetError("wrong block type"); 8935e96a66cSDavid du Colombier goto Err; 8945e96a66cSDavid du Colombier } 8955e96a66cSDavid du Colombier sz = VtEntrySize; 8965e96a66cSDavid du Colombier memset(&e, 0, sizeof e); 8975e96a66cSDavid du Colombier entryPack(&e, zero, 0); 8985e96a66cSDavid du Colombier break; 8995e96a66cSDavid du Colombier case 'p': 9005e96a66cSDavid du Colombier if(b->l.type == BtDir || b->l.type == BtData){ 9015e96a66cSDavid du Colombier vtSetError("wrong block type"); 9025e96a66cSDavid du Colombier goto Err; 9035e96a66cSDavid du Colombier } 9045e96a66cSDavid du Colombier sz = VtScoreSize; 9055e96a66cSDavid du Colombier memmove(zero, vtZeroScore, VtScoreSize); 9065e96a66cSDavid du Colombier break; 9075e96a66cSDavid du Colombier } 9085e96a66cSDavid du Colombier max = fs->blockSize/sz; 9095e96a66cSDavid du Colombier 9105e96a66cSDavid du Colombier for(i = 1; i < argc; i++){ 9115e96a66cSDavid du Colombier offset = atoi(argv[i]); 9125e96a66cSDavid du Colombier if(offset >= max){ 9135e96a66cSDavid du Colombier consPrint("\toffset %d too large (>= %d)\n", i, max); 9145e96a66cSDavid du Colombier continue; 9155e96a66cSDavid du Colombier } 9165e96a66cSDavid du Colombier consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz); 9175e96a66cSDavid du Colombier memmove(b->data+offset*sz, zero, sz); 9185e96a66cSDavid du Colombier } 9195e96a66cSDavid du Colombier blockDirty(b); 9205e96a66cSDavid du Colombier blockPut(b); 9215e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 9225e96a66cSDavid du Colombier 9235e96a66cSDavid du Colombier return 1; 9245e96a66cSDavid du Colombier } 9255e96a66cSDavid du Colombier 9265e96a66cSDavid du Colombier static int 9275e96a66cSDavid du Colombier fsysClre(Fsys* fsys, int argc, char* argv[]) 9285e96a66cSDavid du Colombier { 9295e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'e'); 9305e96a66cSDavid du Colombier } 9315e96a66cSDavid du Colombier 9325e96a66cSDavid du Colombier static int 9335e96a66cSDavid du Colombier fsysClrp(Fsys* fsys, int argc, char* argv[]) 9345e96a66cSDavid du Colombier { 9355e96a66cSDavid du Colombier return fsysClrep(fsys, argc, argv, 'p'); 9365e96a66cSDavid du Colombier } 9375e96a66cSDavid du Colombier 9385e96a66cSDavid du Colombier static int 9395e96a66cSDavid du Colombier fsysEsearch1(File* f, char* s, u32int elo) 9405e96a66cSDavid du Colombier { 9415e96a66cSDavid du Colombier int n, r; 9425e96a66cSDavid du Colombier DirEntry de; 9435e96a66cSDavid du Colombier DirEntryEnum *dee; 9445e96a66cSDavid du Colombier File *ff; 9455e96a66cSDavid du Colombier Entry e, ee; 9465e96a66cSDavid du Colombier char *t; 9475e96a66cSDavid du Colombier 9485e96a66cSDavid du Colombier dee = deeOpen(f); 9495e96a66cSDavid du Colombier if(dee == nil) 9505e96a66cSDavid du Colombier return 0; 9515e96a66cSDavid du Colombier 9525e96a66cSDavid du Colombier n = 0; 9535e96a66cSDavid du Colombier for(;;){ 9545e96a66cSDavid du Colombier r = deeRead(dee, &de); 9555e96a66cSDavid du Colombier if(r < 0){ 9565e96a66cSDavid du Colombier consPrint("\tdeeRead %s/%s: %R\n", s, de.elem); 9575e96a66cSDavid du Colombier break; 9585e96a66cSDavid du Colombier } 9595e96a66cSDavid du Colombier if(r == 0) 9605e96a66cSDavid du Colombier break; 9615e96a66cSDavid du Colombier if(de.mode & ModeSnapshot){ 9625e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 9635e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 9645e96a66cSDavid du Colombier else{ 965e569ccb5SDavid du Colombier if(!fileGetSources(ff, &e, &ee)) 9665e96a66cSDavid du Colombier consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem); 9675e96a66cSDavid du Colombier else if(e.snap != 0 && e.snap < elo){ 9685e96a66cSDavid du Colombier consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem); 9695e96a66cSDavid du Colombier n++; 9705e96a66cSDavid du Colombier } 9715e96a66cSDavid du Colombier fileDecRef(ff); 9725e96a66cSDavid du Colombier } 9735e96a66cSDavid du Colombier } 9745e96a66cSDavid du Colombier else if(de.mode & ModeDir){ 9755e96a66cSDavid du Colombier if((ff = fileWalk(f, de.elem)) == nil) 9765e96a66cSDavid du Colombier consPrint("\tcannot walk %s/%s: %R\n", s, de.elem); 9775e96a66cSDavid du Colombier else{ 978f8e525acSDavid du Colombier t = smprint("%s/%s", s, de.elem); 9795e96a66cSDavid du Colombier n += fsysEsearch1(ff, t, elo); 9805e96a66cSDavid du Colombier vtMemFree(t); 9815e96a66cSDavid du Colombier fileDecRef(ff); 9825e96a66cSDavid du Colombier } 9835e96a66cSDavid du Colombier } 9845e96a66cSDavid du Colombier deCleanup(&de); 9855e96a66cSDavid du Colombier if(r < 0) 9865e96a66cSDavid du Colombier break; 9875e96a66cSDavid du Colombier } 9885e96a66cSDavid du Colombier deeClose(dee); 9895e96a66cSDavid du Colombier 9905e96a66cSDavid du Colombier return n; 9915e96a66cSDavid du Colombier } 9925e96a66cSDavid du Colombier 9935e96a66cSDavid du Colombier static int 9945e96a66cSDavid du Colombier fsysEsearch(Fs* fs, char* path, u32int elo) 9955e96a66cSDavid du Colombier { 9965e96a66cSDavid du Colombier int n; 9975e96a66cSDavid du Colombier File *f; 9985e96a66cSDavid du Colombier DirEntry de; 9995e96a66cSDavid du Colombier 10005e96a66cSDavid du Colombier f = fileOpen(fs, path); 10015e96a66cSDavid du Colombier if(f == nil) 10025e96a66cSDavid du Colombier return 0; 10035e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 10045e96a66cSDavid du Colombier consPrint("\tfileGetDir %s failed: %R\n", path); 10055e96a66cSDavid du Colombier fileDecRef(f); 10065e96a66cSDavid du Colombier return 0; 10075e96a66cSDavid du Colombier } 10085e96a66cSDavid du Colombier if((de.mode & ModeDir) == 0){ 10095e96a66cSDavid du Colombier fileDecRef(f); 10105e96a66cSDavid du Colombier deCleanup(&de); 10115e96a66cSDavid du Colombier return 0; 10125e96a66cSDavid du Colombier } 10135e96a66cSDavid du Colombier deCleanup(&de); 10145e96a66cSDavid du Colombier n = fsysEsearch1(f, path, elo); 10155e96a66cSDavid du Colombier fileDecRef(f); 10165e96a66cSDavid du Colombier return n; 10175e96a66cSDavid du Colombier } 10185e96a66cSDavid du Colombier 10195e96a66cSDavid du Colombier static int 10205e96a66cSDavid du Colombier fsysEpoch(Fsys* fsys, int argc, char* argv[]) 10215e96a66cSDavid du Colombier { 10225e96a66cSDavid du Colombier Fs *fs; 1023dc5a79c1SDavid du Colombier int force, n, remove; 10245e96a66cSDavid du Colombier u32int low, old; 1025dc5a79c1SDavid du Colombier char *usage = "usage: [fsys name] epoch [[-ry] low]"; 10265e96a66cSDavid du Colombier 10275e96a66cSDavid du Colombier force = 0; 1028dc5a79c1SDavid du Colombier remove = 0; 10295e96a66cSDavid du Colombier ARGBEGIN{ 10305e96a66cSDavid du Colombier case 'y': 10315e96a66cSDavid du Colombier force = 1; 10325e96a66cSDavid du Colombier break; 1033dc5a79c1SDavid du Colombier case 'r': 1034dc5a79c1SDavid du Colombier remove = 1; 1035dc5a79c1SDavid du Colombier break; 10365e96a66cSDavid du Colombier default: 10375e96a66cSDavid du Colombier return cliError(usage); 10385e96a66cSDavid du Colombier }ARGEND 10395e96a66cSDavid du Colombier if(argc > 1) 10405e96a66cSDavid du Colombier return cliError(usage); 10415e96a66cSDavid du Colombier if(argc > 0) 10425e96a66cSDavid du Colombier low = strtoul(argv[0], 0, 0); 10435e96a66cSDavid du Colombier else 10445e96a66cSDavid du Colombier low = ~(u32int)0; 10455e96a66cSDavid du Colombier 10468a2c5ad0SDavid du Colombier if(low == 0) 10478a2c5ad0SDavid du Colombier return cliError("low epoch cannot be zero"); 10488a2c5ad0SDavid du Colombier 10495e96a66cSDavid du Colombier fs = fsys->fs; 10505e96a66cSDavid du Colombier 10515e96a66cSDavid du Colombier vtRLock(fs->elk); 10525e96a66cSDavid du Colombier consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi); 105357195852SDavid du Colombier if(low == ~(u32int)0){ 105457195852SDavid du Colombier vtRUnlock(fs->elk); 105557195852SDavid du Colombier return 1; 105657195852SDavid du Colombier } 10575e96a66cSDavid du Colombier n = fsysEsearch(fsys->fs, "/archive", low); 10585e96a66cSDavid du Colombier n += fsysEsearch(fsys->fs, "/snapshot", low); 10595e96a66cSDavid du Colombier consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low); 10605e96a66cSDavid du Colombier vtRUnlock(fs->elk); 10615e96a66cSDavid du Colombier 10625e96a66cSDavid du Colombier /* 10635e96a66cSDavid du Colombier * There's a small race here -- a new snapshot with epoch < low might 10645e96a66cSDavid du Colombier * get introduced now that we unlocked fs->elk. Low has to 10655e96a66cSDavid du Colombier * be <= fs->ehi. Of course, in order for this to happen low has 10665e96a66cSDavid du Colombier * to be equal to the current fs->ehi _and_ a snapshot has to 10675e96a66cSDavid du Colombier * run right now. This is a small enough window that I don't care. 10685e96a66cSDavid du Colombier */ 10695e96a66cSDavid du Colombier if(n != 0 && !force){ 10705e96a66cSDavid du Colombier consPrint("\tnot setting low epoch\n"); 10715e96a66cSDavid du Colombier return 1; 10725e96a66cSDavid du Colombier } 10735e96a66cSDavid du Colombier old = fs->elo; 10745e96a66cSDavid du Colombier if(!fsEpochLow(fs, low)) 10755e96a66cSDavid du Colombier consPrint("\tfsEpochLow: %R\n"); 10765e96a66cSDavid du Colombier else{ 10775e96a66cSDavid du Colombier consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old); 10785e96a66cSDavid du Colombier consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo); 10795e96a66cSDavid du Colombier if(fs->elo < low) 10805e96a66cSDavid du Colombier consPrint("\twarning: new low epoch < old low epoch\n"); 1081dc5a79c1SDavid du Colombier if(force && remove) 1082dc5a79c1SDavid du Colombier fsSnapshotRemove(fs); 10835e96a66cSDavid du Colombier } 10845e96a66cSDavid du Colombier 10855e96a66cSDavid du Colombier return 1; 10865e96a66cSDavid du Colombier } 10875e96a66cSDavid du Colombier 10885e96a66cSDavid du Colombier static int 10895e96a66cSDavid du Colombier fsysCreate(Fsys* fsys, int argc, char* argv[]) 10905e96a66cSDavid du Colombier { 10915e96a66cSDavid du Colombier int r; 10925e96a66cSDavid du Colombier ulong mode; 10935e96a66cSDavid du Colombier char *elem, *p, *path; 10945e96a66cSDavid du Colombier char *usage = "usage: [fsys name] create path uid gid perm"; 10955e96a66cSDavid du Colombier DirEntry de; 10965e96a66cSDavid du Colombier File *file, *parent; 10975e96a66cSDavid du Colombier 10985e96a66cSDavid du Colombier ARGBEGIN{ 10995e96a66cSDavid du Colombier default: 11005e96a66cSDavid du Colombier return cliError(usage); 11015e96a66cSDavid du Colombier }ARGEND 11025e96a66cSDavid du Colombier if(argc != 4) 11035e96a66cSDavid du Colombier return cliError(usage); 11045e96a66cSDavid du Colombier 11055e96a66cSDavid du Colombier if(!fsysParseMode(argv[3], &mode)) 11065e96a66cSDavid du Colombier return cliError(usage); 11075e96a66cSDavid du Colombier if(mode&ModeSnapshot) 11085e96a66cSDavid du Colombier return cliError("create - cannot create with snapshot bit set"); 11095e96a66cSDavid du Colombier 11105e96a66cSDavid du Colombier if(strcmp(argv[1], uidnoworld) == 0) 11115e96a66cSDavid du Colombier return cliError("permission denied"); 11125e96a66cSDavid du Colombier 11135e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 11145e96a66cSDavid du Colombier path = vtStrDup(argv[0]); 11155e96a66cSDavid du Colombier if((p = strrchr(path, '/')) != nil){ 11165e96a66cSDavid du Colombier *p++ = '\0'; 11175e96a66cSDavid du Colombier elem = p; 11185e96a66cSDavid du Colombier p = path; 11195e96a66cSDavid du Colombier if(*p == '\0') 11205e96a66cSDavid du Colombier p = "/"; 11215e96a66cSDavid du Colombier } 11225e96a66cSDavid du Colombier else{ 11235e96a66cSDavid du Colombier p = "/"; 11245e96a66cSDavid du Colombier elem = path; 11255e96a66cSDavid du Colombier } 1126f8e525acSDavid du Colombier 11275e96a66cSDavid du Colombier r = 0; 1128f8e525acSDavid du Colombier if((parent = fileOpen(fsys->fs, p)) == nil) 1129f8e525acSDavid du Colombier goto out; 1130f8e525acSDavid du Colombier 11315e96a66cSDavid du Colombier file = fileCreate(parent, elem, mode, argv[1]); 11325e96a66cSDavid du Colombier fileDecRef(parent); 1133f8e525acSDavid du Colombier if(file == nil){ 1134f8e525acSDavid du Colombier vtSetError("create %s/%s: %R", p, elem); 1135f8e525acSDavid du Colombier goto out; 1136f8e525acSDavid du Colombier } 1137f8e525acSDavid du Colombier 1138f8e525acSDavid du Colombier if(!fileGetDir(file, &de)){ 1139f8e525acSDavid du Colombier vtSetError("stat failed after create: %R"); 1140f8e525acSDavid du Colombier goto out1; 1141f8e525acSDavid du Colombier } 1142f8e525acSDavid du Colombier 11435e96a66cSDavid du Colombier if(strcmp(de.gid, argv[2]) != 0){ 11445e96a66cSDavid du Colombier vtMemFree(de.gid); 11455e96a66cSDavid du Colombier de.gid = vtStrDup(argv[2]); 1146f8e525acSDavid du Colombier if(!fileSetDir(file, &de, argv[1])){ 1147f8e525acSDavid du Colombier vtSetError("wstat failed after create: %R"); 1148f8e525acSDavid du Colombier goto out2; 11495e96a66cSDavid du Colombier } 1150f8e525acSDavid du Colombier } 1151f8e525acSDavid du Colombier r = 1; 1152f8e525acSDavid du Colombier 1153f8e525acSDavid du Colombier out2: 11545e96a66cSDavid du Colombier deCleanup(&de); 1155f8e525acSDavid du Colombier out1: 11565e96a66cSDavid du Colombier fileDecRef(file); 1157f8e525acSDavid du Colombier out: 11585e96a66cSDavid du Colombier vtMemFree(path); 11595e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 11605e96a66cSDavid du Colombier 11615e96a66cSDavid du Colombier return r; 11625e96a66cSDavid du Colombier } 11635e96a66cSDavid du Colombier 11645e96a66cSDavid du Colombier static void 11655e96a66cSDavid du Colombier fsysPrintStat(char *prefix, char *file, DirEntry *de) 11665e96a66cSDavid du Colombier { 11675e96a66cSDavid du Colombier char buf[64]; 11685e96a66cSDavid du Colombier 11695e96a66cSDavid du Colombier if(prefix == nil) 11705e96a66cSDavid du Colombier prefix = ""; 11715e96a66cSDavid du Colombier consPrint("%sstat %q %q %q %q %s %llud\n", prefix, 11725e96a66cSDavid du Colombier file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size); 11735e96a66cSDavid du Colombier } 11745e96a66cSDavid du Colombier 11755e96a66cSDavid du Colombier static int 11765e96a66cSDavid du Colombier fsysStat(Fsys* fsys, int argc, char* argv[]) 11775e96a66cSDavid du Colombier { 11785e96a66cSDavid du Colombier int i; 11795e96a66cSDavid du Colombier File *f; 11805e96a66cSDavid du Colombier DirEntry de; 11815e96a66cSDavid du Colombier char *usage = "usage: [fsys name] stat files..."; 11825e96a66cSDavid du Colombier 11835e96a66cSDavid du Colombier ARGBEGIN{ 11845e96a66cSDavid du Colombier default: 11855e96a66cSDavid du Colombier return cliError(usage); 11865e96a66cSDavid du Colombier }ARGEND 11875e96a66cSDavid du Colombier 11885e96a66cSDavid du Colombier if(argc == 0) 11895e96a66cSDavid du Colombier return cliError(usage); 11905e96a66cSDavid du Colombier 11915e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 11925e96a66cSDavid du Colombier for(i=0; i<argc; i++){ 11935e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[i])) == nil){ 11940c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]); 11955e96a66cSDavid du Colombier continue; 11965e96a66cSDavid du Colombier } 11975e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 11980c6300e7SDavid du Colombier consPrint("%s: %R\n", argv[i]); 11995e96a66cSDavid du Colombier fileDecRef(f); 12005e96a66cSDavid du Colombier continue; 12015e96a66cSDavid du Colombier } 12025e96a66cSDavid du Colombier fsysPrintStat("\t", argv[i], &de); 12035e96a66cSDavid du Colombier deCleanup(&de); 12045e96a66cSDavid du Colombier fileDecRef(f); 12055e96a66cSDavid du Colombier } 12065e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12075e96a66cSDavid du Colombier return 1; 12085e96a66cSDavid du Colombier } 12095e96a66cSDavid du Colombier 12105e96a66cSDavid du Colombier static int 12115e96a66cSDavid du Colombier fsysWstat(Fsys *fsys, int argc, char* argv[]) 12125e96a66cSDavid du Colombier { 12135e96a66cSDavid du Colombier File *f; 12145e96a66cSDavid du Colombier char *p; 12155e96a66cSDavid du Colombier DirEntry de; 12165e96a66cSDavid du Colombier char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n" 12175e96a66cSDavid du Colombier "\tuse - for any field to mean don't change"; 12185e96a66cSDavid du Colombier 12195e96a66cSDavid du Colombier ARGBEGIN{ 12205e96a66cSDavid du Colombier default: 12215e96a66cSDavid du Colombier return cliError(usage); 12225e96a66cSDavid du Colombier }ARGEND 12235e96a66cSDavid du Colombier 12245e96a66cSDavid du Colombier if(argc != 6) 12255e96a66cSDavid du Colombier return cliError(usage); 12265e96a66cSDavid du Colombier 12275e96a66cSDavid du Colombier vtRLock(fsys->fs->elk); 12285e96a66cSDavid du Colombier if((f = fileOpen(fsys->fs, argv[0])) == nil){ 12295e96a66cSDavid du Colombier vtSetError("console wstat - walk - %R"); 12305e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12315e96a66cSDavid du Colombier return 0; 12325e96a66cSDavid du Colombier } 12335e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 12345e96a66cSDavid du Colombier vtSetError("console wstat - stat - %R"); 12355e96a66cSDavid du Colombier fileDecRef(f); 12365e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12375e96a66cSDavid du Colombier return 0; 12385e96a66cSDavid du Colombier } 12395e96a66cSDavid du Colombier fsysPrintStat("\told: w", argv[0], &de); 12405e96a66cSDavid du Colombier 12415e96a66cSDavid du Colombier if(strcmp(argv[1], "-") != 0){ 12425e96a66cSDavid du Colombier if(!validFileName(argv[1])){ 12435e96a66cSDavid du Colombier vtSetError("console wstat - bad elem"); 12445e96a66cSDavid du Colombier goto error; 12455e96a66cSDavid du Colombier } 12465e96a66cSDavid du Colombier vtMemFree(de.elem); 12475e96a66cSDavid du Colombier de.elem = vtStrDup(argv[1]); 12485e96a66cSDavid du Colombier } 12495e96a66cSDavid du Colombier if(strcmp(argv[2], "-") != 0){ 12505e96a66cSDavid du Colombier if(!validUserName(argv[2])){ 12515e96a66cSDavid du Colombier vtSetError("console wstat - bad uid"); 12525e96a66cSDavid du Colombier goto error; 12535e96a66cSDavid du Colombier } 12545e96a66cSDavid du Colombier vtMemFree(de.uid); 12555e96a66cSDavid du Colombier de.uid = vtStrDup(argv[2]); 12565e96a66cSDavid du Colombier } 12575e96a66cSDavid du Colombier if(strcmp(argv[3], "-") != 0){ 12585e96a66cSDavid du Colombier if(!validUserName(argv[3])){ 12595e96a66cSDavid du Colombier vtSetError("console wstat - bad gid"); 12605e96a66cSDavid du Colombier goto error; 12615e96a66cSDavid du Colombier } 12625e96a66cSDavid du Colombier vtMemFree(de.gid); 12635e96a66cSDavid du Colombier de.gid = vtStrDup(argv[3]); 12645e96a66cSDavid du Colombier } 12655e96a66cSDavid du Colombier if(strcmp(argv[4], "-") != 0){ 12665e96a66cSDavid du Colombier if(!fsysParseMode(argv[4], &de.mode)){ 12675e96a66cSDavid du Colombier vtSetError("console wstat - bad mode"); 12685e96a66cSDavid du Colombier goto error; 12695e96a66cSDavid du Colombier } 12705e96a66cSDavid du Colombier } 12715e96a66cSDavid du Colombier if(strcmp(argv[5], "-") != 0){ 12725e96a66cSDavid du Colombier de.size = strtoull(argv[5], &p, 0); 127322a127bbSDavid du Colombier if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){ 12745e96a66cSDavid du Colombier vtSetError("console wstat - bad length"); 12755e96a66cSDavid du Colombier goto error; 12765e96a66cSDavid du Colombier } 12775e96a66cSDavid du Colombier } 12785e96a66cSDavid du Colombier 12795e96a66cSDavid du Colombier if(!fileSetDir(f, &de, uidadm)){ 12805e96a66cSDavid du Colombier vtSetError("console wstat - %R"); 12815e96a66cSDavid du Colombier goto error; 12825e96a66cSDavid du Colombier } 12835e96a66cSDavid du Colombier deCleanup(&de); 12845e96a66cSDavid du Colombier 12855e96a66cSDavid du Colombier if(!fileGetDir(f, &de)){ 12865e96a66cSDavid du Colombier vtSetError("console wstat - stat2 - %R"); 12875e96a66cSDavid du Colombier goto error; 12885e96a66cSDavid du Colombier } 12895e96a66cSDavid du Colombier fsysPrintStat("\tnew: w", argv[0], &de); 12905e96a66cSDavid du Colombier deCleanup(&de); 12915e96a66cSDavid du Colombier fileDecRef(f); 12925e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 12935e96a66cSDavid du Colombier 12945e96a66cSDavid du Colombier return 1; 12955e96a66cSDavid du Colombier 12965e96a66cSDavid du Colombier error: 12975e96a66cSDavid du Colombier deCleanup(&de); /* okay to do this twice */ 12985e96a66cSDavid du Colombier fileDecRef(f); 12995e96a66cSDavid du Colombier vtRUnlock(fsys->fs->elk); 13005e96a66cSDavid du Colombier return 0; 13015e96a66cSDavid du Colombier } 13025e96a66cSDavid du Colombier 1303e569ccb5SDavid du Colombier static void 1304e569ccb5SDavid du Colombier fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b) 1305e569ccb5SDavid du Colombier { 1306e569ccb5SDavid du Colombier USED(name); 1307e569ccb5SDavid du Colombier 1308e569ccb5SDavid du Colombier if((fsck->flags&DoClri) == 0) 1309e569ccb5SDavid du Colombier return; 1310e569ccb5SDavid du Colombier 1311e569ccb5SDavid du Colombier mbDelete(mb, i); 1312e569ccb5SDavid du Colombier mbPack(mb); 1313e569ccb5SDavid du Colombier blockDirty(b); 1314e569ccb5SDavid du Colombier } 1315e569ccb5SDavid du Colombier 1316e569ccb5SDavid du Colombier static void 1317e569ccb5SDavid du Colombier fsckClose(Fsck *fsck, Block *b, u32int epoch) 1318e569ccb5SDavid du Colombier { 1319e569ccb5SDavid du Colombier Label l; 1320e569ccb5SDavid du Colombier 1321e569ccb5SDavid du Colombier if((fsck->flags&DoClose) == 0) 1322e569ccb5SDavid du Colombier return; 1323e569ccb5SDavid du Colombier l = b->l; 1324e569ccb5SDavid du Colombier if(l.state == BsFree || (l.state&BsClosed)){ 1325e569ccb5SDavid du Colombier consPrint("%#ux is already closed\n", b->addr); 1326e569ccb5SDavid du Colombier return; 1327e569ccb5SDavid du Colombier } 1328e569ccb5SDavid du Colombier if(epoch){ 1329e569ccb5SDavid du Colombier l.state |= BsClosed; 1330e569ccb5SDavid du Colombier l.epochClose = epoch; 1331e569ccb5SDavid du Colombier }else 1332e569ccb5SDavid du Colombier l.state = BsFree; 1333e569ccb5SDavid du Colombier 1334e569ccb5SDavid du Colombier if(!blockSetLabel(b, &l, 0)) 1335e569ccb5SDavid du Colombier consPrint("%#ux setlabel: %R\n", b->addr); 1336e569ccb5SDavid du Colombier } 1337e569ccb5SDavid du Colombier 1338e569ccb5SDavid du Colombier static void 1339e569ccb5SDavid du Colombier fsckClre(Fsck *fsck, Block *b, int offset) 1340e569ccb5SDavid du Colombier { 1341e569ccb5SDavid du Colombier Entry e; 1342e569ccb5SDavid du Colombier 1343e569ccb5SDavid du Colombier if((fsck->flags&DoClre) == 0) 1344e569ccb5SDavid du Colombier return; 1345e569ccb5SDavid du Colombier if(offset<0 || offset*VtEntrySize >= fsck->bsize){ 1346e569ccb5SDavid du Colombier consPrint("bad clre\n"); 1347e569ccb5SDavid du Colombier return; 1348e569ccb5SDavid du Colombier } 1349e569ccb5SDavid du Colombier memset(&e, 0, sizeof e); 1350e569ccb5SDavid du Colombier entryPack(&e, b->data, offset); 1351e569ccb5SDavid du Colombier blockDirty(b); 1352e569ccb5SDavid du Colombier } 1353e569ccb5SDavid du Colombier 1354e569ccb5SDavid du Colombier static void 1355e569ccb5SDavid du Colombier fsckClrp(Fsck *fsck, Block *b, int offset) 1356e569ccb5SDavid du Colombier { 1357e569ccb5SDavid du Colombier if((fsck->flags&DoClrp) == 0) 1358e569ccb5SDavid du Colombier return; 1359e569ccb5SDavid du Colombier if(offset<0 || offset*VtScoreSize >= fsck->bsize){ 1360e569ccb5SDavid du Colombier consPrint("bad clre\n"); 1361e569ccb5SDavid du Colombier return; 1362e569ccb5SDavid du Colombier } 1363e569ccb5SDavid du Colombier memmove(b->data+offset*VtScoreSize, vtZeroScore, VtScoreSize); 1364e569ccb5SDavid du Colombier blockDirty(b); 1365e569ccb5SDavid du Colombier } 1366e569ccb5SDavid du Colombier 1367e569ccb5SDavid du Colombier static int 1368e569ccb5SDavid du Colombier fsysCheck(Fsys *fsys, int argc, char *argv[]) 1369e569ccb5SDavid du Colombier { 1370e569ccb5SDavid du Colombier int i, halting; 1371e569ccb5SDavid du Colombier char *usage = "usage: [fsys name] check [-v] [options]"; 1372e569ccb5SDavid du Colombier Fsck fsck; 1373e569ccb5SDavid du Colombier Block *b; 1374e569ccb5SDavid du Colombier Super super; 1375e569ccb5SDavid du Colombier 1376e569ccb5SDavid du Colombier memset(&fsck, 0, sizeof fsck); 1377e569ccb5SDavid du Colombier fsck.fs = fsys->fs; 1378e569ccb5SDavid du Colombier fsck.clri = fsckClri; 1379e569ccb5SDavid du Colombier fsck.clre = fsckClre; 1380e569ccb5SDavid du Colombier fsck.clrp = fsckClrp; 1381e569ccb5SDavid du Colombier fsck.close = fsckClose; 1382e569ccb5SDavid du Colombier fsck.print = consPrint; 1383e569ccb5SDavid du Colombier 1384e569ccb5SDavid du Colombier ARGBEGIN{ 1385e569ccb5SDavid du Colombier default: 1386e569ccb5SDavid du Colombier return cliError(usage); 1387e569ccb5SDavid du Colombier }ARGEND 1388e569ccb5SDavid du Colombier 1389e569ccb5SDavid du Colombier for(i=0; i<argc; i++){ 1390e569ccb5SDavid du Colombier if(strcmp(argv[i], "pblock") == 0) 1391e569ccb5SDavid du Colombier fsck.printblocks = 1; 1392e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pdir") == 0) 1393e569ccb5SDavid du Colombier fsck.printdirs = 1; 1394e569ccb5SDavid du Colombier else if(strcmp(argv[i], "pfile") == 0) 1395e569ccb5SDavid du Colombier fsck.printfiles = 1; 1396e569ccb5SDavid du Colombier else if(strcmp(argv[i], "bclose") == 0) 1397e569ccb5SDavid du Colombier fsck.flags |= DoClose; 1398e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clri") == 0) 1399e569ccb5SDavid du Colombier fsck.flags |= DoClri; 1400e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clre") == 0) 1401e569ccb5SDavid du Colombier fsck.flags |= DoClre; 1402e569ccb5SDavid du Colombier else if(strcmp(argv[i], "clrp") == 0) 1403e569ccb5SDavid du Colombier fsck.flags |= DoClrp; 1404e569ccb5SDavid du Colombier else if(strcmp(argv[i], "fix") == 0) 1405e569ccb5SDavid du Colombier fsck.flags |= DoClose|DoClri|DoClre|DoClrp; 1406e569ccb5SDavid du Colombier else if(strcmp(argv[i], "venti") == 0) 1407e569ccb5SDavid du Colombier fsck.useventi = 1; 1408e569ccb5SDavid du Colombier else if(strcmp(argv[i], "snapshot") == 0) 1409e569ccb5SDavid du Colombier fsck.walksnapshots = 1; 1410e569ccb5SDavid du Colombier else{ 1411e569ccb5SDavid du Colombier consPrint("unknown option '%s'\n", argv[i]); 1412e569ccb5SDavid du Colombier return cliError(usage); 1413e569ccb5SDavid du Colombier } 1414e569ccb5SDavid du Colombier } 1415e569ccb5SDavid du Colombier 1416e569ccb5SDavid du Colombier halting = fsys->fs->halted==0; 1417e569ccb5SDavid du Colombier if(halting) 1418e569ccb5SDavid du Colombier fsHalt(fsys->fs); 1419e569ccb5SDavid du Colombier if(fsys->fs->arch){ 1420e569ccb5SDavid du Colombier b = superGet(fsys->fs->cache, &super); 1421e569ccb5SDavid du Colombier if(b == nil){ 1422e569ccb5SDavid du Colombier consPrint("could not load super block\n"); 1423e569ccb5SDavid du Colombier goto Out; 1424e569ccb5SDavid du Colombier } 1425e569ccb5SDavid du Colombier blockPut(b); 1426e569ccb5SDavid du Colombier if(super.current != NilBlock){ 1427225077b0SDavid du Colombier consPrint("cannot check fs while archiver is running; " 1428225077b0SDavid du Colombier "wait for it to finish\n"); 1429e569ccb5SDavid du Colombier goto Out; 1430e569ccb5SDavid du Colombier } 1431e569ccb5SDavid du Colombier } 1432e569ccb5SDavid du Colombier fsCheck(&fsck); 1433e569ccb5SDavid du Colombier consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n", 1434e569ccb5SDavid du Colombier fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose); 1435e569ccb5SDavid du Colombier Out: 1436e569ccb5SDavid du Colombier if(halting) 1437e569ccb5SDavid du Colombier fsUnhalt(fsys->fs); 1438e569ccb5SDavid du Colombier return 1; 1439e569ccb5SDavid du Colombier } 1440e569ccb5SDavid du Colombier 14415e96a66cSDavid du Colombier static int 14425e96a66cSDavid du Colombier fsysVenti(char* name, int argc, char* argv[]) 14435e96a66cSDavid du Colombier { 14445e96a66cSDavid du Colombier int r; 14455e96a66cSDavid du Colombier char *host; 14465e96a66cSDavid du Colombier char *usage = "usage: [fsys name] venti [address]"; 14475e96a66cSDavid du Colombier Fsys *fsys; 14485e96a66cSDavid du Colombier 14495e96a66cSDavid du Colombier ARGBEGIN{ 14505e96a66cSDavid du Colombier default: 14515e96a66cSDavid du Colombier return cliError(usage); 14525e96a66cSDavid du Colombier }ARGEND 14535e96a66cSDavid du Colombier 14545e96a66cSDavid du Colombier if(argc == 0) 14555e96a66cSDavid du Colombier host = nil; 14565e96a66cSDavid du Colombier else if(argc == 1) 14575e96a66cSDavid du Colombier host = argv[0]; 14585e96a66cSDavid du Colombier else 14595e96a66cSDavid du Colombier return cliError(usage); 14605e96a66cSDavid du Colombier 14615e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 14625e96a66cSDavid du Colombier return 0; 14635e96a66cSDavid du Colombier 14645e96a66cSDavid du Colombier vtLock(fsys->lock); 14655e96a66cSDavid du Colombier if(host == nil) 14665e96a66cSDavid du Colombier host = fsys->venti; 14675e96a66cSDavid du Colombier else{ 14685e96a66cSDavid du Colombier vtMemFree(fsys->venti); 14695e96a66cSDavid du Colombier if(host[0]) 14705e96a66cSDavid du Colombier fsys->venti = vtStrDup(host); 14715e96a66cSDavid du Colombier else{ 14725e96a66cSDavid du Colombier host = nil; 14735e96a66cSDavid du Colombier fsys->venti = nil; 14745e96a66cSDavid du Colombier } 14755e96a66cSDavid du Colombier } 14765e96a66cSDavid du Colombier 14775e96a66cSDavid du Colombier /* already open: do a redial */ 14785e96a66cSDavid du Colombier if(fsys->fs != nil){ 14796042bf6dSDavid du Colombier if(fsys->session == nil){ 14806042bf6dSDavid du Colombier vtSetError("file system was opened with -V"); 14816042bf6dSDavid du Colombier r = 0; 14826042bf6dSDavid du Colombier goto out; 14836042bf6dSDavid du Colombier } 14845e96a66cSDavid du Colombier r = 1; 1485ea58ad6fSDavid du Colombier if(!myRedial(fsys->session, host) 14865e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 14875e96a66cSDavid du Colombier r = 0; 14886042bf6dSDavid du Colombier goto out; 14895e96a66cSDavid du Colombier } 14905e96a66cSDavid du Colombier 14915e96a66cSDavid du Colombier /* not yet open: try to dial */ 14925e96a66cSDavid du Colombier if(fsys->session) 14935e96a66cSDavid du Colombier vtClose(fsys->session); 14945e96a66cSDavid du Colombier r = 1; 1495ea58ad6fSDavid du Colombier if((fsys->session = myDial(host, 0)) == nil 14965e96a66cSDavid du Colombier || !vtConnect(fsys->session, 0)) 14975e96a66cSDavid du Colombier r = 0; 14986042bf6dSDavid du Colombier out: 14995e96a66cSDavid du Colombier vtUnlock(fsys->lock); 15005e96a66cSDavid du Colombier fsysPut(fsys); 15015e96a66cSDavid du Colombier return r; 15025e96a66cSDavid du Colombier } 15035e96a66cSDavid du Colombier 1504b8a11165SDavid du Colombier static ulong 1505b8a11165SDavid du Colombier freemem(void) 1506b8a11165SDavid du Colombier { 1507b8a11165SDavid du Colombier int nf, pgsize = 0; 1508b8a11165SDavid du Colombier uvlong size, userpgs = 0, userused = 0; 1509b8a11165SDavid du Colombier char *ln, *sl; 1510b8a11165SDavid du Colombier char *fields[2]; 1511b8a11165SDavid du Colombier Biobuf *bp; 1512b8a11165SDavid du Colombier 1513b8a11165SDavid du Colombier size = 64*1024*1024; 1514b8a11165SDavid du Colombier bp = Bopen("#c/swap", OREAD); 1515b8a11165SDavid du Colombier if (bp != nil) { 1516b8a11165SDavid du Colombier while ((ln = Brdline(bp, '\n')) != nil) { 1517b8a11165SDavid du Colombier ln[Blinelen(bp)-1] = '\0'; 1518b8a11165SDavid du Colombier nf = tokenize(ln, fields, nelem(fields)); 1519b8a11165SDavid du Colombier if (nf != 2) 1520b8a11165SDavid du Colombier continue; 1521b8a11165SDavid du Colombier if (strcmp(fields[1], "pagesize") == 0) 1522b8a11165SDavid du Colombier pgsize = atoi(fields[0]); 1523b8a11165SDavid du Colombier else if (strcmp(fields[1], "user") == 0) { 1524b8a11165SDavid du Colombier sl = strchr(fields[0], '/'); 1525b8a11165SDavid du Colombier if (sl == nil) 1526b8a11165SDavid du Colombier continue; 1527b8a11165SDavid du Colombier userpgs = atoll(sl+1); 1528b8a11165SDavid du Colombier userused = atoll(fields[0]); 1529b8a11165SDavid du Colombier } 1530b8a11165SDavid du Colombier } 1531b8a11165SDavid du Colombier Bterm(bp); 1532b8a11165SDavid du Colombier if (pgsize > 0 && userpgs > 0) 1533b8a11165SDavid du Colombier size = (userpgs - userused) * pgsize; 1534b8a11165SDavid du Colombier } 1535b8a11165SDavid du Colombier /* cap it to keep the size within 32 bits */ 1536b8a11165SDavid du Colombier if (size >= 3840UL * 1024 * 1024) 1537b8a11165SDavid du Colombier size = 3840UL * 1024 * 1024; 1538b8a11165SDavid du Colombier return size; 1539b8a11165SDavid du Colombier } 1540b8a11165SDavid du Colombier 15415e96a66cSDavid du Colombier static int 15425e96a66cSDavid du Colombier fsysOpen(char* name, int argc, char* argv[]) 15435e96a66cSDavid du Colombier { 15445e96a66cSDavid du Colombier char *p, *host; 15455e96a66cSDavid du Colombier Fsys *fsys; 1546f4051287SDavid du Colombier int noauth, noventi, noperm, rflag, wstatallow, noatimeupd; 1547b8a11165SDavid du Colombier long ncache; 15486042bf6dSDavid du Colombier char *usage = "usage: fsys name open [-APVWr] [-c ncache]"; 15495e96a66cSDavid du Colombier 15505e96a66cSDavid du Colombier ncache = 1000; 1551f4051287SDavid du Colombier noauth = noperm = wstatallow = noventi = noatimeupd = 0; 15525e96a66cSDavid du Colombier rflag = OReadWrite; 15535e96a66cSDavid du Colombier 15545e96a66cSDavid du Colombier ARGBEGIN{ 15555e96a66cSDavid du Colombier default: 15565e96a66cSDavid du Colombier return cliError(usage); 15575e96a66cSDavid du Colombier case 'A': 15585e96a66cSDavid du Colombier noauth = 1; 15595e96a66cSDavid du Colombier break; 15605e96a66cSDavid du Colombier case 'P': 15615e96a66cSDavid du Colombier noperm = 1; 15625e96a66cSDavid du Colombier break; 15636042bf6dSDavid du Colombier case 'V': 15646042bf6dSDavid du Colombier noventi = 1; 15656042bf6dSDavid du Colombier break; 15665e96a66cSDavid du Colombier case 'W': 15675e96a66cSDavid du Colombier wstatallow = 1; 15685e96a66cSDavid du Colombier break; 1569f4051287SDavid du Colombier case 'a': 1570f4051287SDavid du Colombier noatimeupd = 1; 1571f4051287SDavid du Colombier break; 15725e96a66cSDavid du Colombier case 'c': 15735e96a66cSDavid du Colombier p = ARGF(); 15745e96a66cSDavid du Colombier if(p == nil) 15755e96a66cSDavid du Colombier return cliError(usage); 15765e96a66cSDavid du Colombier ncache = strtol(argv[0], &p, 0); 15775e96a66cSDavid du Colombier if(ncache <= 0 || p == argv[0] || *p != '\0') 15785e96a66cSDavid du Colombier return cliError(usage); 15795e96a66cSDavid du Colombier break; 15805e96a66cSDavid du Colombier case 'r': 15815e96a66cSDavid du Colombier rflag = OReadOnly; 15825e96a66cSDavid du Colombier break; 15835e96a66cSDavid du Colombier }ARGEND 15845e96a66cSDavid du Colombier if(argc) 15855e96a66cSDavid du Colombier return cliError(usage); 15865e96a66cSDavid du Colombier 15875e96a66cSDavid du Colombier if((fsys = _fsysGet(name)) == nil) 15885e96a66cSDavid du Colombier return 0; 15895e96a66cSDavid du Colombier 1590b8a11165SDavid du Colombier /* automatic memory sizing? */ 1591b8a11165SDavid du Colombier if(mempcnt > 0) { 1592b8a11165SDavid du Colombier /* TODO: 8K is a hack; use the actual block size */ 1593b8a11165SDavid du Colombier ncache = (((vlong)freemem() * mempcnt) / 100) / (8*1024); 1594b8a11165SDavid du Colombier if (ncache < 100) 1595b8a11165SDavid du Colombier ncache = 100; 1596b8a11165SDavid du Colombier } 1597b8a11165SDavid du Colombier 15985e96a66cSDavid du Colombier vtLock(fsys->lock); 15995e96a66cSDavid du Colombier if(fsys->fs != nil){ 16005e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 16015e96a66cSDavid du Colombier vtUnlock(fsys->lock); 16025e96a66cSDavid du Colombier fsysPut(fsys); 16035e96a66cSDavid du Colombier return 0; 16045e96a66cSDavid du Colombier } 16055e96a66cSDavid du Colombier 16067611b47fSDavid du Colombier if(noventi){ 16077611b47fSDavid du Colombier if(fsys->session){ 16087611b47fSDavid du Colombier vtClose(fsys->session); 16097611b47fSDavid du Colombier fsys->session = nil; 16107611b47fSDavid du Colombier } 16117611b47fSDavid du Colombier } 16127611b47fSDavid du Colombier else if(fsys->session == nil){ 16135e96a66cSDavid du Colombier if(fsys->venti && fsys->venti[0]) 16145e96a66cSDavid du Colombier host = fsys->venti; 16155e96a66cSDavid du Colombier else 16165e96a66cSDavid du Colombier host = nil; 1617ea58ad6fSDavid du Colombier fsys->session = myDial(host, 1); 16186042bf6dSDavid du Colombier if(!vtConnect(fsys->session, nil) && !noventi) 161961201b97SDavid du Colombier fprint(2, "warning: connecting to venti: %R\n"); 16205e96a66cSDavid du Colombier } 16215e96a66cSDavid du Colombier if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){ 1622dc5a79c1SDavid du Colombier vtSetError("fsOpen: %R"); 16235e96a66cSDavid du Colombier vtUnlock(fsys->lock); 16245e96a66cSDavid du Colombier fsysPut(fsys); 16255e96a66cSDavid du Colombier return 0; 16265e96a66cSDavid du Colombier } 16270c6300e7SDavid du Colombier fsys->fs->name = fsys->name; /* for better error messages */ 16285e96a66cSDavid du Colombier fsys->noauth = noauth; 16295e96a66cSDavid du Colombier fsys->noperm = noperm; 16305e96a66cSDavid du Colombier fsys->wstatallow = wstatallow; 1631f4051287SDavid du Colombier fsys->fs->noatimeupd = noatimeupd; 16325e96a66cSDavid du Colombier vtUnlock(fsys->lock); 16335e96a66cSDavid du Colombier fsysPut(fsys); 16345e96a66cSDavid du Colombier 163581cf8742SDavid du Colombier if(strcmp(name, "main") == 0) 163681cf8742SDavid du Colombier usersFileRead(nil); 163781cf8742SDavid du Colombier 16385e96a66cSDavid du Colombier return 1; 16395e96a66cSDavid du Colombier } 16405e96a66cSDavid du Colombier 16415e96a66cSDavid du Colombier static int 16425e96a66cSDavid du Colombier fsysUnconfig(char* name, int argc, char* argv[]) 16435e96a66cSDavid du Colombier { 16445e96a66cSDavid du Colombier Fsys *fsys, **fp; 16455e96a66cSDavid du Colombier char *usage = "usage: fsys name unconfig"; 16465e96a66cSDavid du Colombier 16475e96a66cSDavid du Colombier ARGBEGIN{ 16485e96a66cSDavid du Colombier default: 16495e96a66cSDavid du Colombier return cliError(usage); 16505e96a66cSDavid du Colombier }ARGEND 16515e96a66cSDavid du Colombier if(argc) 16525e96a66cSDavid du Colombier return cliError(usage); 16535e96a66cSDavid du Colombier 16545e96a66cSDavid du Colombier vtLock(sbox.lock); 16555e96a66cSDavid du Colombier fp = &sbox.head; 16565e96a66cSDavid du Colombier for(fsys = *fp; fsys != nil; fsys = fsys->next){ 16575e96a66cSDavid du Colombier if(strcmp(fsys->name, name) == 0) 16585e96a66cSDavid du Colombier break; 16595e96a66cSDavid du Colombier fp = &fsys->next; 16605e96a66cSDavid du Colombier } 16615e96a66cSDavid du Colombier if(fsys == nil){ 16625e96a66cSDavid du Colombier vtSetError(EFsysNotFound, name); 16635e96a66cSDavid du Colombier vtUnlock(sbox.lock); 16645e96a66cSDavid du Colombier return 0; 16655e96a66cSDavid du Colombier } 16665e96a66cSDavid du Colombier if(fsys->ref != 0 || fsys->fs != nil){ 16675e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 16685e96a66cSDavid du Colombier vtUnlock(sbox.lock); 16695e96a66cSDavid du Colombier return 0; 16705e96a66cSDavid du Colombier } 16715e96a66cSDavid du Colombier *fp = fsys->next; 16725e96a66cSDavid du Colombier vtUnlock(sbox.lock); 16735e96a66cSDavid du Colombier 16745e96a66cSDavid du Colombier if(fsys->session != nil){ 16755e96a66cSDavid du Colombier vtClose(fsys->session); 16765e96a66cSDavid du Colombier vtFree(fsys->session); 16775e96a66cSDavid du Colombier } 16785e96a66cSDavid du Colombier if(fsys->venti != nil) 16795e96a66cSDavid du Colombier vtMemFree(fsys->venti); 16805e96a66cSDavid du Colombier if(fsys->dev != nil) 16815e96a66cSDavid du Colombier vtMemFree(fsys->dev); 16825e96a66cSDavid du Colombier if(fsys->name != nil) 16835e96a66cSDavid du Colombier vtMemFree(fsys->name); 16845e96a66cSDavid du Colombier vtMemFree(fsys); 16855e96a66cSDavid du Colombier 16865e96a66cSDavid du Colombier return 1; 16875e96a66cSDavid du Colombier } 16885e96a66cSDavid du Colombier 16895e96a66cSDavid du Colombier static int 16905e96a66cSDavid du Colombier fsysConfig(char* name, int argc, char* argv[]) 16915e96a66cSDavid du Colombier { 16925e96a66cSDavid du Colombier Fsys *fsys; 1693*1bdadbfaSDavid du Colombier char *part; 1694*1bdadbfaSDavid du Colombier char *usage = "usage: fsys name config [dev]"; 16955e96a66cSDavid du Colombier 16965e96a66cSDavid du Colombier ARGBEGIN{ 16975e96a66cSDavid du Colombier default: 16985e96a66cSDavid du Colombier return cliError(usage); 16995e96a66cSDavid du Colombier }ARGEND 1700*1bdadbfaSDavid du Colombier if(argc > 1) 17015e96a66cSDavid du Colombier return cliError(usage); 17025e96a66cSDavid du Colombier 1703*1bdadbfaSDavid du Colombier if(argc == 0) 1704*1bdadbfaSDavid du Colombier part = foptname; 1705*1bdadbfaSDavid du Colombier else 1706*1bdadbfaSDavid du Colombier part = argv[0]; 1707*1bdadbfaSDavid du Colombier 1708*1bdadbfaSDavid du Colombier if((fsys = _fsysGet(part)) != nil){ 17095e96a66cSDavid du Colombier vtLock(fsys->lock); 17105e96a66cSDavid du Colombier if(fsys->fs != nil){ 17115e96a66cSDavid du Colombier vtSetError(EFsysBusy, fsys->name); 17125e96a66cSDavid du Colombier vtUnlock(fsys->lock); 17135e96a66cSDavid du Colombier fsysPut(fsys); 17145e96a66cSDavid du Colombier return 0; 17155e96a66cSDavid du Colombier } 17165e96a66cSDavid du Colombier vtMemFree(fsys->dev); 1717*1bdadbfaSDavid du Colombier fsys->dev = vtStrDup(part); 17185e96a66cSDavid du Colombier vtUnlock(fsys->lock); 17195e96a66cSDavid du Colombier } 1720*1bdadbfaSDavid du Colombier else if((fsys = fsysAlloc(name, part)) == nil) 17215e96a66cSDavid du Colombier return 0; 17225e96a66cSDavid du Colombier 17235e96a66cSDavid du Colombier fsysPut(fsys); 17245e96a66cSDavid du Colombier return 1; 17255e96a66cSDavid du Colombier } 17265e96a66cSDavid du Colombier 17275e96a66cSDavid du Colombier static struct { 17285e96a66cSDavid du Colombier char* cmd; 17295e96a66cSDavid du Colombier int (*f)(Fsys*, int, char**); 17305e96a66cSDavid du Colombier int (*f1)(char*, int, char**); 17315e96a66cSDavid du Colombier } fsyscmd[] = { 17325e96a66cSDavid du Colombier { "close", fsysClose, }, 17335e96a66cSDavid du Colombier { "config", nil, fsysConfig, }, 17345e96a66cSDavid du Colombier { "open", nil, fsysOpen, }, 17355e96a66cSDavid du Colombier { "unconfig", nil, fsysUnconfig, }, 17365e96a66cSDavid du Colombier { "venti", nil, fsysVenti, }, 17375e96a66cSDavid du Colombier 17385e96a66cSDavid du Colombier { "bfree", fsysBfree, }, 17395e96a66cSDavid du Colombier { "block", fsysBlock, }, 1740e569ccb5SDavid du Colombier { "check", fsysCheck, }, 17415e96a66cSDavid du Colombier { "clre", fsysClre, }, 17425e96a66cSDavid du Colombier { "clri", fsysClri, }, 17435e96a66cSDavid du Colombier { "clrp", fsysClrp, }, 17445e96a66cSDavid du Colombier { "create", fsysCreate, }, 17457abd426fSDavid du Colombier { "df", fsysDf, }, 17465e96a66cSDavid du Colombier { "epoch", fsysEpoch, }, 174781cf8742SDavid du Colombier { "halt", fsysHalt, }, 17485e96a66cSDavid du Colombier { "label", fsysLabel, }, 17495e96a66cSDavid du Colombier { "remove", fsysRemove, }, 17505e96a66cSDavid du Colombier { "snap", fsysSnap, }, 17515e96a66cSDavid du Colombier { "snaptime", fsysSnapTime, }, 1752dc5a79c1SDavid du Colombier { "snapclean", fsysSnapClean, }, 17535e96a66cSDavid du Colombier { "stat", fsysStat, }, 17545e96a66cSDavid du Colombier { "sync", fsysSync, }, 175581cf8742SDavid du Colombier { "unhalt", fsysUnhalt, }, 17565e96a66cSDavid du Colombier { "wstat", fsysWstat, }, 17575e96a66cSDavid du Colombier { "vac", fsysVac, }, 17585e96a66cSDavid du Colombier 17595e96a66cSDavid du Colombier { nil, nil, }, 17605e96a66cSDavid du Colombier }; 17615e96a66cSDavid du Colombier 17625e96a66cSDavid du Colombier static int 176381cf8742SDavid du Colombier fsysXXX1(Fsys *fsys, int i, int argc, char* argv[]) 176481cf8742SDavid du Colombier { 176581cf8742SDavid du Colombier int r; 176681cf8742SDavid du Colombier 176781cf8742SDavid du Colombier vtLock(fsys->lock); 176881cf8742SDavid du Colombier if(fsys->fs == nil){ 176981cf8742SDavid du Colombier vtUnlock(fsys->lock); 177081cf8742SDavid du Colombier vtSetError(EFsysNotOpen, fsys->name); 177181cf8742SDavid du Colombier return 0; 177281cf8742SDavid du Colombier } 177381cf8742SDavid du Colombier 1774e569ccb5SDavid du Colombier if(fsys->fs->halted 1775e569ccb5SDavid du Colombier && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){ 177681cf8742SDavid du Colombier vtSetError("file system %s is halted", fsys->name); 177781cf8742SDavid du Colombier vtUnlock(fsys->lock); 177881cf8742SDavid du Colombier return 0; 177981cf8742SDavid du Colombier } 178081cf8742SDavid du Colombier 178181cf8742SDavid du Colombier r = (*fsyscmd[i].f)(fsys, argc, argv); 178281cf8742SDavid du Colombier vtUnlock(fsys->lock); 178381cf8742SDavid du Colombier return r; 178481cf8742SDavid du Colombier } 178581cf8742SDavid du Colombier 178681cf8742SDavid du Colombier static int 17875e96a66cSDavid du Colombier fsysXXX(char* name, int argc, char* argv[]) 17885e96a66cSDavid du Colombier { 17895e96a66cSDavid du Colombier int i, r; 17905e96a66cSDavid du Colombier Fsys *fsys; 17915e96a66cSDavid du Colombier 17925e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 17935e96a66cSDavid du Colombier if(strcmp(fsyscmd[i].cmd, argv[0]) == 0) 17945e96a66cSDavid du Colombier break; 17955e96a66cSDavid du Colombier } 17965e96a66cSDavid du Colombier 17975e96a66cSDavid du Colombier if(fsyscmd[i].cmd == nil){ 17985e96a66cSDavid du Colombier vtSetError("unknown command - '%s'", argv[0]); 17995e96a66cSDavid du Colombier return 0; 18005e96a66cSDavid du Colombier } 18015e96a66cSDavid du Colombier 18025e96a66cSDavid du Colombier /* some commands want the name... */ 180381cf8742SDavid du Colombier if(fsyscmd[i].f1 != nil){ 180481cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 180581cf8742SDavid du Colombier vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]); 18065e96a66cSDavid du Colombier return 0; 18075e96a66cSDavid du Colombier } 180881cf8742SDavid du Colombier return (*fsyscmd[i].f1)(name, argc, argv); 180981cf8742SDavid du Colombier } 18105e96a66cSDavid du Colombier 181181cf8742SDavid du Colombier /* ... but most commands want the Fsys */ 181281cf8742SDavid du Colombier if(strcmp(name, FsysAll) == 0){ 181381cf8742SDavid du Colombier r = 1; 181481cf8742SDavid du Colombier vtRLock(sbox.lock); 181581cf8742SDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next){ 181681cf8742SDavid du Colombier fsys->ref++; 181781cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv) && r; 181881cf8742SDavid du Colombier fsys->ref--; 181981cf8742SDavid du Colombier } 182081cf8742SDavid du Colombier vtRUnlock(sbox.lock); 182181cf8742SDavid du Colombier }else{ 182281cf8742SDavid du Colombier if((fsys = _fsysGet(name)) == nil) 182381cf8742SDavid du Colombier return 0; 182481cf8742SDavid du Colombier r = fsysXXX1(fsys, i, argc, argv); 18255e96a66cSDavid du Colombier fsysPut(fsys); 182681cf8742SDavid du Colombier } 18275e96a66cSDavid du Colombier return r; 18285e96a66cSDavid du Colombier } 18295e96a66cSDavid du Colombier 18305e96a66cSDavid du Colombier static int 18315e96a66cSDavid du Colombier cmdFsysXXX(int argc, char* argv[]) 18325e96a66cSDavid du Colombier { 18335e96a66cSDavid du Colombier char *name; 18345e96a66cSDavid du Colombier 18355e96a66cSDavid du Colombier if((name = sbox.curfsys) == nil){ 18365e96a66cSDavid du Colombier vtSetError(EFsysNoCurrent, argv[0]); 18375e96a66cSDavid du Colombier return 0; 18385e96a66cSDavid du Colombier } 18395e96a66cSDavid du Colombier 18405e96a66cSDavid du Colombier return fsysXXX(name, argc, argv); 18415e96a66cSDavid du Colombier } 18425e96a66cSDavid du Colombier 18435e96a66cSDavid du Colombier static int 18445e96a66cSDavid du Colombier cmdFsys(int argc, char* argv[]) 18455e96a66cSDavid du Colombier { 18465e96a66cSDavid du Colombier Fsys *fsys; 18475e96a66cSDavid du Colombier char *usage = "usage: fsys [name ...]"; 18485e96a66cSDavid du Colombier 18495e96a66cSDavid du Colombier ARGBEGIN{ 18505e96a66cSDavid du Colombier default: 18515e96a66cSDavid du Colombier return cliError(usage); 18525e96a66cSDavid du Colombier }ARGEND 18535e96a66cSDavid du Colombier 18545e96a66cSDavid du Colombier if(argc == 0){ 18555e96a66cSDavid du Colombier vtRLock(sbox.lock); 1856b8a11165SDavid du Colombier currfsysname = sbox.head->name; 18575e96a66cSDavid du Colombier for(fsys = sbox.head; fsys != nil; fsys = fsys->next) 18585e96a66cSDavid du Colombier consPrint("\t%s\n", fsys->name); 18595e96a66cSDavid du Colombier vtRUnlock(sbox.lock); 18605e96a66cSDavid du Colombier return 1; 18615e96a66cSDavid du Colombier } 18625e96a66cSDavid du Colombier if(argc == 1){ 186381cf8742SDavid du Colombier fsys = nil; 186481cf8742SDavid du Colombier if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil) 18655e96a66cSDavid du Colombier return 0; 186681cf8742SDavid du Colombier sbox.curfsys = vtStrDup(argv[0]); 18675e96a66cSDavid du Colombier consPrompt(sbox.curfsys); 186881cf8742SDavid du Colombier if(fsys) 18695e96a66cSDavid du Colombier fsysPut(fsys); 18705e96a66cSDavid du Colombier return 1; 18715e96a66cSDavid du Colombier } 18725e96a66cSDavid du Colombier 18735e96a66cSDavid du Colombier return fsysXXX(argv[0], argc-1, argv+1); 18745e96a66cSDavid du Colombier } 18755e96a66cSDavid du Colombier 18765e96a66cSDavid du Colombier int 18775e96a66cSDavid du Colombier fsysInit(void) 18785e96a66cSDavid du Colombier { 18795e96a66cSDavid du Colombier int i; 18805e96a66cSDavid du Colombier 18815e96a66cSDavid du Colombier fmtinstall('H', encodefmt); 18825e96a66cSDavid du Colombier fmtinstall('V', scoreFmt); 18835e96a66cSDavid du Colombier fmtinstall('R', vtErrFmt); 18845e96a66cSDavid du Colombier fmtinstall('L', labelFmt); 18855e96a66cSDavid du Colombier 18865e96a66cSDavid du Colombier sbox.lock = vtLockAlloc(); 18875e96a66cSDavid du Colombier 18885e96a66cSDavid du Colombier cliAddCmd("fsys", cmdFsys); 18895e96a66cSDavid du Colombier for(i = 0; fsyscmd[i].cmd != nil; i++){ 18905e96a66cSDavid du Colombier if(fsyscmd[i].f != nil) 18915e96a66cSDavid du Colombier cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX); 18925e96a66cSDavid du Colombier } 18935e96a66cSDavid du Colombier /* the venti cmd is special: the fs can be either open or closed */ 18945e96a66cSDavid du Colombier cliAddCmd("venti", cmdFsysXXX); 18955e96a66cSDavid du Colombier cliAddCmd("printconfig", cmdPrintConfig); 18965e96a66cSDavid du Colombier 18975e96a66cSDavid du Colombier return 1; 18985e96a66cSDavid du Colombier } 1899