9fsys.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896
  1. #include "stdinc.h"
  2. #include <bio.h>
  3. #include "dat.h"
  4. #include "fns.h"
  5. #include "9.h"
  6. struct Fsys {
  7. VtLock* lock;
  8. char* name; /* copy here & Fs to ease error reporting */
  9. char* dev;
  10. char* venti;
  11. Fs* fs;
  12. VtSession* session;
  13. int ref;
  14. int noauth;
  15. int noperm;
  16. int wstatallow;
  17. Fsys* next;
  18. };
  19. int mempcnt; /* from fossil.c */
  20. int fsGetBlockSize(Fs *fs);
  21. static struct {
  22. VtLock* lock;
  23. Fsys* head;
  24. Fsys* tail;
  25. char* curfsys;
  26. } sbox;
  27. static char *_argv0;
  28. #define argv0 _argv0
  29. static char FsysAll[] = "all";
  30. static char EFsysBusy[] = "fsys: '%s' busy";
  31. static char EFsysExists[] = "fsys: '%s' already exists";
  32. static char EFsysNoCurrent[] = "fsys: no current fsys";
  33. static char EFsysNotFound[] = "fsys: '%s' not found";
  34. static char EFsysNotOpen[] = "fsys: '%s' not open";
  35. static char *
  36. ventihost(char *host)
  37. {
  38. if(host != nil)
  39. return vtStrDup(host);
  40. host = getenv("venti");
  41. if(host == nil)
  42. host = vtStrDup("$venti");
  43. return host;
  44. }
  45. static void
  46. prventihost(char *host)
  47. {
  48. char *vh;
  49. vh = ventihost(host);
  50. fprint(2, "%s: dialing venti at %s\n",
  51. argv0, netmkaddr(vh, 0, "venti"));
  52. free(vh);
  53. }
  54. static VtSession *
  55. myDial(char *host, int canfail)
  56. {
  57. prventihost(host);
  58. return vtDial(host, canfail);
  59. }
  60. static int
  61. myRedial(VtSession *z, char *host)
  62. {
  63. prventihost(host);
  64. return vtRedial(z, host);
  65. }
  66. static Fsys*
  67. _fsysGet(char* name)
  68. {
  69. Fsys *fsys;
  70. if(name == nil || name[0] == '\0')
  71. name = "main";
  72. vtRLock(sbox.lock);
  73. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  74. if(strcmp(name, fsys->name) == 0){
  75. fsys->ref++;
  76. break;
  77. }
  78. }
  79. vtRUnlock(sbox.lock);
  80. if(fsys == nil)
  81. vtSetError(EFsysNotFound, name);
  82. return fsys;
  83. }
  84. static int
  85. cmdPrintConfig(int argc, char* argv[])
  86. {
  87. Fsys *fsys;
  88. char *usage = "usage: printconfig";
  89. ARGBEGIN{
  90. default:
  91. return cliError(usage);
  92. }ARGEND
  93. if(argc)
  94. return cliError(usage);
  95. vtRLock(sbox.lock);
  96. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  97. consPrint("\tfsys %s config %s\n", fsys->name, fsys->dev);
  98. if(fsys->venti && fsys->venti[0])
  99. consPrint("\tfsys %s venti %q\n", fsys->name,
  100. fsys->venti);
  101. }
  102. vtRUnlock(sbox.lock);
  103. return 1;
  104. }
  105. Fsys*
  106. fsysGet(char* name)
  107. {
  108. Fsys *fsys;
  109. if((fsys = _fsysGet(name)) == nil)
  110. return nil;
  111. vtLock(fsys->lock);
  112. if(fsys->fs == nil){
  113. vtSetError(EFsysNotOpen, fsys->name);
  114. vtUnlock(fsys->lock);
  115. fsysPut(fsys);
  116. return nil;
  117. }
  118. vtUnlock(fsys->lock);
  119. return fsys;
  120. }
  121. char*
  122. fsysGetName(Fsys* fsys)
  123. {
  124. return fsys->name;
  125. }
  126. Fsys*
  127. fsysIncRef(Fsys* fsys)
  128. {
  129. vtLock(sbox.lock);
  130. fsys->ref++;
  131. vtUnlock(sbox.lock);
  132. return fsys;
  133. }
  134. void
  135. fsysPut(Fsys* fsys)
  136. {
  137. vtLock(sbox.lock);
  138. assert(fsys->ref > 0);
  139. fsys->ref--;
  140. vtUnlock(sbox.lock);
  141. }
  142. Fs*
  143. fsysGetFs(Fsys* fsys)
  144. {
  145. assert(fsys != nil && fsys->fs != nil);
  146. return fsys->fs;
  147. }
  148. void
  149. fsysFsRlock(Fsys* fsys)
  150. {
  151. vtRLock(fsys->fs->elk);
  152. }
  153. void
  154. fsysFsRUnlock(Fsys* fsys)
  155. {
  156. vtRUnlock(fsys->fs->elk);
  157. }
  158. int
  159. fsysNoAuthCheck(Fsys* fsys)
  160. {
  161. return fsys->noauth;
  162. }
  163. int
  164. fsysNoPermCheck(Fsys* fsys)
  165. {
  166. return fsys->noperm;
  167. }
  168. int
  169. fsysWstatAllow(Fsys* fsys)
  170. {
  171. return fsys->wstatallow;
  172. }
  173. static char modechars[] = "YUGalLdHSATs";
  174. static ulong modebits[] = {
  175. ModeSticky,
  176. ModeSetUid,
  177. ModeSetGid,
  178. ModeAppend,
  179. ModeExclusive,
  180. ModeLink,
  181. ModeDir,
  182. ModeHidden,
  183. ModeSystem,
  184. ModeArchive,
  185. ModeTemporary,
  186. ModeSnapshot,
  187. 0
  188. };
  189. char*
  190. fsysModeString(ulong mode, char *buf)
  191. {
  192. int i;
  193. char *p;
  194. p = buf;
  195. for(i=0; modebits[i]; i++)
  196. if(mode & modebits[i])
  197. *p++ = modechars[i];
  198. sprint(p, "%luo", mode&0777);
  199. return buf;
  200. }
  201. int
  202. fsysParseMode(char* s, ulong* mode)
  203. {
  204. ulong x, y;
  205. char *p;
  206. x = 0;
  207. for(; *s < '0' || *s > '9'; s++){
  208. if(*s == 0)
  209. return 0;
  210. p = strchr(modechars, *s);
  211. if(p == nil)
  212. return 0;
  213. x |= modebits[p-modechars];
  214. }
  215. y = strtoul(s, &p, 8);
  216. if(*p != '\0' || y > 0777)
  217. return 0;
  218. *mode = x|y;
  219. return 1;
  220. }
  221. File*
  222. fsysGetRoot(Fsys* fsys, char* name)
  223. {
  224. File *root, *sub;
  225. assert(fsys != nil && fsys->fs != nil);
  226. root = fsGetRoot(fsys->fs);
  227. if(name == nil || strcmp(name, "") == 0)
  228. return root;
  229. sub = fileWalk(root, name);
  230. fileDecRef(root);
  231. return sub;
  232. }
  233. static Fsys*
  234. fsysAlloc(char* name, char* dev)
  235. {
  236. Fsys *fsys;
  237. vtLock(sbox.lock);
  238. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  239. if(strcmp(fsys->name, name) != 0)
  240. continue;
  241. vtSetError(EFsysExists, name);
  242. vtUnlock(sbox.lock);
  243. return nil;
  244. }
  245. fsys = vtMemAllocZ(sizeof(Fsys));
  246. fsys->lock = vtLockAlloc();
  247. fsys->name = vtStrDup(name);
  248. fsys->dev = vtStrDup(dev);
  249. fsys->ref = 1;
  250. if(sbox.tail != nil)
  251. sbox.tail->next = fsys;
  252. else
  253. sbox.head = fsys;
  254. sbox.tail = fsys;
  255. vtUnlock(sbox.lock);
  256. return fsys;
  257. }
  258. static int
  259. fsysClose(Fsys* fsys, int argc, char* argv[])
  260. {
  261. char *usage = "usage: [fsys name] close";
  262. ARGBEGIN{
  263. default:
  264. return cliError(usage);
  265. }ARGEND
  266. if(argc)
  267. return cliError(usage);
  268. return cliError("close isn't working yet; halt %s and then kill fossil",
  269. fsys->name);
  270. /*
  271. * Oooh. This could be hard. What if fsys->ref != 1?
  272. * Also, fsClose() either does the job or panics, can we
  273. * gracefully detect it's still busy?
  274. *
  275. * More thought and care needed here.
  276. fsClose(fsys->fs);
  277. fsys->fs = nil;
  278. vtClose(fsys->session);
  279. fsys->session = nil;
  280. if(sbox.curfsys != nil && strcmp(fsys->name, sbox.curfsys) == 0){
  281. sbox.curfsys = nil;
  282. consPrompt(nil);
  283. }
  284. return 1;
  285. */
  286. }
  287. static int
  288. fsysVac(Fsys* fsys, int argc, char* argv[])
  289. {
  290. uchar score[VtScoreSize];
  291. char *usage = "usage: [fsys name] vac path";
  292. ARGBEGIN{
  293. default:
  294. return cliError(usage);
  295. }ARGEND
  296. if(argc != 1)
  297. return cliError(usage);
  298. if(!fsVac(fsys->fs, argv[0], score))
  299. return 0;
  300. consPrint("vac:%V\n", score);
  301. return 1;
  302. }
  303. static int
  304. fsysSnap(Fsys* fsys, int argc, char* argv[])
  305. {
  306. int doarchive;
  307. char *usage = "usage: [fsys name] snap [-a] [-s /active] [-d /archive/yyyy/mmmm]";
  308. char *src, *dst;
  309. src = nil;
  310. dst = nil;
  311. doarchive = 0;
  312. ARGBEGIN{
  313. default:
  314. return cliError(usage);
  315. case 'a':
  316. doarchive = 1;
  317. break;
  318. case 'd':
  319. if((dst = ARGF()) == nil)
  320. return cliError(usage);
  321. break;
  322. case 's':
  323. if((src = ARGF()) == nil)
  324. return cliError(usage);
  325. break;
  326. }ARGEND
  327. if(argc)
  328. return cliError(usage);
  329. if(!fsSnapshot(fsys->fs, src, dst, doarchive))
  330. return 0;
  331. return 1;
  332. }
  333. static int
  334. fsysSnapClean(Fsys *fsys, int argc, char* argv[])
  335. {
  336. u32int arch, snap, life;
  337. char *usage = "usage: [fsys name] snapclean [maxminutes]\n";
  338. ARGBEGIN{
  339. default:
  340. return cliError(usage);
  341. }ARGEND
  342. if(argc > 1)
  343. return cliError(usage);
  344. if(argc == 1)
  345. life = atoi(argv[0]);
  346. else
  347. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  348. fsSnapshotCleanup(fsys->fs, life);
  349. return 1;
  350. }
  351. static int
  352. fsysSnapTime(Fsys* fsys, int argc, char* argv[])
  353. {
  354. char buf[128], *x;
  355. int hh, mm, changed;
  356. u32int arch, snap, life;
  357. char *usage = "usage: [fsys name] snaptime [-a hhmm] [-s snapminutes] [-t maxminutes]";
  358. changed = 0;
  359. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  360. ARGBEGIN{
  361. case 'a':
  362. changed = 1;
  363. x = ARGF();
  364. if(x == nil)
  365. return cliError(usage);
  366. if(strcmp(x, "none") == 0){
  367. arch = ~(u32int)0;
  368. break;
  369. }
  370. if(strlen(x) != 4 || strspn(x, "0123456789") != 4)
  371. return cliError(usage);
  372. hh = (x[0]-'0')*10 + x[1]-'0';
  373. mm = (x[2]-'0')*10 + x[3]-'0';
  374. if(hh >= 24 || mm >= 60)
  375. return cliError(usage);
  376. arch = hh*60+mm;
  377. break;
  378. case 's':
  379. changed = 1;
  380. x = ARGF();
  381. if(x == nil)
  382. return cliError(usage);
  383. if(strcmp(x, "none") == 0){
  384. snap = ~(u32int)0;
  385. break;
  386. }
  387. snap = atoi(x);
  388. break;
  389. case 't':
  390. changed = 1;
  391. x = ARGF();
  392. if(x == nil)
  393. return cliError(usage);
  394. if(strcmp(x, "none") == 0){
  395. life = ~(u32int)0;
  396. break;
  397. }
  398. life = atoi(x);
  399. break;
  400. default:
  401. return cliError(usage);
  402. }ARGEND
  403. if(argc > 0)
  404. return cliError(usage);
  405. if(changed){
  406. snapSetTimes(fsys->fs->snap, arch, snap, life);
  407. return 1;
  408. }
  409. snapGetTimes(fsys->fs->snap, &arch, &snap, &life);
  410. if(arch != ~(u32int)0)
  411. sprint(buf, "-a %02d%02d", arch/60, arch%60);
  412. else
  413. sprint(buf, "-a none");
  414. if(snap != ~(u32int)0)
  415. sprint(buf+strlen(buf), " -s %d", snap);
  416. else
  417. sprint(buf+strlen(buf), " -s none");
  418. if(life != ~(u32int)0)
  419. sprint(buf+strlen(buf), " -t %ud", life);
  420. else
  421. sprint(buf+strlen(buf), " -t none");
  422. consPrint("\tsnaptime %s\n", buf);
  423. return 1;
  424. }
  425. static int
  426. fsysSync(Fsys* fsys, int argc, char* argv[])
  427. {
  428. char *usage = "usage: [fsys name] sync";
  429. int n;
  430. ARGBEGIN{
  431. default:
  432. return cliError(usage);
  433. }ARGEND
  434. if(argc > 0)
  435. return cliError(usage);
  436. n = cacheDirty(fsys->fs->cache);
  437. fsSync(fsys->fs);
  438. consPrint("\t%s sync: wrote %d blocks\n", fsys->name, n);
  439. return 1;
  440. }
  441. static int
  442. fsysHalt(Fsys *fsys, int argc, char* argv[])
  443. {
  444. char *usage = "usage: [fsys name] halt";
  445. ARGBEGIN{
  446. default:
  447. return cliError(usage);
  448. }ARGEND
  449. if(argc > 0)
  450. return cliError(usage);
  451. fsHalt(fsys->fs);
  452. return 1;
  453. }
  454. static int
  455. fsysUnhalt(Fsys *fsys, int argc, char* argv[])
  456. {
  457. char *usage = "usage: [fsys name] unhalt";
  458. ARGBEGIN{
  459. default:
  460. return cliError(usage);
  461. }ARGEND
  462. if(argc > 0)
  463. return cliError(usage);
  464. if(!fsys->fs->halted)
  465. return cliError("file system %s not halted", fsys->name);
  466. fsUnhalt(fsys->fs);
  467. return 1;
  468. }
  469. static int
  470. fsysRemove(Fsys* fsys, int argc, char* argv[])
  471. {
  472. File *file;
  473. char *usage = "usage: [fsys name] remove path ...";
  474. ARGBEGIN{
  475. default:
  476. return cliError(usage);
  477. }ARGEND
  478. if(argc == 0)
  479. return cliError(usage);
  480. vtRLock(fsys->fs->elk);
  481. while(argc > 0){
  482. if((file = fileOpen(fsys->fs, argv[0])) == nil)
  483. consPrint("%s: %R\n", argv[0]);
  484. else{
  485. if(!fileRemove(file, uidadm))
  486. consPrint("%s: %R\n", argv[0]);
  487. fileDecRef(file);
  488. }
  489. argc--;
  490. argv++;
  491. }
  492. vtRUnlock(fsys->fs->elk);
  493. return 1;
  494. }
  495. static int
  496. fsysClri(Fsys* fsys, int argc, char* argv[])
  497. {
  498. char *usage = "usage: [fsys name] clri path ...";
  499. ARGBEGIN{
  500. default:
  501. return cliError(usage);
  502. }ARGEND
  503. if(argc == 0)
  504. return cliError(usage);
  505. vtRLock(fsys->fs->elk);
  506. while(argc > 0){
  507. if(!fileClriPath(fsys->fs, argv[0], uidadm))
  508. consPrint("clri %s: %R\n", argv[0]);
  509. argc--;
  510. argv++;
  511. }
  512. vtRUnlock(fsys->fs->elk);
  513. return 1;
  514. }
  515. /*
  516. * Inspect and edit the labels for blocks on disk.
  517. */
  518. static int
  519. fsysLabel(Fsys* fsys, int argc, char* argv[])
  520. {
  521. Fs *fs;
  522. Label l;
  523. int n, r;
  524. u32int addr;
  525. Block *b, *bb;
  526. char *usage = "usage: [fsys name] label addr [type state epoch epochClose tag]";
  527. ARGBEGIN{
  528. default:
  529. return cliError(usage);
  530. }ARGEND
  531. if(argc != 1 && argc != 6)
  532. return cliError(usage);
  533. r = 0;
  534. vtRLock(fsys->fs->elk);
  535. fs = fsys->fs;
  536. addr = strtoul(argv[0], 0, 0);
  537. b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
  538. if(b == nil)
  539. goto Out0;
  540. l = b->l;
  541. consPrint("%slabel %#ux %ud %ud %ud %ud %#x\n",
  542. argc==6 ? "old: " : "", addr, l.type, l.state,
  543. l.epoch, l.epochClose, l.tag);
  544. if(argc == 6){
  545. if(strcmp(argv[1], "-") != 0)
  546. l.type = atoi(argv[1]);
  547. if(strcmp(argv[2], "-") != 0)
  548. l.state = atoi(argv[2]);
  549. if(strcmp(argv[3], "-") != 0)
  550. l.epoch = strtoul(argv[3], 0, 0);
  551. if(strcmp(argv[4], "-") != 0)
  552. l.epochClose = strtoul(argv[4], 0, 0);
  553. if(strcmp(argv[5], "-") != 0)
  554. l.tag = strtoul(argv[5], 0, 0);
  555. consPrint("new: label %#ux %ud %ud %ud %ud %#x\n",
  556. addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
  557. bb = _blockSetLabel(b, &l);
  558. if(bb == nil)
  559. goto Out1;
  560. n = 0;
  561. for(;;){
  562. if(blockWrite(bb, Waitlock)){
  563. while(bb->iostate != BioClean){
  564. assert(bb->iostate == BioWriting);
  565. vtSleep(bb->ioready);
  566. }
  567. break;
  568. }
  569. consPrint("blockWrite: %R\n");
  570. if(n++ >= 5){
  571. consPrint("giving up\n");
  572. break;
  573. }
  574. sleep(5*1000);
  575. }
  576. blockPut(bb);
  577. }
  578. r = 1;
  579. Out1:
  580. blockPut(b);
  581. Out0:
  582. vtRUnlock(fs->elk);
  583. return r;
  584. }
  585. /*
  586. * Inspect and edit the blocks on disk.
  587. */
  588. static int
  589. fsysBlock(Fsys* fsys, int argc, char* argv[])
  590. {
  591. Fs *fs;
  592. char *s;
  593. Block *b;
  594. uchar *buf;
  595. u32int addr;
  596. int c, count, i, offset;
  597. char *usage = "usage: [fsys name] block addr offset [count [data]]";
  598. ARGBEGIN{
  599. default:
  600. return cliError(usage);
  601. }ARGEND
  602. if(argc < 2 || argc > 4)
  603. return cliError(usage);
  604. fs = fsys->fs;
  605. addr = strtoul(argv[0], 0, 0);
  606. offset = strtoul(argv[1], 0, 0);
  607. if(offset < 0 || offset >= fs->blockSize){
  608. vtSetError("bad offset");
  609. return 0;
  610. }
  611. if(argc > 2)
  612. count = strtoul(argv[2], 0, 0);
  613. else
  614. count = 100000000;
  615. if(offset+count > fs->blockSize)
  616. count = fs->blockSize - count;
  617. vtRLock(fs->elk);
  618. b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
  619. if(b == nil){
  620. vtSetError("cacheLocal %#ux: %R", addr);
  621. vtRUnlock(fs->elk);
  622. return 0;
  623. }
  624. consPrint("\t%sblock %#ux %ud %ud %.*H\n",
  625. argc==4 ? "old: " : "", addr, offset, count, count, b->data+offset);
  626. if(argc == 4){
  627. s = argv[3];
  628. if(strlen(s) != 2*count){
  629. vtSetError("bad data count");
  630. goto Out;
  631. }
  632. buf = vtMemAllocZ(count);
  633. for(i = 0; i < count*2; i++){
  634. if(s[i] >= '0' && s[i] <= '9')
  635. c = s[i] - '0';
  636. else if(s[i] >= 'a' && s[i] <= 'f')
  637. c = s[i] - 'a' + 10;
  638. else if(s[i] >= 'A' && s[i] <= 'F')
  639. c = s[i] - 'A' + 10;
  640. else{
  641. vtSetError("bad hex");
  642. vtMemFree(buf);
  643. goto Out;
  644. }
  645. if((i & 1) == 0)
  646. c <<= 4;
  647. buf[i>>1] |= c;
  648. }
  649. memmove(b->data+offset, buf, count);
  650. consPrint("\tnew: block %#ux %ud %ud %.*H\n",
  651. addr, offset, count, count, b->data+offset);
  652. blockDirty(b);
  653. }
  654. Out:
  655. blockPut(b);
  656. vtRUnlock(fs->elk);
  657. return 1;
  658. }
  659. /*
  660. * Free a disk block.
  661. */
  662. static int
  663. fsysBfree(Fsys* fsys, int argc, char* argv[])
  664. {
  665. Fs *fs;
  666. Label l;
  667. char *p;
  668. Block *b;
  669. u32int addr;
  670. char *usage = "usage: [fsys name] bfree addr ...";
  671. ARGBEGIN{
  672. default:
  673. return cliError(usage);
  674. }ARGEND
  675. if(argc == 0)
  676. return cliError(usage);
  677. fs = fsys->fs;
  678. vtRLock(fs->elk);
  679. while(argc > 0){
  680. addr = strtoul(argv[0], &p, 0);
  681. if(*p != '\0'){
  682. consPrint("bad address - '%ud'\n", addr);
  683. /* syntax error; let's stop */
  684. vtRUnlock(fs->elk);
  685. return 0;
  686. }
  687. b = cacheLocal(fs->cache, PartData, addr, OReadOnly);
  688. if(b == nil){
  689. consPrint("loading %#ux: %R\n", addr);
  690. continue;
  691. }
  692. l = b->l;
  693. if(l.state == BsFree)
  694. consPrint("%#ux is already free\n", addr);
  695. else{
  696. consPrint("label %#ux %ud %ud %ud %ud %#x\n",
  697. addr, l.type, l.state, l.epoch, l.epochClose, l.tag);
  698. l.state = BsFree;
  699. l.type = BtMax;
  700. l.tag = 0;
  701. l.epoch = 0;
  702. l.epochClose = 0;
  703. if(!blockSetLabel(b, &l, 0))
  704. consPrint("freeing %#ux: %R\n", addr);
  705. }
  706. blockPut(b);
  707. argc--;
  708. argv++;
  709. }
  710. vtRUnlock(fs->elk);
  711. return 1;
  712. }
  713. static int
  714. fsysDf(Fsys *fsys, int argc, char* argv[])
  715. {
  716. char *usage = "usage: [fsys name] df";
  717. u32int used, tot, bsize;
  718. Fs *fs;
  719. ARGBEGIN{
  720. default:
  721. return cliError(usage);
  722. }ARGEND
  723. if(argc != 0)
  724. return cliError(usage);
  725. fs = fsys->fs;
  726. cacheCountUsed(fs->cache, fs->elo, &used, &tot, &bsize);
  727. consPrint("\t%s: %,llud used + %,llud free = %,llud (%.1f%% used)\n",
  728. fsys->name, used*(vlong)bsize, (tot-used)*(vlong)bsize,
  729. tot*(vlong)bsize, used*100.0/tot);
  730. return 1;
  731. }
  732. /*
  733. * Zero an entry or a pointer.
  734. */
  735. static int
  736. fsysClrep(Fsys* fsys, int argc, char* argv[], int ch)
  737. {
  738. Fs *fs;
  739. Entry e;
  740. Block *b;
  741. u32int addr;
  742. int i, max, offset, sz;
  743. uchar zero[VtEntrySize];
  744. char *usage = "usage: [fsys name] clr%c addr offset ...";
  745. ARGBEGIN{
  746. default:
  747. return cliError(usage, ch);
  748. }ARGEND
  749. if(argc < 2)
  750. return cliError(usage, ch);
  751. fs = fsys->fs;
  752. vtRLock(fsys->fs->elk);
  753. addr = strtoul(argv[0], 0, 0);
  754. b = cacheLocal(fs->cache, PartData, addr, argc==4 ? OReadWrite : OReadOnly);
  755. if(b == nil){
  756. vtSetError("cacheLocal %#ux: %R", addr);
  757. Err:
  758. vtRUnlock(fsys->fs->elk);
  759. return 0;
  760. }
  761. switch(ch){
  762. default:
  763. vtSetError("clrep");
  764. goto Err;
  765. case 'e':
  766. if(b->l.type != BtDir){
  767. vtSetError("wrong block type");
  768. goto Err;
  769. }
  770. sz = VtEntrySize;
  771. memset(&e, 0, sizeof e);
  772. entryPack(&e, zero, 0);
  773. break;
  774. case 'p':
  775. if(b->l.type == BtDir || b->l.type == BtData){
  776. vtSetError("wrong block type");
  777. goto Err;
  778. }
  779. sz = VtScoreSize;
  780. memmove(zero, vtZeroScore, VtScoreSize);
  781. break;
  782. }
  783. max = fs->blockSize/sz;
  784. for(i = 1; i < argc; i++){
  785. offset = atoi(argv[i]);
  786. if(offset >= max){
  787. consPrint("\toffset %d too large (>= %d)\n", i, max);
  788. continue;
  789. }
  790. consPrint("\tblock %#ux %d %d %.*H\n", addr, offset*sz, sz, sz, b->data+offset*sz);
  791. memmove(b->data+offset*sz, zero, sz);
  792. }
  793. blockDirty(b);
  794. blockPut(b);
  795. vtRUnlock(fsys->fs->elk);
  796. return 1;
  797. }
  798. static int
  799. fsysClre(Fsys* fsys, int argc, char* argv[])
  800. {
  801. return fsysClrep(fsys, argc, argv, 'e');
  802. }
  803. static int
  804. fsysClrp(Fsys* fsys, int argc, char* argv[])
  805. {
  806. return fsysClrep(fsys, argc, argv, 'p');
  807. }
  808. static int
  809. fsysEsearch1(File* f, char* s, u32int elo)
  810. {
  811. int n, r;
  812. DirEntry de;
  813. DirEntryEnum *dee;
  814. File *ff;
  815. Entry e, ee;
  816. char *t;
  817. dee = deeOpen(f);
  818. if(dee == nil)
  819. return 0;
  820. n = 0;
  821. for(;;){
  822. r = deeRead(dee, &de);
  823. if(r < 0){
  824. consPrint("\tdeeRead %s/%s: %R\n", s, de.elem);
  825. break;
  826. }
  827. if(r == 0)
  828. break;
  829. if(de.mode & ModeSnapshot){
  830. if((ff = fileWalk(f, de.elem)) == nil)
  831. consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
  832. else{
  833. if(!fileGetSources(ff, &e, &ee))
  834. consPrint("\tcannot get sources for %s/%s: %R\n", s, de.elem);
  835. else if(e.snap != 0 && e.snap < elo){
  836. consPrint("\t%ud\tclri %s/%s\n", e.snap, s, de.elem);
  837. n++;
  838. }
  839. fileDecRef(ff);
  840. }
  841. }
  842. else if(de.mode & ModeDir){
  843. if((ff = fileWalk(f, de.elem)) == nil)
  844. consPrint("\tcannot walk %s/%s: %R\n", s, de.elem);
  845. else{
  846. t = smprint("%s/%s", s, de.elem);
  847. n += fsysEsearch1(ff, t, elo);
  848. vtMemFree(t);
  849. fileDecRef(ff);
  850. }
  851. }
  852. deCleanup(&de);
  853. if(r < 0)
  854. break;
  855. }
  856. deeClose(dee);
  857. return n;
  858. }
  859. static int
  860. fsysEsearch(Fs* fs, char* path, u32int elo)
  861. {
  862. int n;
  863. File *f;
  864. DirEntry de;
  865. f = fileOpen(fs, path);
  866. if(f == nil)
  867. return 0;
  868. if(!fileGetDir(f, &de)){
  869. consPrint("\tfileGetDir %s failed: %R\n", path);
  870. fileDecRef(f);
  871. return 0;
  872. }
  873. if((de.mode & ModeDir) == 0){
  874. fileDecRef(f);
  875. deCleanup(&de);
  876. return 0;
  877. }
  878. deCleanup(&de);
  879. n = fsysEsearch1(f, path, elo);
  880. fileDecRef(f);
  881. return n;
  882. }
  883. static int
  884. fsysEpoch(Fsys* fsys, int argc, char* argv[])
  885. {
  886. Fs *fs;
  887. int force, n, remove;
  888. u32int low, old;
  889. char *usage = "usage: [fsys name] epoch [[-ry] low]";
  890. force = 0;
  891. remove = 0;
  892. ARGBEGIN{
  893. case 'y':
  894. force = 1;
  895. break;
  896. case 'r':
  897. remove = 1;
  898. break;
  899. default:
  900. return cliError(usage);
  901. }ARGEND
  902. if(argc > 1)
  903. return cliError(usage);
  904. if(argc > 0)
  905. low = strtoul(argv[0], 0, 0);
  906. else
  907. low = ~(u32int)0;
  908. if(low == 0)
  909. return cliError("low epoch cannot be zero");
  910. fs = fsys->fs;
  911. vtRLock(fs->elk);
  912. consPrint("\tlow %ud hi %ud\n", fs->elo, fs->ehi);
  913. if(low == ~(u32int)0){
  914. vtRUnlock(fs->elk);
  915. return 1;
  916. }
  917. n = fsysEsearch(fsys->fs, "/archive", low);
  918. n += fsysEsearch(fsys->fs, "/snapshot", low);
  919. consPrint("\t%d snapshot%s found with epoch < %ud\n", n, n==1 ? "" : "s", low);
  920. vtRUnlock(fs->elk);
  921. /*
  922. * There's a small race here -- a new snapshot with epoch < low might
  923. * get introduced now that we unlocked fs->elk. Low has to
  924. * be <= fs->ehi. Of course, in order for this to happen low has
  925. * to be equal to the current fs->ehi _and_ a snapshot has to
  926. * run right now. This is a small enough window that I don't care.
  927. */
  928. if(n != 0 && !force){
  929. consPrint("\tnot setting low epoch\n");
  930. return 1;
  931. }
  932. old = fs->elo;
  933. if(!fsEpochLow(fs, low))
  934. consPrint("\tfsEpochLow: %R\n");
  935. else{
  936. consPrint("\told: epoch%s %ud\n", force ? " -y" : "", old);
  937. consPrint("\tnew: epoch%s %ud\n", force ? " -y" : "", fs->elo);
  938. if(fs->elo < low)
  939. consPrint("\twarning: new low epoch < old low epoch\n");
  940. if(force && remove)
  941. fsSnapshotRemove(fs);
  942. }
  943. return 1;
  944. }
  945. static int
  946. fsysCreate(Fsys* fsys, int argc, char* argv[])
  947. {
  948. int r;
  949. ulong mode;
  950. char *elem, *p, *path;
  951. char *usage = "usage: [fsys name] create path uid gid perm";
  952. DirEntry de;
  953. File *file, *parent;
  954. ARGBEGIN{
  955. default:
  956. return cliError(usage);
  957. }ARGEND
  958. if(argc != 4)
  959. return cliError(usage);
  960. if(!fsysParseMode(argv[3], &mode))
  961. return cliError(usage);
  962. if(mode&ModeSnapshot)
  963. return cliError("create - cannot create with snapshot bit set");
  964. if(strcmp(argv[1], uidnoworld) == 0)
  965. return cliError("permission denied");
  966. vtRLock(fsys->fs->elk);
  967. path = vtStrDup(argv[0]);
  968. if((p = strrchr(path, '/')) != nil){
  969. *p++ = '\0';
  970. elem = p;
  971. p = path;
  972. if(*p == '\0')
  973. p = "/";
  974. }
  975. else{
  976. p = "/";
  977. elem = path;
  978. }
  979. r = 0;
  980. if((parent = fileOpen(fsys->fs, p)) == nil)
  981. goto out;
  982. file = fileCreate(parent, elem, mode, argv[1]);
  983. fileDecRef(parent);
  984. if(file == nil){
  985. vtSetError("create %s/%s: %R", p, elem);
  986. goto out;
  987. }
  988. if(!fileGetDir(file, &de)){
  989. vtSetError("stat failed after create: %R");
  990. goto out1;
  991. }
  992. if(strcmp(de.gid, argv[2]) != 0){
  993. vtMemFree(de.gid);
  994. de.gid = vtStrDup(argv[2]);
  995. if(!fileSetDir(file, &de, argv[1])){
  996. vtSetError("wstat failed after create: %R");
  997. goto out2;
  998. }
  999. }
  1000. r = 1;
  1001. out2:
  1002. deCleanup(&de);
  1003. out1:
  1004. fileDecRef(file);
  1005. out:
  1006. vtMemFree(path);
  1007. vtRUnlock(fsys->fs->elk);
  1008. return r;
  1009. }
  1010. static void
  1011. fsysPrintStat(char *prefix, char *file, DirEntry *de)
  1012. {
  1013. char buf[64];
  1014. if(prefix == nil)
  1015. prefix = "";
  1016. consPrint("%sstat %q %q %q %q %s %llud\n", prefix,
  1017. file, de->elem, de->uid, de->gid, fsysModeString(de->mode, buf), de->size);
  1018. }
  1019. static int
  1020. fsysStat(Fsys* fsys, int argc, char* argv[])
  1021. {
  1022. int i;
  1023. File *f;
  1024. DirEntry de;
  1025. char *usage = "usage: [fsys name] stat files...";
  1026. ARGBEGIN{
  1027. default:
  1028. return cliError(usage);
  1029. }ARGEND
  1030. if(argc == 0)
  1031. return cliError(usage);
  1032. vtRLock(fsys->fs->elk);
  1033. for(i=0; i<argc; i++){
  1034. if((f = fileOpen(fsys->fs, argv[i])) == nil){
  1035. consPrint("%s: %R\n", argv[i]);
  1036. continue;
  1037. }
  1038. if(!fileGetDir(f, &de)){
  1039. consPrint("%s: %R\n", argv[i]);
  1040. fileDecRef(f);
  1041. continue;
  1042. }
  1043. fsysPrintStat("\t", argv[i], &de);
  1044. deCleanup(&de);
  1045. fileDecRef(f);
  1046. }
  1047. vtRUnlock(fsys->fs->elk);
  1048. return 1;
  1049. }
  1050. static int
  1051. fsysWstat(Fsys *fsys, int argc, char* argv[])
  1052. {
  1053. File *f;
  1054. char *p;
  1055. DirEntry de;
  1056. char *usage = "usage: [fsys name] wstat file elem uid gid mode length\n"
  1057. "\tuse - for any field to mean don't change";
  1058. ARGBEGIN{
  1059. default:
  1060. return cliError(usage);
  1061. }ARGEND
  1062. if(argc != 6)
  1063. return cliError(usage);
  1064. vtRLock(fsys->fs->elk);
  1065. if((f = fileOpen(fsys->fs, argv[0])) == nil){
  1066. vtSetError("console wstat - walk - %R");
  1067. vtRUnlock(fsys->fs->elk);
  1068. return 0;
  1069. }
  1070. if(!fileGetDir(f, &de)){
  1071. vtSetError("console wstat - stat - %R");
  1072. fileDecRef(f);
  1073. vtRUnlock(fsys->fs->elk);
  1074. return 0;
  1075. }
  1076. fsysPrintStat("\told: w", argv[0], &de);
  1077. if(strcmp(argv[1], "-") != 0){
  1078. if(!validFileName(argv[1])){
  1079. vtSetError("console wstat - bad elem");
  1080. goto error;
  1081. }
  1082. vtMemFree(de.elem);
  1083. de.elem = vtStrDup(argv[1]);
  1084. }
  1085. if(strcmp(argv[2], "-") != 0){
  1086. if(!validUserName(argv[2])){
  1087. vtSetError("console wstat - bad uid");
  1088. goto error;
  1089. }
  1090. vtMemFree(de.uid);
  1091. de.uid = vtStrDup(argv[2]);
  1092. }
  1093. if(strcmp(argv[3], "-") != 0){
  1094. if(!validUserName(argv[3])){
  1095. vtSetError("console wstat - bad gid");
  1096. goto error;
  1097. }
  1098. vtMemFree(de.gid);
  1099. de.gid = vtStrDup(argv[3]);
  1100. }
  1101. if(strcmp(argv[4], "-") != 0){
  1102. if(!fsysParseMode(argv[4], &de.mode)){
  1103. vtSetError("console wstat - bad mode");
  1104. goto error;
  1105. }
  1106. }
  1107. if(strcmp(argv[5], "-") != 0){
  1108. de.size = strtoull(argv[5], &p, 0);
  1109. if(argv[5][0] == '\0' || *p != '\0' || (vlong)de.size < 0){
  1110. vtSetError("console wstat - bad length");
  1111. goto error;
  1112. }
  1113. }
  1114. if(!fileSetDir(f, &de, uidadm)){
  1115. vtSetError("console wstat - %R");
  1116. goto error;
  1117. }
  1118. deCleanup(&de);
  1119. if(!fileGetDir(f, &de)){
  1120. vtSetError("console wstat - stat2 - %R");
  1121. goto error;
  1122. }
  1123. fsysPrintStat("\tnew: w", argv[0], &de);
  1124. deCleanup(&de);
  1125. fileDecRef(f);
  1126. vtRUnlock(fsys->fs->elk);
  1127. return 1;
  1128. error:
  1129. deCleanup(&de); /* okay to do this twice */
  1130. fileDecRef(f);
  1131. vtRUnlock(fsys->fs->elk);
  1132. return 0;
  1133. }
  1134. static void
  1135. fsckClri(Fsck *fsck, char *name, MetaBlock *mb, int i, Block *b)
  1136. {
  1137. USED(name);
  1138. if((fsck->flags&DoClri) == 0)
  1139. return;
  1140. mbDelete(mb, i);
  1141. mbPack(mb);
  1142. blockDirty(b);
  1143. }
  1144. static void
  1145. fsckClose(Fsck *fsck, Block *b, u32int epoch)
  1146. {
  1147. Label l;
  1148. if((fsck->flags&DoClose) == 0)
  1149. return;
  1150. l = b->l;
  1151. if(l.state == BsFree || (l.state&BsClosed)){
  1152. consPrint("%#ux is already closed\n", b->addr);
  1153. return;
  1154. }
  1155. if(epoch){
  1156. l.state |= BsClosed;
  1157. l.epochClose = epoch;
  1158. }else
  1159. l.state = BsFree;
  1160. if(!blockSetLabel(b, &l, 0))
  1161. consPrint("%#ux setlabel: %R\n", b->addr);
  1162. }
  1163. static void
  1164. fsckClre(Fsck *fsck, Block *b, int offset)
  1165. {
  1166. Entry e;
  1167. if((fsck->flags&DoClre) == 0)
  1168. return;
  1169. if(offset<0 || offset*VtEntrySize >= fsck->bsize){
  1170. consPrint("bad clre\n");
  1171. return;
  1172. }
  1173. memset(&e, 0, sizeof e);
  1174. entryPack(&e, b->data, offset);
  1175. blockDirty(b);
  1176. }
  1177. static void
  1178. fsckClrp(Fsck *fsck, Block *b, int offset)
  1179. {
  1180. if((fsck->flags&DoClrp) == 0)
  1181. return;
  1182. if(offset<0 || offset*VtScoreSize >= fsck->bsize){
  1183. consPrint("bad clre\n");
  1184. return;
  1185. }
  1186. memmove(b->data+offset*VtScoreSize, vtZeroScore, VtScoreSize);
  1187. blockDirty(b);
  1188. }
  1189. static int
  1190. fsysCheck(Fsys *fsys, int argc, char *argv[])
  1191. {
  1192. int i, halting;
  1193. char *usage = "usage: [fsys name] check [-v] [options]";
  1194. Fsck fsck;
  1195. Block *b;
  1196. Super super;
  1197. memset(&fsck, 0, sizeof fsck);
  1198. fsck.fs = fsys->fs;
  1199. fsck.clri = fsckClri;
  1200. fsck.clre = fsckClre;
  1201. fsck.clrp = fsckClrp;
  1202. fsck.close = fsckClose;
  1203. fsck.print = consPrint;
  1204. ARGBEGIN{
  1205. default:
  1206. return cliError(usage);
  1207. }ARGEND
  1208. for(i=0; i<argc; i++){
  1209. if(strcmp(argv[i], "pblock") == 0)
  1210. fsck.printblocks = 1;
  1211. else if(strcmp(argv[i], "pdir") == 0)
  1212. fsck.printdirs = 1;
  1213. else if(strcmp(argv[i], "pfile") == 0)
  1214. fsck.printfiles = 1;
  1215. else if(strcmp(argv[i], "bclose") == 0)
  1216. fsck.flags |= DoClose;
  1217. else if(strcmp(argv[i], "clri") == 0)
  1218. fsck.flags |= DoClri;
  1219. else if(strcmp(argv[i], "clre") == 0)
  1220. fsck.flags |= DoClre;
  1221. else if(strcmp(argv[i], "clrp") == 0)
  1222. fsck.flags |= DoClrp;
  1223. else if(strcmp(argv[i], "fix") == 0)
  1224. fsck.flags |= DoClose|DoClri|DoClre|DoClrp;
  1225. else if(strcmp(argv[i], "venti") == 0)
  1226. fsck.useventi = 1;
  1227. else if(strcmp(argv[i], "snapshot") == 0)
  1228. fsck.walksnapshots = 1;
  1229. else{
  1230. consPrint("unknown option '%s'\n", argv[i]);
  1231. return cliError(usage);
  1232. }
  1233. }
  1234. halting = fsys->fs->halted==0;
  1235. if(halting)
  1236. fsHalt(fsys->fs);
  1237. if(fsys->fs->arch){
  1238. b = superGet(fsys->fs->cache, &super);
  1239. if(b == nil){
  1240. consPrint("could not load super block\n");
  1241. goto Out;
  1242. }
  1243. blockPut(b);
  1244. if(super.current != NilBlock){
  1245. consPrint("cannot check fs while archiver is running; "
  1246. "wait for it to finish\n");
  1247. goto Out;
  1248. }
  1249. }
  1250. fsCheck(&fsck);
  1251. consPrint("fsck: %d clri, %d clre, %d clrp, %d bclose\n",
  1252. fsck.nclri, fsck.nclre, fsck.nclrp, fsck.nclose);
  1253. Out:
  1254. if(halting)
  1255. fsUnhalt(fsys->fs);
  1256. return 1;
  1257. }
  1258. static int
  1259. fsysVenti(char* name, int argc, char* argv[])
  1260. {
  1261. int r;
  1262. char *host;
  1263. char *usage = "usage: [fsys name] venti [address]";
  1264. Fsys *fsys;
  1265. ARGBEGIN{
  1266. default:
  1267. return cliError(usage);
  1268. }ARGEND
  1269. if(argc == 0)
  1270. host = nil;
  1271. else if(argc == 1)
  1272. host = argv[0];
  1273. else
  1274. return cliError(usage);
  1275. if((fsys = _fsysGet(name)) == nil)
  1276. return 0;
  1277. vtLock(fsys->lock);
  1278. if(host == nil)
  1279. host = fsys->venti;
  1280. else{
  1281. vtMemFree(fsys->venti);
  1282. if(host[0])
  1283. fsys->venti = vtStrDup(host);
  1284. else{
  1285. host = nil;
  1286. fsys->venti = nil;
  1287. }
  1288. }
  1289. /* already open: do a redial */
  1290. if(fsys->fs != nil){
  1291. if(fsys->session == nil){
  1292. vtSetError("file system was opened with -V");
  1293. r = 0;
  1294. goto out;
  1295. }
  1296. r = 1;
  1297. if(!myRedial(fsys->session, host)
  1298. || !vtConnect(fsys->session, 0))
  1299. r = 0;
  1300. goto out;
  1301. }
  1302. /* not yet open: try to dial */
  1303. if(fsys->session)
  1304. vtClose(fsys->session);
  1305. r = 1;
  1306. if((fsys->session = myDial(host, 0)) == nil
  1307. || !vtConnect(fsys->session, 0))
  1308. r = 0;
  1309. out:
  1310. vtUnlock(fsys->lock);
  1311. fsysPut(fsys);
  1312. return r;
  1313. }
  1314. static ulong
  1315. freemem(void)
  1316. {
  1317. int nf, pgsize = 0;
  1318. uvlong size, userpgs = 0, userused = 0;
  1319. char *ln, *sl;
  1320. char *fields[2];
  1321. Biobuf *bp;
  1322. size = 64*1024*1024;
  1323. bp = Bopen("#c/swap", OREAD);
  1324. if (bp != nil) {
  1325. while ((ln = Brdline(bp, '\n')) != nil) {
  1326. ln[Blinelen(bp)-1] = '\0';
  1327. nf = tokenize(ln, fields, nelem(fields));
  1328. if (nf != 2)
  1329. continue;
  1330. if (strcmp(fields[1], "pagesize") == 0)
  1331. pgsize = atoi(fields[0]);
  1332. else if (strcmp(fields[1], "user") == 0) {
  1333. sl = strchr(fields[0], '/');
  1334. if (sl == nil)
  1335. continue;
  1336. userpgs = atoll(sl+1);
  1337. userused = atoll(fields[0]);
  1338. }
  1339. }
  1340. Bterm(bp);
  1341. if (pgsize > 0 && userpgs > 0)
  1342. size = (userpgs - userused) * pgsize;
  1343. }
  1344. /* cap it to keep the size within 32 bits */
  1345. if (size >= 3840UL * 1024 * 1024)
  1346. size = 3840UL * 1024 * 1024;
  1347. return size;
  1348. }
  1349. static int
  1350. fsysOpen(char* name, int argc, char* argv[])
  1351. {
  1352. char *p, *host;
  1353. Fsys *fsys;
  1354. int noauth, noventi, noperm, rflag, wstatallow, noatimeupd;
  1355. long ncache;
  1356. char *usage = "usage: fsys name open [-APVWr] [-c ncache]";
  1357. ncache = 1000;
  1358. noauth = noperm = wstatallow = noventi = noatimeupd = 0;
  1359. rflag = OReadWrite;
  1360. ARGBEGIN{
  1361. default:
  1362. return cliError(usage);
  1363. case 'A':
  1364. noauth = 1;
  1365. break;
  1366. case 'P':
  1367. noperm = 1;
  1368. break;
  1369. case 'V':
  1370. noventi = 1;
  1371. break;
  1372. case 'W':
  1373. wstatallow = 1;
  1374. break;
  1375. case 'a':
  1376. noatimeupd = 1;
  1377. break;
  1378. case 'c':
  1379. p = ARGF();
  1380. if(p == nil)
  1381. return cliError(usage);
  1382. ncache = strtol(argv[0], &p, 0);
  1383. if(ncache <= 0 || p == argv[0] || *p != '\0')
  1384. return cliError(usage);
  1385. break;
  1386. case 'r':
  1387. rflag = OReadOnly;
  1388. break;
  1389. }ARGEND
  1390. if(argc)
  1391. return cliError(usage);
  1392. if((fsys = _fsysGet(name)) == nil)
  1393. return 0;
  1394. /* automatic memory sizing? */
  1395. if(mempcnt > 0) {
  1396. /* TODO: 8K is a hack; use the actual block size */
  1397. ncache = (((vlong)freemem() * mempcnt) / 100) / (8*1024);
  1398. if (ncache < 100)
  1399. ncache = 100;
  1400. }
  1401. vtLock(fsys->lock);
  1402. if(fsys->fs != nil){
  1403. vtSetError(EFsysBusy, fsys->name);
  1404. vtUnlock(fsys->lock);
  1405. fsysPut(fsys);
  1406. return 0;
  1407. }
  1408. if(noventi){
  1409. if(fsys->session){
  1410. vtClose(fsys->session);
  1411. fsys->session = nil;
  1412. }
  1413. }
  1414. else if(fsys->session == nil){
  1415. if(fsys->venti && fsys->venti[0])
  1416. host = fsys->venti;
  1417. else
  1418. host = nil;
  1419. fsys->session = myDial(host, 1);
  1420. if(!vtConnect(fsys->session, nil) && !noventi)
  1421. fprint(2, "warning: connecting to venti: %R\n");
  1422. }
  1423. if((fsys->fs = fsOpen(fsys->dev, fsys->session, ncache, rflag)) == nil){
  1424. vtSetError("fsOpen: %R");
  1425. vtUnlock(fsys->lock);
  1426. fsysPut(fsys);
  1427. return 0;
  1428. }
  1429. fsys->fs->name = fsys->name; /* for better error messages */
  1430. fsys->noauth = noauth;
  1431. fsys->noperm = noperm;
  1432. fsys->wstatallow = wstatallow;
  1433. fsys->fs->noatimeupd = noatimeupd;
  1434. vtUnlock(fsys->lock);
  1435. fsysPut(fsys);
  1436. if(strcmp(name, "main") == 0)
  1437. usersFileRead(nil);
  1438. return 1;
  1439. }
  1440. static int
  1441. fsysUnconfig(char* name, int argc, char* argv[])
  1442. {
  1443. Fsys *fsys, **fp;
  1444. char *usage = "usage: fsys name unconfig";
  1445. ARGBEGIN{
  1446. default:
  1447. return cliError(usage);
  1448. }ARGEND
  1449. if(argc)
  1450. return cliError(usage);
  1451. vtLock(sbox.lock);
  1452. fp = &sbox.head;
  1453. for(fsys = *fp; fsys != nil; fsys = fsys->next){
  1454. if(strcmp(fsys->name, name) == 0)
  1455. break;
  1456. fp = &fsys->next;
  1457. }
  1458. if(fsys == nil){
  1459. vtSetError(EFsysNotFound, name);
  1460. vtUnlock(sbox.lock);
  1461. return 0;
  1462. }
  1463. if(fsys->ref != 0 || fsys->fs != nil){
  1464. vtSetError(EFsysBusy, fsys->name);
  1465. vtUnlock(sbox.lock);
  1466. return 0;
  1467. }
  1468. *fp = fsys->next;
  1469. vtUnlock(sbox.lock);
  1470. if(fsys->session != nil){
  1471. vtClose(fsys->session);
  1472. vtFree(fsys->session);
  1473. }
  1474. if(fsys->venti != nil)
  1475. vtMemFree(fsys->venti);
  1476. if(fsys->dev != nil)
  1477. vtMemFree(fsys->dev);
  1478. if(fsys->name != nil)
  1479. vtMemFree(fsys->name);
  1480. vtMemFree(fsys);
  1481. return 1;
  1482. }
  1483. static int
  1484. fsysConfig(char* name, int argc, char* argv[])
  1485. {
  1486. Fsys *fsys;
  1487. char *part;
  1488. char *usage = "usage: fsys name config [dev]";
  1489. ARGBEGIN{
  1490. default:
  1491. return cliError(usage);
  1492. }ARGEND
  1493. if(argc > 1)
  1494. return cliError(usage);
  1495. if(argc == 0)
  1496. part = foptname;
  1497. else
  1498. part = argv[0];
  1499. if((fsys = _fsysGet(part)) != nil){
  1500. vtLock(fsys->lock);
  1501. if(fsys->fs != nil){
  1502. vtSetError(EFsysBusy, fsys->name);
  1503. vtUnlock(fsys->lock);
  1504. fsysPut(fsys);
  1505. return 0;
  1506. }
  1507. vtMemFree(fsys->dev);
  1508. fsys->dev = vtStrDup(part);
  1509. vtUnlock(fsys->lock);
  1510. }
  1511. else if((fsys = fsysAlloc(name, part)) == nil)
  1512. return 0;
  1513. fsysPut(fsys);
  1514. return 1;
  1515. }
  1516. static struct {
  1517. char* cmd;
  1518. int (*f)(Fsys*, int, char**);
  1519. int (*f1)(char*, int, char**);
  1520. } fsyscmd[] = {
  1521. { "close", fsysClose, },
  1522. { "config", nil, fsysConfig, },
  1523. { "open", nil, fsysOpen, },
  1524. { "unconfig", nil, fsysUnconfig, },
  1525. { "venti", nil, fsysVenti, },
  1526. { "bfree", fsysBfree, },
  1527. { "block", fsysBlock, },
  1528. { "check", fsysCheck, },
  1529. { "clre", fsysClre, },
  1530. { "clri", fsysClri, },
  1531. { "clrp", fsysClrp, },
  1532. { "create", fsysCreate, },
  1533. { "df", fsysDf, },
  1534. { "epoch", fsysEpoch, },
  1535. { "halt", fsysHalt, },
  1536. { "label", fsysLabel, },
  1537. { "remove", fsysRemove, },
  1538. { "snap", fsysSnap, },
  1539. { "snaptime", fsysSnapTime, },
  1540. { "snapclean", fsysSnapClean, },
  1541. { "stat", fsysStat, },
  1542. { "sync", fsysSync, },
  1543. { "unhalt", fsysUnhalt, },
  1544. { "wstat", fsysWstat, },
  1545. { "vac", fsysVac, },
  1546. { nil, nil, },
  1547. };
  1548. static int
  1549. fsysXXX1(Fsys *fsys, int i, int argc, char* argv[])
  1550. {
  1551. int r;
  1552. vtLock(fsys->lock);
  1553. if(fsys->fs == nil){
  1554. vtUnlock(fsys->lock);
  1555. vtSetError(EFsysNotOpen, fsys->name);
  1556. return 0;
  1557. }
  1558. if(fsys->fs->halted
  1559. && fsyscmd[i].f != fsysUnhalt && fsyscmd[i].f != fsysCheck){
  1560. vtSetError("file system %s is halted", fsys->name);
  1561. vtUnlock(fsys->lock);
  1562. return 0;
  1563. }
  1564. r = (*fsyscmd[i].f)(fsys, argc, argv);
  1565. vtUnlock(fsys->lock);
  1566. return r;
  1567. }
  1568. static int
  1569. fsysXXX(char* name, int argc, char* argv[])
  1570. {
  1571. int i, r;
  1572. Fsys *fsys;
  1573. for(i = 0; fsyscmd[i].cmd != nil; i++){
  1574. if(strcmp(fsyscmd[i].cmd, argv[0]) == 0)
  1575. break;
  1576. }
  1577. if(fsyscmd[i].cmd == nil){
  1578. vtSetError("unknown command - '%s'", argv[0]);
  1579. return 0;
  1580. }
  1581. /* some commands want the name... */
  1582. if(fsyscmd[i].f1 != nil){
  1583. if(strcmp(name, FsysAll) == 0){
  1584. vtSetError("cannot use fsys %#q with %#q command", FsysAll, argv[0]);
  1585. return 0;
  1586. }
  1587. return (*fsyscmd[i].f1)(name, argc, argv);
  1588. }
  1589. /* ... but most commands want the Fsys */
  1590. if(strcmp(name, FsysAll) == 0){
  1591. r = 1;
  1592. vtRLock(sbox.lock);
  1593. for(fsys = sbox.head; fsys != nil; fsys = fsys->next){
  1594. fsys->ref++;
  1595. r = fsysXXX1(fsys, i, argc, argv) && r;
  1596. fsys->ref--;
  1597. }
  1598. vtRUnlock(sbox.lock);
  1599. }else{
  1600. if((fsys = _fsysGet(name)) == nil)
  1601. return 0;
  1602. r = fsysXXX1(fsys, i, argc, argv);
  1603. fsysPut(fsys);
  1604. }
  1605. return r;
  1606. }
  1607. static int
  1608. cmdFsysXXX(int argc, char* argv[])
  1609. {
  1610. char *name;
  1611. if((name = sbox.curfsys) == nil){
  1612. vtSetError(EFsysNoCurrent, argv[0]);
  1613. return 0;
  1614. }
  1615. return fsysXXX(name, argc, argv);
  1616. }
  1617. static int
  1618. cmdFsys(int argc, char* argv[])
  1619. {
  1620. Fsys *fsys;
  1621. char *usage = "usage: fsys [name ...]";
  1622. ARGBEGIN{
  1623. default:
  1624. return cliError(usage);
  1625. }ARGEND
  1626. if(argc == 0){
  1627. vtRLock(sbox.lock);
  1628. currfsysname = sbox.head->name;
  1629. for(fsys = sbox.head; fsys != nil; fsys = fsys->next)
  1630. consPrint("\t%s\n", fsys->name);
  1631. vtRUnlock(sbox.lock);
  1632. return 1;
  1633. }
  1634. if(argc == 1){
  1635. fsys = nil;
  1636. if(strcmp(argv[0], FsysAll) != 0 && (fsys = fsysGet(argv[0])) == nil)
  1637. return 0;
  1638. sbox.curfsys = vtStrDup(argv[0]);
  1639. consPrompt(sbox.curfsys);
  1640. if(fsys)
  1641. fsysPut(fsys);
  1642. return 1;
  1643. }
  1644. return fsysXXX(argv[0], argc-1, argv+1);
  1645. }
  1646. int
  1647. fsysInit(void)
  1648. {
  1649. int i;
  1650. fmtinstall('H', encodefmt);
  1651. fmtinstall('V', scoreFmt);
  1652. fmtinstall('R', vtErrFmt);
  1653. fmtinstall('L', labelFmt);
  1654. sbox.lock = vtLockAlloc();
  1655. cliAddCmd("fsys", cmdFsys);
  1656. for(i = 0; fsyscmd[i].cmd != nil; i++){
  1657. if(fsyscmd[i].f != nil)
  1658. cliAddCmd(fsyscmd[i].cmd, cmdFsysXXX);
  1659. }
  1660. /* the venti cmd is special: the fs can be either open or closed */
  1661. cliAddCmd("venti", cmdFsysXXX);
  1662. cliAddCmd("printconfig", cmdPrintConfig);
  1663. return 1;
  1664. }