From dev-return-6914-apmail-apr-dev-archive=apr.apache.org@apr.apache.org Tue Jul 02 18:38:37 2002 Return-Path: Delivered-To: apmail-apr-dev-archive@apr.apache.org Received: (qmail 16406 invoked by uid 500); 2 Jul 2002 18:38:37 -0000 Mailing-List: contact dev-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Delivered-To: mailing list dev@apr.apache.org Received: (qmail 16395 invoked from network); 2 Jul 2002 18:38:37 -0000 Sender: gregames Message-ID: <3D21F22D.5AF48489@apache.org> Date: Tue, 02 Jul 2002 14:34:21 -0400 From: Greg Ames X-Mailer: Mozilla 4.77 [en] (X11; U; Linux 2.2.19-10mdk i686) MIME-Version: 1.0 To: dev@apr.apache.org Subject: [PATCH] FreeBSD sendfile [was: new httpd build running on daedalus] References: <3D1CA72B.92124E68@apache.org> <20020628131827.B2953@apache.org> <20020628133516.G2953@apache.org> Content-Type: multipart/mixed; boundary="------------B7D8A3E5660075FB19022501" X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N This is a multi-part message in MIME format. --------------B7D8A3E5660075FB19022501 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit [moved to dev@apr] Justin Erenkrantz wrote: > > On Fri, Jun 28, 2002 at 04:40:11PM -0400, Jeff Trawick wrote: > > > What is the change in the FreeBSD API? > > > > before the kernel we picked up Wednesday night: bytes to send includes headers > > after the kernel we picked up Wednesday night: bytes to send doesn't > > include headers > > Ouch. > > Good-bye binary compatibility on FreeBSD. -- justin This patch tries to maintain binary compatibility on FreeBSD 4.4 and above by doing a runtime kernel version test. It works on daedalus. Jeff said he'd try it on a 3.x FreeBSD box, where the runtime test I'm using isn't available. Greg --------------B7D8A3E5660075FB19022501 Content-Type: text/plain; charset=us-ascii; name="FreeBSD.sendfile.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="FreeBSD.sendfile.patch" ? srclib/apr/configure.lineno Index: srclib/apr/configure.in =================================================================== RCS file: /home/cvspublic/apr/configure.in,v retrieving revision 1.459 diff -u -d -b -r1.459 configure.in --- srclib/apr/configure.in 1 Jul 2002 14:50:46 -0000 1.459 +++ srclib/apr/configure.in 2 Jul 2002 15:04:47 -0000 @@ -934,6 +934,7 @@ sys/signal.h \ sys/socket.h \ sys/stat.h \ + sys/sysctl.h \ sys/syslimits.h \ sys/time.h \ sys/types.h \ Index: srclib/apr/network_io/unix/sendrecv.c =================================================================== RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v retrieving revision 1.84 diff -u -d -b -r1.84 sendrecv.c --- srclib/apr/network_io/unix/sendrecv.c 17 May 2002 21:19:45 -0000 1.84 +++ srclib/apr/network_io/unix/sendrecv.c 2 Jul 2002 15:04:47 -0000 @@ -59,6 +59,10 @@ #include "fileio.h" #endif /* APR_HAS_SENDFILE */ +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read) { struct timeval tv, *tvptr; @@ -435,6 +439,48 @@ #elif defined(__FreeBSD__) +static int include_hdrs_in_length(void) +{ +#ifdef HAVE_SYS_SYSCTL_H + /* this assumes: + * if the header exits, so does the syscall, and + * if the header doesn't exist, the kernel is older than 4.4 + */ + +/* see http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/param.h + * rev 1.61.2.29 for kernel version number + */ +#define KERNEL_WITH_SENDFILE_LENGTH_FIX 460001 + + typedef enum { UNKNOWN = 0, + NEW, + OLD + } api_e; + + static api_e api; + int kernel_version = 0; /* init to silence compiler warning */ + size_t kernel_version_size = sizeof(kernel_version); + + if (api != UNKNOWN) { + return (api == OLD); + } + if (sysctlbyname("kern.osreldate", &kernel_version, + &kernel_version_size, NULL, NULL) == 0 && + kernel_version < KERNEL_WITH_SENDFILE_LENGTH_FIX) { + api = OLD; + return 1; + } + /* size of kern.osreldate might change in the future + * causing the sysctlbyname to fail, + * but if it's the future, we should use the newer API + */ + api = NEW; + return 0; +#elif + /* the build system's kernel is older than 4.4. Use the old API */ + return 1; +#endif +} /* Release 3.1 or greater */ apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file, apr_hdtr_t * hdtr, apr_off_t * offset, apr_size_t * len, @@ -445,20 +491,25 @@ struct sf_hdtr headerstruct; size_t bytes_to_send = *len; + /* Ignore flags for now. */ + flags = 0; + if (!hdtr) { hdtr = &no_hdtr; } - /* Ignore flags for now. */ - flags = 0; + else if (hdtr->numheaders && include_hdrs_in_length()) { - /* On FreeBSD, the number of bytes to send must include the length of - * the headers. Don't look at the man page for this :( Instead, look - * at the the logic in src/sys/kern/uipc_syscalls::sendfile(). + /* On early versions of FreeBSD sendfile, the number of bytes to send + * must include the length of the headers. Don't look at the man page + * for this :( Instead, look at the the logic in + * src/sys/kern/uipc_syscalls::sendfile(). + * + * This was fixed in the middle of 4.6-STABLE */ - for (i = 0; i < hdtr->numheaders; i++) { bytes_to_send += hdtr->headers[i].iov_len; + } } headerstruct.headers = hdtr->headers; --------------B7D8A3E5660075FB19022501--