cw.c 42 KB

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