/* returns exp(r = x + c) for |c| < |x| with no overlap. */
-double __exp__D(x, c)
-double x, c;
+double
+__exp__D(double x, double c)
{
double z,hi,lo;
int k;
* log(x) = a+b to 63 bits, with a rounded to 26 bits.
*/
struct Double
-#ifdef _ANSI_SOURCE
__log__D(double x)
-#else
-__log__D(x) double x;
-#endif
{
int m, j;
double F, f, g, q, u, v, u2;
static const double zero = 0., one = 1.0, tiny = 1e-300;
double
-tgamma(x)
- double x;
+tgamma(double x)
{
struct Double u;
* Accurate to max(ulp(1/128) absolute, 2^-66 relative) error.
*/
static struct Double
-large_gam(x)
- double x;
+large_gam(double x)
{
double z, p;
struct Double t, u, v;
* It also has correct monotonicity.
*/
static double
-small_gam(x)
- double x;
+small_gam(double x)
{
double y, ym1, t;
struct Double yy, r;
* Good on (0, 1+x0+LEFT]. Accurate to 1ulp.
*/
static double
-smaller_gam(x)
- double x;
+smaller_gam(double x)
{
double t, d;
struct Double r, xx;
* returns (z+c)^2 * P(z)/Q(z) + a0
*/
static struct Double
-ratfun_gam(z, c)
- double z, c;
+ratfun_gam(double z, double c)
{
double p, q;
struct Double r, t;
}
static double
-neg_gam(x)
- double x;
+neg_gam(double x)
{
int sgn = 1;
struct Double lg, lsine;
#define ASSERT(p) if (!(p)) botch("p")
#include <stdio.h>
static void
-botch(s)
- char *s;
+botch(char *s)
{
fprintf(stderr, "\r\nassertion botched: %s\r\n", s);
(void) fflush(stderr); /* just in case user buffered it */
#define TRACE() rtld_printf("TRACE %s:%d\n", __FILE__, __LINE__)
void *
-malloc(nbytes)
- size_t nbytes;
+malloc(size_t nbytes)
{
register union overhead *op;
register int bucket;
* Allocate more memory to the indicated bucket.
*/
static void
-morecore(bucket)
- int bucket;
+morecore(int bucket)
{
register union overhead *op;
register int sz; /* size of desired block */
}
void
-free(cp)
- void *cp;
+free(void *cp)
{
register int size;
register union overhead *op;
int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */
void *
-realloc(cp, nbytes)
- void *cp;
- size_t nbytes;
+realloc(void *cp, size_t nbytes)
{
register u_int onb;
register int i;
* Return bucket number, or -1 if not found.
*/
static int
-findbucket(freep, srchlen)
- union overhead *freep;
- int srchlen;
+findbucket(union overhead *freep, int srchlen)
{
register union overhead *p;
register int i, j;
* for each size category, the second showing the number of mallocs -
* frees for each size category.
*/
-mstats(s)
- char *s;
+void
+mstats(char *s)
{
register int i, j;
register union overhead *p;
static int
-morepages(n)
-int n;
+morepages(int n)
{
int fd = -1;
int offset;
static int thread_flag;
static void *
-def_lock_create()
+def_lock_create(void)
{
void *base;
char *p;
}
void
-lockdflt_init()
+lockdflt_init(void)
{
int i;
struct iaddr a;
ssize_t n;
+ /*
+ * Read one message non-blocking, ignore signals.
+ */
do {
n = read(routefd, &msg, sizeof(msg));
} while (n == -1 && errno == EINTR);
+ /*
+ * No operation if no messages ready or the message is
+ * not sized properly.
+ */
rtm = (struct rt_msghdr *)msg;
if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
- rtm->rtm_version != RTM_VERSION)
+ rtm->rtm_version != RTM_VERSION) {
return;
+ }
+ /*
+ * Process the message.
+ */
switch (rtm->rtm_type) {
case RTM_NEWADDR:
ifam = (struct ifa_msghdr *)rtm;
if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
break;
sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
- if (sa == NULL)
+ if (sa == NULL) {
+ warning("RTM_NEWADDR: No IFA");
goto die;
+ }
if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
error("king bula sez: len mismatch");
/* new addr is the one we set */
break;
+ warning("RTM_NEWADDR: Our IFA not found");
goto die;
case RTM_DELADDR:
ifam = (struct ifa_msghdr *)rtm;
break;
if (scripttime == 0 || t < scripttime + 10)
break;
+ warning("RTM_DELADDR: Third-party %d", (int)(t - scripttime));
goto die;
case RTM_IFINFO:
ifm = (struct if_msghdr *)rtm;
if (ifm->ifm_index != ifi->index)
break;
- if ((rtm->rtm_flags & RTF_UP) == 0)
+ if ((rtm->rtm_flags & RTF_UP) == 0) {
+ warning("RTM_IFINFO: Interface not up");
goto die;
+ }
linkstat =
LINK_STATE_IS_UP(ifm->ifm_data.ifi_link_state) ? 1 : 0;
case RTM_IFANNOUNCE:
ifan = (struct if_announcemsghdr *)rtm;
if (ifan->ifan_what == IFAN_DEPARTURE &&
- ifan->ifan_index == ifi->index)
+ ifan->ifan_index == ifi->index) {
+ warning("RTM_IFANNOUNCE: Interface departure");
goto die;
+ }
break;
default:
break;
static void master_auth_rxmsg(hammer2_msg_t *msg);
static void master_link_signal(hammer2_router_t *router);
static void master_link_rxmsg(hammer2_msg_t *msg);
+static void master_reconnect(const char *mntpt);
/*
* Start-up the master listener daemon for the machine.
struct sockaddr_in asin;
socklen_t alen;
pthread_t thread;
+ hammer2_master_service_info_t *info;
int lfd = (int)(intptr_t)data;
int fd;
+ int i;
+ int count;
+ struct statfs *mntbuf = NULL;
+ struct statvfs *mntvbuf = NULL;
/*
* Nobody waits for us
pthread_detach(pthread_self());
/*
+ * Scan existing hammer2 mounts and reconnect to them using
+ * HAMMER2IOC_RECLUSTER.
+ */
+ count = getmntvinfo(&mntbuf, &mntvbuf, MNT_NOWAIT);
+ for (i = 0; i < count; ++i) {
+ if (strcmp(mntbuf[i].f_fstypename, "hammer2") == 0)
+ master_reconnect(mntbuf[i].f_mntonname);
+ }
+
+ /*
* Accept connections and create pthreads to handle them after
* validating the IP.
*/
}
thread = NULL;
fprintf(stderr, "master_accept: accept fd %d\n", fd);
- pthread_create(&thread, NULL,
- master_service, (void *)(intptr_t)fd);
+ info = malloc(sizeof(*info));
+ bzero(info, sizeof(*info));
+ info->fd = fd;
+ info->detachme = 1;
+ pthread_create(&thread, NULL, master_service, info);
}
return (NULL);
}
/*
+ * Normally the mount program supplies a cluster communications
+ * descriptor to the hammer2 vfs on mount, but if you kill the service
+ * daemon and restart it that link will be lost.
+ *
+ * This procedure attempts to [re]connect to existing mounts when
+ * the service daemon is started up before going into its accept
+ * loop.
+ */
+static
+void
+master_reconnect(const char *mntpt)
+{
+ struct hammer2_ioc_recluster recls;
+ hammer2_master_service_info_t *info;
+ pthread_t thread;
+ int fd;
+ int pipefds[2];
+
+ fd = open(mntpt, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "reconnect %s: no access to mount\n", mntpt);
+ return;
+ }
+ if (pipe(pipefds) < 0) {
+ fprintf(stderr, "reconnect %s: pipe() failed\n", mntpt);
+ return;
+ }
+ bzero(&recls, sizeof(recls));
+ recls.fd = pipefds[0];
+ if (ioctl(fd, HAMMER2IOC_RECLUSTER, &recls) < 0) {
+ fprintf(stderr, "reconnect %s: ioctl failed\n", mntpt);
+ close(pipefds[0]);
+ close(pipefds[1]);
+ close(fd);
+ return;
+ }
+ close(pipefds[0]);
+
+ info = malloc(sizeof(*info));
+ bzero(info, sizeof(*info));
+ info->fd = pipefds[1];
+ info->detachme = 1;
+ pthread_create(&thread, NULL, master_service, info);
+}
+
+/*
* Service an accepted connection (runs as a pthread)
*
* (also called from a couple of other places)
void *
master_service(void *data)
{
+ hammer2_master_service_info_t *info = data;
hammer2_iocom_t iocom;
- int fd;
- fd = (int)(intptr_t)data;
- hammer2_iocom_init(&iocom, fd, -1,
+ if (info->detachme)
+ pthread_detach(pthread_self());
+
+ hammer2_iocom_init(&iocom, info->fd, -1,
master_auth_signal,
master_auth_rxmsg,
NULL);
fprintf(stderr,
"iocom on fd %d terminated error rx=%d, tx=%d\n",
- fd, iocom.ioq_rx.error, iocom.ioq_tx.error);
- close(fd);
+ info->fd, iocom.ioq_rx.error, iocom.ioq_tx.error);
+ close(info->fd);
+ info->fd = -1; /* safety */
+ free(info);
return (NULL);
}
typedef struct hammer2_idmap hammer2_idmap_t;
+struct hammer2_master_service_info {
+ int fd;
+ int detachme;
+};
+
+typedef struct hammer2_master_service_info hammer2_master_service_info_t;
+
extern int DebugOpt;
extern int VerboseOpt;
extern int QuietOpt;
void (*rcvmsg_func)(hammer2_msg_t *),
void (*altmsg_func)(hammer2_iocom_t *))
{
+ struct stat st;
+
bzero(iocom, sizeof(*iocom));
iocom->router = hammer2_router_alloc();
/*
* Negotiate session crypto synchronously. This will mark the
- * connection as error'd if it fails.
+ * connection as error'd if it fails. If this is a pipe it's
+ * a linkage that we set up ourselves to the filesystem and there
+ * is no crypto.
*/
- hammer2_crypto_negotiate(iocom);
+ if (fstat(sock_fd, &st) < 0)
+ assert(0);
+ if (S_ISSOCK(st.st_mode))
+ hammer2_crypto_negotiate(iocom);
/*
* Make sure our fds are set to non-blocking for the iocom core.
void
hammer2_volconf_start(h2span_media_config_t *conf, const char *hostname)
{
+ hammer2_master_service_info_t *info;
+
switch(conf->state) {
case H2MC_STOPPED:
case H2MC_CONNECT:
fprintf(stderr, "Unable to connect to %s\n", hostname);
conf->state = H2MC_CONNECT;
} else {
- pthread_create(&conf->iocom_thread, NULL,
- master_service,
- (void *)(intptr_t)conf->fd);
+ info = malloc(sizeof(*info));
+ bzero(info, sizeof(*info));
+ info->fd = conf->fd;
+ info->detachme = 0;
conf->state = H2MC_RUNNING;
+ pthread_create(&conf->iocom_thread, NULL,
+ master_service, info);
}
break;
case H2MC_RUNNING:
These devices support SATA/ATA disk drives
and provide RAID0 (striping), RAID1 (mirroring), and RAID5 functionality.
.Sh LOADER TUNABLES
-.Pp
The following tunables are settable from the loader:
.Bl -tag -width indent
.It Va hw.hptrr.attach_generic
LDADD+= -lpcap -lutil
DPADD+= ${LIBPCAP} ${LIBUTIL}
CFLAGS+= -DHAVE_SNPRINTF -I${.CURDIR}/../../contrib/libpcap
-WARNS?= 4
+WARNS?= 5
PROG= pflogd
SRCS= pflogd.c privsep.c privsep_fdpass.c