]> granicus.if.org Git - apache/commitdiff
Introduce an EnableSendfile directive (defaulted to ON) to allow users
authorWilliam A. Rowe Jr <wrowe@apache.org>
Mon, 14 Oct 2002 17:42:45 +0000 (17:42 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Mon, 14 Oct 2002 17:42:45 +0000 (17:42 +0000)
  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
server/core.c

index 0d3a6c79bb20c21c1eb59257aae9b004defff480..98feebfb537c9faaef5d8c2ac0518f496fd18c4b 100644 (file)
@@ -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;
 
index b52598c25da7ac00fd56c9151335bc96b541a009..f3b1a48885be45469665caffd68d64b63a691062 100644 (file)
@@ -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;