1368c31abSDavid du Colombier #ifdef PLAN9PORT
2368c31abSDavid du Colombier #include <u.h>
3368c31abSDavid du Colombier #include <signal.h>
4368c31abSDavid du Colombier #endif
5368c31abSDavid du Colombier #include "stdinc.h"
6b8a11165SDavid du Colombier #include <bio.h>
7368c31abSDavid du Colombier #include "dat.h"
8368c31abSDavid du Colombier #include "fns.h"
9368c31abSDavid du Colombier
10368c31abSDavid du Colombier #include "whack.h"
11368c31abSDavid du Colombier
127fd2696aSDavid du Colombier typedef struct Allocs Allocs;
137fd2696aSDavid du Colombier struct Allocs {
147fd2696aSDavid du Colombier u32int mem;
157fd2696aSDavid du Colombier u32int bcmem;
167fd2696aSDavid du Colombier u32int icmem;
177fd2696aSDavid du Colombier u32int stfree; /* free memory at start */
187fd2696aSDavid du Colombier uint mempcnt;
197fd2696aSDavid du Colombier };
207fd2696aSDavid du Colombier
21368c31abSDavid du Colombier int debug;
22368c31abSDavid du Colombier int nofork;
23368c31abSDavid du Colombier int mainstacksize = 256*1024;
24368c31abSDavid du Colombier VtSrv *ventisrv;
25368c31abSDavid du Colombier
26368c31abSDavid du Colombier static void ventiserver(void*);
27368c31abSDavid du Colombier
28b8a11165SDavid du Colombier static ulong
freemem(void)29b8a11165SDavid du Colombier freemem(void)
30b8a11165SDavid du Colombier {
31b8a11165SDavid du Colombier int nf, pgsize = 0;
32b8a11165SDavid du Colombier uvlong size, userpgs = 0, userused = 0;
33b8a11165SDavid du Colombier char *ln, *sl;
34b8a11165SDavid du Colombier char *fields[2];
35b8a11165SDavid du Colombier Biobuf *bp;
36b8a11165SDavid du Colombier
37b8a11165SDavid du Colombier size = 64*1024*1024;
38b8a11165SDavid du Colombier bp = Bopen("#c/swap", OREAD);
39b8a11165SDavid du Colombier if (bp != nil) {
40b8a11165SDavid du Colombier while ((ln = Brdline(bp, '\n')) != nil) {
41b8a11165SDavid du Colombier ln[Blinelen(bp)-1] = '\0';
42b8a11165SDavid du Colombier nf = tokenize(ln, fields, nelem(fields));
43b8a11165SDavid du Colombier if (nf != 2)
44b8a11165SDavid du Colombier continue;
45b8a11165SDavid du Colombier if (strcmp(fields[1], "pagesize") == 0)
46b8a11165SDavid du Colombier pgsize = atoi(fields[0]);
47b8a11165SDavid du Colombier else if (strcmp(fields[1], "user") == 0) {
48b8a11165SDavid du Colombier sl = strchr(fields[0], '/');
49b8a11165SDavid du Colombier if (sl == nil)
50b8a11165SDavid du Colombier continue;
51b8a11165SDavid du Colombier userpgs = atoll(sl+1);
52b8a11165SDavid du Colombier userused = atoll(fields[0]);
53b8a11165SDavid du Colombier }
54b8a11165SDavid du Colombier }
55b8a11165SDavid du Colombier Bterm(bp);
56*36066be0SDavid du Colombier if (pgsize > 0 && userpgs > 0 && userused > 0)
57b8a11165SDavid du Colombier size = (userpgs - userused) * pgsize;
58b8a11165SDavid du Colombier }
59b8a11165SDavid du Colombier /* cap it to keep the size within 32 bits */
60b8a11165SDavid du Colombier if (size >= 3840UL * 1024 * 1024)
61b8a11165SDavid du Colombier size = 3840UL * 1024 * 1024;
62b8a11165SDavid du Colombier return size;
63b8a11165SDavid du Colombier }
64b8a11165SDavid du Colombier
657fd2696aSDavid du Colombier static void
allocminima(Allocs * all)667fd2696aSDavid du Colombier allocminima(Allocs *all) /* enforce minima for sanity */
677fd2696aSDavid du Colombier {
687fd2696aSDavid du Colombier if (all->icmem < 6 * 1024 * 1024)
697fd2696aSDavid du Colombier all->icmem = 6 * 1024 * 1024;
70c18ab83fSDavid du Colombier if (all->mem < 1024 * 1024 || all->mem == Unspecified) /* lumps */
717fd2696aSDavid du Colombier all->mem = 1024 * 1024;
727fd2696aSDavid du Colombier if (all->bcmem < 2 * 1024 * 1024)
737fd2696aSDavid du Colombier all->bcmem = 2 * 1024 * 1024;
747fd2696aSDavid du Colombier }
757fd2696aSDavid du Colombier
767fd2696aSDavid du Colombier /* automatic memory allocations sizing per venti(8) guidelines */
777fd2696aSDavid du Colombier static Allocs
allocbypcnt(u32int mempcnt,u32int stfree)787fd2696aSDavid du Colombier allocbypcnt(u32int mempcnt, u32int stfree)
797fd2696aSDavid du Colombier {
807fd2696aSDavid du Colombier u32int avail;
817fd2696aSDavid du Colombier vlong blmsize;
827fd2696aSDavid du Colombier Allocs all;
837fd2696aSDavid du Colombier static u32int free;
847fd2696aSDavid du Colombier
85c18ab83fSDavid du Colombier all.mem = Unspecified;
86c18ab83fSDavid du Colombier all.bcmem = all.icmem = 0;
877fd2696aSDavid du Colombier all.mempcnt = mempcnt;
887fd2696aSDavid du Colombier all.stfree = stfree;
897fd2696aSDavid du Colombier
907fd2696aSDavid du Colombier if (free == 0)
917fd2696aSDavid du Colombier free = freemem();
927fd2696aSDavid du Colombier blmsize = stfree - free;
937fd2696aSDavid du Colombier if (blmsize <= 0)
947fd2696aSDavid du Colombier blmsize = 0;
95*36066be0SDavid du Colombier avail = ((vlong)stfree * mempcnt) / 100;
96*36066be0SDavid du Colombier if (blmsize >= avail || (avail -= blmsize) <= (1 + 2 + 6) * 1024 * 1024)
977fd2696aSDavid du Colombier fprint(2, "%s: bloom filter bigger than mem pcnt; "
987fd2696aSDavid du Colombier "resorting to minimum values (9MB total)\n", argv0);
997fd2696aSDavid du Colombier else {
1007fd2696aSDavid du Colombier if (avail >= 3840UL * 1024 * 1024)
1017fd2696aSDavid du Colombier avail = 3840UL * 1024 * 1024; /* sanity */
1027fd2696aSDavid du Colombier avail /= 2;
1037fd2696aSDavid du Colombier all.icmem = avail;
1047fd2696aSDavid du Colombier avail /= 3;
1057fd2696aSDavid du Colombier all.mem = avail;
1067fd2696aSDavid du Colombier all.bcmem = 2 * avail;
1077fd2696aSDavid du Colombier }
1087fd2696aSDavid du Colombier return all;
1097fd2696aSDavid du Colombier }
1107fd2696aSDavid du Colombier
1117fd2696aSDavid du Colombier /*
1127fd2696aSDavid du Colombier * we compute default values for allocations,
1137fd2696aSDavid du Colombier * which can be overridden by (in order):
1147fd2696aSDavid du Colombier * configuration file parameters,
1157fd2696aSDavid du Colombier * command-line options other than -m, and -m.
1167fd2696aSDavid du Colombier */
1177fd2696aSDavid du Colombier static Allocs
sizeallocs(Allocs opt,Config * cfg)1187fd2696aSDavid du Colombier sizeallocs(Allocs opt, Config *cfg)
1197fd2696aSDavid du Colombier {
1207fd2696aSDavid du Colombier Allocs all;
1217fd2696aSDavid du Colombier
1227fd2696aSDavid du Colombier /* work out sane defaults */
1237fd2696aSDavid du Colombier all = allocbypcnt(20, opt.stfree);
1247fd2696aSDavid du Colombier
1257fd2696aSDavid du Colombier /* config file parameters override */
126c18ab83fSDavid du Colombier if (cfg->mem && cfg->mem != Unspecified)
1277fd2696aSDavid du Colombier all.mem = cfg->mem;
1287fd2696aSDavid du Colombier if (cfg->bcmem)
1297fd2696aSDavid du Colombier all.bcmem = cfg->bcmem;
1307fd2696aSDavid du Colombier if (cfg->icmem)
1317fd2696aSDavid du Colombier all.icmem = cfg->icmem;
1327fd2696aSDavid du Colombier
1337fd2696aSDavid du Colombier /* command-line options override */
134c18ab83fSDavid du Colombier if (opt.mem && opt.mem != Unspecified)
1357fd2696aSDavid du Colombier all.mem = opt.mem;
1367fd2696aSDavid du Colombier if (opt.bcmem)
1377fd2696aSDavid du Colombier all.bcmem = opt.bcmem;
1387fd2696aSDavid du Colombier if (opt.icmem)
1397fd2696aSDavid du Colombier all.icmem = opt.icmem;
1407fd2696aSDavid du Colombier
1417fd2696aSDavid du Colombier /* automatic memory sizing? */
1427fd2696aSDavid du Colombier if(opt.mempcnt > 0)
1437fd2696aSDavid du Colombier all = allocbypcnt(opt.mempcnt, opt.stfree);
1447fd2696aSDavid du Colombier
1457fd2696aSDavid du Colombier allocminima(&all);
1467fd2696aSDavid du Colombier return all;
1477fd2696aSDavid du Colombier }
1487fd2696aSDavid du Colombier
149368c31abSDavid du Colombier void
usage(void)150368c31abSDavid du Colombier usage(void)
151368c31abSDavid du Colombier {
152368c31abSDavid du Colombier fprint(2, "usage: venti [-Ldrsw] [-a ventiaddr] [-c config] "
1537fd2696aSDavid du Colombier "[-h httpaddr] [-m %%mem] [-B blockcachesize] [-C cachesize] [-I icachesize] "
154b8a11165SDavid du Colombier "[-W webroot]\n");
155368c31abSDavid du Colombier threadexitsall("usage");
156368c31abSDavid du Colombier }
157b8a11165SDavid du Colombier
158368c31abSDavid du Colombier void
threadmain(int argc,char * argv[])159368c31abSDavid du Colombier threadmain(int argc, char *argv[])
160368c31abSDavid du Colombier {
161368c31abSDavid du Colombier char *configfile, *haddr, *vaddr, *webroot;
1627fd2696aSDavid du Colombier u32int mem, icmem, bcmem, minbcmem, mempcnt, stfree;
1637fd2696aSDavid du Colombier Allocs allocs;
164368c31abSDavid du Colombier Config config;
165368c31abSDavid du Colombier
166368c31abSDavid du Colombier traceinit();
167368c31abSDavid du Colombier threadsetname("main");
168b8a11165SDavid du Colombier mempcnt = 0;
169368c31abSDavid du Colombier vaddr = nil;
170368c31abSDavid du Colombier haddr = nil;
171368c31abSDavid du Colombier configfile = nil;
172368c31abSDavid du Colombier webroot = nil;
173c18ab83fSDavid du Colombier mem = Unspecified;
174368c31abSDavid du Colombier icmem = 0;
175368c31abSDavid du Colombier bcmem = 0;
176368c31abSDavid du Colombier ARGBEGIN{
177368c31abSDavid du Colombier case 'a':
178368c31abSDavid du Colombier vaddr = EARGF(usage());
179368c31abSDavid du Colombier break;
180368c31abSDavid du Colombier case 'B':
181368c31abSDavid du Colombier bcmem = unittoull(EARGF(usage()));
182368c31abSDavid du Colombier break;
183368c31abSDavid du Colombier case 'c':
184368c31abSDavid du Colombier configfile = EARGF(usage());
185368c31abSDavid du Colombier break;
186368c31abSDavid du Colombier case 'C':
187368c31abSDavid du Colombier mem = unittoull(EARGF(usage()));
188368c31abSDavid du Colombier break;
189368c31abSDavid du Colombier case 'D':
190368c31abSDavid du Colombier settrace(EARGF(usage()));
191368c31abSDavid du Colombier break;
192368c31abSDavid du Colombier case 'd':
193368c31abSDavid du Colombier debug = 1;
194368c31abSDavid du Colombier nofork = 1;
195368c31abSDavid du Colombier break;
196368c31abSDavid du Colombier case 'h':
197368c31abSDavid du Colombier haddr = EARGF(usage());
198368c31abSDavid du Colombier break;
199b8a11165SDavid du Colombier case 'm':
200b8a11165SDavid du Colombier mempcnt = atoi(EARGF(usage()));
201b8a11165SDavid du Colombier if (mempcnt <= 0 || mempcnt >= 100)
202b8a11165SDavid du Colombier usage();
203b8a11165SDavid du Colombier break;
204368c31abSDavid du Colombier case 'I':
205368c31abSDavid du Colombier icmem = unittoull(EARGF(usage()));
206368c31abSDavid du Colombier break;
207368c31abSDavid du Colombier case 'L':
208368c31abSDavid du Colombier ventilogging = 1;
209368c31abSDavid du Colombier break;
210368c31abSDavid du Colombier case 'r':
211368c31abSDavid du Colombier readonly = 1;
212368c31abSDavid du Colombier break;
213368c31abSDavid du Colombier case 's':
214368c31abSDavid du Colombier nofork = 1;
215368c31abSDavid du Colombier break;
216368c31abSDavid du Colombier case 'w': /* compatibility with old venti */
217368c31abSDavid du Colombier queuewrites = 1;
218368c31abSDavid du Colombier break;
219368c31abSDavid du Colombier case 'W':
220368c31abSDavid du Colombier webroot = EARGF(usage());
221368c31abSDavid du Colombier break;
222368c31abSDavid du Colombier default:
223368c31abSDavid du Colombier usage();
224368c31abSDavid du Colombier }ARGEND
225368c31abSDavid du Colombier
226368c31abSDavid du Colombier if(argc)
227368c31abSDavid du Colombier usage();
228368c31abSDavid du Colombier
229368c31abSDavid du Colombier if(!nofork)
230368c31abSDavid du Colombier rfork(RFNOTEG);
231368c31abSDavid du Colombier
232368c31abSDavid du Colombier #ifdef PLAN9PORT
233368c31abSDavid du Colombier {
234368c31abSDavid du Colombier /* sigh - needed to avoid signals when writing to hungup networks */
235368c31abSDavid du Colombier struct sigaction sa;
236368c31abSDavid du Colombier memset(&sa, 0, sizeof sa);
237368c31abSDavid du Colombier sa.sa_handler = SIG_IGN;
238368c31abSDavid du Colombier sigaction(SIGPIPE, &sa, nil);
239368c31abSDavid du Colombier }
240368c31abSDavid du Colombier #endif
241368c31abSDavid du Colombier
242368c31abSDavid du Colombier ventifmtinstall();
243368c31abSDavid du Colombier trace(TraceQuiet, "venti started");
244368c31abSDavid du Colombier fprint(2, "%T venti: ");
245368c31abSDavid du Colombier
246368c31abSDavid du Colombier if(configfile == nil)
247368c31abSDavid du Colombier configfile = "venti.conf";
248368c31abSDavid du Colombier
249c18ab83fSDavid du Colombier /* remember free memory before initventi & loadbloom, for auto-sizing */
250c18ab83fSDavid du Colombier stfree = freemem();
251368c31abSDavid du Colombier fprint(2, "conf...");
252368c31abSDavid du Colombier if(initventi(configfile, &config) < 0)
253368c31abSDavid du Colombier sysfatal("can't init server: %r");
2547fd2696aSDavid du Colombier /*
2557fd2696aSDavid du Colombier * load bloom filter
2567fd2696aSDavid du Colombier */
257368c31abSDavid du Colombier if(mainindex->bloom && loadbloom(mainindex->bloom) < 0)
258368c31abSDavid du Colombier sysfatal("can't load bloom filter: %r");
259368c31abSDavid du Colombier
2607fd2696aSDavid du Colombier /*
2617fd2696aSDavid du Colombier * size memory allocations; assumes bloom filter is loaded
2627fd2696aSDavid du Colombier */
2637fd2696aSDavid du Colombier allocs = sizeallocs((Allocs){mem, bcmem, icmem, stfree, mempcnt},
2647fd2696aSDavid du Colombier &config);
2657fd2696aSDavid du Colombier mem = allocs.mem;
2667fd2696aSDavid du Colombier bcmem = allocs.bcmem;
2677fd2696aSDavid du Colombier icmem = allocs.icmem;
2687fd2696aSDavid du Colombier fprint(2, "%s: mem %,ud bcmem %,ud icmem %,ud...",
2697fd2696aSDavid du Colombier argv0, mem, bcmem, icmem);
270b8a11165SDavid du Colombier
2717fd2696aSDavid du Colombier /*
2727fd2696aSDavid du Colombier * default other configuration-file parameters
2737fd2696aSDavid du Colombier */
274368c31abSDavid du Colombier if(haddr == nil)
275368c31abSDavid du Colombier haddr = config.haddr;
276368c31abSDavid du Colombier if(vaddr == nil)
277368c31abSDavid du Colombier vaddr = config.vaddr;
278368c31abSDavid du Colombier if(vaddr == nil)
279368c31abSDavid du Colombier vaddr = "tcp!*!venti";
280368c31abSDavid du Colombier if(webroot == nil)
281368c31abSDavid du Colombier webroot = config.webroot;
282368c31abSDavid du Colombier if(queuewrites == 0)
283368c31abSDavid du Colombier queuewrites = config.queuewrites;
2847fd2696aSDavid du Colombier
285368c31abSDavid du Colombier if(haddr){
286368c31abSDavid du Colombier fprint(2, "httpd %s...", haddr);
287368c31abSDavid du Colombier if(httpdinit(haddr, webroot) < 0)
288368c31abSDavid du Colombier fprint(2, "warning: can't start http server: %r");
289368c31abSDavid du Colombier }
290368c31abSDavid du Colombier fprint(2, "init...");
291368c31abSDavid du Colombier
2927fd2696aSDavid du Colombier /*
2937fd2696aSDavid du Colombier * lump cache
2947fd2696aSDavid du Colombier */
295368c31abSDavid du Colombier if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n",
296368c31abSDavid du Colombier mem, mem / (8 * 1024));
297368c31abSDavid du Colombier initlumpcache(mem, mem / (8 * 1024));
298368c31abSDavid du Colombier
2997fd2696aSDavid du Colombier /*
3007fd2696aSDavid du Colombier * index cache
3017fd2696aSDavid du Colombier */
302f9e1cf08SDavid du Colombier initicache(icmem);
303368c31abSDavid du Colombier initicachewrite();
304368c31abSDavid du Colombier
305368c31abSDavid du Colombier /*
3067fd2696aSDavid du Colombier * block cache: need a block for every arena and every process
307368c31abSDavid du Colombier */
308368c31abSDavid du Colombier minbcmem = maxblocksize *
309368c31abSDavid du Colombier (mainindex->narenas + mainindex->nsects*4 + 16);
310368c31abSDavid du Colombier if(bcmem < minbcmem)
311368c31abSDavid du Colombier bcmem = minbcmem;
312368c31abSDavid du Colombier if(0) fprint(2, "initialize %d bytes of disk block cache\n", bcmem);
313368c31abSDavid du Colombier initdcache(bcmem);
314368c31abSDavid du Colombier
315368c31abSDavid du Colombier if(mainindex->bloom)
316368c31abSDavid du Colombier startbloomproc(mainindex->bloom);
317368c31abSDavid du Colombier
318368c31abSDavid du Colombier fprint(2, "sync...");
319f9e1cf08SDavid du Colombier if(!readonly && syncindex(mainindex) < 0)
320368c31abSDavid du Colombier sysfatal("can't sync server: %r");
321368c31abSDavid du Colombier
322368c31abSDavid du Colombier if(!readonly && queuewrites){
323368c31abSDavid du Colombier fprint(2, "queue...");
324368c31abSDavid du Colombier if(initlumpqueues(mainindex->nsects) < 0){
325368c31abSDavid du Colombier fprint(2, "can't initialize lump queues,"
326368c31abSDavid du Colombier " disabling write queueing: %r");
327368c31abSDavid du Colombier queuewrites = 0;
328368c31abSDavid du Colombier }
329368c31abSDavid du Colombier }
330368c31abSDavid du Colombier
331f9e1cf08SDavid du Colombier if(initarenasum() < 0)
332f9e1cf08SDavid du Colombier fprint(2, "warning: can't initialize arena summing process: %r");
333f9e1cf08SDavid du Colombier
334368c31abSDavid du Colombier fprint(2, "announce %s...", vaddr);
335368c31abSDavid du Colombier ventisrv = vtlisten(vaddr);
336368c31abSDavid du Colombier if(ventisrv == nil)
337368c31abSDavid du Colombier sysfatal("can't announce %s: %r", vaddr);
338368c31abSDavid du Colombier
339368c31abSDavid du Colombier fprint(2, "serving.\n");
340368c31abSDavid du Colombier if(nofork)
341368c31abSDavid du Colombier ventiserver(nil);
342368c31abSDavid du Colombier else
343368c31abSDavid du Colombier vtproc(ventiserver, nil);
34423566e0cSDavid du Colombier
34523566e0cSDavid du Colombier threadexits(nil);
346368c31abSDavid du Colombier }
347368c31abSDavid du Colombier
348368c31abSDavid du Colombier static void
vtrerror(VtReq * r,char * error)349368c31abSDavid du Colombier vtrerror(VtReq *r, char *error)
350368c31abSDavid du Colombier {
351368c31abSDavid du Colombier r->rx.msgtype = VtRerror;
352368c31abSDavid du Colombier r->rx.error = estrdup(error);
353368c31abSDavid du Colombier }
354368c31abSDavid du Colombier
355368c31abSDavid du Colombier static void
ventiserver(void * v)356368c31abSDavid du Colombier ventiserver(void *v)
357368c31abSDavid du Colombier {
358368c31abSDavid du Colombier Packet *p;
359368c31abSDavid du Colombier VtReq *r;
360368c31abSDavid du Colombier char err[ERRMAX];
361368c31abSDavid du Colombier uint ms;
362368c31abSDavid du Colombier int cached, ok;
363368c31abSDavid du Colombier
364368c31abSDavid du Colombier USED(v);
365368c31abSDavid du Colombier threadsetname("ventiserver");
366368c31abSDavid du Colombier trace(TraceWork, "start");
367368c31abSDavid du Colombier while((r = vtgetreq(ventisrv)) != nil){
368368c31abSDavid du Colombier trace(TraceWork, "finish");
369368c31abSDavid du Colombier trace(TraceWork, "start request %F", &r->tx);
370368c31abSDavid du Colombier trace(TraceRpc, "<- %F", &r->tx);
371368c31abSDavid du Colombier r->rx.msgtype = r->tx.msgtype+1;
372368c31abSDavid du Colombier addstat(StatRpcTotal, 1);
373368c31abSDavid du Colombier if(0) print("req (arenas[0]=%p sects[0]=%p) %F\n",
374368c31abSDavid du Colombier mainindex->arenas[0], mainindex->sects[0], &r->tx);
375368c31abSDavid du Colombier switch(r->tx.msgtype){
376368c31abSDavid du Colombier default:
377368c31abSDavid du Colombier vtrerror(r, "unknown request");
378368c31abSDavid du Colombier break;
379368c31abSDavid du Colombier case VtTread:
380368c31abSDavid du Colombier ms = msec();
381368c31abSDavid du Colombier r->rx.data = readlump(r->tx.score, r->tx.blocktype, r->tx.count, &cached);
382368c31abSDavid du Colombier ms = msec() - ms;
383368c31abSDavid du Colombier addstat2(StatRpcRead, 1, StatRpcReadTime, ms);
384368c31abSDavid du Colombier if(r->rx.data == nil){
385368c31abSDavid du Colombier addstat(StatRpcReadFail, 1);
386368c31abSDavid du Colombier rerrstr(err, sizeof err);
387368c31abSDavid du Colombier vtrerror(r, err);
388368c31abSDavid du Colombier }else{
389368c31abSDavid du Colombier addstat(StatRpcReadBytes, packetsize(r->rx.data));
390368c31abSDavid du Colombier addstat(StatRpcReadOk, 1);
391368c31abSDavid du Colombier if(cached)
392368c31abSDavid du Colombier addstat2(StatRpcReadCached, 1, StatRpcReadCachedTime, ms);
393368c31abSDavid du Colombier else
394368c31abSDavid du Colombier addstat2(StatRpcReadUncached, 1, StatRpcReadUncachedTime, ms);
395368c31abSDavid du Colombier }
396368c31abSDavid du Colombier break;
397368c31abSDavid du Colombier case VtTwrite:
398368c31abSDavid du Colombier if(readonly){
399368c31abSDavid du Colombier vtrerror(r, "read only");
400368c31abSDavid du Colombier break;
401368c31abSDavid du Colombier }
402368c31abSDavid du Colombier p = r->tx.data;
403368c31abSDavid du Colombier r->tx.data = nil;
404368c31abSDavid du Colombier addstat(StatRpcWriteBytes, packetsize(p));
405368c31abSDavid du Colombier ms = msec();
406368c31abSDavid du Colombier ok = writelump(p, r->rx.score, r->tx.blocktype, 0, ms);
407368c31abSDavid du Colombier ms = msec() - ms;
408368c31abSDavid du Colombier addstat2(StatRpcWrite, 1, StatRpcWriteTime, ms);
409368c31abSDavid du Colombier
410368c31abSDavid du Colombier if(ok < 0){
411368c31abSDavid du Colombier addstat(StatRpcWriteFail, 1);
412368c31abSDavid du Colombier rerrstr(err, sizeof err);
413368c31abSDavid du Colombier vtrerror(r, err);
414368c31abSDavid du Colombier }
415368c31abSDavid du Colombier break;
416368c31abSDavid du Colombier case VtTsync:
417368c31abSDavid du Colombier flushqueue();
418368c31abSDavid du Colombier flushdcache();
419368c31abSDavid du Colombier break;
420368c31abSDavid du Colombier }
421368c31abSDavid du Colombier trace(TraceRpc, "-> %F", &r->rx);
422368c31abSDavid du Colombier vtrespond(r);
423368c31abSDavid du Colombier trace(TraceWork, "start");
424368c31abSDavid du Colombier }
425368c31abSDavid du Colombier flushdcache();
426368c31abSDavid du Colombier flushicache();
427368c31abSDavid du Colombier threadexitsall(0);
428368c31abSDavid du Colombier }
429