void ifinit(void) { struct interface ifs, *ifp; int s; char buf[BUFSIZ], *cp, *cplim; struct ifconf ifc; struct ifreq ifreq, *ifr; struct sockaddr_in *sin; u_long i; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); close(s); return; } ifc.ifc_len = sizeof (buf); ifc.ifc_buf = buf; if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { syslog(LOG_ERR, "ioctl (get interface configuration)"); close(s); return; } ifr = ifc.ifc_req; lookforinterfaces = 0; cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */ for (cp = buf; cp < cplim; cp += sizeof (ifr->ifr_name) + sizeof(ifr->ifr_ifru)) { ifr = (struct ifreq *)cp; bzero((char *)&ifs, sizeof(ifs)); ifs.int_addr = ifr->ifr_addr; ifreq = *ifr; if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { syslog(LOG_ERR, "%s: ioctl (get interface flags)", ifr->ifr_name); continue; } ifs.int_flags = ifreq.ifr_flags | IFF_INTERFACE; if ((ifs.int_flags & IFF_UP) == 0 || ifr->ifr_addr.sa_family == AF_UNSPEC) { lookforinterfaces = 1; continue; } /* argh, this'll have to change sometime */ if (ifs.int_addr.sa_family != AF_INET) continue; if (ifs.int_flags & IFF_POINTOPOINT) { if (ioctl(s, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "%s: ioctl (get dstaddr)", ifr->ifr_name); continue; } if (ifr->ifr_addr.sa_family == AF_UNSPEC) { lookforinterfaces = 1; continue; } ifs.int_dstaddr = ifreq.ifr_dstaddr; } /* * already known to us? * This allows multiple point-to-point links * to share a source address (possibly with one * other link), but assumes that there will not be * multiple links with the same destination address. */ if (ifs.int_flags & IFF_POINTOPOINT) { if (if_ifwithdstaddr(&ifs.int_dstaddr)) continue; } else if (if_ifwithaddr(&ifs.int_addr)) continue; if (ifs.int_flags & IFF_LOOPBACK) { ifs.int_flags |= IFF_PASSIVE; foundloopback = 1; loopaddr = ifs.int_addr; for (ifp = ifnet; ifp; ifp = ifp->int_next) if (ifp->int_flags & IFF_POINTOPOINT) add_ptopt_localrt(ifp); } if (ifs.int_flags & IFF_BROADCAST) { if (ioctl(s, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { syslog(LOG_ERR, "%s: ioctl (get broadaddr)", ifr->ifr_name); continue; } ifs.int_broadaddr = ifreq.ifr_broadaddr; } #ifdef SIOCGIFMETRIC if (ioctl(s, SIOCGIFMETRIC, (char *)&ifreq) < 0) { syslog(LOG_ERR, "%s: ioctl (get metric)", ifr->ifr_name); ifs.int_metric = 0; } else ifs.int_metric = ifreq.ifr_metric; #else ifs.int_metric = 0; #endif /* * Use a minimum metric of one; * treat the interface metric (default 0) * as an increment to the hop count of one. */ ifs.int_metric++; if (ioctl(s, SIOCGIFNETMASK, (char *)&ifreq) < 0) { syslog(LOG_ERR, "%s: ioctl (get netmask)", ifr->ifr_name); continue; } sin = (struct sockaddr_in *)&ifreq.ifr_addr; ifs.int_subnetmask = ntohl(sin->sin_addr.s_addr); sin = (struct sockaddr_in *)&ifs.int_addr; i = ntohl(sin->sin_addr.s_addr); if (IN_CLASSA(i)) ifs.int_netmask = IN_CLASSA_NET; else if (IN_CLASSB(i)) ifs.int_netmask = IN_CLASSB_NET; else ifs.int_netmask = IN_CLASSC_NET; ifs.int_net = i & ifs.int_netmask; ifs.int_subnet = i & ifs.int_subnetmask; if (ifs.int_subnetmask != ifs.int_netmask) ifs.int_flags |= IFF_SUBNET; ifp = (struct interface *)malloc(sizeof (struct interface)); if (ifp == 0) { printf("routed: out of memory\n"); break; } *ifp = ifs; /* * Count the # of directly connected networks * and point to point links which aren't looped * back to ourself. This is used below to * decide if we should be a routing ``supplier''. */ if ((ifs.int_flags & IFF_LOOPBACK) == 0 && ((ifs.int_flags & IFF_POINTOPOINT) == 0 || if_ifwithaddr(&ifs.int_dstaddr) == 0)) externalinterfaces++; /* * If we have a point-to-point link, we want to act * as a supplier even if it's our only interface, * as that's the only way our peer on the other end * can tell that the link is up. */ if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) supplier = 1; ifp->int_name = malloc(strlen(ifr->ifr_name) + 1); if (ifp->int_name == 0) { fprintf(stderr, "routed: ifinit: out of memory\n"); syslog(LOG_ERR, "routed: ifinit: out of memory\n"); close(s); return; } strcpy(ifp->int_name, ifr->ifr_name); *ifnext = ifp; ifnext = &ifp->int_next; traceinit(ifp); addrouteforif(ifp); } if (externalinterfaces > 1 && supplier < 0) supplier = 1; close(s); }
/* * This is called at startup and after that, every CHECK_INTERVAL seconds or * when a SIGHUP is received. */ void initifs(void) { static char *buf = NULL; static uint_t maxbufsize = 0; int bufsize; int numifs; struct lifnum lifn; struct lifconf lifc; struct lifreq lifr; struct lifreq *lifrp; int n; struct interface ifs; struct interface *ifp; int netmaskchange = 0; boolean_t changes = _B_FALSE; lifn.lifn_family = AF_INET6; lifn.lifn_flags = 0; if (ioctl(iocsoc, SIOCGLIFNUM, (char *)&lifn) < 0) { syslog(LOG_ERR, "initifs: ioctl (get interface numbers): %m"); return; } numifs = lifn.lifn_count; bufsize = numifs * sizeof (struct lifreq); if (buf == NULL || bufsize > maxbufsize) { if (buf != NULL) free(buf); maxbufsize = bufsize; buf = (char *)malloc(maxbufsize); if (buf == NULL) { syslog(LOG_ERR, "initifs: out of memory"); return; } } lifc.lifc_family = AF_INET6; lifc.lifc_flags = 0; lifc.lifc_len = bufsize; lifc.lifc_buf = buf; if (ioctl(iocsoc, SIOCGLIFCONF, (char *)&lifc) < 0) { syslog(LOG_ERR, "initifs: ioctl (get interface configuration): %m"); return; } /* * Mark all of the currently known interfaces in order to determine * which of the these interfaces no longer exist. */ for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) ifp->int_flags |= RIP6_IFF_MARKED; lifrp = lifc.lifc_req; for (n = lifc.lifc_len / sizeof (struct lifreq); n > 0; n--, lifrp++) { bzero((char *)&ifs, sizeof (ifs)); (void) strncpy(lifr.lifr_name, lifrp->lifr_name, sizeof (lifr.lifr_name)); if (ioctl(iocsoc, SIOCGLIFFLAGS, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get interface flags): %m"); continue; } if (!(lifr.lifr_flags & IFF_IPV6) || !(lifr.lifr_flags & IFF_MULTICAST) || (lifr.lifr_flags & IFF_LOOPBACK)) continue; ifp = if_ifwithname(lifr.lifr_name); if (ifp != NULL) ifp->int_flags &= ~RIP6_IFF_MARKED; if (lifr.lifr_flags & IFF_POINTOPOINT) ifs.int_flags |= RIP6_IFF_POINTOPOINT; if (lifr.lifr_flags & IFF_NORTEXCH) ifs.int_flags |= RIP6_IFF_NORTEXCH; if (lifr.lifr_flags & IFF_PRIVATE) ifs.int_flags |= RIP6_IFF_PRIVATE; if (lifr.lifr_flags & IFF_UP) { ifs.int_flags |= RIP6_IFF_UP; } else { if (ifp != NULL) { if (ifp->int_flags & RIP6_IFF_UP) { /* * If there is an transition from up to * down for an exisiting interface, * increment the counter. */ ifp->int_transitions++; changes = _B_TRUE; } if_purge(ifp); } continue; } if (ifs.int_flags & RIP6_IFF_POINTOPOINT) { /* * For point-to-point interfaces, retrieve both the * local and the remote addresses. */ if (ioctl(iocsoc, SIOCGLIFADDR, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get interface address): " "%m"); continue; } ifs.int_addr = ((struct sockaddr_in6 *)&lifr.lifr_addr)->sin6_addr; if (ioctl(iocsoc, SIOCGLIFDSTADDR, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get destination address): " "%m"); continue; } ifs.int_dstaddr = ((struct sockaddr_in6 *) &lifr.lifr_dstaddr)->sin6_addr; ifs.int_prefix_length = IPV6_ABITS; } else { /* * For other interfaces, retreieve the prefix (including * the prefix length. */ if (ioctl(iocsoc, SIOCGLIFSUBNET, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get subnet prefix): %m"); continue; } /* * This should never happen but check for it in any case * since the kernel stores it as an signed integer. */ if (lifr.lifr_addrlen < 0 || lifr.lifr_addrlen > IPV6_ABITS) { syslog(LOG_ERR, "initifs: ioctl (get subnet prefix) " "returned invalid prefix length of %d", lifr.lifr_addrlen); continue; } ifs.int_prefix_length = lifr.lifr_addrlen; ifs.int_addr = ((struct sockaddr_in6 *) &lifr.lifr_subnet)->sin6_addr; } if (ioctl(iocsoc, SIOCGLIFMETRIC, (char *)&lifr) < 0 || lifr.lifr_metric < 0) ifs.int_metric = 1; else ifs.int_metric = lifr.lifr_metric + 1; if (ioctl(iocsoc, SIOCGLIFINDEX, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get index): %m"); continue; } ifs.int_ifindex = lifr.lifr_index; if (ioctl(iocsoc, SIOCGLIFMTU, (char *)&lifr) < 0) { syslog(LOG_ERR, "initifs: ioctl (get mtu): %m"); continue; } /* * If the interface's recorded MTU doesn't make sense, use * IPV6_MIN_MTU instead. */ if (lifr.lifr_mtu < IPV6_MIN_MTU) ifs.int_mtu = IPV6_MIN_MTU; else ifs.int_mtu = lifr.lifr_mtu; if (ifp != NULL) { /* * RIP6_IFF_NORTEXCH flag change by itself shouldn't * cause an if_purge() call, which also purges all the * routes heard off this interface. So, let's suppress * changes of RIP6_IFF_NORTEXCH in the following * comparisons. */ if (ifp->int_prefix_length == ifs.int_prefix_length && ((ifp->int_flags | RIP6_IFF_NORTEXCH) == (ifs.int_flags | RIP6_IFF_NORTEXCH)) && ifp->int_metric == ifs.int_metric && ifp->int_ifindex == ifs.int_ifindex) { /* * Now let's make sure we capture the latest * value of RIP6_IFF_NORTEXCH flag. */ if (ifs.int_flags & RIP6_IFF_NORTEXCH) ifp->int_flags |= RIP6_IFF_NORTEXCH; else ifp->int_flags &= ~RIP6_IFF_NORTEXCH; if (!(ifp->int_flags & RIP6_IFF_POINTOPOINT) && IN6_ARE_ADDR_EQUAL(&ifp->int_addr, &ifs.int_addr)) continue; if ((ifp->int_flags & RIP6_IFF_POINTOPOINT) && IN6_ARE_ADDR_EQUAL(&ifp->int_dstaddr, &ifs.int_dstaddr)) continue; } if_purge(ifp); if (ifp->int_prefix_length != ifs.int_prefix_length) netmaskchange = 1; ifp->int_addr = ifs.int_addr; ifp->int_dstaddr = ifs.int_dstaddr; ifp->int_metric = ifs.int_metric; /* * If there is an transition from down to up for an * exisiting interface, increment the counter. */ if (!(ifp->int_flags & RIP6_IFF_UP) && (ifs.int_flags & RIP6_IFF_UP)) ifp->int_transitions++; ifp->int_flags |= ifs.int_flags; ifp->int_prefix_length = ifs.int_prefix_length; /* * If the interface index has changed, we may need to * set up the listen socket again. */ if (ifp->int_ifindex != ifs.int_ifindex) { if (ifp->int_sock != -1) { resetup_listen_sock(ifp, ifs.int_ifindex); } ifp->int_ifindex = ifs.int_ifindex; } ifp->int_mtu = ifs.int_mtu; } else { char *cp; int log_num; ifp = (struct interface *) malloc(sizeof (struct interface)); if (ifp == NULL) { syslog(LOG_ERR, "initifs: out of memory"); return; } *ifp = ifs; ifp->int_name = ifp->int_ifbase = NULL; ifp->int_name = (char *)malloc((size_t)strlen(lifr.lifr_name) + 1); if (ifp->int_name == NULL) { free(ifp); syslog(LOG_ERR, "initifs: out of memory"); return; } (void) strcpy(ifp->int_name, lifr.lifr_name); ifp->int_ifbase = (char *)malloc((size_t)strlen(lifr.lifr_name) + 1); if (ifp->int_ifbase == NULL) { free(ifp->int_name); free(ifp); syslog(LOG_ERR, "initifs: out of memory"); return; } (void) strcpy(ifp->int_ifbase, lifr.lifr_name); cp = (char *)index(ifp->int_ifbase, IF_SEPARATOR); if (cp != NULL) { /* * Verify that the value following the separator * is an integer greater than zero (the only * possible value for a logical interface). */ log_num = atoi((char *)(cp + 1)); if (log_num <= 0) { free(ifp->int_ifbase); free(ifp->int_name); free(ifp); syslog(LOG_ERR, "initifs: interface name %s could " "not be parsed", ifp->int_name); return; } *cp = '\0'; } else { log_num = 0; } if (log_num == 0) { ifp->int_sock = setup_listen_sock(ifp->int_ifindex); } else { ifp->int_sock = -1; } ifp->int_next = ifnet; ifnet = ifp; traceinit(ifp); } addrouteforif(ifp); changes = _B_TRUE; } /* * Any remaining interfaces that are still marked and which were in an * up state (RIP6_IFF_UP) need to removed from the routing table. */ for (ifp = ifnet; ifp != NULL; ifp = ifp->int_next) { if ((ifp->int_flags & (RIP6_IFF_MARKED | RIP6_IFF_UP)) == (RIP6_IFF_MARKED | RIP6_IFF_UP)) { if_purge(ifp); ifp->int_flags &= ~RIP6_IFF_MARKED; changes = _B_TRUE; } } if (netmaskchange) rtchangeall(); if (supplier & changes) dynamic_update((struct interface *)NULL); }
void threadmain(int argc, char *argv[]) { char *haddr, *vaddr, *webroot, *file; traceinit(); threadsetname("main"); vaddr = nil; haddr = "tcp!*!9000"; webroot = nil; ARGBEGIN{ case 'a': vaddr = EARGF(usage()); break; case 'D': settrace(EARGF(usage())); break; case 'd': debug = 1; nofork = 1; break; case 'h': haddr = EARGF(usage()); break; case 'L': ventilogging = 1; break; case 'r': readonly = 1; break; case 's': nofork = 1; break; case 'W': webroot = EARGF(usage()); break; default: usage(); }ARGEND if(argc < 1) usage(); file = argv[0]; if(!nofork) rfork(RFNOTEG); #ifdef PLAN9PORT { /* sigh - needed to avoid signals when writing to hungup networks */ struct sigaction sa; memset(&sa, 0, sizeof sa); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, nil); } #endif ventifmtinstall(); trace(TraceQuiet, "venti started"); fprint(2, "%T venti: "); statsinit(); mminit(file, readonly ? OREAD : ORDWR); /* * default other configuration-file parameters */ if(vaddr == nil) vaddr = "tcp!*!venti"; if(haddr){ fprint(2, "httpd %s...", haddr); if(httpdinit(haddr, webroot) < 0) fprint(2, "warning: can't start http server: %r"); } fprint(2, "init..."); fprint(2, "announce %s...", vaddr); ventisrv = vtlisten(vaddr); if(ventisrv == nil) sysfatal("can't announce %s: %r", vaddr); fprint(2, "serving.\n"); if(nofork) ventiserver(nil); else vtproc(ventiserver, nil); threadexits(nil); }
/* * Find the network interfaces which have configured themselves. * If the interface is present but not yet up (for example an * ARPANET IMP), set the lookforinterfaces flag so we'll * come back later and look again. */ void ifinit(void) { struct interface ifs, *ifp; size_t needed; int mib[6], no_ipxaddr = 0, flags = 0; char *buf, *cplim, *cp; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr_dl *sdl = NULL; mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_IPX; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) quit("route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) quit("malloc"); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) lookforinterfaces = 0; cplim = buf + needed; for (cp = buf; cp < cplim; cp += ifm->ifm_msglen) { ifm = (struct if_msghdr *)cp; if (ifm->ifm_type == RTM_IFINFO) { bzero(&ifs, sizeof(ifs)); ifs.int_flags = flags = ifm->ifm_flags | IFF_INTERFACE; if ((flags & IFF_UP) == 0 || no_ipxaddr) lookforinterfaces = 1; sdl = (struct sockaddr_dl *) (ifm + 1); sdl->sdl_data[sdl->sdl_nlen] = 0; no_ipxaddr = 1; continue; } if (ifm->ifm_type != RTM_NEWADDR) quit("ifinit: out of sync"); if ((flags & IFF_UP) == 0) continue; ifam = (struct ifa_msghdr *)ifm; info.rti_addrs = ifam->ifam_addrs; rt_xaddrs((char *)(ifam + 1), cp + ifam->ifam_msglen, &info); if (ifaaddr == 0) { syslog(LOG_ERR, "%s: (get addr)", sdl->sdl_data); continue; } ifs.int_addr = *ifaaddr; if (ifs.int_addr.sa_family != AF_IPX) continue; no_ipxaddr = 0; if (ifs.int_flags & IFF_POINTOPOINT) { if (brdaddr == 0) { syslog(LOG_ERR, "%s: (get dstaddr)", sdl->sdl_data); continue; } if (brdaddr->sa_family == AF_UNSPEC) { lookforinterfaces = 1; continue; } ifs.int_dstaddr = *brdaddr; } if (ifs.int_flags & IFF_BROADCAST) { if (brdaddr == 0) { syslog(LOG_ERR, "%s: (get broadaddr)", sdl->sdl_data); continue; } ifs.int_dstaddr = *brdaddr; } if (ifs.int_flags & IFF_LOOPBACK) { ifs.int_dstaddr = ifs.int_addr; } /* * already known to us? * what makes a POINTOPOINT if unique is its dst addr, * NOT its source address */ if ( ((ifs.int_flags & IFF_POINTOPOINT) && if_ifwithdstaddr(&ifs.int_dstaddr)) || ( ((ifs.int_flags & IFF_POINTOPOINT) == 0) && if_ifwithaddr(&ifs.int_addr))) continue; ifp = (struct interface *) malloc(sdl->sdl_nlen + 1 + sizeof(ifs)); if (ifp == NULL) { syslog(LOG_ERR, "IPXrouted: out of memory\n"); lookforinterfaces = 1; break; } *ifp = ifs; /* * Count the # of directly connected networks * and point to point links which aren't looped * back to ourself. This is used below to * decide if we should be a routing ``supplier''. */ if ((ifs.int_flags & IFF_POINTOPOINT) == 0 || if_ifwithaddr(&ifs.int_dstaddr) == 0) externalinterfaces++; /* * If we have a point-to-point link, we want to act * as a supplier even if it's our only interface, * as that's the only way our peer on the other end * can tell that the link is up. */ if ((ifs.int_flags & IFF_POINTOPOINT) && supplier < 0) supplier = 1; ifp->int_name = (char *)(ifp + 1); strcpy(ifp->int_name, sdl->sdl_data); ifp->int_metric = ifam->ifam_metric; ifp->int_next = ifnet; ifnet = ifp; traceinit(ifp); addrouteforif(ifp); } if (externalinterfaces > 1 && supplier < 0) supplier = 1; free(buf); }
void threadmain(int argc, char *argv[]) { char *configfile, *haddr, *vaddr, *webroot; u32int mem, icmem, bcmem, minbcmem, mempcnt, stfree; Allocs allocs; Config config; traceinit(); threadsetname("main"); mempcnt = 0; vaddr = nil; haddr = nil; configfile = nil; webroot = nil; mem = Unspecified; icmem = 0; bcmem = 0; ARGBEGIN{ case 'a': vaddr = EARGF(usage()); break; case 'B': bcmem = unittoull(EARGF(usage())); break; case 'c': configfile = EARGF(usage()); break; case 'C': mem = unittoull(EARGF(usage())); break; case 'D': settrace(EARGF(usage())); break; case 'd': debug = 1; nofork = 1; break; case 'h': haddr = EARGF(usage()); break; case 'm': mempcnt = atoi(EARGF(usage())); if (mempcnt <= 0 || mempcnt >= 100) usage(); break; case 'I': icmem = unittoull(EARGF(usage())); break; case 'L': ventilogging = 1; break; case 'r': readonly = 1; break; case 's': nofork = 1; break; case 'w': /* compatibility with old venti */ queuewrites = 1; break; case 'W': webroot = EARGF(usage()); break; default: usage(); }ARGEND if(argc) usage(); if(!nofork) rfork(RFNOTEG); #ifdef PLAN9PORT { /* sigh - needed to avoid signals when writing to hungup networks */ struct sigaction sa; memset(&sa, 0, sizeof sa); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, nil); } #endif ventifmtinstall(); trace(TraceQuiet, "venti started"); fprint(2, "%T venti: "); if(configfile == nil) configfile = "venti.conf"; /* remember free memory before initventi & loadbloom, for auto-sizing */ stfree = freemem(); fprint(2, "conf..."); if(initventi(configfile, &config) < 0) sysfatal("can't init server: %r"); /* * load bloom filter */ if(mainindex->bloom && loadbloom(mainindex->bloom) < 0) sysfatal("can't load bloom filter: %r"); /* * size memory allocations; assumes bloom filter is loaded */ allocs = sizeallocs((Allocs){mem, bcmem, icmem, stfree, mempcnt}, &config); mem = allocs.mem; bcmem = allocs.bcmem; icmem = allocs.icmem; fprint(2, "%s: mem %,ud bcmem %,ud icmem %,ud...", argv0, mem, bcmem, icmem); /* * default other configuration-file parameters */ if(haddr == nil) haddr = config.haddr; if(vaddr == nil) vaddr = config.vaddr; if(vaddr == nil) vaddr = "tcp!*!venti"; if(webroot == nil) webroot = config.webroot; if(queuewrites == 0) queuewrites = config.queuewrites; if(haddr){ fprint(2, "httpd %s...", haddr); if(httpdinit(haddr, webroot) < 0) fprint(2, "warning: can't start http server: %r"); } fprint(2, "init..."); /* * lump cache */ if(0) fprint(2, "initialize %d bytes of lump cache for %d lumps\n", mem, mem / (8 * 1024)); initlumpcache(mem, mem / (8 * 1024)); /* * index cache */ initicache(icmem); initicachewrite(); /* * block cache: need a block for every arena and every process */ minbcmem = maxblocksize * (mainindex->narenas + mainindex->nsects*4 + 16); if(bcmem < minbcmem) bcmem = minbcmem; if(0) fprint(2, "initialize %d bytes of disk block cache\n", bcmem); initdcache(bcmem); if(mainindex->bloom) startbloomproc(mainindex->bloom); fprint(2, "sync..."); if(!readonly && syncindex(mainindex) < 0) sysfatal("can't sync server: %r"); if(!readonly && queuewrites){ fprint(2, "queue..."); if(initlumpqueues(mainindex->nsects) < 0){ fprint(2, "can't initialize lump queues," " disabling write queueing: %r"); queuewrites = 0; } } if(initarenasum() < 0) fprint(2, "warning: can't initialize arena summing process: %r"); fprint(2, "announce %s...", vaddr); ventisrv = vtlisten(vaddr); if(ventisrv == nil) sysfatal("can't announce %s: %r", vaddr); fprint(2, "serving.\n"); if(nofork) ventiserver(nil); else vtproc(ventiserver, nil); threadexits(nil); }