From 96daee2b470e6b3f99aafd60f7495db0d060132f Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 19 Aug 2008 21:34:16 +0000 Subject: [PATCH] Integrate Solaris patches, with a bit of polishing. Don't look for umem on FreeBSD, which have dummy stub version for dtrace or ZFS compatibility. Generally restrict probes for Solaris specific stuff to when we run on solaris, no need to make configure slower than it is. Don't pretend we can get anywhere without poll(2) we use it for lots of things: Remove #if conditionals around poll-acceptor. Sort a couple of lists, before they get too unsorted. Submitted by: Theo Schlossnagle git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@3113 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/Makefile.am | 12 +- varnish-cache/bin/varnishd/cache_acceptor.c | 6 +- varnish-cache/bin/varnishd/cache_acceptor.h | 4 +- .../bin/varnishd/cache_acceptor_poll.c | 4 - .../bin/varnishd/cache_acceptor_ports.c | 169 +++++++++++++++++ varnish-cache/bin/varnishd/cache_pool.c | 33 ++++ varnish-cache/bin/varnishd/storage_umem.c | 173 ++++++++++++++++++ varnish-cache/bin/varnishd/tcp.c | 3 + varnish-cache/bin/varnishd/varnishd.c | 9 + varnish-cache/configure.ac | 36 ++-- 10 files changed, 422 insertions(+), 27 deletions(-) create mode 100644 varnish-cache/bin/varnishd/cache_acceptor_ports.c create mode 100644 varnish-cache/bin/varnishd/storage_umem.c diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 82c1eef3..e487812d 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -9,8 +9,9 @@ dist_man_MANS = varnishd.1 varnishd_SOURCES = \ cache_acceptor.c \ cache_acceptor_epoll.c \ - cache_acceptor_poll.c \ cache_acceptor_kqueue.c \ + cache_acceptor_poll.c \ + cache_acceptor_ports.c \ cache_backend.c \ cache_backend_cfg.c \ cache_backend_poll.c \ @@ -27,19 +28,19 @@ varnishd_SOURCES = \ cache_httpconn.c \ cache_main.c \ cache_panic.c \ - cache_pool.c \ cache_pipe.c \ + cache_pool.c \ cache_response.c \ cache_session.c \ cache_vary.c \ cache_vcl.c \ cache_vrt.c \ cache_vrt_acl.c \ - cache_vrt_re.c \ cache_vrt_esi.c \ + cache_vrt_re.c \ cache_ws.c \ - hash_simple_list.c \ hash_classic.c \ + hash_simple_list.c \ instance.c \ mgt_child.c \ mgt_cli.c \ @@ -51,15 +52,16 @@ varnishd_SOURCES = \ storage_file.c \ storage_malloc.c \ storage_synth.c \ + storage_umem.c \ tcp.c \ varnishd.c noinst_HEADERS = \ acct_fields.h \ cache.h \ + cache_acceptor.h \ cache_backend.h \ cache_backend_poll.h \ - cache_acceptor.h \ common.h \ default_vcl.h \ hash_slinger.h \ diff --git a/varnish-cache/bin/varnishd/cache_acceptor.c b/varnish-cache/bin/varnishd/cache_acceptor.c index 7eee94f6..e4fa352c 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.c +++ b/varnish-cache/bin/varnishd/cache_acceptor.c @@ -46,7 +46,6 @@ #include #include -#include "config.h" #include "cli.h" #include "cli_priv.h" #include "shmlog.h" @@ -60,9 +59,10 @@ static struct acceptor *vca_acceptors[] = { #if defined(HAVE_EPOLL_CTL) &acceptor_epoll, #endif -#if defined(HAVE_POLL) - &acceptor_poll, +#if defined(HAVE_PORT_CREATE) + &acceptor_ports, #endif + &acceptor_poll, NULL, }; diff --git a/varnish-cache/bin/varnishd/cache_acceptor.h b/varnish-cache/bin/varnishd/cache_acceptor.h index dcda822e..f885c1c3 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor.h +++ b/varnish-cache/bin/varnishd/cache_acceptor.h @@ -48,8 +48,10 @@ extern struct acceptor acceptor_epoll; extern struct acceptor acceptor_kqueue; #endif -#if defined(HAVE_POLL) extern struct acceptor acceptor_poll; + +#if defined(HAVE_PORT_CREATE) +extern struct acceptor acceptor_ports; #endif /* vca_acceptor.c */ diff --git a/varnish-cache/bin/varnishd/cache_acceptor_poll.c b/varnish-cache/bin/varnishd/cache_acceptor_poll.c index 195123e9..d9a0b19f 100644 --- a/varnish-cache/bin/varnishd/cache_acceptor_poll.c +++ b/varnish-cache/bin/varnishd/cache_acceptor_poll.c @@ -32,8 +32,6 @@ #include "config.h" -#if defined(HAVE_POLL) - #include #include #include @@ -167,5 +165,3 @@ struct acceptor acceptor_poll = { .name = "poll", .init = vca_poll_init, }; - -#endif /* defined(HAVE_POLL) */ diff --git a/varnish-cache/bin/varnishd/cache_acceptor_ports.c b/varnish-cache/bin/varnishd/cache_acceptor_ports.c new file mode 100644 index 00000000..12d29ece --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_acceptor_ports.c @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006 Linpro AS + * Copyright (c) 2007 OmniTI Computer Consulting, Inc. + * Copyright (c) 2007 Theo Schlossnagle + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + * + * XXX: We need to pass sessions back into the event engine when they are + * reused. Not sure what the most efficient way is for that. For now + * write the session pointer to a pipe which the event engine monitors. + */ + +#include "config.h" +#if defined(HAVE_PORT_CREATE) + +#include +#include +#include +#include +#include + +#include + +#ifndef HAVE_CLOCK_GETTIME +#include "compat/clock_gettime.h" +#endif + +#include "shmlog.h" +#include "cache.h" +#include "cache_acceptor.h" + +#define MAX_EVENTS 256 +static pthread_t vca_ports_thread; +int solaris_dport = -1; + +static VTAILQ_HEAD(,sess) sesshead = VTAILQ_HEAD_INITIALIZER(sesshead); + +static void +vca_add(int fd, void *data) +{ + AZ(port_associate(solaris_dport, PORT_SOURCE_FD, fd, POLLIN | POLLERR | POLLPRI, data)); +} + +static void +vca_del(int fd) +{ + port_dissociate(solaris_dport, PORT_SOURCE_FD, fd); +} + +static void +vca_port_ev(port_event_t *ev) { + struct sess *sp; + if(ev->portev_source == PORT_SOURCE_USER) { + sp = ev->portev_user; + CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); + assert(sp->fd >= 0); + AZ(sp->obj); + VTAILQ_INSERT_TAIL(&sesshead, sp, list); + vca_add(sp->fd, sp); + } else { + int i; + CAST_OBJ_NOTNULL(sp, ev->portev_user, SESS_MAGIC); + if(ev->portev_events & POLLERR) { + VTAILQ_REMOVE(&sesshead, sp, list); + vca_close_session(sp, "EOF"); + SES_Delete(sp); + return; + } + i = HTC_Rx(sp->htc); + if (i == 0) + return; + if (i > 0) { + VTAILQ_REMOVE(&sesshead, sp, list); + if (sp->fd != -1) + vca_del(sp->fd); + vca_handover(sp, i); + } + } + return; +} + +static void * +vca_main(void *arg) +{ + struct sess *sp; + + (void)arg; + + solaris_dport = port_create(); + assert(solaris_dport >= 0); + + while (1) { + port_event_t ev[MAX_EVENTS]; + int nevents, ei; + double deadline; + struct timespec ts; + ts.tv_sec = 0L; + ts.tv_nsec = 50L /*ms*/ * 1000L /*us*/ * 1000L /*ns*/; + nevents = 1; + if (port_getn(solaris_dport, ev, MAX_EVENTS, &nevents, &ts) == 0) { + for (ei=0; eisess_timeout; + for (;;) { + sp = VTAILQ_FIRST(&sesshead); + if (sp == NULL) + break; + if (sp->t_open > deadline) + break; + VTAILQ_REMOVE(&sesshead, sp, list); + if(sp->fd != -1) + vca_del(sp->fd); + vca_close_session(sp, "timeout"); + SES_Delete(sp); + } + } +} + +static void +vca_ports_pass(struct sess *sp) +{ + int r; + while((r = port_send(solaris_dport, 0, sp)) == -1 && + errno == EAGAIN); + AZ(r); +} + +/*--------------------------------------------------------------------*/ + +static void +vca_ports_init(void) +{ + + AZ(pthread_create(&vca_ports_thread, NULL, vca_main, NULL)); +} + +struct acceptor acceptor_ports = { + .name = "ports", + .init = vca_ports_init, + .pass = vca_ports_pass +}; + +#endif /* defined(HAVE_PORT_CREATE) */ diff --git a/varnish-cache/bin/varnishd/cache_pool.c b/varnish-cache/bin/varnishd/cache_pool.c index 704b043e..c12825a0 100644 --- a/varnish-cache/bin/varnishd/cache_pool.c +++ b/varnish-cache/bin/varnishd/cache_pool.c @@ -52,6 +52,8 @@ #include #elif defined(__linux__) #include +#elif defined(__sun) +#include #else #error Unknown sendfile() implementation #endif @@ -191,6 +193,37 @@ WRK_Sendfile(struct worker *w, int fd, off_t off, unsigned len) sendfile(*w->wfd, fd, &off, len) != len) w->werr++; } while (0); +#elif defined(__sun) +#ifdef HAVE_SENDFILEV + do { + sendfilevec_t svvec[HTTP_HDR_MAX * 2 + 1]; + size_t xferred = 0, expected = 0; + int i; + for (i = 0; i < w->niov; i++) { + svvec[i].sfv_fd = SFV_FD_SELF; + svvec[i].sfv_flag = 0; + svvec[i].sfv_off = (off_t) w->iov[i].iov_base; + svvec[i].sfv_len = w->iov[i].iov_len; + expected += svvec[i].sfv_len; + } + svvec[i].sfv_fd = fd; + svvec[i].sfv_flag = 0; + svvec[i].sfv_off = off; + svvec[i].sfv_len = len; + expected += svvec[i].sfv_len; + if (sendfilev(*w->wfd, svvec, i, &xferred) == -1 || + xferred != expected) + w->werr++; + w->liov = 0; + w->niov = 0; + } while (0); +#else + do { + if (WRK_Flush(w) == 0 && + sendfile(*w->wfd, fd, &off, len) != len) + w->werr++; + } while (0); +#endif #else #error Unknown sendfile() implementation #endif diff --git a/varnish-cache/bin/varnishd/storage_umem.c b/varnish-cache/bin/varnishd/storage_umem.c new file mode 100644 index 00000000..a1cf9a4c --- /dev/null +++ b/varnish-cache/bin/varnishd/storage_umem.c @@ -0,0 +1,173 @@ +/*- + * Copyright (c) 2006 Verdens Gang AS + * Copyright (c) 2006-2008 Linpro AS + * All rights reserved. + * + * Author: Poul-Henning Kamp + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: storage_umem.c 3036 2008-07-31 09:24:25Z phk $ + * + * Storage method based on umem_alloc(3MALLOC) + */ + +#include "config.h" + +#ifdef HAVE_UMEM_H + +#include + +#include +#include +#include + +#include + +#include "config.h" +#include "shmlog.h" +#include "cache.h" +#include "stevedore.h" + +static size_t smu_max = SIZE_MAX; +static MTX smu_mtx; + +struct smu { + struct storage s; + size_t sz; +}; + +static struct storage * +smu_alloc(struct stevedore *st, size_t size) +{ + struct smu *smu; + + LOCK(&smu_mtx); + VSL_stats->sma_nreq++; + if (VSL_stats->sma_nbytes + size > smu_max) + size = 0; + else { + VSL_stats->sma_nobj++; + VSL_stats->sma_nbytes += size; + VSL_stats->sma_balloc += size; + } + UNLOCK(&smu_mtx); + + if (size == 0) + return (NULL); + + smu = umem_zalloc(sizeof *smu, UMEM_DEFAULT); + if (smu == NULL) + return (NULL); + smu->sz = size; + smu->s.priv = smu; + smu->s.ptr = umem_alloc(size, UMEM_DEFAULT); + XXXAN(smu->s.ptr); + smu->s.len = 0; + smu->s.space = size; + smu->s.fd = -1; + smu->s.stevedore = st; + smu->s.magic = STORAGE_MAGIC; + return (&smu->s); +} + +/*lint -e{818} not const-able */ +static void +smu_free(struct storage *s) +{ + struct smu *smu; + + CHECK_OBJ_NOTNULL(s, STORAGE_MAGIC); + smu = s->priv; + assert(smu->sz == smu->s.space); + LOCK(&smu_mtx); + VSL_stats->sma_nobj--; + VSL_stats->sma_nbytes -= smu->sz; + VSL_stats->sma_bfree += smu->sz; + UNLOCK(&smu_mtx); + umem_free(smu->s.ptr, smu->s.space); + umem_free(smu, sizeof *smu); +} + +static void +smu_trim(const struct storage *s, size_t size) +{ + struct smu *smu; + void *p; + + CHECK_OBJ_NOTNULL(s, STORAGE_MAGIC); + smu = s->priv; + assert(smu->sz == smu->s.space); + if ((p = umem_alloc(size, UMEM_DEFAULT)) != NULL) { + memcpy(p, smu->s.ptr, size); + umem_free(smu->s.ptr, smu->s.space); + LOCK(&smu_mtx); + VSL_stats->sma_nbytes -= (smu->sz - size); + VSL_stats->sma_bfree += smu->sz - size; + smu->sz = size; + UNLOCK(&smu_mtx); + smu->s.ptr = p; + smu->s.space = size; + } +} + +static void +smu_init(struct stevedore *parent, int ac, char * const *av) +{ + const char *e; + uintmax_t u; + + (void)parent; + + AZ(av[ac]); + if (ac > 1) + ARGV_ERR("(-sumem) too many arguments\n"); + + if (ac == 0 || *av[0] == '\0') + return; + + e = str2bytes(av[0], &u, 0); + if (e != NULL) + ARGV_ERR("(-sumem) size \"%s\": %s\n", av[0], e); + if ((u != (uintmax_t)(size_t)u)) + ARGV_ERR("(-sumem) size \"%s\": too big\n", av[0]); + smu_max = u; +} + +static void +smu_open(const struct stevedore *st) +{ + (void)st; + AZ(pthread_mutex_init(&smu_mtx, NULL)); +} + +struct stevedore smu_stevedore = { + .magic = STEVEDORE_MAGIC, + .name = "umem", + .init = smu_init, + .open = smu_open, + .alloc = smu_alloc, + .free = smu_free, + .trim = smu_trim, +}; + +#endif /* HAVE_UMEM_H */ diff --git a/varnish-cache/bin/varnishd/tcp.c b/varnish-cache/bin/varnishd/tcp.c index ad95b7bd..af54042a 100644 --- a/varnish-cache/bin/varnishd/tcp.c +++ b/varnish-cache/bin/varnishd/tcp.c @@ -38,6 +38,9 @@ #include #include +#ifdef HAVE_SYS_FILIO_H +#include +#endif #include #include #include diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index 9f57f813..07821371 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -113,10 +113,16 @@ arg_ul(const char *p) /*--------------------------------------------------------------------*/ extern struct stevedore sma_stevedore; extern struct stevedore smf_stevedore; +#ifdef HAVE_LIBUMEM +extern struct stevedore smu_stevedore; +#endif static struct choice stv_choice[] = { { "file", &smf_stevedore }, { "malloc", &sma_stevedore }, +#ifdef HAVE_LIBUMEM + { "umem", &smu_stevedore }, +#endif { NULL, NULL } }; @@ -214,6 +220,9 @@ usage(void) fprintf(stderr, FMT, "-s kind[,storageoptions]", "Backend storage specification"); fprintf(stderr, FMT, "", " -s malloc"); +#ifdef HAVE_LIBUMEM + fprintf(stderr, FMT, "", " -s umem"); +#endif fprintf(stderr, FMT, "", " -s file [default: use /tmp]"); fprintf(stderr, FMT, "", " -s file,"); fprintf(stderr, FMT, "", " -s file,,"); diff --git a/varnish-cache/configure.ac b/varnish-cache/configure.ac index 45f57586..0a8bc0ba 100644 --- a/varnish-cache/configure.ac +++ b/varnish-cache/configure.ac @@ -129,6 +129,20 @@ case $host in AC_DEFINE([SENDFILE_WORKS], [1], [Define if SENDFILE works]) fi ;; +*-*-solaris*) + AC_CHECK_HEADERS([sys/filio.h]) + AC_CHECK_LIB(sendfile, sendfile) + AC_CHECK_LIB(umem, malloc) + AC_CHECK_HEADERS([umem.h]) + + if test "$ac_cv_lib_sendfile_sendfile" = yes; then + save_LIBS="${LIBS}" + LIBS="${NET_LIBS}" + AC_CHECK_FUNCS([sendfile]) + AC_CHECK_FUNCS([sendfilev]) + LIBS="${save_LIBS}" + fi + ;; *) AC_MSG_WARN([won't look for sendfile() on $host]) ;; @@ -191,23 +205,17 @@ else ac_cv_func_epoll_ctl=no fi -# --enable-poll -AC_ARG_ENABLE(poll, - AS_HELP_STRING([--enable-poll], - [use poll if available (default is YES)]), +# --enable-ports +AC_ARG_ENABLE(ports, + AS_HELP_STRING([--enable-ports], + [use ports if available (default is YES)]), , - [enable_poll=yes]) + [enable_ports=yes]) -if test "$enable_poll" = yes; then - AC_CHECK_FUNCS([poll]) +if test "$enable_ports" = yes; then + AC_CHECK_FUNCS([port_create]) else - ac_cv_func_poll=no -fi - -if test "$ac_cv_func_kqueue" != yes && - test "$ac_cv_func_epoll_ctl" != yes && - test "$ac_cv_func_poll" != yes; then - AC_MSG_ERROR([no usable acceptor mechanism]) + ac_cv_func_port_create=no fi # Solaris defines SO_{RCV,SND}TIMEO, but does not implement them. -- 2.39.5