chk.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  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. #include "all.h"
  10. #define DSIZE 546000
  11. #define MAXDEPTH 100
  12. static char* abits;
  13. static int32_t sizabits;
  14. static char* qbits;
  15. static int32_t sizqbits;
  16. static char* name;
  17. static int32_t sizname;
  18. static int32_t fstart;
  19. static int32_t fsize;
  20. static int32_t nfiles;
  21. static int32_t maxq;
  22. static char* fence;
  23. static char* fencebase;
  24. static Device dev;
  25. static int32_t ndup;
  26. static int32_t nused;
  27. static int32_t nfdup;
  28. static int32_t nqbad;
  29. static int32_t nfree;
  30. static int32_t nbad;
  31. static int mod;
  32. static int flags;
  33. static int ronly;
  34. static int cwflag;
  35. static int32_t sbaddr;
  36. static int32_t oldblock;
  37. static int depth;
  38. static int maxdepth;
  39. /* local prototypes */
  40. static int fsck(Dentry*);
  41. static void ckfreelist(Superb*);
  42. static void mkfreelist(Superb*);
  43. static Dentry* maked(int32_t, int, int32_t);
  44. static void modd(int32_t, int, Dentry*);
  45. static void xread(int32_t, int32_t);
  46. static int amark(int32_t);
  47. static int fmark(int32_t);
  48. static void missing(void);
  49. static void qmark(int32_t);
  50. static void* zalloc(uint32_t);
  51. static void* dalloc(uint32_t);
  52. static Iobuf* xtag(int32_t, int, int32_t);
  53. static
  54. void*
  55. zalloc(uint32_t n)
  56. {
  57. char *p;
  58. p = malloc(n);
  59. if(p == 0)
  60. panic("zalloc: out of memory\n");
  61. memset(p, '\0', n);
  62. return p;
  63. }
  64. static
  65. void*
  66. dalloc(uint32_t n)
  67. {
  68. char *p;
  69. if(fencebase == 0)
  70. fence = fencebase = zalloc(MAXDEPTH*sizeof(Dentry));
  71. p = fence;
  72. fence += n;
  73. if(fence > fencebase+MAXDEPTH*sizeof(Dentry))
  74. panic("dalloc too much memory\n");
  75. return p;
  76. }
  77. void
  78. check(Filsys *fs, int32_t flag)
  79. {
  80. Iobuf *p;
  81. Superb *sb;
  82. Dentry *d;
  83. int32_t raddr;
  84. int32_t nqid;
  85. wlock(&mainlock);
  86. dev = fs->dev;
  87. flags = flag;
  88. fence = fencebase;
  89. sizname = 4000;
  90. name = zalloc(sizname);
  91. sizname -= NAMELEN+10; /* for safety */
  92. sbaddr = superaddr(dev);
  93. raddr = getraddr(dev);
  94. p = xtag(sbaddr, Tsuper, QPSUPER);
  95. if(!p){
  96. cprint("bad superblock\n");
  97. goto out;
  98. }
  99. sb = (Superb*)p->iobuf;
  100. fstart = 1;
  101. fsize = sb->fsize;
  102. sizabits = (fsize-fstart + 7)/8;
  103. abits = zalloc(sizabits);
  104. nqid = sb->qidgen+100; /* not as much of a botch */
  105. if(nqid > 1024*1024*8)
  106. nqid = 1024*1024*8;
  107. if(nqid < 64*1024)
  108. nqid = 64*1024;
  109. sizqbits = (nqid+7)/8;
  110. qbits = zalloc(sizqbits);
  111. mod = 0;
  112. nfree = 0;
  113. nfdup = 0;
  114. nused = 0;
  115. nbad = 0;
  116. ndup = 0;
  117. nqbad = 0;
  118. depth = 0;
  119. maxdepth = 0;
  120. if(flags & Ctouch) {
  121. oldblock = fsize/DSIZE;
  122. oldblock *= DSIZE;
  123. if(oldblock < 0)
  124. oldblock = 0;
  125. cprint("oldblock = %ld\n", oldblock);
  126. }
  127. if(amark(sbaddr))
  128. {}
  129. if(cwflag) {
  130. if(amark(sb->roraddr))
  131. {}
  132. if(amark(sb->next))
  133. {}
  134. }
  135. if(!(flags & Cquiet))
  136. cprint("checking file system: %s\n", fs->name);
  137. nfiles = 0;
  138. maxq = 0;
  139. d = maked(raddr, 0, QPROOT);
  140. if(d) {
  141. if(amark(raddr))
  142. {}
  143. if(fsck(d))
  144. modd(raddr, 0, d);
  145. depth--;
  146. fence -= sizeof(Dentry);
  147. if(depth)
  148. cprint("depth not zero on return\n");
  149. }
  150. if(flags & Cfree) {
  151. mkfreelist(sb);
  152. sb->qidgen = maxq;
  153. settag(p, Tsuper, QPNONE);
  154. }
  155. if(sb->qidgen < maxq)
  156. cprint("qid generator low path=%ld maxq=%ld\n",
  157. sb->qidgen, maxq);
  158. if(!(flags & Cfree))
  159. ckfreelist(sb);
  160. if(mod) {
  161. cprint("file system was modified\n");
  162. settag(p, Tsuper, QPNONE);
  163. }
  164. if(!(flags & Cquiet)){
  165. cprint("%8ld files\n", nfiles);
  166. cprint("%8ld blocks in the file system\n", fsize-fstart);
  167. cprint("%8ld used blocks\n", nused);
  168. cprint("%8ld free blocks\n", sb->tfree);
  169. }
  170. if(!(flags & Cfree)){
  171. if(nfree != sb->tfree)
  172. cprint("%8ld free blocks found\n", nfree);
  173. if(nfdup)
  174. cprint("%8ld blocks duplicated in the free list\n", nfdup);
  175. if(fsize-fstart-nused-nfree)
  176. cprint("%8ld missing blocks\n", fsize-fstart-nused-nfree);
  177. }
  178. if(ndup)
  179. cprint("%8ld address duplications\n", ndup);
  180. if(nbad)
  181. cprint("%8ld bad block addresses\n", nbad);
  182. if(nqbad)
  183. cprint("%8ld bad qids\n", nqbad);
  184. if(!(flags & Cquiet))
  185. cprint("%8ld maximum qid path\n", maxq);
  186. missing();
  187. out:
  188. if(p)
  189. putbuf(p);
  190. free(abits);
  191. free(name);
  192. free(qbits);
  193. wunlock(&mainlock);
  194. }
  195. static
  196. int
  197. touch(int32_t a)
  198. {
  199. Iobuf *p;
  200. if((flags&Ctouch) && a && a < oldblock){
  201. p = getbuf(dev, a, Bread|Bmod);
  202. if(p)
  203. putbuf(p);
  204. return 1;
  205. }
  206. return 0;
  207. }
  208. static
  209. int
  210. checkdir(int32_t a, int32_t qpath)
  211. {
  212. Dentry *nd;
  213. int i, ns, dmod;
  214. ns = strlen(name);
  215. dmod = touch(a);
  216. for(i=0; i<DIRPERBUF; i++) {
  217. nd = maked(a, i, qpath);
  218. if(!nd)
  219. break;
  220. if(fsck(nd)) {
  221. modd(a, i, nd);
  222. dmod++;
  223. }
  224. depth--;
  225. fence -= sizeof(Dentry);
  226. name[ns] = 0;
  227. }
  228. name[ns] = 0;
  229. return dmod;
  230. }
  231. static
  232. int
  233. checkindir(int32_t a, Dentry *d, int32_t qpath)
  234. {
  235. Iobuf *p;
  236. int i, dmod;
  237. dmod = touch(a);
  238. p = xtag(a, Tind1, qpath);
  239. if(!p)
  240. return dmod;
  241. for(i=0; i<INDPERBUF; i++) {
  242. a = ((int32_t*)p->iobuf)[i];
  243. if(!a)
  244. continue;
  245. if(amark(a)) {
  246. if(flags & Cbad) {
  247. ((int32_t*)p->iobuf)[i] = 0;
  248. p->flags |= Bmod;
  249. }
  250. continue;
  251. }
  252. if(d->mode & DDIR)
  253. dmod += checkdir(a, qpath);
  254. else if(flags & Crdall)
  255. xread(a, qpath);
  256. }
  257. putbuf(p);
  258. return dmod;
  259. }
  260. static
  261. int
  262. fsck(Dentry *d)
  263. {
  264. char *s;
  265. Rune r;
  266. Iobuf *p;
  267. int l, i, ns, dmod;
  268. int32_t a, qpath;
  269. depth++;
  270. if(depth >= maxdepth){
  271. maxdepth = depth;
  272. if(maxdepth >= MAXDEPTH){
  273. cprint("max depth exceeded: %s\n", name);
  274. return 0;
  275. }
  276. }
  277. dmod = 0;
  278. if(!(d->mode & DALLOC))
  279. return 0;
  280. nfiles++;
  281. ns = strlen(name);
  282. i = strlen(d->name);
  283. if(i >= NAMELEN){
  284. d->name[NAMELEN-1] = 0;
  285. cprint("%s->name (%s) not terminated\n", name, d->name);
  286. return 0;
  287. }
  288. ns += i;
  289. if(ns >= sizname){
  290. cprint("%s->name (%s) name too large\n", name, d->name);
  291. return 0;
  292. }
  293. for (s = d->name; *s; s += l){
  294. l = chartorune(&r, s);
  295. if (r == Runeerror)
  296. for (i = 0; i < l; i++){
  297. s[i] = '_';
  298. cprint("%s->name (%s) bad UTF\n", name, d->name);
  299. dmod++;
  300. }
  301. }
  302. strcat(name, d->name);
  303. if(d->mode & DDIR){
  304. if(ns > 1)
  305. strcat(name, "/");
  306. if(flags & Cpdir)
  307. cprint("%s\n", name);
  308. } else
  309. if(flags & Cpfile)
  310. cprint("%s\n", name);
  311. qpath = d->qid.path & ~QPDIR;
  312. qmark(qpath);
  313. if(qpath > maxq)
  314. maxq = qpath;
  315. for(i=0; i<NDBLOCK; i++) {
  316. a = d->dblock[i];
  317. if(!a)
  318. continue;
  319. if(amark(a)) {
  320. d->dblock[i] = 0;
  321. dmod++;
  322. continue;
  323. }
  324. if(d->mode & DDIR)
  325. dmod += checkdir(a, qpath);
  326. else if(flags & Crdall)
  327. xread(a, qpath);
  328. }
  329. a = d->iblock;
  330. if(a && amark(a)) {
  331. d->iblock = 0;
  332. dmod++;
  333. }
  334. else if(a)
  335. dmod += checkindir(a, d, qpath);
  336. a = d->diblock;
  337. if(a && amark(a)) {
  338. d->diblock = 0;
  339. return dmod + 1;
  340. }
  341. dmod += touch(a);
  342. if(p = xtag(a, Tind2, qpath)){
  343. for(i=0; i<INDPERBUF; i++){
  344. a = ((int32_t*)p->iobuf)[i];
  345. if(!a)
  346. continue;
  347. if(amark(a)) {
  348. if(flags & Cbad) {
  349. ((int32_t*)p->iobuf)[i] = 0;
  350. p->flags |= Bmod;
  351. }
  352. continue;
  353. }
  354. dmod += checkindir(a, d, qpath);
  355. }
  356. putbuf(p);
  357. }
  358. return dmod;
  359. }
  360. static
  361. void
  362. ckfreelist(Superb *sb)
  363. {
  364. int32_t a, lo, hi;
  365. int n, i;
  366. Iobuf *p;
  367. Fbuf *fb;
  368. strcpy(name, "free list");
  369. cprint("check %s\n", name);
  370. fb = &sb->fbuf;
  371. a = sbaddr;
  372. p = 0;
  373. lo = 0;
  374. hi = 0;
  375. for(;;) {
  376. n = fb->nfree;
  377. if(n < 0 || n > FEPERBUF) {
  378. cprint("check: nfree bad %ld\n", a);
  379. break;
  380. }
  381. for(i=1; i<n; i++) {
  382. a = fb->free[i];
  383. if(a && !fmark(a)) {
  384. if(!lo || lo > a)
  385. lo = a;
  386. if(!hi || hi < a)
  387. hi = a;
  388. }
  389. }
  390. a = fb->free[0];
  391. if(!a)
  392. break;
  393. if(fmark(a))
  394. break;
  395. if(!lo || lo > a)
  396. lo = a;
  397. if(!hi || hi < a)
  398. hi = a;
  399. if(p)
  400. putbuf(p);
  401. p = xtag(a, Tfree, QPNONE);
  402. if(!p)
  403. break;
  404. fb = (Fbuf*)p->iobuf;
  405. }
  406. if(p)
  407. putbuf(p);
  408. cprint("lo = %ld; hi = %ld\n", lo, hi);
  409. }
  410. /*
  411. * make freelist from scratch
  412. */
  413. static
  414. void
  415. mkfreelist(Superb *sb)
  416. {
  417. int32_t a;
  418. int i, b;
  419. strcpy(name, "free list");
  420. memset(&sb->fbuf, 0, sizeof(sb->fbuf));
  421. sb->fbuf.nfree = 1;
  422. sb->tfree = 0;
  423. for(a=fsize-fstart-1; a >= 0; a--) {
  424. i = a/8;
  425. if(i < 0 || i >= sizabits)
  426. continue;
  427. b = 1 << (a&7);
  428. if(abits[i] & b)
  429. continue;
  430. addfree(dev, fstart+a, sb);
  431. abits[i] |= b;
  432. }
  433. }
  434. static
  435. Dentry*
  436. maked(int32_t a, int s, int32_t qpath)
  437. {
  438. Iobuf *p;
  439. Dentry *d, *d1;
  440. p = xtag(a, Tdir, qpath);
  441. if(!p)
  442. return 0;
  443. d = getdir(p, s);
  444. d1 = dalloc(sizeof(Dentry));
  445. memmove(d1, d, sizeof(Dentry));
  446. putbuf(p);
  447. return d1;
  448. }
  449. static
  450. void
  451. modd(int32_t a, int s, Dentry *d1)
  452. {
  453. Iobuf *p;
  454. Dentry *d;
  455. if(!(flags & Cbad))
  456. return;
  457. p = getbuf(dev, a, Bread);
  458. d = getdir(p, s);
  459. if(!d) {
  460. if(p)
  461. putbuf(p);
  462. return;
  463. }
  464. memmove(d, d1, sizeof(Dentry));
  465. p->flags |= Bmod;
  466. putbuf(p);
  467. }
  468. static
  469. void
  470. xread(int32_t a, int32_t qpath)
  471. {
  472. Iobuf *p;
  473. p = xtag(a, Tfile, qpath);
  474. if(p)
  475. putbuf(p);
  476. }
  477. static
  478. Iobuf*
  479. xtag(int32_t a, int tag, int32_t qpath)
  480. {
  481. Iobuf *p;
  482. if(a == 0)
  483. return 0;
  484. p = getbuf(dev, a, Bread);
  485. if(!p) {
  486. cprint("check: \"%s\": xtag: p null\n", name);
  487. if(flags & (Cream|Ctag)) {
  488. p = getbuf(dev, a, Bmod);
  489. if(p) {
  490. memset(p->iobuf, 0, RBUFSIZE);
  491. settag(p, tag, qpath);
  492. mod++;
  493. return p;
  494. }
  495. }
  496. return 0;
  497. }
  498. if(checktag(p, tag, qpath)) {
  499. cprint("check: \"%s\": xtag: checktag\n", name);
  500. if(flags & Cream)
  501. memset(p->iobuf, 0, RBUFSIZE);
  502. if(flags & (Cream|Ctag)) {
  503. settag(p, tag, qpath);
  504. mod++;
  505. }
  506. return p;
  507. }
  508. return p;
  509. }
  510. static
  511. int
  512. amark(int32_t a)
  513. {
  514. int32_t i;
  515. int b;
  516. if(a < fstart || a >= fsize) {
  517. cprint("check: \"%s\": range %ld\n",
  518. name, a);
  519. nbad++;
  520. return 1;
  521. }
  522. a -= fstart;
  523. i = a/8;
  524. b = 1 << (a&7);
  525. if(abits[i] & b) {
  526. if(!ronly) {
  527. if(ndup < 10)
  528. cprint("check: \"%s\": address dup %ld\n",
  529. name, fstart+a);
  530. else
  531. if(ndup == 10)
  532. cprint("...");
  533. }
  534. ndup++;
  535. return 0; /* really?? */
  536. }
  537. abits[i] |= b;
  538. nused++;
  539. return 0;
  540. }
  541. static
  542. int
  543. fmark(int32_t a)
  544. {
  545. int32_t i;
  546. int b;
  547. if(a < fstart || a >= fsize) {
  548. cprint("check: \"%s\": range %ld\n",
  549. name, a);
  550. nbad++;
  551. return 1;
  552. }
  553. a -= fstart;
  554. i = a/8;
  555. b = 1 << (a&7);
  556. if(abits[i] & b) {
  557. cprint("check: \"%s\": address dup %ld\n",
  558. name, fstart+a);
  559. nfdup++;
  560. return 1;
  561. }
  562. abits[i] |= b;
  563. nfree++;
  564. return 0;
  565. }
  566. static
  567. void
  568. missing(void)
  569. {
  570. int32_t a, i;
  571. int b, n;
  572. n = 0;
  573. for(a=fsize-fstart-1; a>=0; a--) {
  574. i = a/8;
  575. b = 1 << (a&7);
  576. if(!(abits[i] & b)) {
  577. cprint("missing: %ld\n", fstart+a);
  578. n++;
  579. }
  580. if(n > 10) {
  581. cprint(" ...\n");
  582. break;
  583. }
  584. }
  585. }
  586. static
  587. void
  588. qmark(int32_t qpath)
  589. {
  590. int i, b;
  591. i = qpath/8;
  592. b = 1 << (qpath&7);
  593. if(i < 0 || i >= sizqbits) {
  594. nqbad++;
  595. if(nqbad < 20)
  596. cprint("check: \"%s\": qid out of range %lx\n",
  597. name, qpath);
  598. return;
  599. }
  600. if((qbits[i] & b) && !ronly) {
  601. nqbad++;
  602. if(nqbad < 20)
  603. cprint("check: \"%s\": qid dup %lx\n",
  604. name, qpath);
  605. }
  606. qbits[i] |= b;
  607. }