From 7840912d6e82ae87e3af4618894e38de682404f6 Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" Date: Mon, 14 Oct 2002 17:42:45 +0000 Subject: [PATCH] Introduce an EnableSendfile directive (defaulted to ON) to allow users to disable sendfile mechanics for NFS volume mounts and other kernel objects that don't support sendfile. And EnableSendfile off can be used to help narrow bugs down to the sendfile mechanics or eliminate the possiblity that sendfile is a factor on any given platform. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@97205 13f79535-47bb-0310-9956-ffa450edef68 --- include/http_core.h | 7 +++- server/core.c | 81 +++++++++++++++++++++++++++++++-------------- 2 files changed, 63 insertions(+), 25 deletions(-) diff --git a/include/http_core.h b/include/http_core.h index 0d3a6c79bb..98feebfb53 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -532,7 +532,12 @@ typedef struct { #define ENABLE_MMAP_OFF (0) #define ENABLE_MMAP_ON (1) #define ENABLE_MMAP_UNSET (2) - int enable_mmap; /* whether files in this dir can be mmap'ed */ + unsigned int enable_mmap : 2; /* whether files in this dir can be mmap'ed */ + +#define ENABLE_SENDFILE_OFF (0) +#define ENABLE_SENDFILE_ON (1) +#define ENABLE_SENDFILE_UNSET (2) + unsigned int enable_sendfile : 2; /* files in this dir can be mmap'ed */ } core_dir_config; diff --git a/server/core.c b/server/core.c index b52598c25d..f3b1a48885 100644 --- a/server/core.c +++ b/server/core.c @@ -181,6 +181,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->etag_remove = ETAG_UNSET; conf->enable_mmap = ENABLE_MMAP_UNSET; + conf->enable_sendfile = ENABLE_SENDFILE_UNSET; return (void *)conf; } @@ -447,6 +448,10 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) conf->enable_mmap = new->enable_mmap; } + if (new->enable_sendfile != ENABLE_SENDFILE_UNSET) { + conf->enable_sendfile = new->enable_sendfile; + } + return (void*)conf; } @@ -1458,6 +1463,29 @@ static const char *set_enable_mmap(cmd_parms *cmd, void *d_, return NULL; } +static const char *set_enable_sendfile(cmd_parms *cmd, void *d_, + const char *arg) +{ + core_dir_config *d = d_; + const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); + + if (err != NULL) { + return err; + } + + if (strcasecmp(arg, "on") == 0) { + d->enable_sendfile = ENABLE_SENDFILE_ON; + } + else if (strcasecmp(arg, "off") == 0) { + d->enable_sendfile = ENABLE_SENDFILE_OFF; + } + else { + return "parameter must be 'on' or 'off'"; + } + + return NULL; +} + static const char *satisfy(cmd_parms *cmd, void *c_, const char *arg) { core_dir_config *c = c_; @@ -2936,6 +2964,8 @@ AP_INIT_RAW_ARGS("FileETag", set_etag_bits, NULL, OR_FILEINFO, "Specify components used to construct a file's ETag"), AP_INIT_TAKE1("EnableMMAP", set_enable_mmap, NULL, OR_FILEINFO, "Controls whether memory-mapping may be used to read files"), +AP_INIT_TAKE1("EnableSendfile", set_enable_sendfile, NULL, OR_FILEINFO, + "Controls whether sendfile may be used to transmit files"), /* Old server config file commands */ @@ -3283,8 +3313,13 @@ static int default_handler(request_rec *r) } } - if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY, 0, - r->pool)) != APR_SUCCESS) { + + if ((status = apr_file_open(&fd, r->filename, APR_READ | APR_BINARY +#if APR_HAS_SENDFILE + | ((d->enable_sendfile == ENABLE_SENDFILE_OFF) + ? 0 : APR_OPEN_FOR_SENDFILE) +#endif + , 0, r->pool)) != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, status, r, "file permissions deny server access: %s", r->filename); return HTTP_FORBIDDEN; @@ -3306,8 +3341,9 @@ static int default_handler(request_rec *r) } bb = apr_brigade_create(r->pool, c->bucket_alloc); -#if APR_HAS_LARGE_FILES - if (r->finfo.size > AP_MAX_SENDFILE) { +#if APR_HAS_SENDFILE && APR_HAS_LARGE_FILES + if ((d->enable_sendfile != ENABLE_SENDFILE_OFF) && + (r->finfo.size > AP_MAX_SENDFILE)) { /* APR_HAS_LARGE_FILES issue; must split into mutiple buckets, * no greater than MAX(apr_size_t), and more granular than that * in case the brigade code/filters attempt to read it directly. @@ -3888,27 +3924,24 @@ static apr_status_t core_output_filter(ap_filter_t *f, apr_bucket_brigade *b) } #if APR_HAS_SENDFILE - if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) { - /* Prepare the socket to be reused */ - flags |= APR_SENDFILE_DISCONNECT_SOCKET; - } + if (apr_file_flags_get(fd) & APR_OPEN_FOR_SENDFILE) { - rv = sendfile_it_all(net, /* the network information */ - fd, /* the file to send */ - &hdtr, /* header and trailer iovecs */ - foffset, /* offset in the file to begin - sending from */ - flen, /* length of file */ - nbytes + flen, /* total length including - headers */ - flags); /* apr_sendfile flags */ - - /* If apr_sendfile() returns APR_ENOTIMPL, call emulate_sendfile(). - * emulate_sendfile() is useful to enable the same Apache binary - * distribution to support Windows NT/2000 (supports TransmitFile) - * and Win95/98 (do not support TransmitFile) - */ - if (rv == APR_ENOTIMPL) + if (c->keepalive == AP_CONN_CLOSE && APR_BUCKET_IS_EOS(last_e)) { + /* Prepare the socket to be reused */ + flags |= APR_SENDFILE_DISCONNECT_SOCKET; + } + + rv = sendfile_it_all(net, /* the network information */ + fd, /* the file to send */ + &hdtr, /* header and trailer iovecs */ + foffset, /* offset in the file to begin + sending from */ + flen, /* length of file */ + nbytes + flen, /* total length including + headers */ + flags); /* apr_sendfile flags */ + } + else #endif { apr_size_t unused_bytes_sent; -- 2.40.0