cw.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275
  1. #include "all.h"
  2. #define DEBUG 0
  3. #define FIRST SUPER_ADDR
  4. #define ADDFREE (100)
  5. #define CACHE_ADDR SUPER_ADDR
  6. #define MAXAGE 10000
  7. #define CDEV(d) (d->cw.c)
  8. #define WDEV(d) (d->cw.w)
  9. #define RDEV(d) (d->cw.ro)
  10. /* cache state */
  11. enum
  12. {
  13. /* states -- beware these are recorded on the cache */
  14. /* cache worm */
  15. Cnone = 0, /* 0 ? */
  16. Cdirty, /* 1 0 */
  17. Cdump, /* 1 0->1 */
  18. Cread, /* 1 1 */
  19. Cwrite, /* 2 1 */
  20. Cdump1, /* inactive form of dump */
  21. Cerror,
  22. /* opcodes -- these are not recorded */
  23. Onone,
  24. Oread,
  25. Owrite,
  26. Ogrow,
  27. Odump,
  28. Orele,
  29. Ofree,
  30. };
  31. typedef struct Cw Cw;
  32. struct Cw
  33. {
  34. Device* dev;
  35. Device* cdev;
  36. Device* wdev;
  37. Device* rodev;
  38. Cw* link;
  39. Filter ncwio[3];
  40. int dbucket; /* last bucket dumped */
  41. long daddr; /* last block dumped */
  42. long ncopy;
  43. int nodump;
  44. /*
  45. * following are cached variables for dumps
  46. */
  47. long fsize;
  48. long ndump;
  49. int depth;
  50. int all; /* local flag to recur on modified directories */
  51. int allflag; /* global flag to recur on modified directories */
  52. long falsehits; /* times recur found modified blocks */
  53. struct
  54. {
  55. char name[500];
  56. char namepad[NAMELEN+10];
  57. };
  58. };
  59. static
  60. char* cwnames[] =
  61. {
  62. [Cnone] "none",
  63. [Cdirty] "dirty",
  64. [Cdump] "dump",
  65. [Cread] "read",
  66. [Cwrite] "write",
  67. [Cdump1] "dump1",
  68. [Cerror] "error",
  69. [Onone] "none",
  70. [Oread] "read",
  71. [Owrite] "write",
  72. [Ogrow] "grow",
  73. [Odump] "dump",
  74. [Orele] "rele",
  75. };
  76. Centry* getcentry(Bucket*, long);
  77. int cwio(Device*, long, void*, int);
  78. void cmd_cwcmd(int, char*[]);
  79. /*
  80. * console command
  81. * initiate a dump
  82. */
  83. void
  84. cmd_dump(int argc, char *argv[])
  85. {
  86. Filsys *fs;
  87. fs = cons.curfs;
  88. if(argc > 1)
  89. fs = fsstr(argv[1]);
  90. if(fs == 0) {
  91. print("%s: unknown file system\n", argv[1]);
  92. return;
  93. }
  94. cfsdump(fs);
  95. }
  96. /*
  97. * console command
  98. * worm stats
  99. */
  100. static
  101. void
  102. cmd_statw(int, char*[])
  103. {
  104. Filsys *fs;
  105. Iobuf *p;
  106. Superb *sb;
  107. Cache *h;
  108. Bucket *b;
  109. Centry *c, *ce;
  110. long m, nw, bw, state[Onone];
  111. long sbfsize, sbcwraddr, sbroraddr, sblast, sbnext;
  112. long hmsize, hmaddr, dsize, dsizepct;
  113. Device *dev;
  114. Cw *cw;
  115. int s;
  116. fs = cons.curfs;
  117. dev = fs->dev;
  118. if(dev->type != Devcw) {
  119. print("curfs not type cw\n");
  120. return;
  121. }
  122. cw = dev->private;
  123. if(cw == 0) {
  124. print("curfs not inited\n");
  125. return;
  126. }
  127. print("cwstats %s\n", fs->name);
  128. sbfsize = 0;
  129. sbcwraddr = 0;
  130. sbroraddr = 0;
  131. sblast = 0;
  132. sbnext = 0;
  133. print(" filesys %s\n", fs->name);
  134. print(" nio =%7W%7W%7W\n", cw->ncwio+0, cw->ncwio+1, cw->ncwio+2);
  135. p = getbuf(dev, cwsaddr(dev), Bread);
  136. if(!p || checktag(p, Tsuper, QPSUPER)) {
  137. print("cwstats: checktag super\n");
  138. if(p) {
  139. putbuf(p);
  140. p = 0;
  141. }
  142. }
  143. if(p) {
  144. sb = (Superb*)p->iobuf;
  145. sbfsize = sb->fsize;
  146. sbcwraddr = sb->cwraddr;
  147. sbroraddr = sb->roraddr;
  148. sblast = sb->last;
  149. sbnext = sb->next;
  150. putbuf(p);
  151. }
  152. p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);
  153. if(!p || checktag(p, Tcache, QPSUPER)) {
  154. print("cwstats: checktag c bucket\n");
  155. if(p)
  156. putbuf(p);
  157. return;
  158. }
  159. h = (Cache*)p->iobuf;
  160. hmaddr = h->maddr;
  161. hmsize = h->msize;
  162. print(" maddr = %8ld\n", hmaddr);
  163. print(" msize = %8ld\n", hmsize);
  164. print(" caddr = %8ld\n", h->caddr);
  165. print(" csize = %8ld\n", h->csize);
  166. print(" sbaddr = %8ld\n", h->sbaddr);
  167. print(" craddr = %8ld %8ld\n", h->cwraddr, sbcwraddr);
  168. print(" roaddr = %8ld %8ld\n", h->roraddr, sbroraddr);
  169. /* print stats in terms of (first-)disc sides */
  170. dsize = wormsizeside(dev, 0);
  171. if (dsize < 1) {
  172. if (DEBUG)
  173. print("wormsizeside returned size %ld for %Z side 0\n",
  174. dsize, dev);
  175. dsize = h->wsize; /* it's probably a fake worm */
  176. if (dsize < 1)
  177. dsize = 1000; /* don't divide by zero */
  178. }
  179. dsizepct = dsize/100;
  180. print(" fsize = %8ld %8ld %2ld+%2ld%%\n", h->fsize, sbfsize,
  181. h->fsize/dsize, (h->fsize%dsize)/dsizepct);
  182. print(" slast = %8ld\n", sblast);
  183. print(" snext = %8ld\n", sbnext);
  184. print(" wmax = %8ld %2ld+%2ld%%\n", h->wmax,
  185. h->wmax/dsize, (h->wmax%dsize)/dsizepct);
  186. print(" wsize = %8ld %2ld+%2ld%%\n", h->wsize,
  187. h->wsize/dsize, (h->wsize%dsize)/dsizepct);
  188. putbuf(p);
  189. bw = 0; /* max filled bucket */
  190. memset(state, 0, sizeof(state));
  191. for(m=0; m<hmsize; m++) {
  192. p = getbuf(cw->cdev, hmaddr + m/BKPERBLK, Bread);
  193. if(!p || checktag(p, Tbuck, hmaddr + m/BKPERBLK)) {
  194. print("cwstats: checktag c bucket\n");
  195. if(p)
  196. putbuf(p);
  197. return;
  198. }
  199. b = (Bucket*)p->iobuf + m%BKPERBLK;
  200. ce = b->entry + CEPERBK;
  201. nw = 0;
  202. for(c=b->entry; c<ce; c++) {
  203. s = c->state;
  204. state[s]++;
  205. if(s != Cnone && s != Cread)
  206. nw++;
  207. }
  208. putbuf(p);
  209. if(nw > bw)
  210. bw = nw;
  211. }
  212. for(s=Cnone; s<Cerror; s++)
  213. print(" %6ld %s\n", state[s], cwnames[s]);
  214. print(" cache %2ld%% full\n", (bw*100)/CEPERBK);
  215. }
  216. int
  217. dumpblock(Device *dev)
  218. {
  219. Iobuf *p, *cb, *p1, *p2;
  220. Cache *h;
  221. Centry *c, *ce, *bc;
  222. Bucket *b;
  223. long m, a, msize, maddr, wmax, caddr;
  224. int s1, s2, count;
  225. Cw *cw;
  226. cw = dev->private;
  227. if(cw == 0 || cw->nodump)
  228. return 0;
  229. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);
  230. h = (Cache*)cb->iobuf;
  231. msize = h->msize;
  232. maddr = h->maddr;
  233. wmax = h->wmax;
  234. caddr = h->caddr;
  235. putbuf(cb);
  236. for(m=msize; m>=0; m--) {
  237. a = cw->dbucket + 1;
  238. if(a < 0 || a >= msize)
  239. a = 0;
  240. cw->dbucket = a;
  241. p = getbuf(cw->cdev, maddr + a/BKPERBLK, Bread);
  242. b = (Bucket*)p->iobuf + a%BKPERBLK;
  243. ce = b->entry + CEPERBK;
  244. bc = 0;
  245. for(c=b->entry; c<ce; c++)
  246. if(c->state == Cdump) {
  247. if(bc == 0) {
  248. bc = c;
  249. continue;
  250. }
  251. if(c->waddr < cw->daddr) {
  252. if(bc->waddr < cw->daddr &&
  253. bc->waddr > c->waddr)
  254. bc = c;
  255. continue;
  256. }
  257. if(bc->waddr < cw->daddr ||
  258. bc->waddr > c->waddr)
  259. bc = c;
  260. }
  261. if(bc) {
  262. c = bc;
  263. goto found;
  264. }
  265. putbuf(p);
  266. }
  267. if(cw->ncopy) {
  268. print("%ld blocks copied to worm\n", cw->ncopy);
  269. cw->ncopy = 0;
  270. }
  271. cw->nodump = 1;
  272. return 0;
  273. found:
  274. a = a*CEPERBK + (c - b->entry) + caddr;
  275. p1 = getbuf(devnone, Cwdump1, 0);
  276. count = 0;
  277. retry:
  278. count++;
  279. if(count > 10)
  280. goto stop;
  281. if(devread(cw->cdev, a, p1->iobuf))
  282. goto stop;
  283. m = c->waddr;
  284. cw->daddr = m;
  285. s1 = devwrite(cw->wdev, m, p1->iobuf);
  286. if(s1) {
  287. p2 = getbuf(devnone, Cwdump2, 0);
  288. s2 = devread(cw->wdev, m, p2->iobuf);
  289. if(s2) {
  290. if(s1 == 0x61 && s2 == 0x60) {
  291. putbuf(p2);
  292. goto retry;
  293. }
  294. goto stop1;
  295. }
  296. if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE))
  297. goto stop1;
  298. putbuf(p2);
  299. }
  300. /*
  301. * reread and compare
  302. */
  303. if(conf.dumpreread) {
  304. p2 = getbuf(devnone, Cwdump2, 0);
  305. s1 = devread(cw->wdev, m, p2->iobuf);
  306. if(s1)
  307. goto stop1;
  308. if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {
  309. print("reread C%ld W%ld didnt compare\n", a, m);
  310. goto stop1;
  311. }
  312. putbuf(p2);
  313. }
  314. putbuf(p1);
  315. c->state = Cread;
  316. p->flags |= Bmod;
  317. putbuf(p);
  318. if(m > wmax) {
  319. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);
  320. h = (Cache*)cb->iobuf;
  321. if(m > h->wmax)
  322. h->wmax = m;
  323. putbuf(cb);
  324. }
  325. cw->ncopy++;
  326. return 1;
  327. stop1:
  328. putbuf(p2);
  329. putbuf(p1);
  330. c->state = Cdump1;
  331. p->flags |= Bmod;
  332. putbuf(p);
  333. return 1;
  334. stop:
  335. putbuf(p1);
  336. putbuf(p);
  337. print("stopping dump!!\n");
  338. cw->nodump = 1;
  339. return 0;
  340. }
  341. void
  342. cwinit1(Device *dev)
  343. {
  344. Cw *cw;
  345. static int first;
  346. cw = dev->private;
  347. if(cw)
  348. return;
  349. if(first == 0) {
  350. cmd_install("dump", "-- make dump backup to worm", cmd_dump);
  351. cmd_install("statw", "-- cache/worm stats", cmd_statw);
  352. cmd_install("cwcmd", "subcommand -- cache/worm errata", cmd_cwcmd);
  353. roflag = flag_install("ro", "-- ro reads and writes");
  354. first = 1;
  355. }
  356. cw = ialloc(sizeof(Cw), 0);
  357. dev->private = cw;
  358. cw->allflag = 0;
  359. dofilter(cw->ncwio+0, C0a, C0b, 1);
  360. dofilter(cw->ncwio+1, C1a, C1b, 1);
  361. dofilter(cw->ncwio+2, C2a, C2b, 1);
  362. cw->dev = dev;
  363. cw->cdev = CDEV(dev);
  364. cw->wdev = WDEV(dev);
  365. cw->rodev = RDEV(dev);
  366. devinit(cw->cdev);
  367. devinit(cw->wdev);
  368. }
  369. void
  370. cwinit(Device *dev)
  371. {
  372. Cw *cw;
  373. Cache *h;
  374. Iobuf *cb, *p;
  375. long l, m;
  376. cwinit1(dev);
  377. cw = dev->private;
  378. l = devsize(cw->wdev);
  379. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);
  380. h = (Cache*)cb->iobuf;
  381. h->toytime = toytime() + SECOND(30);
  382. h->time = time();
  383. m = h->wsize;
  384. if(l != m) {
  385. print("wdev changed size %ld to %ld\n", m, l);
  386. h->wsize = l;
  387. cb->flags |= Bmod;
  388. }
  389. for(m=0; m<h->msize; m++) {
  390. p = getbuf(cw->cdev, h->maddr + m/BKPERBLK, Bread);
  391. if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK))
  392. panic("cwinit: checktag c bucket");
  393. putbuf(p);
  394. }
  395. putbuf(cb);
  396. }
  397. long
  398. cwsaddr(Device *dev)
  399. {
  400. Iobuf *cb;
  401. long sa;
  402. cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);
  403. sa = ((Cache*)cb->iobuf)->sbaddr;
  404. putbuf(cb);
  405. return sa;
  406. }
  407. long
  408. cwraddr(Device *dev)
  409. {
  410. Iobuf *cb;
  411. long ra;
  412. switch(dev->type) {
  413. default:
  414. print("unknown dev in cwraddr %Z\n", dev);
  415. return 1;
  416. case Devcw:
  417. cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);
  418. ra = ((Cache*)cb->iobuf)->cwraddr;
  419. break;
  420. case Devro:
  421. cb = getbuf(CDEV(dev->ro.parent), CACHE_ADDR, Bread|Bres);
  422. ra = ((Cache*)cb->iobuf)->roraddr;
  423. break;
  424. }
  425. putbuf(cb);
  426. return ra;
  427. }
  428. long
  429. cwsize(Device *dev)
  430. {
  431. Iobuf *cb;
  432. long fs;
  433. cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);
  434. fs = ((Cache*)cb->iobuf)->fsize;
  435. putbuf(cb);
  436. return fs;
  437. }
  438. int
  439. cwread(Device *dev, long b, void *c)
  440. {
  441. return cwio(dev, b, c, Oread) == Cerror;
  442. }
  443. int
  444. cwwrite(Device *dev, long b, void *c)
  445. {
  446. return cwio(dev, b, c, Owrite) == Cerror;
  447. }
  448. int
  449. roread(Device *dev, long b, void *c)
  450. {
  451. Device *d;
  452. int s;
  453. /*
  454. * maybe better is to try buffer pool first
  455. */
  456. d = dev->ro.parent;
  457. if(d == 0 || d->type != Devcw ||
  458. d->private == 0 || RDEV(d) != dev) {
  459. print("bad rodev %Z\n", dev);
  460. return 1;
  461. }
  462. s = cwio(d, b, 0, Onone);
  463. if(s == Cdump || s == Cdump1 || s == Cread) {
  464. s = cwio(d, b, c, Oread);
  465. if(s == Cdump || s == Cdump1 || s == Cread) {
  466. if(cons.flags & roflag)
  467. print("roread: %Z %ld -> %Z(hit)\n", dev, b, d);
  468. return 0;
  469. }
  470. }
  471. if(cons.flags & roflag)
  472. print("roread: %Z %ld -> %Z(miss)\n", dev, b, WDEV(d));
  473. return devread(WDEV(d), b, c);
  474. }
  475. int
  476. cwio(Device *dev, long addr, void *buf, int opcode)
  477. {
  478. Iobuf *p, *p1, *p2, *cb;
  479. Cache *h;
  480. Bucket *b;
  481. Centry *c;
  482. long bn, a1, a2, max, newmax;
  483. int state;
  484. Cw *cw;
  485. cw = dev->private;
  486. cw->ncwio[0].count++;
  487. cw->ncwio[1].count++;
  488. cw->ncwio[2].count++;
  489. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);
  490. h = (Cache*)cb->iobuf;
  491. if(toytime() >= h->toytime) {
  492. cb->flags |= Bmod;
  493. h->toytime = toytime() + SECOND(30);
  494. h->time = time();
  495. }
  496. if(addr < 0) {
  497. putbuf(cb);
  498. return Cerror;
  499. }
  500. bn = addr % h->msize;
  501. a1 = h->maddr + bn/BKPERBLK;
  502. a2 = bn*CEPERBK + h->caddr;
  503. max = h->wmax;
  504. putbuf(cb);
  505. newmax = 0;
  506. p = getbuf(cw->cdev, a1, Bread|Bmod);
  507. if(!p || checktag(p, Tbuck, a1))
  508. panic("cwio: checktag c bucket");
  509. b = (Bucket*)p->iobuf + bn%BKPERBLK;
  510. c = getcentry(b, addr);
  511. if(c == 0) {
  512. putbuf(p);
  513. print("disk cache bucket %ld is full\n", a1);
  514. return Cerror;
  515. }
  516. a2 += c - b->entry;
  517. state = c->state;
  518. switch(opcode)
  519. {
  520. default:
  521. goto bad;
  522. case Onone:
  523. break;
  524. case Oread:
  525. switch(state) {
  526. default:
  527. goto bad;
  528. case Cread:
  529. if(!devread(cw->cdev, a2, buf))
  530. break;
  531. c->state = Cnone;
  532. case Cnone:
  533. if(devread(cw->wdev, addr, buf)) {
  534. state = Cerror;
  535. break;
  536. }
  537. if(addr > max)
  538. newmax = addr;
  539. if(!devwrite(cw->cdev, a2, buf))
  540. c->state = Cread;
  541. break;
  542. case Cdirty:
  543. case Cdump:
  544. case Cdump1:
  545. case Cwrite:
  546. if(devread(cw->cdev, a2, buf))
  547. state = Cerror;
  548. break;
  549. }
  550. break;
  551. case Owrite:
  552. switch(state) {
  553. default:
  554. goto bad;
  555. case Cdump:
  556. case Cdump1:
  557. /*
  558. * this is hard part -- a dump block must be
  559. * sent to the worm if it is rewritten.
  560. * if this causes an error, there is no
  561. * place to save the dump1 data. the block
  562. * is just reclassified as 'dump1' (botch)
  563. */
  564. p1 = getbuf(devnone, Cwio1, 0);
  565. if(devread(cw->cdev, a2, p1->iobuf)) {
  566. putbuf(p1);
  567. print("cwio: write induced dump error - r cache\n");
  568. casenone:
  569. if(devwrite(cw->cdev, a2, buf)) {
  570. state = Cerror;
  571. break;
  572. }
  573. c->state = Cdump1;
  574. break;
  575. }
  576. if(devwrite(cw->wdev, addr, p1->iobuf)) {
  577. p2 = getbuf(devnone, Cwio2, 0);
  578. if(devread(cw->wdev, addr, p2->iobuf)) {
  579. putbuf(p1);
  580. putbuf(p2);
  581. print("cwio: write induced dump error - r+w worm\n");
  582. goto casenone;
  583. }
  584. if(memcmp(p1->iobuf, p2->iobuf, RBUFSIZE)) {
  585. putbuf(p1);
  586. putbuf(p2);
  587. print("cwio: write induced dump error - w worm\n");
  588. goto casenone;
  589. }
  590. putbuf(p2);
  591. }
  592. putbuf(p1);
  593. c->state = Cread;
  594. if(addr > max)
  595. newmax = addr;
  596. cw->ncopy++;
  597. case Cnone:
  598. case Cread:
  599. if(devwrite(cw->cdev, a2, buf)) {
  600. state = Cerror;
  601. break;
  602. }
  603. c->state = Cwrite;
  604. break;
  605. case Cdirty:
  606. case Cwrite:
  607. if(devwrite(cw->cdev, a2, buf))
  608. state = Cerror;
  609. break;
  610. }
  611. break;
  612. case Ogrow:
  613. if(state != Cnone) {
  614. print("cwgrow with state = %s\n",
  615. cwnames[state]);
  616. break;
  617. }
  618. c->state = Cdirty;
  619. break;
  620. case Odump:
  621. if(state != Cdirty) { /* BOTCH */
  622. print("cwdump with state = %s\n",
  623. cwnames[state]);
  624. break;
  625. }
  626. c->state = Cdump;
  627. cw->ndump++; /* only called from dump command */
  628. break;
  629. case Orele:
  630. if(state != Cwrite) {
  631. if(state != Cdump1)
  632. print("cwrele with state = %s\n",
  633. cwnames[state]);
  634. break;
  635. }
  636. c->state = Cnone;
  637. break;
  638. case Ofree:
  639. if(state == Cwrite || state == Cread)
  640. c->state = Cnone;
  641. break;
  642. }
  643. if(DEBUG)
  644. print("cwio: %ld s=%s o=%s ns=%s\n",
  645. addr, cwnames[state],
  646. cwnames[opcode],
  647. cwnames[c->state]);
  648. putbuf(p);
  649. if(newmax) {
  650. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bres);
  651. h = (Cache*)cb->iobuf;
  652. if(newmax > h->wmax)
  653. h->wmax = newmax;
  654. putbuf(cb);
  655. }
  656. return state;
  657. bad:
  658. print("cw state = %s; cw opcode = %s",
  659. cwnames[state], cwnames[opcode]);
  660. return Cerror;
  661. }
  662. extern Filsys* dev2fs(Device *dev);
  663. int
  664. cwgrow(Device *dev, Superb *sb, int uid)
  665. {
  666. char str[NAMELEN];
  667. Iobuf *cb;
  668. Cache *h;
  669. Filsys *filsys;
  670. long fs, nfs, ws;
  671. cb = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bmod|Bres);
  672. h = (Cache*)cb->iobuf;
  673. ws = h->wsize;
  674. fs = h->fsize;
  675. if(fs >= ws)
  676. return 0;
  677. nfs = fs + ADDFREE;
  678. if(nfs >= ws)
  679. nfs = ws;
  680. h->fsize = nfs;
  681. putbuf(cb);
  682. sb->fsize = nfs;
  683. filsys = dev2fs(dev);
  684. if (filsys == nil)
  685. print("%Z", dev);
  686. else
  687. print("%s", filsys->name);
  688. uidtostr(str, uid, 1);
  689. print(" grow from %ld to %ld limit %ld by %s uid=%d\n",
  690. fs, nfs, ws, str, uid);
  691. for(nfs--; nfs>=fs; nfs--) {
  692. switch(cwio(dev, nfs, 0, Ogrow)) {
  693. case Cerror:
  694. return 0;
  695. case Cnone:
  696. addfree(dev, nfs, sb);
  697. }
  698. }
  699. return 1;
  700. }
  701. int
  702. cwfree(Device *dev, long addr)
  703. {
  704. int state;
  705. if(dev->type == Devcw) {
  706. state = cwio(dev, addr, 0, Ofree);
  707. if(state != Cdirty)
  708. return 1; /* do not put in freelist */
  709. }
  710. return 0; /* put in freelist */
  711. }
  712. int
  713. bktcheck(Bucket *b)
  714. {
  715. Centry *c, *c1, *c2, *ce;
  716. int err;
  717. err = 0;
  718. if(b->agegen < CEPERBK || b->agegen > MAXAGE) {
  719. print("agegen %ld\n", b->agegen);
  720. err = 1;
  721. }
  722. ce = b->entry + CEPERBK;
  723. c1 = 0; /* lowest age last pass */
  724. for(;;) {
  725. c2 = 0; /* lowest age this pass */
  726. for(c = b->entry; c < ce; c++) {
  727. if(c1 != 0 && c != c1) {
  728. if(c->age == c1->age) {
  729. print("same age %d\n", c->age);
  730. err = 1;
  731. }
  732. if(c1->waddr == c->waddr)
  733. if(c1->state != Cnone)
  734. if(c->state != Cnone) {
  735. print("same waddr %ld\n", c->waddr);
  736. err = 1;
  737. }
  738. }
  739. if(c1 != 0 && c->age <= c1->age)
  740. continue;
  741. if(c2 == 0 || c->age < c2->age)
  742. c2 = c;
  743. }
  744. if(c2 == 0)
  745. break;
  746. c1 = c2;
  747. if(c1->age >= b->agegen) {
  748. print("age >= generator %d %ld\n", c1->age, b->agegen);
  749. err = 1;
  750. }
  751. }
  752. return err;
  753. }
  754. void
  755. resequence(Bucket *b)
  756. {
  757. Centry *c, *ce, *cr;
  758. int age, i;
  759. ce = b->entry + CEPERBK;
  760. for(c = b->entry; c < ce; c++) {
  761. c->age += CEPERBK;
  762. if(c->age < CEPERBK)
  763. c->age = MAXAGE;
  764. }
  765. b->agegen += CEPERBK;
  766. age = 0;
  767. for(i=0;; i++) {
  768. cr = 0;
  769. for(c = b->entry; c < ce; c++) {
  770. if(c->age < i)
  771. continue;
  772. if(cr == 0 || c->age < age) {
  773. cr = c;
  774. age = c->age;
  775. }
  776. }
  777. if(cr == 0)
  778. break;
  779. cr->age = i;
  780. }
  781. b->agegen = i;
  782. cons.nreseq++;
  783. }
  784. Centry*
  785. getcentry(Bucket *b, long addr)
  786. {
  787. Centry *c, *ce, *cr;
  788. int s, age;
  789. /*
  790. * search for cache hit
  791. * find oldest block as byproduct
  792. */
  793. ce = b->entry + CEPERBK;
  794. age = 0;
  795. cr = 0;
  796. for(c = b->entry; c < ce; c++) {
  797. s = c->state;
  798. if(s == Cnone) {
  799. cr = c;
  800. age = 0;
  801. continue;
  802. }
  803. if(c->waddr == addr)
  804. goto found;
  805. if(s == Cread) {
  806. if(cr == 0 || c->age < age) {
  807. cr = c;
  808. age = c->age;
  809. }
  810. }
  811. }
  812. /*
  813. * remap entry
  814. */
  815. c = cr;
  816. if(c == 0)
  817. return 0; /* bucket is full */
  818. c->state = Cnone;
  819. c->waddr = addr;
  820. found:
  821. /*
  822. * update the age to get filo cache.
  823. * small number in age means old
  824. */
  825. if(!cons.noage || c->state == Cnone) {
  826. age = b->agegen;
  827. c->age = age;
  828. age++;
  829. b->agegen = age;
  830. if(age < 0 || age >= MAXAGE)
  831. resequence(b);
  832. }
  833. return c;
  834. }
  835. /*
  836. * ream the cache
  837. * calculate new buckets
  838. */
  839. Iobuf*
  840. cacheinit(Device *dev)
  841. {
  842. Iobuf *cb, *p;
  843. Cache *h;
  844. Device *cdev;
  845. long m;
  846. print("cache init %Z\n", dev);
  847. cdev = CDEV(dev);
  848. devinit(cdev);
  849. cb = getbuf(cdev, CACHE_ADDR, Bmod|Bres);
  850. memset(cb->iobuf, 0, RBUFSIZE);
  851. settag(cb, Tcache, QPSUPER);
  852. h = (Cache*)cb->iobuf;
  853. /*
  854. * calculate csize such that
  855. * tsize = msize/BKPERBLK + csize and
  856. * msize = csize/CEPERBK
  857. */
  858. h->maddr = CACHE_ADDR + 1;
  859. m = devsize(cdev) - h->maddr;
  860. h->csize = ((long long)(m-1) * CEPERBK*BKPERBLK) / (CEPERBK*BKPERBLK+1);
  861. h->msize = h->csize/CEPERBK - 5;
  862. while(!prime(h->msize))
  863. h->msize--;
  864. h->csize = h->msize*CEPERBK;
  865. h->caddr = h->maddr + (h->msize+BKPERBLK-1)/BKPERBLK;
  866. h->wsize = devsize(WDEV(dev));
  867. if(h->msize <= 0)
  868. panic("cache too small");
  869. if(h->caddr + h->csize > m)
  870. panic("cache size error");
  871. /*
  872. * setup cache map
  873. */
  874. for(m=h->maddr; m<h->caddr; m++) {
  875. p = getbuf(cdev, m, Bmod);
  876. memset(p->iobuf, 0, RBUFSIZE);
  877. settag(p, Tbuck, m);
  878. putbuf(p);
  879. }
  880. print("done cacheinit\n");
  881. return cb;
  882. }
  883. long
  884. getstartsb(Device *dev)
  885. {
  886. Filsys *f;
  887. Startsb *s;
  888. for(f=filsys; f->name; f++)
  889. if(devcmpr(f->dev, dev) == 0)
  890. goto found;
  891. print("getstartsb: not found 1 %Z\n", dev);
  892. return FIRST;
  893. found:
  894. for(s=startsb; s->name; s++)
  895. if(strcmp(f->name, s->name) == 0)
  896. return s->startsb;
  897. print("getstartsb: not found 2 %Z %s\n", dev, f->name);
  898. return FIRST;
  899. }
  900. /*
  901. * ream the cache
  902. * calculate new buckets
  903. * get superblock from
  904. * last worm dump block.
  905. */
  906. void
  907. cwrecover(Device *dev)
  908. {
  909. Iobuf *p, *cb;
  910. Cache *h;
  911. Superb *s;
  912. long m, baddr;
  913. Device *wdev;
  914. cwinit1(dev);
  915. wdev = WDEV(dev);
  916. p = getbuf(devnone, Cwxx1, 0);
  917. s = (Superb*)p->iobuf;
  918. baddr = 0;
  919. m = getstartsb(dev);
  920. localconfinit();
  921. if(conf.firstsb)
  922. m = conf.firstsb;
  923. for(;;) {
  924. memset(p->iobuf, 0, RBUFSIZE);
  925. if(devread(wdev, m, p->iobuf) ||
  926. checktag(p, Tsuper, QPSUPER))
  927. break;
  928. baddr = m;
  929. m = s->next;
  930. print("dump %ld is good; %ld next\n", baddr, m);
  931. if(baddr == conf.recovsb)
  932. break;
  933. }
  934. putbuf(p);
  935. if(!baddr)
  936. panic("recover: no superblock\n");
  937. p = getbuf(wdev, baddr, Bread);
  938. s = (Superb*)p->iobuf;
  939. cb = cacheinit(dev);
  940. h = (Cache*)cb->iobuf;
  941. h->sbaddr = baddr;
  942. h->cwraddr = s->cwraddr;
  943. h->roraddr = s->roraddr;
  944. h->fsize = s->fsize + 100; /* this must be conservative */
  945. if(conf.recovcw)
  946. h->cwraddr = conf.recovcw;
  947. if(conf.recovro)
  948. h->roraddr = conf.recovro;
  949. putbuf(cb);
  950. putbuf(p);
  951. p = getbuf(dev, baddr, Bread|Bmod);
  952. s = (Superb*)p->iobuf;
  953. memset(&s->fbuf, 0, sizeof(s->fbuf));
  954. s->fbuf.free[0] = 0;
  955. s->fbuf.nfree = 1;
  956. s->tfree = 0;
  957. if(conf.recovcw)
  958. s->cwraddr = conf.recovcw;
  959. if(conf.recovro)
  960. s->roraddr = conf.recovro;
  961. putbuf(p);
  962. print("done recover\n");
  963. }
  964. /*
  965. * ream the cache
  966. * calculate new buckets
  967. * initialize superblock.
  968. */
  969. void
  970. cwream(Device *dev)
  971. {
  972. Iobuf *p, *cb;
  973. Cache *h;
  974. Superb *s;
  975. long m, baddr;
  976. Device *cdev;
  977. print("cwream %Z\n", dev);
  978. cwinit1(dev);
  979. cdev = CDEV(dev);
  980. devinit(cdev);
  981. baddr = FIRST; /* baddr = super addr
  982. baddr+1 = cw root
  983. baddr+2 = ro root
  984. baddr+3 = reserved next superblock */
  985. cb = cacheinit(dev);
  986. h = (Cache*)cb->iobuf;
  987. h->sbaddr = baddr;
  988. h->cwraddr = baddr+1;
  989. h->roraddr = baddr+2;
  990. h->fsize = 0; /* prevents superream from freeing */
  991. putbuf(cb);
  992. for(m=0; m<3; m++)
  993. cwio(dev, baddr+m, 0, Ogrow);
  994. superream(dev, baddr);
  995. rootream(dev, baddr+1); /* cw root */
  996. rootream(dev, baddr+2); /* ro root */
  997. cb = getbuf(cdev, CACHE_ADDR, Bread|Bmod|Bres);
  998. h = (Cache*)cb->iobuf;
  999. h->fsize = baddr+4;
  1000. putbuf(cb);
  1001. p = getbuf(dev, baddr, Bread|Bmod|Bimm);
  1002. s = (Superb*)p->iobuf;
  1003. s->last = baddr;
  1004. s->cwraddr = baddr+1;
  1005. s->roraddr = baddr+2;
  1006. s->next = baddr+3;
  1007. s->fsize = baddr+4;
  1008. putbuf(p);
  1009. for(m=0; m<3; m++)
  1010. cwio(dev, baddr+m, 0, Odump);
  1011. }
  1012. long
  1013. rewalk1(Cw *cw, long addr, int slot, Wpath *up)
  1014. {
  1015. Iobuf *p, *p1;
  1016. Dentry *d;
  1017. if(up == 0)
  1018. return cwraddr(cw->dev);
  1019. up->addr = rewalk1(cw, up->addr, up->slot, up->up);
  1020. p = getbuf(cw->dev, up->addr, Bread|Bmod);
  1021. d = getdir(p, up->slot);
  1022. if(!d || !(d->mode & DALLOC)) {
  1023. print("rewalk1 1\n");
  1024. if(p)
  1025. putbuf(p);
  1026. return addr;
  1027. }
  1028. p1 = dnodebuf(p, d, slot/DIRPERBUF, 0, 0);
  1029. if(!p1) {
  1030. print("rewalk1 2\n");
  1031. if(p)
  1032. putbuf(p);
  1033. return addr;
  1034. }
  1035. if(DEBUG)
  1036. print("rewalk1 %ld to %ld \"%s\"\n",
  1037. addr, p1->addr, d->name);
  1038. addr = p1->addr;
  1039. p1->flags |= Bmod;
  1040. putbuf(p1);
  1041. putbuf(p);
  1042. return addr;
  1043. }
  1044. long
  1045. rewalk2(Cw *cw, long addr, int slot, Wpath *up)
  1046. {
  1047. Iobuf *p, *p1;
  1048. Dentry *d;
  1049. if(up == 0)
  1050. return cwraddr(cw->rodev);
  1051. up->addr = rewalk2(cw, up->addr, up->slot, up->up);
  1052. p = getbuf(cw->rodev, up->addr, Bread);
  1053. d = getdir(p, up->slot);
  1054. if(!d || !(d->mode & DALLOC)) {
  1055. print("rewalk2 1\n");
  1056. if(p)
  1057. putbuf(p);
  1058. return addr;
  1059. }
  1060. p1 = dnodebuf(p, d, slot/DIRPERBUF, 0, 0);
  1061. if(!p1) {
  1062. print("rewalk2 2\n");
  1063. if(p)
  1064. putbuf(p);
  1065. return addr;
  1066. }
  1067. if(DEBUG)
  1068. print("rewalk2 %ld to %ld \"%s\"\n",
  1069. addr, p1->addr, d->name);
  1070. addr = p1->addr;
  1071. putbuf(p1);
  1072. putbuf(p);
  1073. return addr;
  1074. }
  1075. void
  1076. rewalk(Cw *cw)
  1077. {
  1078. int h;
  1079. File *f;
  1080. for(h=0; h<nelem(flist); h++) {
  1081. for(f=flist[h]; f; f=f->next) {
  1082. if(!f->fs)
  1083. continue;
  1084. if(cw->dev == f->fs->dev)
  1085. f->addr = rewalk1(cw, f->addr, f->slot, f->wpath);
  1086. else
  1087. if(cw->rodev == f->fs->dev)
  1088. f->addr = rewalk2(cw, f->addr, f->slot, f->wpath);
  1089. }
  1090. }
  1091. }
  1092. long
  1093. split(Cw *cw, Iobuf *p, long addr)
  1094. {
  1095. long na;
  1096. int state;
  1097. na = 0;
  1098. if(p && (p->flags & Bmod)) {
  1099. p->flags |= Bimm;
  1100. putbuf(p);
  1101. p = 0;
  1102. }
  1103. state = cwio(cw->dev, addr, 0, Onone); /* read the state (twice?) */
  1104. switch(state)
  1105. {
  1106. default:
  1107. panic("split: unknown state %s", cwnames[state]);
  1108. case Cerror:
  1109. case Cnone:
  1110. case Cdump:
  1111. case Cread:
  1112. break;
  1113. case Cdump1:
  1114. case Cwrite:
  1115. /*
  1116. * botch.. could be done by relabeling
  1117. */
  1118. if(!p) {
  1119. p = getbuf(cw->dev, addr, Bread);
  1120. if(!p) {
  1121. print("split: null getbuf\n");
  1122. break;
  1123. }
  1124. }
  1125. na = cw->fsize;
  1126. cw->fsize = na+1;
  1127. cwio(cw->dev, na, 0, Ogrow);
  1128. cwio(cw->dev, na, p->iobuf, Owrite);
  1129. cwio(cw->dev, na, 0, Odump);
  1130. cwio(cw->dev, addr, 0, Orele);
  1131. break;
  1132. case Cdirty:
  1133. cwio(cw->dev, addr, 0, Odump);
  1134. break;
  1135. }
  1136. if(p)
  1137. putbuf(p);
  1138. return na;
  1139. }
  1140. int
  1141. isdirty(Cw *cw, Iobuf *p, long addr, int tag)
  1142. {
  1143. int s;
  1144. if(p && (p->flags & Bmod))
  1145. return 1;
  1146. s = cwio(cw->dev, addr, 0, Onone);
  1147. if(s == Cdirty || s == Cwrite)
  1148. return 1;
  1149. if(tag == Tind1 || tag == Tind2) /* botch, get these modified */
  1150. if(s != Cnone)
  1151. return 1;
  1152. return 0;
  1153. }
  1154. long
  1155. cwrecur(Cw *cw, long addr, int tag, int tag1, long qp)
  1156. {
  1157. Iobuf *p;
  1158. Dentry *d;
  1159. int i, j, shouldstop;
  1160. long na;
  1161. char *np;
  1162. shouldstop = 0;
  1163. p = getbuf(cw->dev, addr, Bprobe);
  1164. if(!isdirty(cw, p, addr, tag)) {
  1165. if(!cw->all) {
  1166. if(DEBUG)
  1167. print("cwrecur: %ld t=%s not dirty %s\n",
  1168. addr, tagnames[tag], cw->name);
  1169. if(p)
  1170. putbuf(p);
  1171. return 0;
  1172. }
  1173. shouldstop = 1;
  1174. }
  1175. if(DEBUG)
  1176. print("cwrecur: %ld t=%s %s\n",
  1177. addr, tagnames[tag], cw->name);
  1178. if(cw->depth >= 100) {
  1179. print("dump depth too great %s\n", cw->name);
  1180. if(p)
  1181. putbuf(p);
  1182. return 0;
  1183. }
  1184. cw->depth++;
  1185. switch(tag)
  1186. {
  1187. default:
  1188. print("cwrecur: unknown tag %d %s\n", tag, cw->name);
  1189. case Tfile:
  1190. break;
  1191. case Tsuper:
  1192. case Tdir:
  1193. if(!p) {
  1194. p = getbuf(cw->dev, addr, Bread);
  1195. if(!p) {
  1196. print("cwrecur: Tdir p null %s\n",
  1197. cw->name);
  1198. break;
  1199. }
  1200. }
  1201. if(tag == Tdir) {
  1202. cw->namepad[0] = 0; /* force room */
  1203. np = strchr(cw->name, 0);
  1204. *np++ = '/';
  1205. } else {
  1206. np = 0; /* set */
  1207. cw->name[0] = 0;
  1208. }
  1209. for(i=0; i<DIRPERBUF; i++) {
  1210. d = getdir(p, i);
  1211. if(!(d->mode & DALLOC))
  1212. continue;
  1213. qp = d->qid.path & ~QPDIR;
  1214. if(tag == Tdir)
  1215. strncpy(np, d->name, NAMELEN);
  1216. else
  1217. if(i > 0)
  1218. print("cwrecur: root with >1 directory\n");
  1219. tag1 = Tfile;
  1220. if(d->mode & DDIR)
  1221. tag1 = Tdir;
  1222. for(j=0; j<NDBLOCK; j++) {
  1223. if(na = d->dblock[j]) {
  1224. na = cwrecur(cw, na, tag1, 0, qp);
  1225. if(na) {
  1226. d->dblock[j] = na;
  1227. p->flags |= Bmod;
  1228. }
  1229. }
  1230. }
  1231. if(na = d->iblock) {
  1232. na = cwrecur(cw, na, Tind1, tag1, qp);
  1233. if(na) {
  1234. d->iblock = na;
  1235. p->flags |= Bmod;
  1236. }
  1237. }
  1238. if(na = d->diblock) {
  1239. na = cwrecur(cw, na, Tind2, tag1, qp);
  1240. if(na) {
  1241. d->diblock = na;
  1242. p->flags |= Bmod;
  1243. }
  1244. }
  1245. }
  1246. break;
  1247. case Tind1:
  1248. j = tag1;
  1249. tag1 = 0;
  1250. goto tind;
  1251. case Tind2:
  1252. j = Tind1;
  1253. tind:
  1254. if(!p) {
  1255. p = getbuf(cw->dev, addr, Bread);
  1256. if(!p) {
  1257. print("cwrecur: Tind p null %s\n",
  1258. cw->name);
  1259. break;
  1260. }
  1261. }
  1262. for(i=0; i<INDPERBUF; i++) {
  1263. if(na = ((long*)p->iobuf)[i]) {
  1264. na = cwrecur(cw, na, j, tag1, qp);
  1265. if(na) {
  1266. ((long*)p->iobuf)[i] = na;
  1267. p->flags |= Bmod;
  1268. }
  1269. }
  1270. }
  1271. break;
  1272. }
  1273. na = split(cw, p, addr);
  1274. cw->depth--;
  1275. if(na && shouldstop) {
  1276. if(cw->falsehits < 10)
  1277. print("shouldstop %ld %ld t=%s %s\n",
  1278. addr, na, tagnames[tag], cw->name);
  1279. cw->falsehits++;
  1280. }
  1281. return na;
  1282. }
  1283. void
  1284. cfsdump(Filsys *fs)
  1285. {
  1286. Iobuf *pr, *p1, *p;
  1287. Dentry *dr, *d1, *d;
  1288. Cache *h;
  1289. Superb *s;
  1290. long orba, rba, oroa, roa, sba, a, m, n, i, tim;
  1291. char tstr[20];
  1292. Cw *cw;
  1293. if(fs->dev->type != Devcw) {
  1294. print("cant dump; not cw device: %Z\n", fs->dev);
  1295. return;
  1296. }
  1297. cw = fs->dev->private;
  1298. if(cw == 0) {
  1299. print("cant dump: has not been inited: %Z\n", fs->dev);
  1300. return;
  1301. }
  1302. tim = toytime();
  1303. wlock(&mainlock); /* dump */
  1304. /*
  1305. * set up static structure
  1306. * with frequent variables
  1307. */
  1308. cw->ndump = 0;
  1309. cw->name[0] = 0;
  1310. cw->depth = 0;
  1311. /*
  1312. * cw root
  1313. */
  1314. sync("before dump");
  1315. cw->fsize = cwsize(cw->dev);
  1316. orba = cwraddr(cw->dev);
  1317. print("cwroot %ld", orba);
  1318. cons.noage = 1;
  1319. cw->all = cw->allflag;
  1320. rba = cwrecur(cw, orba, Tsuper, 0, QPROOT);
  1321. if(rba == 0)
  1322. rba = orba;
  1323. print("->%ld\n", rba);
  1324. sync("after cw");
  1325. /*
  1326. * partial super block
  1327. */
  1328. p = getbuf(cw->dev, cwsaddr(cw->dev), Bread|Bmod|Bimm);
  1329. s = (Superb*)p->iobuf;
  1330. s->fsize = cw->fsize;
  1331. s->cwraddr = rba;
  1332. putbuf(p);
  1333. /*
  1334. * partial cache block
  1335. */
  1336. p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bimm|Bres);
  1337. h = (Cache*)p->iobuf;
  1338. h->fsize = cw->fsize;
  1339. h->cwraddr = rba;
  1340. putbuf(p);
  1341. /*
  1342. * ro root
  1343. */
  1344. oroa = cwraddr(cw->rodev);
  1345. pr = getbuf(cw->dev, oroa, Bread|Bmod);
  1346. dr = getdir(pr, 0);
  1347. datestr(tstr, time()); /* tstr = "yyyymmdd" */
  1348. n = 0;
  1349. for(a=0;; a++) {
  1350. p1 = dnodebuf(pr, dr, a, Tdir, 0);
  1351. if(!p1)
  1352. goto bad;
  1353. n++;
  1354. for(i=0; i<DIRPERBUF; i++) {
  1355. d1 = getdir(p1, i);
  1356. if(!d1)
  1357. goto bad;
  1358. if(!(d1->mode & DALLOC))
  1359. goto found1;
  1360. if(!memcmp(d1->name, tstr, 4))
  1361. goto found2; /* found entry */
  1362. }
  1363. putbuf(p1);
  1364. }
  1365. /*
  1366. * no year directory, create one
  1367. */
  1368. found1:
  1369. p = getbuf(cw->dev, rba, Bread);
  1370. d = getdir(p, 0);
  1371. d1->qid = d->qid;
  1372. d1->qid.version += n;
  1373. memmove(d1->name, tstr, 4);
  1374. d1->mode = d->mode;
  1375. d1->uid = d->uid;
  1376. d1->gid = d->gid;
  1377. putbuf(p);
  1378. accessdir(p1, d1, FWRITE, 0);
  1379. /*
  1380. * put mmdd[count] in year directory
  1381. */
  1382. found2:
  1383. accessdir(p1, d1, FREAD, 0);
  1384. putbuf(pr);
  1385. pr = p1;
  1386. dr = d1;
  1387. n = 0;
  1388. m = 0;
  1389. for(a=0;; a++) {
  1390. p1 = dnodebuf(pr, dr, a, Tdir, 0);
  1391. if(!p1)
  1392. goto bad;
  1393. n++;
  1394. for(i=0; i<DIRPERBUF; i++) {
  1395. d1 = getdir(p1, i);
  1396. if(!d1)
  1397. goto bad;
  1398. if(!(d1->mode & DALLOC))
  1399. goto found;
  1400. if(!memcmp(d1->name, tstr+4, 4))
  1401. m++;
  1402. }
  1403. putbuf(p1);
  1404. }
  1405. /*
  1406. * empty slot put in root
  1407. */
  1408. found:
  1409. if(m) /* how many dumps this date */
  1410. sprint(tstr+8, "%ld", m);
  1411. p = getbuf(cw->dev, rba, Bread);
  1412. d = getdir(p, 0);
  1413. *d1 = *d; /* qid is QPROOT */
  1414. putbuf(p);
  1415. strcpy(d1->name, tstr+4);
  1416. d1->qid.version += n;
  1417. accessdir(p1, d1, FWRITE, 0);
  1418. putbuf(p1);
  1419. putbuf(pr);
  1420. cw->fsize = cwsize(cw->dev);
  1421. oroa = cwraddr(cw->rodev); /* probably redundant */
  1422. print("roroot %ld", oroa);
  1423. cons.noage = 0;
  1424. cw->all = 0;
  1425. roa = cwrecur(cw, oroa, Tsuper, 0, QPROOT);
  1426. if(roa == 0) {
  1427. print("[same]");
  1428. roa = oroa;
  1429. }
  1430. print("->%ld /%.4s/%s\n", roa, tstr, tstr+4);
  1431. sync("after ro");
  1432. /*
  1433. * final super block
  1434. */
  1435. a = cwsaddr(cw->dev);
  1436. print("sblock %ld", a);
  1437. p = getbuf(cw->dev, a, Bread|Bmod|Bimm);
  1438. s = (Superb*)p->iobuf;
  1439. s->last = a;
  1440. sba = s->next;
  1441. s->next = cw->fsize;
  1442. cw->fsize++;
  1443. s->fsize = cw->fsize;
  1444. s->roraddr = roa;
  1445. cwio(cw->dev, sba, 0, Ogrow);
  1446. cwio(cw->dev, sba, p->iobuf, Owrite);
  1447. cwio(cw->dev, sba, 0, Odump);
  1448. print("->%ld (->%ld)\n", sba, s->next);
  1449. putbuf(p);
  1450. /*
  1451. * final cache block
  1452. */
  1453. p = getbuf(cw->cdev, CACHE_ADDR, Bread|Bmod|Bimm|Bres);
  1454. h = (Cache*)p->iobuf;
  1455. h->fsize = cw->fsize;
  1456. h->roraddr = roa;
  1457. h->sbaddr = sba;
  1458. putbuf(p);
  1459. rewalk(cw);
  1460. sync("all done");
  1461. print("%ld blocks queued for worm\n", cw->ndump);
  1462. print("%ld falsehits\n", cw->falsehits);
  1463. cw->nodump = 0;
  1464. /*
  1465. * extend all of the locks
  1466. */
  1467. tim = toytime() - tim;
  1468. for(i=0; i<NTLOCK; i++)
  1469. if(tlocks[i].time > 0)
  1470. tlocks[i].time += tim;
  1471. wunlock(&mainlock);
  1472. return;
  1473. bad:
  1474. panic("dump: bad");
  1475. }
  1476. void
  1477. mvstates(Device *dev, int s1, int s2, int side)
  1478. {
  1479. Iobuf *p, *cb;
  1480. Cache *h;
  1481. Bucket *b;
  1482. Centry *c, *ce;
  1483. long m, lo, hi, msize, maddr;
  1484. Cw *cw;
  1485. cw = dev->private;
  1486. lo = 0;
  1487. hi = lo + devsize(dev->cw.w); /* size of all sides totalled */
  1488. if(side >= 0) {
  1489. /* operate on only a single disc side */
  1490. Sidestarts ss;
  1491. wormsidestarts(dev, side, &ss);
  1492. lo = ss.sstart;
  1493. hi = ss.s1start;
  1494. }
  1495. cb = getbuf(cw->cdev, CACHE_ADDR, Bread|Bres);
  1496. if(!cb || checktag(cb, Tcache, QPSUPER))
  1497. panic("cwstats: checktag c bucket");
  1498. h = (Cache*)cb->iobuf;
  1499. msize = h->msize;
  1500. maddr = h->maddr;
  1501. putbuf(cb);
  1502. for(m=0; m<msize; m++) {
  1503. p = getbuf(cw->cdev, maddr + m/BKPERBLK, Bread|Bmod);
  1504. if(!p || checktag(p, Tbuck, maddr + m/BKPERBLK))
  1505. panic("cwtest: checktag c bucket");
  1506. b = (Bucket*)p->iobuf + m%BKPERBLK;
  1507. ce = b->entry + CEPERBK;
  1508. for(c=b->entry; c<ce; c++)
  1509. if(c->state == s1 && c->waddr >= lo && c->waddr < hi)
  1510. c->state = s2;
  1511. putbuf(p);
  1512. }
  1513. }
  1514. void
  1515. prchain(Device *dev, long m, int flg)
  1516. {
  1517. Iobuf *p;
  1518. Superb *s;
  1519. if(m == 0) {
  1520. if(flg)
  1521. m = cwsaddr(dev);
  1522. else
  1523. m = getstartsb(dev);
  1524. }
  1525. p = getbuf(devnone, Cwxx2, 0);
  1526. s = (Superb*)p->iobuf;
  1527. for(;;) {
  1528. memset(p->iobuf, 0, RBUFSIZE);
  1529. if(devread(WDEV(dev), m, p->iobuf) ||
  1530. checktag(p, Tsuper, QPSUPER))
  1531. break;
  1532. if(flg) {
  1533. print("dump %ld is good; %ld prev\n", m, s->last);
  1534. print("\t%ld cwroot; %ld roroot\n", s->cwraddr, s->roraddr);
  1535. if(m <= s->last)
  1536. break;
  1537. m = s->last;
  1538. } else {
  1539. print("dump %ld is good; %ld next\n", m, s->next);
  1540. print("\t%ld cwroot; %ld roroot\n", s->cwraddr, s->roraddr);
  1541. if(m >= s->next)
  1542. break;
  1543. m = s->next;
  1544. }
  1545. }
  1546. putbuf(p);
  1547. }
  1548. void
  1549. touchsb(Device *dev)
  1550. {
  1551. Iobuf *p;
  1552. long m;
  1553. m = cwsaddr(dev);
  1554. p = getbuf(devnone, Cwxx2, 0);
  1555. memset(p->iobuf, 0, RBUFSIZE);
  1556. if(devread(WDEV(dev), m, p->iobuf) ||
  1557. checktag(p, Tsuper, QPSUPER))
  1558. print("WORM SUPER BLOCK READ FAILED\n");
  1559. else
  1560. print("touch superblock %ld\n", m);
  1561. putbuf(p);
  1562. }
  1563. void
  1564. storesb(Device *dev, long last, int doit)
  1565. {
  1566. Iobuf *ph, *ps;
  1567. Cache *h;
  1568. Superb *s;
  1569. long sbaddr, qidgen;
  1570. sbaddr = cwsaddr(dev);
  1571. ps = getbuf(devnone, Cwxx2, 0);
  1572. if(!ps) {
  1573. print("sbstore: getbuf\n");
  1574. return;
  1575. }
  1576. /*
  1577. * try to read last sb
  1578. */
  1579. memset(ps->iobuf, 0, RBUFSIZE);
  1580. if(devread(WDEV(dev), last, ps->iobuf) ||
  1581. checktag(ps, Tsuper, QPSUPER))
  1582. print("read last failed\n");
  1583. else
  1584. print("read last succeeded\n");
  1585. s = (Superb*)ps->iobuf;
  1586. qidgen = s->qidgen;
  1587. if(qidgen == 0)
  1588. qidgen = 0x31415;
  1589. qidgen += 1000;
  1590. if(s->next != sbaddr)
  1591. print("next(last) is not sbaddr %ld %ld\n",
  1592. s->next, sbaddr);
  1593. else
  1594. print("next(last) is sbaddr\n");
  1595. /*
  1596. * read cached superblock
  1597. */
  1598. ph = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);
  1599. if(!ph || checktag(ph, Tcache, QPSUPER)) {
  1600. print("cwstats: checktag c bucket\n");
  1601. if(ph)
  1602. putbuf(ph);
  1603. putbuf(ps);
  1604. return;
  1605. } else
  1606. print("read cached sb succeeded\n");
  1607. h = (Cache*)ph->iobuf;
  1608. memset(ps->iobuf, 0, RBUFSIZE);
  1609. settag(ps, Tsuper, QPSUPER);
  1610. ps->flags = 0;
  1611. s = (Superb*)ps->iobuf;
  1612. s->cwraddr = h->cwraddr;
  1613. s->roraddr = h->roraddr;
  1614. s->fsize = h->fsize;
  1615. s->fstart = 2;
  1616. s->last = last;
  1617. s->next = h->roraddr+1;
  1618. s->qidgen = qidgen;
  1619. putbuf(ph);
  1620. if(s->fsize-1 != s->next ||
  1621. s->fsize-2 != s->roraddr ||
  1622. s->fsize-5 != s->cwraddr) {
  1623. print("addrs not in relationship %ld %ld %ld %ld\n",
  1624. s->cwraddr, s->roraddr, s->next, s->fsize);
  1625. putbuf(ps);
  1626. return;
  1627. } else
  1628. print("addresses in relation\n");
  1629. if(doit)
  1630. if(devwrite(WDEV(dev), sbaddr, ps->iobuf))
  1631. print("WORM SUPER BLOCK WRITE FAILED\n");
  1632. ps->flags = 0;
  1633. putbuf(ps);
  1634. }
  1635. void
  1636. savecache(Device *dev)
  1637. {
  1638. Iobuf *p, *cb;
  1639. Cache *h;
  1640. Bucket *b;
  1641. Centry *c, *ce;
  1642. long m, n, maddr, msize, left, *longp, nbyte;
  1643. Device *cdev;
  1644. if(walkto("/adm/cache"))
  1645. goto bad;
  1646. if(con_open(FID2, OWRITE|OTRUNC))
  1647. goto bad;
  1648. cdev = CDEV(dev);
  1649. cb = getbuf(cdev, CACHE_ADDR, Bread|Bres);
  1650. if(!cb || checktag(cb, Tcache, QPSUPER))
  1651. panic("savecache: checktag c bucket");
  1652. h = (Cache*)cb->iobuf;
  1653. msize = h->msize;
  1654. maddr = h->maddr;
  1655. putbuf(cb);
  1656. n = BUFSIZE; /* calculate write size */
  1657. if(n > MAXDAT)
  1658. n = MAXDAT;
  1659. cb = getbuf(devnone, Cwxx4, 0);
  1660. longp = (long*)cb->iobuf;
  1661. left = n/sizeof(long);
  1662. cons.offset = 0;
  1663. for(m=0; m<msize; m++) {
  1664. if(left < BKPERBLK) {
  1665. nbyte = (n/sizeof(long) - left) * sizeof(long);
  1666. con_write(FID2, cb->iobuf, cons.offset, nbyte);
  1667. cons.offset += nbyte;
  1668. longp = (long*)cb->iobuf;
  1669. left = n/sizeof(long);
  1670. }
  1671. p = getbuf(cdev, maddr + m/BKPERBLK, Bread);
  1672. if(!p || checktag(p, Tbuck, maddr + m/BKPERBLK))
  1673. panic("cwtest: checktag c bucket");
  1674. b = (Bucket*)p->iobuf + m%BKPERBLK;
  1675. ce = b->entry + CEPERBK;
  1676. for(c=b->entry; c<ce; c++)
  1677. if(c->state == Cread) {
  1678. *longp++ = c->waddr;
  1679. left--;
  1680. }
  1681. putbuf(p);
  1682. }
  1683. nbyte = (n/sizeof(long) - left) * sizeof(long);
  1684. con_write(FID2, cb->iobuf, cons.offset, nbyte);
  1685. putbuf(cb);
  1686. return;
  1687. bad:
  1688. print("cant open /adm/cache\n");
  1689. }
  1690. void
  1691. loadcache(Device *dev, int dskno)
  1692. {
  1693. Iobuf *p, *cb;
  1694. long m, nbyte, *longp, count;
  1695. Sidestarts ss;
  1696. if(walkto("/adm/cache"))
  1697. goto bad;
  1698. if(con_open(FID2, OREAD))
  1699. goto bad;
  1700. cb = getbuf(devnone, Cwxx4, 0);
  1701. cons.offset = 0;
  1702. count = 0;
  1703. if (dskno >= 0)
  1704. wormsidestarts(dev, dskno, &ss);
  1705. for(;;) {
  1706. memset(cb->iobuf, 0, BUFSIZE);
  1707. nbyte = con_read(FID2, cb->iobuf, cons.offset, 100) / sizeof(long);
  1708. if(nbyte <= 0)
  1709. break;
  1710. cons.offset += nbyte * sizeof(long);
  1711. longp = (long*)cb->iobuf;
  1712. while(nbyte > 0) {
  1713. m = *longp++;
  1714. nbyte--;
  1715. if(m == 0)
  1716. continue;
  1717. /* if given a diskno, restrict to just that disc side */
  1718. if(dskno < 0 || m >= ss.sstart && m < ss.s1start) {
  1719. p = getbuf(dev, m, Bread);
  1720. if(p)
  1721. putbuf(p);
  1722. count++;
  1723. }
  1724. }
  1725. }
  1726. putbuf(cb);
  1727. print("%ld blocks loaded from worm %d\n", count, dskno);
  1728. return;
  1729. bad:
  1730. print("cant open /adm/cache\n");
  1731. }
  1732. void
  1733. morecache(Device *dev, int dskno, long size)
  1734. {
  1735. Iobuf *p;
  1736. long m, ml, mh, mm, count;
  1737. Cache *h;
  1738. Sidestarts ss;
  1739. p = getbuf(CDEV(dev), CACHE_ADDR, Bread|Bres);
  1740. if(!p || checktag(p, Tcache, QPSUPER))
  1741. panic("savecache: checktag c bucket");
  1742. h = (Cache*)p->iobuf;
  1743. mm = h->wmax;
  1744. putbuf(p);
  1745. wormsidestarts(dev, dskno, &ss);
  1746. ml = ss.sstart; /* start at beginning of disc side #dskno */
  1747. mh = ml + size;
  1748. if(mh > mm) {
  1749. mh = mm;
  1750. print("limited to %ld\n", mh-ml);
  1751. }
  1752. count = 0;
  1753. for(m=ml; m < mh; m++) {
  1754. p = getbuf(dev, m, Bread);
  1755. if(p)
  1756. putbuf(p);
  1757. count++;
  1758. }
  1759. print("%ld blocks loaded from worm %d\n", count, dskno);
  1760. }
  1761. void
  1762. blockcmp(Device *dev, long wa, long ca)
  1763. {
  1764. Iobuf *p1, *p2;
  1765. int i, c;
  1766. p1 = getbuf(WDEV(dev), wa, Bread);
  1767. if(!p1) {
  1768. print("dowcmp: wdev error\n");
  1769. return;
  1770. }
  1771. p2 = getbuf(CDEV(dev), ca, Bread);
  1772. if(!p2) {
  1773. print("dowcmp: cdev error\n");
  1774. putbuf(p1);
  1775. return;
  1776. }
  1777. c = 0;
  1778. for(i=0; i<RBUFSIZE; i++)
  1779. if(p1->iobuf[i] != p2->iobuf[i]) {
  1780. print("%4d: %.2x %.2x\n",
  1781. i,
  1782. p1->iobuf[i]&0xff,
  1783. p2->iobuf[i]&0xff);
  1784. c++;
  1785. if(c >= 10)
  1786. break;
  1787. }
  1788. if(c == 0)
  1789. print("no error\n");
  1790. putbuf(p1);
  1791. putbuf(p2);
  1792. }
  1793. void
  1794. wblock(Device *dev, long addr)
  1795. {
  1796. Iobuf *p1;
  1797. int i;
  1798. p1 = getbuf(dev, addr, Bread);
  1799. if(p1) {
  1800. i = devwrite(WDEV(dev), addr, p1->iobuf);
  1801. print("i = %d\n", i);
  1802. putbuf(p1);
  1803. }
  1804. }
  1805. void
  1806. cwtest(Device*)
  1807. {
  1808. }
  1809. #ifdef XXX
  1810. /* garbage to change sb size
  1811. * probably will need it someday
  1812. */
  1813. fsz = number(0, 0, 10);
  1814. count = 0;
  1815. if(fsz == number(0, -1, 10))
  1816. count = -1; /* really do it */
  1817. print("fsize = %ld\n", fsz);
  1818. cdev = CDEV(dev);
  1819. cb = getbuf(cdev, CACHE_ADDR, Bread|Bres);
  1820. if(!cb || checktag(cb, Tcache, QPSUPER))
  1821. panic("cwstats: checktag c bucket");
  1822. h = (Cache*)cb->iobuf;
  1823. for(m=0; m<h->msize; m++) {
  1824. p = getbuf(cdev, h->maddr + m/BKPERBLK, Bread|Bmod);
  1825. if(!p || checktag(p, Tbuck, h->maddr + m/BKPERBLK))
  1826. panic("cwtest: checktag c bucket");
  1827. b = (Bucket*)p->iobuf + m%BKPERBLK;
  1828. ce = b->entry + CEPERBK;
  1829. for(c=b->entry; c<ce; c++) {
  1830. if(c->waddr < fsz)
  1831. continue;
  1832. if(count < 0) {
  1833. c->state = Cnone;
  1834. continue;
  1835. }
  1836. if(c->state != Cdirty)
  1837. count++;
  1838. }
  1839. putbuf(p);
  1840. }
  1841. if(count < 0) {
  1842. print("old cache hsize = %ld\n", h->fsize);
  1843. h->fsize = fsz;
  1844. cb->flags |= Bmod;
  1845. p = getbuf(dev, h->sbaddr, Bread|Bmod);
  1846. s = (Superb*)p->iobuf;
  1847. print("old super hsize = %ld\n", s->fsize);
  1848. s->fsize = fsz;
  1849. putbuf(p);
  1850. }
  1851. putbuf(cb);
  1852. print("count = %ld\n", count);
  1853. #endif
  1854. int
  1855. convstate(char *name)
  1856. {
  1857. int i;
  1858. for(i=0; i<nelem(cwnames); i++)
  1859. if(cwnames[i])
  1860. if(strcmp(cwnames[i], name) == 0)
  1861. return i;
  1862. return -1;
  1863. }
  1864. void
  1865. searchtag(Device *d, long a, int tag, int n)
  1866. {
  1867. Iobuf *p;
  1868. Tag *t;
  1869. int i;
  1870. if(a == 0)
  1871. a = getstartsb(d);
  1872. p = getbuf(devnone, Cwxx2, 0);
  1873. t = (Tag*)(p->iobuf+BUFSIZE);
  1874. for(i=0; i<n; i++) {
  1875. memset(p->iobuf, 0, RBUFSIZE);
  1876. if(devread(WDEV(d), a+i, p->iobuf)) {
  1877. if(n == 1000)
  1878. break;
  1879. continue;
  1880. }
  1881. if(t->tag == tag) {
  1882. print("tag %d found at %Z %ld\n", tag, d, a+i);
  1883. break;
  1884. }
  1885. }
  1886. putbuf(p);
  1887. }
  1888. void
  1889. cmd_cwcmd(int argc, char *argv[])
  1890. {
  1891. Device *dev;
  1892. char *arg;
  1893. long s1, s2, a, b, n;
  1894. Cw *cw;
  1895. char str[28];
  1896. if(argc <= 1) {
  1897. print(" cwcmd mvstate state1 state2 [platter]\n");
  1898. print(" cwcmd prchain [start] [bakflg]\n");
  1899. print(" cwcmd searchtag [start] [tag] [blocks]\n");
  1900. print(" cwcmd touchsb\n");
  1901. print(" cwcmd savecache\n");
  1902. print(" cwcmd loadcache [dskno]\n");
  1903. print(" cwcmd morecache dskno [count]\n");
  1904. print(" cwcmd blockcmp wbno cbno\n");
  1905. print(" cwcmd startdump [01]\n");
  1906. print(" cwcmd acct\n");
  1907. print(" cwcmd clearacct\n");
  1908. goto out;
  1909. }
  1910. arg = argv[1];
  1911. /*
  1912. * items not depend on a cw filesystem
  1913. */
  1914. if(strcmp(arg, "acct") == 0) {
  1915. for(a=0; a<nelem(growacct); a++) {
  1916. b = growacct[a];
  1917. if(b) {
  1918. uidtostr(str, a, 1);
  1919. print("%10ld %s\n",
  1920. (b*ADDFREE*RBUFSIZE+500000)/1000000,
  1921. str);
  1922. }
  1923. }
  1924. goto out;
  1925. }
  1926. if(strcmp(arg, "clearacct") == 0) {
  1927. memset(growacct, 0, sizeof(growacct));
  1928. goto out;
  1929. }
  1930. /*
  1931. * items depend on cw filesystem
  1932. */
  1933. dev = cons.curfs->dev;
  1934. if(dev == 0 || dev->type != Devcw || dev->private == 0) {
  1935. print("cfs not a cw filesystem: %Z\n", dev);
  1936. goto out;
  1937. }
  1938. cw = dev->private;
  1939. if(strcmp(arg, "searchtag") == 0) {
  1940. a = 0;
  1941. if(argc > 2)
  1942. a = number(argv[2], 0, 10);
  1943. b = Tsuper;
  1944. if(argc > 3)
  1945. b = number(argv[3], 0, 10);
  1946. n = 1000;
  1947. if(argc > 4)
  1948. n = number(argv[4], 0, 10);
  1949. searchtag(dev, a, b, n);
  1950. goto out;
  1951. }
  1952. if(strcmp(arg, "mvstate") == 0) {
  1953. if(argc < 4)
  1954. goto bad;
  1955. s1 = convstate(argv[2]);
  1956. s2 = convstate(argv[3]);
  1957. if(s1 < 0 || s2 < 0)
  1958. goto bad;
  1959. a = -1;
  1960. if(argc > 4)
  1961. a = number(argv[4], 0, 10);
  1962. mvstates(dev, s1, s2, a);
  1963. goto out;
  1964. bad:
  1965. print("cwcmd mvstate: bad args\n");
  1966. goto out;
  1967. }
  1968. if(strcmp(arg, "prchain") == 0) {
  1969. a = 0;
  1970. if(argc > 2)
  1971. a = number(argv[2], 0, 10);
  1972. s1 = 0;
  1973. if(argc > 3)
  1974. s1 = number(argv[3], 0, 10);
  1975. prchain(dev, a, s1);
  1976. goto out;
  1977. }
  1978. if(strcmp(arg, "touchsb") == 0) {
  1979. touchsb(dev);
  1980. goto out;
  1981. }
  1982. if(strcmp(arg, "savecache") == 0) {
  1983. savecache(dev);
  1984. goto out;
  1985. }
  1986. if(strcmp(arg, "loadcache") == 0) {
  1987. s1 = -1;
  1988. if(argc > 2)
  1989. s1 = number(argv[2], 0, 10);
  1990. loadcache(dev, s1);
  1991. goto out;
  1992. }
  1993. if(strcmp(arg, "morecache") == 0) {
  1994. if(argc <= 2) {
  1995. print("arg count\n");
  1996. goto out;
  1997. }
  1998. s1 = number(argv[2], 0, 10);
  1999. if(argc > 3)
  2000. s2 = number(argv[3], 0, 10);
  2001. else
  2002. s2 = wormsizeside(dev, s1); /* default to 1 disc side */
  2003. morecache(dev, s1, s2);
  2004. goto out;
  2005. }
  2006. if(strcmp(arg, "blockcmp") == 0) {
  2007. if(argc < 4) {
  2008. print("cannot arg count\n");
  2009. goto out;
  2010. }
  2011. s1 = number(argv[2], 0, 10);
  2012. s2 = number(argv[3], 0, 10);
  2013. blockcmp(dev, s1, s2);
  2014. goto out;
  2015. }
  2016. if(strcmp(arg, "startdump") == 0) {
  2017. if(argc > 2)
  2018. cw->nodump = number(argv[2], 0, 10);
  2019. cw->nodump = !cw->nodump;
  2020. if(cw->nodump)
  2021. print("dump stopped\n");
  2022. else
  2023. print("dump allowed\n");
  2024. goto out;
  2025. }
  2026. if(strcmp(arg, "allflag") == 0) {
  2027. if(argc > 2)
  2028. cw->allflag = number(argv[2], 0, 10);
  2029. else
  2030. cw->allflag = !cw->allflag;
  2031. print("allflag = %d; falsehits = %ld\n",
  2032. cw->allflag, cw->falsehits);
  2033. goto out;
  2034. }
  2035. if(strcmp(arg, "storesb") == 0) {
  2036. a = 4168344;
  2037. b = 0;
  2038. if(argc > 2)
  2039. a = number(argv[2], 4168344, 10);
  2040. if(argc > 3)
  2041. b = number(argv[3], 0, 10);
  2042. storesb(dev, a, b);
  2043. goto out;
  2044. }
  2045. if(strcmp(arg, "test") == 0) {
  2046. cwtest(dev);
  2047. goto out;
  2048. }
  2049. print("unknown cwcmd %s\n", arg);
  2050. out:;
  2051. }