main.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568
  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. int sfd;
  11. int cmdmode = 0660;
  12. int rfd;
  13. int chat;
  14. extern char *wrenfile;
  15. extern int nwren;
  16. char *myname;
  17. int cmdfd;
  18. int writeallow; /* never on; for compatibility with fs */
  19. int wstatallow;
  20. int writegroup;
  21. int allownone;
  22. int noatime;
  23. int srvfd(char*, int, int);
  24. void usage(void);
  25. void confinit(void);
  26. Chan *chaninit(char*);
  27. void consinit(void);
  28. void forkserve(void);
  29. void
  30. main(int argc, char *argv[])
  31. {
  32. Filsys *fs;
  33. int ream, fsok;
  34. int newbufsize, nocheck;
  35. char buf[NAMELEN];
  36. int pid, ctl;
  37. progname = "kfs";
  38. procname = "init";
  39. /*
  40. * insulate from invoker's environment and keep it from swapping
  41. */
  42. rfork(RFNAMEG|RFNOTEG|RFREND);
  43. confinit();
  44. sfd = -1;
  45. ream = 0;
  46. newbufsize = 0;
  47. nocheck = 0;
  48. wrenfile = "/dev/sdC0/fs";
  49. pid = getpid();
  50. snprint(buf, sizeof buf, "/proc/%d/ctl", pid);
  51. ctl = open(buf, OWRITE);
  52. fprint(ctl, "noswap\n");
  53. close(ctl);
  54. buf[0] = '\0';
  55. ARGBEGIN{
  56. case 'b':
  57. newbufsize = atol(ARGF());
  58. break;
  59. case 'c':
  60. nocheck = 1;
  61. break;
  62. case 'f':
  63. wrenfile = ARGF();
  64. break;
  65. case 'm':
  66. nwren = atol(ARGF());
  67. break;
  68. case 'n':
  69. strncpy(buf, ARGF(), NAMELEN-1);
  70. buf[NAMELEN-1] = '\0';
  71. break;
  72. case 'p':
  73. cmdmode = atol(ARGF());
  74. break;
  75. case 'r':
  76. ream = 1;
  77. break;
  78. case 's':
  79. sfd = 0;
  80. rfd = dup(1, -1);
  81. close(1);
  82. if(open("/dev/cons", OWRITE) < 0)
  83. open("#c/cons", OWRITE);
  84. break;
  85. case 'B':
  86. conf.niobuf = strtoul(ARGF(), 0, 0);
  87. break;
  88. case 'C':
  89. chat = 1;
  90. break;
  91. default:
  92. usage();
  93. }ARGEND
  94. if(argc != 0)
  95. usage();
  96. cmdfd = 2;
  97. if (access(wrenfile, AREAD|AWRITE) == -1)
  98. sysfatal("%s cannot access device", wrenfile);
  99. formatinit();
  100. sublockinit();
  101. if(buf[0])
  102. sprint(service, "kfs.%s", buf);
  103. else
  104. strcpy(service, "kfs");
  105. chan = chaninit(service);
  106. consinit();
  107. tlocks = ialloc(NTLOCK * sizeof *tlocks);
  108. uid = ialloc(conf.nuid * sizeof(*uid));
  109. uidspace = ialloc(conf.uidspace * sizeof(*uidspace));
  110. gidspace = ialloc(conf.gidspace * sizeof(*gidspace));
  111. /*
  112. * init global locks
  113. */
  114. wlock(&mainlock); wunlock(&mainlock);
  115. /*
  116. * init the file system, ream it if needed, and get the block sizes
  117. */
  118. ream = fsinit(ream, newbufsize);
  119. iobufinit();
  120. for(fs=filesys; fs->name; fs++)
  121. if(fs->flags & FREAM){ /* set by fsinit if reamed */
  122. ream++;
  123. rootream(fs->dev, getraddr(fs->dev));
  124. superream(fs->dev, superaddr(fs->dev));
  125. }
  126. boottime = time(nil);
  127. consserve();
  128. fsok = superok(filesys[0].dev, superaddr(filesys[0].dev), 0);
  129. if(!nocheck && !ream && !fsok)
  130. cmd_exec("check fq");
  131. startproc(forkserve, "srv");
  132. startproc(syncproc, "sync");
  133. exits(0);
  134. }
  135. void
  136. forkserve(void)
  137. {
  138. serve(chan);
  139. }
  140. static
  141. struct
  142. {
  143. int nfilter;
  144. Filter* filters[100];
  145. }f;
  146. int alarmed;
  147. void
  148. catchalarm(void *regs, char *msg)
  149. {
  150. USED(regs);
  151. USED(msg);
  152. if(strcmp(msg, "alarm") == 0){
  153. alarmed = 1;
  154. noted(NCONT);
  155. } else
  156. noted(NDFLT);
  157. }
  158. /*
  159. * process to synch blocks
  160. * it puts out a block/line every second
  161. * it waits 10 seconds if catches up.
  162. * in both cases, it takes about 10 seconds
  163. * to get up-to-date.
  164. *
  165. * it also updates the filter stats
  166. * and executes commands
  167. */
  168. void
  169. syncproc(void)
  170. {
  171. char buf[4*1024];
  172. Filter *ft;
  173. uint32_t c0, c1;
  174. int32_t t, n, d;
  175. int i, p[2];
  176. /*
  177. * make a pipe for commands
  178. */
  179. if(pipe(p) < 0)
  180. panic("command pipe");
  181. sprint(buf, "#s/%s.cmd", service);
  182. srvfd(buf, cmdmode, p[0]);
  183. close(p[0]);
  184. cmdfd = p[1];
  185. notify(catchalarm);
  186. t = time(nil);
  187. for(;;){
  188. i = syncblock();
  189. alarmed = 0;
  190. alarm(i ? 1000: 10000);
  191. n = read(cmdfd, buf, sizeof buf - 1);
  192. if(n <= 0 && !alarmed)
  193. sleep(i ? 1000: 10000);
  194. alarm(0);
  195. if(n > 0){
  196. buf[n] = '\0';
  197. if(cmd_exec(buf))
  198. fprint(cmdfd, "done");
  199. else
  200. fprint(cmdfd, "unknown command");
  201. }
  202. n = time(nil);
  203. d = n - t;
  204. if(d < 0 || d > 5*60)
  205. d = 0;
  206. while(d >= 1) {
  207. d -= 1;
  208. for(i=0; i<f.nfilter; i++) {
  209. ft = f.filters[i];
  210. c0 = ft->count;
  211. c1 = c0 - ft->oldcount;
  212. ft->oldcount = c0;
  213. ft->filter[0] = famd(ft->filter[0], c1, 59, 60);
  214. ft->filter[1] = famd(ft->filter[1], c1, 599, 600);
  215. ft->filter[2] = famd(ft->filter[2], c1, 5999, 6000);
  216. }
  217. }
  218. t = n;
  219. }
  220. }
  221. void
  222. dofilter(Filter *ft)
  223. {
  224. int i;
  225. i = f.nfilter;
  226. if(i >= sizeof f.filters / sizeof f.filters[0]) {
  227. print("dofilter: too many filters\n");
  228. return;
  229. }
  230. f.filters[i] = ft;
  231. f.nfilter = i+1;
  232. }
  233. void
  234. startproc(void (*f)(void), char *name)
  235. {
  236. switch(rfork(RFMEM|RFFDG|RFPROC)){
  237. case -1:
  238. panic("can't fork");
  239. case 0:
  240. break;
  241. default:
  242. return;
  243. }
  244. procname = name;
  245. f();
  246. _exits(nil);
  247. }
  248. void
  249. confinit(void)
  250. {
  251. conf.niobuf = 0;
  252. conf.nuid = 600;
  253. conf.nserve = 2;
  254. conf.uidspace = conf.nuid*6;
  255. conf.gidspace = conf.nuid*3;
  256. cons.flags = 0;
  257. }
  258. static void
  259. dochaninit(Chan *cp, int fd)
  260. {
  261. cp->chan = fd;
  262. fileinit(cp);
  263. wlock(&cp->reflock);
  264. wunlock(&cp->reflock);
  265. lock(&cp->flock);
  266. unlock(&cp->flock);
  267. }
  268. Chan*
  269. chaninit(char *server)
  270. {
  271. Chan *cp;
  272. char buf[3*NAMELEN];
  273. int p[2];
  274. sprint(buf, "#s/%s", server);
  275. if(sfd < 0){
  276. if(pipe(p) < 0)
  277. panic("can't make a pipe");
  278. sfd = p[0];
  279. rfd = p[1];
  280. }
  281. srvfd(buf, 0666, sfd);
  282. close(sfd);
  283. cp = ialloc(sizeof *cp);
  284. cons.srvchan = cp;
  285. dochaninit(cp, rfd);
  286. return cp;
  287. }
  288. int
  289. netserve(char *netaddr)
  290. {
  291. int afd, lfd, fd;
  292. char adir[2*NAMELEN], ldir[2*NAMELEN];
  293. Chan *netchan;
  294. if(access("/net/tcp/clone", 0) < 0)
  295. bind("#I", "/net", MAFTER);
  296. if(access("/net.alt/tcp/clone", 0) < 0)
  297. bind("#I1", "/net.alt", MAFTER);
  298. afd = announce(netaddr, adir);
  299. if (afd < 0)
  300. return -1;
  301. switch (rfork(RFMEM|RFFDG|RFPROC)) {
  302. case -1:
  303. return -1;
  304. case 0:
  305. break;
  306. default:
  307. return 0;
  308. }
  309. for (;;) {
  310. lfd = listen(adir, ldir);
  311. if (lfd < 0)
  312. continue;
  313. fd = accept(lfd, ldir);
  314. if (fd < 0) {
  315. close(lfd);
  316. continue;
  317. }
  318. netchan = mallocz(sizeof(Chan), 1);
  319. if(netchan == nil)
  320. panic("out of memory");
  321. dochaninit(netchan, fd);
  322. switch (rfork(RFMEM|RFFDG|RFPROC)) {
  323. case -1:
  324. panic("can't fork");
  325. case 0:
  326. close(afd);
  327. close(lfd);
  328. serve(netchan);
  329. free(netchan);
  330. exits(0);
  331. default:
  332. close(fd);
  333. close(lfd);
  334. continue;
  335. }
  336. }
  337. }
  338. int
  339. srvfd(char *s, int mode, int sfd)
  340. {
  341. int fd;
  342. char buf[32];
  343. fd = create(s, ORCLOSE|OWRITE, mode);
  344. if(fd < 0){
  345. remove(s);
  346. fd = create(s, ORCLOSE|OWRITE, mode);
  347. if(fd < 0)
  348. panic(s);
  349. }
  350. sprint(buf, "%d", sfd);
  351. if(write(fd, buf, strlen(buf)) != strlen(buf))
  352. panic("srv write");
  353. return sfd;
  354. }
  355. void
  356. consinit(void)
  357. {
  358. int i;
  359. cons.chan = ialloc(sizeof(Chan));
  360. wlock(&cons.chan->reflock);
  361. wunlock(&cons.chan->reflock);
  362. lock(&cons.chan->flock);
  363. unlock(&cons.chan->flock);
  364. dofilter(&cons.work);
  365. dofilter(&cons.rate);
  366. dofilter(&cons.bhit);
  367. dofilter(&cons.bread);
  368. dofilter(&cons.binit);
  369. for(i = 0; i < MAXTAG; i++)
  370. dofilter(&cons.tags[i]);
  371. }
  372. /*
  373. * always called with mainlock locked
  374. */
  375. void
  376. syncall(void)
  377. {
  378. for(;;)
  379. if(!syncblock())
  380. return;
  381. }
  382. int
  383. askream(Filsys *fs)
  384. {
  385. char c;
  386. print("File system %s inconsistent\n", fs->name);
  387. print("Would you like to ream it (y/n)? ");
  388. read(0, &c, 1);
  389. return c == 'y';
  390. }
  391. uint32_t
  392. memsize(void)
  393. {
  394. char *p, buf[128];
  395. int fd, n, by2pg, secs;
  396. by2pg = 4*1024;
  397. p = getenv("cputype");
  398. if(p && strcmp(p, "68020") == 0)
  399. by2pg = 8*1024;
  400. secs = 4*1024*1024;
  401. fd = open("/dev/swap", OREAD);
  402. if(fd < 0)
  403. return secs;
  404. n = read(fd, buf, sizeof(buf)-1);
  405. close(fd);
  406. if(n <= 0)
  407. return secs;
  408. buf[n] = 0;
  409. p = strchr(buf, '/');
  410. if(p)
  411. secs = strtoul(p+1, 0, 0)*by2pg;
  412. return secs;
  413. }
  414. /*
  415. * init the devices
  416. * wipe some of the file systems, or all if ream is set
  417. * this code really assumes that only one file system exists
  418. */
  419. int
  420. fsinit(int ream, int newbufsize)
  421. {
  422. Filsys *fs;
  423. RBUFSIZE = 4 * 1024;
  424. for(fs=filesys; fs->name; fs++)
  425. (*devcall[fs->dev.type].init)(fs->dev);
  426. if(newbufsize == 0)
  427. newbufsize = RBUFSIZE;
  428. if(conf.niobuf == 0) {
  429. conf.niobuf = memsize()/10;
  430. if(conf.niobuf > 2*1024*1024)
  431. conf.niobuf = 2*1024*1024;
  432. conf.niobuf /= newbufsize;
  433. if(conf.niobuf < 30)
  434. conf.niobuf = 30;
  435. }
  436. BUFSIZE = RBUFSIZE - sizeof(Tag);
  437. for(fs=filesys; fs->name; fs++)
  438. if(ream || (*devcall[fs->dev.type].check)(fs->dev) && askream(fs)){
  439. RBUFSIZE = newbufsize;
  440. BUFSIZE = RBUFSIZE - sizeof(Tag);
  441. (*devcall[fs->dev.type].ream)(fs->dev);
  442. fs->flags |= FREAM;
  443. ream = 1;
  444. }
  445. /*
  446. * set up the block size dependant variables
  447. */
  448. BUFSIZE = RBUFSIZE - sizeof(Tag);
  449. DIRPERBUF = BUFSIZE / sizeof(Dentry);
  450. INDPERBUF = BUFSIZE / sizeof(int32_t);
  451. INDPERBUF2 = INDPERBUF * INDPERBUF;
  452. FEPERBUF = (BUFSIZE - sizeof(Super1) - sizeof(int32_t)) / sizeof(int32_t);
  453. return ream;
  454. }
  455. /*
  456. * allocate rest of mem
  457. * for io buffers.
  458. */
  459. #define HWIDTH 5 /* buffers per hash */
  460. void
  461. iobufinit(void)
  462. {
  463. int32_t i;
  464. Iobuf *p, *q;
  465. Hiob *hp;
  466. i = conf.niobuf*RBUFSIZE;
  467. niob = i / (sizeof(Iobuf) + RBUFSIZE + sizeof(Hiob)/HWIDTH);
  468. nhiob = niob / HWIDTH;
  469. while(!prime(nhiob))
  470. nhiob++;
  471. if(chat)
  472. print(" %ld buffers; %ld hashes\n", niob, nhiob);
  473. hiob = ialloc(nhiob * sizeof(Hiob));
  474. hp = hiob;
  475. for(i=0; i<nhiob; i++) {
  476. lock(hp);
  477. unlock(hp);
  478. hp++;
  479. }
  480. p = ialloc(niob * sizeof(Iobuf));
  481. hp = hiob;
  482. for(i=0; i<niob; i++) {
  483. qlock(p);
  484. qunlock(p);
  485. if(hp == hiob)
  486. hp = hiob + nhiob;
  487. hp--;
  488. q = hp->link;
  489. if(q) {
  490. p->fore = q;
  491. p->back = q->back;
  492. q->back = p;
  493. p->back->fore = p;
  494. } else {
  495. hp->link = p;
  496. p->fore = p;
  497. p->back = p;
  498. }
  499. p->dev = devnone;
  500. p->addr = -1;
  501. p->xiobuf = ialloc(RBUFSIZE);
  502. p->iobuf = (char*)-1;
  503. p++;
  504. }
  505. }
  506. void
  507. usage(void)
  508. {
  509. fprint(2, "usage: kfs [-cCr] [-b bufsize] [-s infd outfd] [-f fsfile]\n");
  510. exits(0);
  511. }