cw.c 42 KB

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