]> git.kaiwu.me - nginx.git/commitdiff
directio
authorIgor Sysoev <igor@sysoev.ru>
Wed, 30 Jul 2008 12:34:04 +0000 (12:34 +0000)
committerIgor Sysoev <igor@sysoev.ru>
Wed, 30 Jul 2008 12:34:04 +0000 (12:34 +0000)
18 files changed:
auto/os/features
src/core/ngx_open_file_cache.c
src/core/ngx_open_file_cache.h
src/core/ngx_output_chain.c
src/core/ngx_palloc.c
src/core/ngx_palloc.h
src/http/modules/ngx_http_flv_module.c
src/http/modules/ngx_http_gzip_static_module.c
src/http/modules/ngx_http_index_module.c
src/http/modules/ngx_http_static_module.c
src/http/modules/perl/nginx.xs
src/http/ngx_http_core_module.c
src/http/ngx_http_core_module.h
src/http/ngx_http_script.c
src/os/unix/ngx_alloc.h
src/os/unix/ngx_files.c
src/os/unix/ngx_files.h
src/os/win32/ngx_files.h

index c542c7eefe3e9430528ec4be0ee542bef710c0d2..ffb27a4813e5a845c7edde2d5c6fd3dea144b7d2 100644 (file)
@@ -170,3 +170,23 @@ if [ $ngx_found = no ]; then
         CRYPT_LIB="-lcrypt"
     fi
 fi
+
+
+ngx_feature="O_DIRECT"
+ngx_feature_name="NGX_HAVE_O_DIRECT"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_SETFL, O_DIRECT);"
+. auto/feature
+
+
+ngx_feature="F_NOCACHE"
+ngx_feature_name="NGX_HAVE_F_NOCACHE"
+ngx_feature_run=no
+ngx_feature_incs="#include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="fcntl(0, F_NOCACHE, 1);"
+. auto/feature
index 704d0ab7947b959d6b61ca83b631cd044878ad38..f2e8afc516e4a6657c00ca593a8b2ebf00a47b19 100644 (file)
@@ -497,6 +497,13 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
 
     } else {
         of->fd = fd;
+
+        if (of->directio <= ngx_file_size(&fi)) {
+            if (ngx_directio(fd) == -1) {
+                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                              ngx_directio_n " \"%s\" failed", name);
+            }
+        }
     }
 
 done:
index 4d8393b5d09168ae9f44e77eed52bf63d154ead7..1e1a279159d84b738a36e782a04d7262f7222586 100644 (file)
@@ -17,6 +17,7 @@ typedef struct {
     ngx_file_uniq_t          uniq;
     time_t                   mtime;
     off_t                    size;
+    off_t                    directio;
     ngx_err_t                err;
 
     time_t                   valid;
index 423a650d30c8bdbe25c30597c2c8973027472ce6..c4bd67851eb4be058e4e668f48bc040b5d56c34d 100644 (file)
@@ -32,6 +32,7 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
     size_t        size;
     ngx_int_t     rc, last;
     ngx_uint_t    recycled;
+    ngx_buf_t    *b;
     ngx_chain_t  *cl, *out, **last_out;
 
     if (ctx->in == NULL && ctx->busy == NULL) {
@@ -161,13 +162,29 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in)
                         }
                     }
 
-                    ctx->buf = ngx_create_temp_buf(ctx->pool, size);
-                    if (ctx->buf == NULL) {
+                    b = ngx_calloc_buf(ctx->pool);
+                    if (b == NULL) {
                         return NGX_ERROR;
                     }
 
-                    ctx->buf->tag = ctx->tag;
-                    ctx->buf->recycled = recycled;
+                    /*
+                     * allocate block aligned to a disk sector size
+                     * to enable O_DIRECT
+                     */
+
+                    b->start = ngx_pmemalign(ctx->pool, size, 512);
+                    if (b->start == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    b->pos = b->start;
+                    b->last = b->start;
+                    b->end = b->last + size;
+                    b->temporary = 1;
+                    b->tag = ctx->tag;
+                    b->recycled = recycled;
+
+                    ctx->buf = b;
                     ctx->allocated++;
                 }
             }
index 5a0ea5121b9b3cb6be0f0cec4ce20f075ed67fd6..0cadd4aed551bac875505d1449c497ba888063c7 100644 (file)
@@ -195,17 +195,35 @@ ngx_palloc_large(ngx_pool_t *pool, size_t size)
     void              *p;
     ngx_pool_large_t  *large;
 
-#if 0
-    p = ngx_memalign(ngx_pagesize, size, pool->log);
+    p = ngx_alloc(size, pool->log);
     if (p == NULL) {
         return NULL;
     }
-#else
-    p = ngx_alloc(size, pool->log);
+
+    large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
+    if (large == NULL) {
+        ngx_free(p);
+        return NULL;
+    }
+
+    large->alloc = p;
+    large->next = pool->large;
+    pool->large = large;
+
+    return p;
+}
+
+
+void *
+ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment)
+{
+    void              *p;
+    ngx_pool_large_t  *large;
+
+    p = ngx_memalign(alignment, size, pool->log);
     if (p == NULL) {
         return NULL;
     }
-#endif
 
     large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
     if (large == NULL) {
index 34878f5f27bab63b830ac9b4f4f61a1961bdee53..2b3a30cbd00ea5c8947ab18aa4e3036fc394a4f3 100644 (file)
@@ -77,6 +77,7 @@ void ngx_destroy_pool(ngx_pool_t *pool);
 void *ngx_palloc(ngx_pool_t *pool, size_t size);
 void *ngx_pnalloc(ngx_pool_t *pool, size_t size);
 void *ngx_pcalloc(ngx_pool_t *pool, size_t size);
+void *ngx_pmemalign(ngx_pool_t *pool, size_t size, size_t alignment);
 ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p);
 
 
index bed1b48a61c3327311f5b46a5c42b13ecc8b2fc6..dceb68abc04181dd12efed7a9744bafdefcda5ef 100644 (file)
@@ -107,6 +107,7 @@ ngx_http_flv_handler(ngx_http_request_t *r)
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
index 51fe0d56d6bcbfd0a15f093240ffab086de92976..bc3a65f110013b474d7cabcea4ffcab4ff08f9f1 100644 (file)
@@ -121,6 +121,7 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
index bc4cd5009a06fb62e86193eb17e81ebd8031ae67..6d4cf34d38c8228efd5b133e2e163c2bc522f4bd 100644 (file)
@@ -210,6 +210,7 @@ ngx_http_index_handler(ngx_http_request_t *r)
 
         ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+        of.directio = clcf->directio;
         of.valid = clcf->open_file_cache_valid;
         of.min_uses = clcf->open_file_cache_min_uses;
         of.errors = clcf->open_file_cache_errors;
index ce2f0fc653263f52dc8c0b0ae0fa26a7470d1704..8d399fccd365c20c6798cdde2054d82c600f8ade 100644 (file)
@@ -98,6 +98,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
index f86b76f3e69c77020ba44efe8173ea710aec907c..6e7ad776079fe4648c87d148c7996c0d9d33c945 100644 (file)
@@ -652,6 +652,7 @@ sendfile(r, filename, offset = -1, bytes = 0)
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
index 0ddfc04d16de2e4e10a0768793f3fb0e04400766..468b3e151397c4fcd96b8dfc6dbe250330b67a65 100644 (file)
@@ -54,6 +54,8 @@ static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
 static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+static char *ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 static char *ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -353,6 +355,13 @@ static ngx_command_t  ngx_http_core_commands[] = {
       offsetof(ngx_http_core_loc_conf_t, sendfile_max_chunk),
       NULL },
 
+    { ngx_string("directio"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_core_directio,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
     { ngx_string("tcp_nopush"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
@@ -2586,6 +2595,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
     lcf->client_body_in_file_only = NGX_CONF_UNSET;
     lcf->sendfile = NGX_CONF_UNSET;
     lcf->sendfile_max_chunk = NGX_CONF_UNSET_SIZE;
+    lcf->directio = NGX_CONF_UNSET;
     lcf->tcp_nopush = NGX_CONF_UNSET;
     lcf->tcp_nodelay = NGX_CONF_UNSET;
     lcf->send_timeout = NGX_CONF_UNSET_MSEC;
@@ -2774,6 +2784,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
     ngx_conf_merge_value(conf->sendfile, prev->sendfile, 0);
     ngx_conf_merge_size_value(conf->sendfile_max_chunk,
                               prev->sendfile_max_chunk, 0);
+    ngx_conf_merge_off_value(conf->directio, prev->directio,
+                              NGX_MAX_OFF_T_VALUE);
     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
 
@@ -3339,6 +3351,33 @@ ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 }
 
 
+static char *
+ngx_http_core_directio(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_core_loc_conf_t *clcf = conf;
+
+    ngx_str_t  *value;
+
+    if (clcf->directio != NGX_CONF_UNSET) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    if (ngx_strcmp(value[1].data, "off") == 0) {
+        clcf->directio = NGX_MAX_OFF_T_VALUE;
+        return NGX_CONF_OK;
+    }
+
+    clcf->directio = ngx_parse_offset(&value[1]);
+    if (clcf->directio == (off_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 static char *
 ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
index 85d96b079716556123c79287b9c6bbae4175622c..57ee748e7c0dd6a718a711045c04a92167498ef5 100644 (file)
@@ -265,6 +265,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_str_t     default_type;
 
     off_t         client_max_body_size;    /* client_max_body_size */
+    off_t         directio;                /* directio */
 
     size_t        client_body_buffer_size; /* client_body_buffer_size */
     size_t        send_lowat;              /* send_lowat */
index 7a47417e4dafadaeb4040caafc0f036f3389c652..0ffa07cc8c2b156e6505c8fafa84c99178e078c2 100644 (file)
@@ -996,6 +996,7 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e)
 
     ngx_memzero(&of, sizeof(ngx_open_file_info_t));
 
+    of.directio = clcf->directio;
     of.valid = clcf->open_file_cache_valid;
     of.min_uses = clcf->open_file_cache_min_uses;
     of.errors = clcf->open_file_cache_errors;
index 8b7b766b2edb15894432089bc784736185b3a01e..c7a31aa54b27e16cd055870f665a602407017f56 100644 (file)
@@ -21,8 +21,8 @@ void *ngx_calloc(size_t size, ngx_log_t *log);
 /*
  * Linux has memalign() or posix_memalign()
  * Solaris has memalign()
- * FreeBSD has not memalign() or posix_memalign() but its malloc() alignes
- * allocations bigger than page size at the page boundary.
+ * FreeBSD 7.0 has posix_memalign(), besides, early version's malloc()
+ * aligns allocations bigger than page size at the page boundary
  */
 
 #if (NGX_HAVE_POSIX_MEMALIGN || NGX_HAVE_MEMALIGN)
index 7ee8cbd84240d806b36648a16cdcbc316358d5da..e2148d843a2d628888e67b19a11517be5128bcf2 100644 (file)
@@ -351,3 +351,22 @@ ngx_unlock_fd(ngx_fd_t fd)
 
     return 0;
 }
+
+
+#if (NGX_HAVE_O_DIRECT)
+
+ngx_int_t
+ngx_directio(ngx_fd_t fd)
+{
+    int  flags;
+
+    flags = fcntl(fd, F_GETFL);
+
+    if (flags == -1) {
+        return -1;
+    }
+
+    return fcntl(fd, F_SETFL, flags | O_DIRECT);
+}
+
+#endif
index 0c080c494fe0a58c125813be4a1a3fb33e3aa537..62af63bce74b31eec17470d1af4dec4becc6e9b7 100644 (file)
@@ -189,4 +189,22 @@ ngx_err_t ngx_unlock_fd(ngx_fd_t fd);
 #define ngx_unlock_fd_n          "fcntl(F_SETLK, F_UNLCK)"
 
 
+#if (NGX_HAVE_O_DIRECT)
+
+ngx_int_t ngx_directio(ngx_fd_t fd);
+#define ngx_directio_n           "fcntl(O_DIRECT)"
+
+#elif (NGX_HAVE_F_NOCACHE)
+
+#define ngx_directio(fd)         fcntl(fd, F_NOCACHE, 1)
+#define ngx_directio_n           "fcntl(F_NOCACHE)"
+
+#else
+
+#define ngx_directio(fd)         0
+#define ngx_directio_n           "ngx_directio_n"
+
+#endif
+
+
 #endif /* _NGX_FILES_H_INCLUDED_ */
index 0c4e14fa37e54c8c8c533e7a23135838dbd0d90a..5973e95b302f3f239178d8561b259273bbcbbc59 100644 (file)
@@ -200,7 +200,7 @@ typedef struct {
 
 
 ngx_int_t ngx_open_glob(ngx_glob_t *gl);
-#define ngx_open_glob_n          "FindFirstFile()"
+#define ngx_open_glob_n             "FindFirstFile()"
 
 ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name);
 void ngx_close_glob(ngx_glob_t *gl);
@@ -216,4 +216,8 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce,
     off_t offset, ngx_pool_t *pool);
 
 
+#define ngx_directio(fd)            0
+#define ngx_directio_n              "ngx_directio_n"
+
+
 #endif /* _NGX_FILES_H_INCLUDED_ */