101a344a2SDavid du Colombier /* cached-worm file server */
201a344a2SDavid du Colombier #include "all.h"
301a344a2SDavid du Colombier #include "io.h"
401a344a2SDavid du Colombier #include "9p1.h"
501a344a2SDavid du Colombier
6*225077b0SDavid du Colombier extern int oldcachefmt;
7*225077b0SDavid du Colombier
801a344a2SDavid du Colombier Map *devmap;
901a344a2SDavid du Colombier
1001a344a2SDavid du Colombier Biobuf bin;
1101a344a2SDavid du Colombier
1201a344a2SDavid du Colombier void
machinit(void)1301a344a2SDavid du Colombier machinit(void)
1401a344a2SDavid du Colombier {
1501a344a2SDavid du Colombier active.exiting = 0;
1601a344a2SDavid du Colombier }
1701a344a2SDavid du Colombier
1801a344a2SDavid du Colombier /*
1901a344a2SDavid du Colombier * Put a string on the console.
2001a344a2SDavid du Colombier */
2101a344a2SDavid du Colombier void
puts(char * s,int n)2201a344a2SDavid du Colombier puts(char *s, int n)
2301a344a2SDavid du Colombier {
2401a344a2SDavid du Colombier print("%.*s", n, s);
2501a344a2SDavid du Colombier }
2601a344a2SDavid du Colombier
2701a344a2SDavid du Colombier void
prflush(void)2801a344a2SDavid du Colombier prflush(void)
2901a344a2SDavid du Colombier {
3001a344a2SDavid du Colombier }
3101a344a2SDavid du Colombier
3201a344a2SDavid du Colombier /*
3301a344a2SDavid du Colombier * Print a string on the console.
3401a344a2SDavid du Colombier */
3501a344a2SDavid du Colombier void
putstrn(char * str,int n)3601a344a2SDavid du Colombier putstrn(char *str, int n)
3701a344a2SDavid du Colombier {
3801a344a2SDavid du Colombier puts(str, n);
3901a344a2SDavid du Colombier }
4001a344a2SDavid du Colombier
4101a344a2SDavid du Colombier /*
4201a344a2SDavid du Colombier * get a character from the console
4301a344a2SDavid du Colombier */
4401a344a2SDavid du Colombier int
getc(void)4501a344a2SDavid du Colombier getc(void)
4601a344a2SDavid du Colombier {
4701a344a2SDavid du Colombier return Bgetrune(&bin);
4801a344a2SDavid du Colombier }
4901a344a2SDavid du Colombier
5001a344a2SDavid du Colombier void
panic(char * fmt,...)5101a344a2SDavid du Colombier panic(char *fmt, ...)
5201a344a2SDavid du Colombier {
5301a344a2SDavid du Colombier int n;
5401a344a2SDavid du Colombier va_list arg;
5501a344a2SDavid du Colombier char buf[PRINTSIZE];
5601a344a2SDavid du Colombier
5701a344a2SDavid du Colombier va_start(arg, fmt);
5801a344a2SDavid du Colombier n = vseprint(buf, buf + sizeof buf, fmt, arg) - buf;
5901a344a2SDavid du Colombier va_end(arg);
6001a344a2SDavid du Colombier buf[n] = '\0';
6101a344a2SDavid du Colombier print("panic: %s\n", buf);
6201a344a2SDavid du Colombier exit();
6301a344a2SDavid du Colombier }
6401a344a2SDavid du Colombier
6501a344a2SDavid du Colombier int
okay(char * quest)6601a344a2SDavid du Colombier okay(char *quest)
6701a344a2SDavid du Colombier {
6801a344a2SDavid du Colombier char *ln;
6901a344a2SDavid du Colombier
7001a344a2SDavid du Colombier print("okay to %s? ", quest);
7101a344a2SDavid du Colombier if ((ln = Brdline(&bin, '\n')) == nil)
7201a344a2SDavid du Colombier return 0;
7301a344a2SDavid du Colombier ln[Blinelen(&bin)-1] = '\0';
7401a344a2SDavid du Colombier if (isascii(*ln) && isupper(*ln))
7501a344a2SDavid du Colombier *ln = tolower(*ln);
7601a344a2SDavid du Colombier return *ln == 'y';
7701a344a2SDavid du Colombier }
7801a344a2SDavid du Colombier
7901a344a2SDavid du Colombier static void
mapinit(char * mapfile)8001a344a2SDavid du Colombier mapinit(char *mapfile)
8101a344a2SDavid du Colombier {
8201a344a2SDavid du Colombier int nf;
8301a344a2SDavid du Colombier char *ln;
8401a344a2SDavid du Colombier char *fields[2];
8501a344a2SDavid du Colombier Biobuf *bp;
8601a344a2SDavid du Colombier Map *map;
8701a344a2SDavid du Colombier
8801a344a2SDavid du Colombier if (mapfile == nil)
8901a344a2SDavid du Colombier return;
9001a344a2SDavid du Colombier bp = Bopen(mapfile, OREAD);
9101a344a2SDavid du Colombier if (bp == nil)
9201a344a2SDavid du Colombier sysfatal("can't read %s", mapfile);
9301a344a2SDavid du Colombier devmap = nil;
9401a344a2SDavid du Colombier while ((ln = Brdline(bp, '\n')) != nil) {
9501a344a2SDavid du Colombier ln[Blinelen(bp)-1] = '\0';
9601a344a2SDavid du Colombier if (*ln == '\0' || *ln == '#')
9701a344a2SDavid du Colombier continue;
9801a344a2SDavid du Colombier nf = tokenize(ln, fields, nelem(fields));
9901a344a2SDavid du Colombier if (nf != 2)
10001a344a2SDavid du Colombier continue;
10101a344a2SDavid du Colombier if(testconfig(fields[0]) != 0) {
10201a344a2SDavid du Colombier print("bad `from' device %s in %s\n",
10301a344a2SDavid du Colombier fields[0], mapfile);
10401a344a2SDavid du Colombier continue;
10501a344a2SDavid du Colombier }
10601a344a2SDavid du Colombier map = malloc(sizeof *map);
10701a344a2SDavid du Colombier map->from = strdup(fields[0]);
10801a344a2SDavid du Colombier map->to = strdup(fields[1]);
10901a344a2SDavid du Colombier map->fdev = iconfig(fields[0]);
110368c31abSDavid du Colombier map->tdev = nil;
111368c31abSDavid du Colombier if (access(map->to, AEXIST) < 0) {
112368c31abSDavid du Colombier /*
113368c31abSDavid du Colombier * map->to isn't an existing file, so it had better be
114368c31abSDavid du Colombier * a config string for a device.
115368c31abSDavid du Colombier */
11601a344a2SDavid du Colombier if(testconfig(fields[1]) == 0)
11701a344a2SDavid du Colombier map->tdev = iconfig(fields[1]);
118368c31abSDavid du Colombier }
11901a344a2SDavid du Colombier /* else map->to is the replacement file name */
12001a344a2SDavid du Colombier map->next = devmap;
12101a344a2SDavid du Colombier devmap = map;
12201a344a2SDavid du Colombier }
12301a344a2SDavid du Colombier Bterm(bp);
12401a344a2SDavid du Colombier }
12501a344a2SDavid du Colombier
12601a344a2SDavid du Colombier static void
confinit(void)12701a344a2SDavid du Colombier confinit(void)
12801a344a2SDavid du Colombier {
12901a344a2SDavid du Colombier conf.nmach = 1;
13001a344a2SDavid du Colombier
13101a344a2SDavid du Colombier conf.mem = meminit();
13201a344a2SDavid du Colombier
13301a344a2SDavid du Colombier conf.nuid = 1000;
13401a344a2SDavid du Colombier conf.nserve = 15; /* tunable */
13501a344a2SDavid du Colombier conf.nfile = 30000;
13601a344a2SDavid du Colombier conf.nlgmsg = 100;
13701a344a2SDavid du Colombier conf.nsmmsg = 500;
13801a344a2SDavid du Colombier
13901a344a2SDavid du Colombier localconfinit();
14001a344a2SDavid du Colombier
14101a344a2SDavid du Colombier conf.nwpath = conf.nfile*8;
14201a344a2SDavid du Colombier conf.nauth = conf.nfile/10;
14301a344a2SDavid du Colombier conf.gidspace = conf.nuid*3;
14401a344a2SDavid du Colombier
14501a344a2SDavid du Colombier cons.flags = 0;
14601a344a2SDavid du Colombier
14701a344a2SDavid du Colombier if (conf.devmap)
14801a344a2SDavid du Colombier mapinit(conf.devmap);
14901a344a2SDavid du Colombier }
15001a344a2SDavid du Colombier
15101a344a2SDavid du Colombier /*
15201a344a2SDavid du Colombier * compute BUFSIZE*(NDBLOCK+INDPERBUF+INDPERBUF+INDPERBUF+INDPERBUF⁴)
15301a344a2SDavid du Colombier * while watching for overflow; in that case, return 0.
15401a344a2SDavid du Colombier */
15501a344a2SDavid du Colombier
15601a344a2SDavid du Colombier static uvlong
adduvlongov(uvlong a,uvlong b)15701a344a2SDavid du Colombier adduvlongov(uvlong a, uvlong b)
15801a344a2SDavid du Colombier {
15901a344a2SDavid du Colombier uvlong r = a + b;
16001a344a2SDavid du Colombier
16101a344a2SDavid du Colombier if (r < a || r < b)
16201a344a2SDavid du Colombier return 0;
16301a344a2SDavid du Colombier return r;
16401a344a2SDavid du Colombier }
16501a344a2SDavid du Colombier
16601a344a2SDavid du Colombier static uvlong
muluvlongov(uvlong a,uvlong b)16701a344a2SDavid du Colombier muluvlongov(uvlong a, uvlong b)
16801a344a2SDavid du Colombier {
16901a344a2SDavid du Colombier uvlong r = a * b;
17001a344a2SDavid du Colombier
17101a344a2SDavid du Colombier if (a != 0 && r/a != b || r < a || r < b)
17201a344a2SDavid du Colombier return 0;
17301a344a2SDavid du Colombier return r;
17401a344a2SDavid du Colombier }
17501a344a2SDavid du Colombier
17601a344a2SDavid du Colombier static uvlong
maxsize(void)17701a344a2SDavid du Colombier maxsize(void)
17801a344a2SDavid du Colombier {
17901a344a2SDavid du Colombier int i;
18001a344a2SDavid du Colombier uvlong max = NDBLOCK, ind = 1;
18101a344a2SDavid du Colombier
18201a344a2SDavid du Colombier for (i = 0; i < NIBLOCK; i++) {
18301a344a2SDavid du Colombier ind = muluvlongov(ind, INDPERBUF); /* power of INDPERBUF */
18401a344a2SDavid du Colombier if (ind == 0)
18501a344a2SDavid du Colombier return 0;
18601a344a2SDavid du Colombier max = adduvlongov(max, ind);
18701a344a2SDavid du Colombier if (max == 0)
18801a344a2SDavid du Colombier return 0;
18901a344a2SDavid du Colombier }
19001a344a2SDavid du Colombier return muluvlongov(max, BUFSIZE);
19101a344a2SDavid du Colombier }
19201a344a2SDavid du Colombier
19301a344a2SDavid du Colombier enum {
19401a344a2SDavid du Colombier INDPERBUF = ((uvlong)INDPERBUF *INDPERBUF),
19501a344a2SDavid du Colombier INDPERBUF⁴ = ((uvlong)INDPERBUF*INDPERBUF),
19601a344a2SDavid du Colombier };
19701a344a2SDavid du Colombier
19801a344a2SDavid du Colombier static void
printsizes(void)19901a344a2SDavid du Colombier printsizes(void)
20001a344a2SDavid du Colombier {
20101a344a2SDavid du Colombier uvlong max = maxsize();
20201a344a2SDavid du Colombier
20301a344a2SDavid du Colombier print("\tblock size = %d; ", RBUFSIZE);
20401a344a2SDavid du Colombier if (max == 0)
20501a344a2SDavid du Colombier print("max file size exceeds 2⁶⁴ bytes\n");
20601a344a2SDavid du Colombier else {
20701a344a2SDavid du Colombier uvlong offlim = 1ULL << (sizeof(Off)*8 - 1);
20801a344a2SDavid du Colombier
20901a344a2SDavid du Colombier if (max >= offlim)
21001a344a2SDavid du Colombier max = offlim - 1;
21101a344a2SDavid du Colombier print("max file size = %,llud\n", (Wideoff)max);
21201a344a2SDavid du Colombier }
21301a344a2SDavid du Colombier if (INDPERBUF/INDPERBUF != INDPERBUF)
21401a344a2SDavid du Colombier print("overflow computing INDPERBUF\n");
21501a344a2SDavid du Colombier if (INDPERBUF⁴/INDPERBUF != INDPERBUF)
21601a344a2SDavid du Colombier print("overflow computing INDPERBUF⁴\n");
21701a344a2SDavid du Colombier print("\tINDPERBUF = %d, INDPERBUF^4 = %,lld, ", INDPERBUF,
21801a344a2SDavid du Colombier (Wideoff)INDPERBUF⁴);
21901a344a2SDavid du Colombier print("CEPERBK = %d\n", CEPERBK);
22001a344a2SDavid du Colombier print("\tsizeofs: Dentry = %d, Cache = %d\n",
22101a344a2SDavid du Colombier sizeof(Dentry), sizeof(Cache));
22201a344a2SDavid du Colombier }
22301a344a2SDavid du Colombier
22401a344a2SDavid du Colombier void
usage(void)22501a344a2SDavid du Colombier usage(void)
22601a344a2SDavid du Colombier {
227*225077b0SDavid du Colombier fprint(2, "usage: %s [-cf][-a ann-str][-m dev-map] config-dev\n",
228*225077b0SDavid du Colombier argv0);
22901a344a2SDavid du Colombier exits("usage");
23001a344a2SDavid du Colombier }
23101a344a2SDavid du Colombier
23201a344a2SDavid du Colombier void
main(int argc,char ** argv)23301a344a2SDavid du Colombier main(int argc, char **argv)
23401a344a2SDavid du Colombier {
23501a344a2SDavid du Colombier int i, nets = 0;
23601a344a2SDavid du Colombier char *ann;
23701a344a2SDavid du Colombier
23801a344a2SDavid du Colombier rfork(RFNOTEG);
23901a344a2SDavid du Colombier formatinit();
24001a344a2SDavid du Colombier machinit();
24101a344a2SDavid du Colombier conf.confdev = "n"; /* Devnone */
24201a344a2SDavid du Colombier
24301a344a2SDavid du Colombier ARGBEGIN{
244*225077b0SDavid du Colombier case 'a': /* announce on this net */
24501a344a2SDavid du Colombier ann = EARGF(usage());
24601a344a2SDavid du Colombier if (nets >= Maxnets) {
24701a344a2SDavid du Colombier fprint(2, "%s: too many networks to announce: %s\n",
24801a344a2SDavid du Colombier argv0, ann);
24901a344a2SDavid du Colombier exits("too many nets");
25001a344a2SDavid du Colombier }
25101a344a2SDavid du Colombier annstrs[nets++] = ann;
25201a344a2SDavid du Colombier break;
253*225077b0SDavid du Colombier case 'c': /* use new, faster cache layout */
254*225077b0SDavid du Colombier oldcachefmt = 0;
255*225077b0SDavid du Colombier break;
256*225077b0SDavid du Colombier case 'f': /* enter configuration mode first */
25701a344a2SDavid du Colombier conf.configfirst++;
25801a344a2SDavid du Colombier break;
259*225077b0SDavid du Colombier case 'm': /* name device-map file */
26001a344a2SDavid du Colombier conf.devmap = EARGF(usage());
26101a344a2SDavid du Colombier break;
26201a344a2SDavid du Colombier default:
26301a344a2SDavid du Colombier usage();
26401a344a2SDavid du Colombier break;
26501a344a2SDavid du Colombier }ARGEND
26601a344a2SDavid du Colombier
26701a344a2SDavid du Colombier if (argc != 1)
26801a344a2SDavid du Colombier usage();
26901a344a2SDavid du Colombier conf.confdev = argv[0]; /* config string for dev holding full config */
27001a344a2SDavid du Colombier
27101a344a2SDavid du Colombier Binit(&bin, 0, OREAD);
27201a344a2SDavid du Colombier confinit();
27301a344a2SDavid du Colombier
27401a344a2SDavid du Colombier print("\nPlan 9 %d-bit cached-worm file server with %d-deep indir blks\n",
27501a344a2SDavid du Colombier sizeof(Off)*8 - 1, NIBLOCK);
27601a344a2SDavid du Colombier printsizes();
27701a344a2SDavid du Colombier
27801a344a2SDavid du Colombier qlock(&reflock);
27901a344a2SDavid du Colombier qunlock(&reflock);
28001a344a2SDavid du Colombier serveq = newqueue(1000, "9P service"); /* tunable */
28101a344a2SDavid du Colombier raheadq = newqueue(1000, "readahead"); /* tunable */
28201a344a2SDavid du Colombier
28301a344a2SDavid du Colombier mbinit();
28401a344a2SDavid du Colombier netinit();
28501a344a2SDavid du Colombier scsiinit();
28601a344a2SDavid du Colombier
28701a344a2SDavid du Colombier files = malloc(conf.nfile * sizeof *files);
28801a344a2SDavid du Colombier for(i=0; i < conf.nfile; i++) {
28901a344a2SDavid du Colombier qlock(&files[i]);
29001a344a2SDavid du Colombier qunlock(&files[i]);
29101a344a2SDavid du Colombier }
29201a344a2SDavid du Colombier
29301a344a2SDavid du Colombier wpaths = malloc(conf.nwpath * sizeof(*wpaths));
29401a344a2SDavid du Colombier uid = malloc(conf.nuid * sizeof(*uid));
29501a344a2SDavid du Colombier gidspace = malloc(conf.gidspace * sizeof(*gidspace));
29601a344a2SDavid du Colombier authinit();
29701a344a2SDavid du Colombier
29801a344a2SDavid du Colombier print("iobufinit\n");
29901a344a2SDavid du Colombier iobufinit();
30001a344a2SDavid du Colombier
30101a344a2SDavid du Colombier arginit();
30201a344a2SDavid du Colombier boottime = time(nil);
30301a344a2SDavid du Colombier
30401a344a2SDavid du Colombier print("sysinit\n");
30501a344a2SDavid du Colombier sysinit();
30601a344a2SDavid du Colombier
30701a344a2SDavid du Colombier /*
30801a344a2SDavid du Colombier * Ethernet i/o processes
30901a344a2SDavid du Colombier */
31001a344a2SDavid du Colombier netstart();
31101a344a2SDavid du Colombier
31201a344a2SDavid du Colombier /*
31301a344a2SDavid du Colombier * read ahead processes
31401a344a2SDavid du Colombier */
31501a344a2SDavid du Colombier newproc(rahead, 0, "rah");
31601a344a2SDavid du Colombier
31701a344a2SDavid du Colombier /*
31801a344a2SDavid du Colombier * server processes
31901a344a2SDavid du Colombier */
32001a344a2SDavid du Colombier for(i=0; i < conf.nserve; i++)
32101a344a2SDavid du Colombier newproc(serve, 0, "srv");
32201a344a2SDavid du Colombier
32301a344a2SDavid du Colombier /*
32401a344a2SDavid du Colombier * worm "dump" copy process
32501a344a2SDavid du Colombier */
32601a344a2SDavid du Colombier newproc(wormcopy, 0, "wcp");
32701a344a2SDavid du Colombier
32801a344a2SDavid du Colombier /*
32901a344a2SDavid du Colombier * processes to read the console
33001a344a2SDavid du Colombier */
33101a344a2SDavid du Colombier consserve();
33201a344a2SDavid du Colombier
33301a344a2SDavid du Colombier /*
33401a344a2SDavid du Colombier * "sync" copy process
33501a344a2SDavid du Colombier * this doesn't return.
33601a344a2SDavid du Colombier */
33701a344a2SDavid du Colombier procsetname("scp");
33801a344a2SDavid du Colombier synccopy();
33901a344a2SDavid du Colombier }
34001a344a2SDavid du Colombier
34101a344a2SDavid du Colombier /*
34201a344a2SDavid du Colombier * read ahead processes.
34301a344a2SDavid du Colombier * read message from q and then
34401a344a2SDavid du Colombier * read the device.
34501a344a2SDavid du Colombier */
34601a344a2SDavid du Colombier int
rbcmp(void * va,void * vb)34701a344a2SDavid du Colombier rbcmp(void *va, void *vb)
34801a344a2SDavid du Colombier {
34901a344a2SDavid du Colombier Rabuf *ra, *rb;
35001a344a2SDavid du Colombier
35101a344a2SDavid du Colombier ra = *(Rabuf**)va;
35201a344a2SDavid du Colombier rb = *(Rabuf**)vb;
35301a344a2SDavid du Colombier if(rb == 0)
35401a344a2SDavid du Colombier return 1;
35501a344a2SDavid du Colombier if(ra == 0)
35601a344a2SDavid du Colombier return -1;
35701a344a2SDavid du Colombier if(ra->dev > rb->dev)
35801a344a2SDavid du Colombier return 1;
35901a344a2SDavid du Colombier if(ra->dev < rb->dev)
36001a344a2SDavid du Colombier return -1;
36101a344a2SDavid du Colombier if(ra->addr > rb->addr)
36201a344a2SDavid du Colombier return 1;
36301a344a2SDavid du Colombier if(ra->addr < rb->addr)
36401a344a2SDavid du Colombier return -1;
36501a344a2SDavid du Colombier return 0;
36601a344a2SDavid du Colombier }
36701a344a2SDavid du Colombier
36801a344a2SDavid du Colombier void
rahead(void *)36901a344a2SDavid du Colombier rahead(void *)
37001a344a2SDavid du Colombier {
37101a344a2SDavid du Colombier Rabuf *rb[50];
37201a344a2SDavid du Colombier Iobuf *p;
37301a344a2SDavid du Colombier int i, n;
37401a344a2SDavid du Colombier
37501a344a2SDavid du Colombier for (;;) {
37601a344a2SDavid du Colombier rb[0] = fs_recv(raheadq, 0);
37701a344a2SDavid du Colombier for(n = 1; n < nelem(rb); n++) {
37801a344a2SDavid du Colombier if(raheadq->count <= 0)
37901a344a2SDavid du Colombier break;
38001a344a2SDavid du Colombier rb[n] = fs_recv(raheadq, 0);
38101a344a2SDavid du Colombier }
38201a344a2SDavid du Colombier qsort(rb, n, sizeof rb[0], rbcmp);
38301a344a2SDavid du Colombier for(i = 0; i < n; i++) {
38401a344a2SDavid du Colombier if(rb[i] == 0)
38501a344a2SDavid du Colombier continue;
38601a344a2SDavid du Colombier p = getbuf(rb[i]->dev, rb[i]->addr, Brd);
38701a344a2SDavid du Colombier if(p)
38801a344a2SDavid du Colombier putbuf(p);
38901a344a2SDavid du Colombier lock(&rabuflock);
39001a344a2SDavid du Colombier rb[i]->link = rabuffree;
39101a344a2SDavid du Colombier rabuffree = rb[i];
39201a344a2SDavid du Colombier unlock(&rabuflock);
39301a344a2SDavid du Colombier }
39401a344a2SDavid du Colombier }
39501a344a2SDavid du Colombier }
39601a344a2SDavid du Colombier
39701a344a2SDavid du Colombier /*
39801a344a2SDavid du Colombier * main filesystem server loop.
39901a344a2SDavid du Colombier * entered by many processes.
40001a344a2SDavid du Colombier * they wait for message buffers and
40101a344a2SDavid du Colombier * then process them.
40201a344a2SDavid du Colombier */
40301a344a2SDavid du Colombier void
serve(void *)40401a344a2SDavid du Colombier serve(void *)
40501a344a2SDavid du Colombier {
40601a344a2SDavid du Colombier int i;
40701a344a2SDavid du Colombier Chan *cp;
40801a344a2SDavid du Colombier Msgbuf *mb;
40901a344a2SDavid du Colombier
41001a344a2SDavid du Colombier for (;;) {
41101a344a2SDavid du Colombier qlock(&reflock);
41201a344a2SDavid du Colombier /* read 9P request from a network input process */
41301a344a2SDavid du Colombier mb = fs_recv(serveq, 0);
41401a344a2SDavid du Colombier assert(mb->magic == Mbmagic);
41501a344a2SDavid du Colombier /* fs kernel sets chan in /sys/src/fs/ip/il.c:/^getchan */
41601a344a2SDavid du Colombier cp = mb->chan;
41701a344a2SDavid du Colombier if (cp == nil)
41801a344a2SDavid du Colombier panic("serve: nil mb->chan");
41901a344a2SDavid du Colombier rlock(&cp->reflock);
42001a344a2SDavid du Colombier qunlock(&reflock);
42101a344a2SDavid du Colombier
42201a344a2SDavid du Colombier rlock(&mainlock);
42301a344a2SDavid du Colombier
42401a344a2SDavid du Colombier if (mb->data == nil)
42501a344a2SDavid du Colombier panic("serve: nil mb->data");
42601a344a2SDavid du Colombier /* better sniffing code in /sys/src/cmd/disk/kfs/9p12.c */
42701a344a2SDavid du Colombier if(cp->protocol == nil){
42801a344a2SDavid du Colombier /* do we recognise the protocol in this packet? */
42901a344a2SDavid du Colombier /* better sniffing code: /sys/src/cmd/disk/kfs/9p12.c */
43001a344a2SDavid du Colombier for(i = 0; fsprotocol[i] != nil; i++)
43101a344a2SDavid du Colombier if(fsprotocol[i](mb) != 0) {
43201a344a2SDavid du Colombier cp->protocol = fsprotocol[i];
43301a344a2SDavid du Colombier break;
43401a344a2SDavid du Colombier }
43501a344a2SDavid du Colombier if(cp->protocol == nil){
43601a344a2SDavid du Colombier print("no protocol for message\n");
43701a344a2SDavid du Colombier for(i = 0; i < 12; i++)
43801a344a2SDavid du Colombier print(" %2.2uX", mb->data[i]);
43901a344a2SDavid du Colombier print("\n");
44001a344a2SDavid du Colombier }
44101a344a2SDavid du Colombier } else
44201a344a2SDavid du Colombier /* process the request, generate an answer and reply */
44301a344a2SDavid du Colombier cp->protocol(mb);
44401a344a2SDavid du Colombier
44501a344a2SDavid du Colombier mbfree(mb);
44601a344a2SDavid du Colombier runlock(&mainlock);
44701a344a2SDavid du Colombier runlock(&cp->reflock);
44801a344a2SDavid du Colombier }
44901a344a2SDavid du Colombier }
45001a344a2SDavid du Colombier
45101a344a2SDavid du Colombier void
exit(void)45201a344a2SDavid du Colombier exit(void)
45301a344a2SDavid du Colombier {
45401a344a2SDavid du Colombier lock(&active);
45501a344a2SDavid du Colombier active.exiting = 1;
45601a344a2SDavid du Colombier unlock(&active);
45701a344a2SDavid du Colombier
45801a344a2SDavid du Colombier print("halted at %T.\n", time(nil));
45901a344a2SDavid du Colombier postnote(PNGROUP, getpid(), "die");
46001a344a2SDavid du Colombier exits(nil);
46101a344a2SDavid du Colombier }
46201a344a2SDavid du Colombier
46301a344a2SDavid du Colombier enum {
46401a344a2SDavid du Colombier DUMPTIME = 5, /* 5 am */
46501a344a2SDavid du Colombier WEEKMASK = 0, /* every day (1=sun, 2=mon, 4=tue, etc.) */
46601a344a2SDavid du Colombier };
46701a344a2SDavid du Colombier
46801a344a2SDavid du Colombier /*
46901a344a2SDavid du Colombier * calculate the next dump time.
47001a344a2SDavid du Colombier * minimum delay is 100 minutes.
47101a344a2SDavid du Colombier */
47201a344a2SDavid du Colombier Timet
nextdump(Timet t)47301a344a2SDavid du Colombier nextdump(Timet t)
47401a344a2SDavid du Colombier {
47501a344a2SDavid du Colombier Timet nddate = nextime(t+MINUTE(100), DUMPTIME, WEEKMASK);
47601a344a2SDavid du Colombier
47701a344a2SDavid du Colombier if(!conf.nodump)
47801a344a2SDavid du Colombier print("next dump at %T\n", nddate);
47901a344a2SDavid du Colombier return nddate;
48001a344a2SDavid du Colombier }
48101a344a2SDavid du Colombier
48201a344a2SDavid du Colombier /*
48301a344a2SDavid du Colombier * process to copy dump blocks from
48401a344a2SDavid du Colombier * cache to worm. it runs flat out when
48501a344a2SDavid du Colombier * it gets work, but only looks for
48601a344a2SDavid du Colombier * work every 10 seconds.
48701a344a2SDavid du Colombier */
48801a344a2SDavid du Colombier void
wormcopy(void *)48901a344a2SDavid du Colombier wormcopy(void *)
49001a344a2SDavid du Colombier {
49101a344a2SDavid du Colombier int f, dorecalc = 1;
49201a344a2SDavid du Colombier Timet dt, t = 0, nddate = 0, ntoytime = 0;
49301a344a2SDavid du Colombier Filsys *fs;
49401a344a2SDavid du Colombier
49501a344a2SDavid du Colombier for (;;) {
49601a344a2SDavid du Colombier if (dorecalc) {
49701a344a2SDavid du Colombier dorecalc = 0;
49801a344a2SDavid du Colombier t = time(nil);
49901a344a2SDavid du Colombier nddate = nextdump(t); /* chatters */
50001a344a2SDavid du Colombier ntoytime = time(nil);
50101a344a2SDavid du Colombier }
50201a344a2SDavid du Colombier dt = time(nil) - t;
50301a344a2SDavid du Colombier if(dt < 0 || dt > MINUTE(100)) {
50401a344a2SDavid du Colombier if(dt < 0)
50501a344a2SDavid du Colombier print("time went back\n");
50601a344a2SDavid du Colombier else
50701a344a2SDavid du Colombier print("time jumped ahead\n");
50801a344a2SDavid du Colombier dorecalc = 1;
50901a344a2SDavid du Colombier continue;
51001a344a2SDavid du Colombier }
51101a344a2SDavid du Colombier t += dt;
51201a344a2SDavid du Colombier f = 0;
51301a344a2SDavid du Colombier if(t > ntoytime)
51401a344a2SDavid du Colombier ntoytime = time(nil) + HOUR(1);
51501a344a2SDavid du Colombier else if(t > nddate) {
51601a344a2SDavid du Colombier if(!conf.nodump) {
51701a344a2SDavid du Colombier print("automatic dump %T\n", t);
51801a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++)
51901a344a2SDavid du Colombier if(fs->dev->type == Devcw)
52001a344a2SDavid du Colombier cfsdump(fs);
52101a344a2SDavid du Colombier }
52201a344a2SDavid du Colombier dorecalc = 1;
52301a344a2SDavid du Colombier } else {
52401a344a2SDavid du Colombier rlock(&mainlock);
52501a344a2SDavid du Colombier for(fs=filsys; fs->name; fs++)
52601a344a2SDavid du Colombier if(fs->dev->type == Devcw)
52701a344a2SDavid du Colombier f |= dumpblock(fs->dev);
52801a344a2SDavid du Colombier runlock(&mainlock);
52901a344a2SDavid du Colombier if(!f)
53001a344a2SDavid du Colombier delay(10000);
53101a344a2SDavid du Colombier wormprobe();
53201a344a2SDavid du Colombier }
53301a344a2SDavid du Colombier }
53401a344a2SDavid du Colombier }
53501a344a2SDavid du Colombier
53601a344a2SDavid du Colombier /*
53701a344a2SDavid du Colombier * process to synch blocks
53801a344a2SDavid du Colombier * it puts out a block/cache-line every second
53901a344a2SDavid du Colombier * it waits 10 seconds if caught up.
54001a344a2SDavid du Colombier * in both cases, it takes about 10 seconds
54101a344a2SDavid du Colombier * to get up-to-date.
54201a344a2SDavid du Colombier */
54301a344a2SDavid du Colombier void
synccopy(void)54401a344a2SDavid du Colombier synccopy(void)
54501a344a2SDavid du Colombier {
54601a344a2SDavid du Colombier int f;
54701a344a2SDavid du Colombier
54801a344a2SDavid du Colombier for (;;) {
54901a344a2SDavid du Colombier rlock(&mainlock);
55001a344a2SDavid du Colombier f = syncblock();
55101a344a2SDavid du Colombier runlock(&mainlock);
55201a344a2SDavid du Colombier if(!f)
55301a344a2SDavid du Colombier delay(10000);
55401a344a2SDavid du Colombier else
55501a344a2SDavid du Colombier delay(1000);
55601a344a2SDavid du Colombier }
55701a344a2SDavid du Colombier }
55801a344a2SDavid du Colombier
55901a344a2SDavid du Colombier Devsize
inqsize(char * file)56001a344a2SDavid du Colombier inqsize(char *file)
56101a344a2SDavid du Colombier {
56201a344a2SDavid du Colombier int nf;
56301a344a2SDavid du Colombier char *ln, *end, *data = malloc(strlen(file) + 5 + 1);
56401a344a2SDavid du Colombier char *fields[4];
56501a344a2SDavid du Colombier Devsize rv = -1;
56601a344a2SDavid du Colombier Biobuf *bp;
56701a344a2SDavid du Colombier
56801a344a2SDavid du Colombier strcpy(data, file);
56901a344a2SDavid du Colombier end = strstr(data, "/data");
57001a344a2SDavid du Colombier if (end == nil)
571368c31abSDavid du Colombier strcat(data, "/ctl");
57201a344a2SDavid du Colombier else
57301a344a2SDavid du Colombier strcpy(end, "/ctl");
57401a344a2SDavid du Colombier bp = Bopen(data, OREAD);
57501a344a2SDavid du Colombier if (bp) {
57601a344a2SDavid du Colombier while (rv < 0 && (ln = Brdline(bp, '\n')) != nil) {
57701a344a2SDavid du Colombier ln[Blinelen(bp)-1] = '\0';
57801a344a2SDavid du Colombier nf = tokenize(ln, fields, nelem(fields));
57901a344a2SDavid du Colombier if (nf == 3 && strcmp(fields[0], "geometry") == 0)
58001a344a2SDavid du Colombier rv = atoi(fields[2]);
58101a344a2SDavid du Colombier }
58201a344a2SDavid du Colombier Bterm(bp);
58301a344a2SDavid du Colombier }
58401a344a2SDavid du Colombier free(data);
58501a344a2SDavid du Colombier return rv;
58601a344a2SDavid du Colombier }
587