directio

Igor Sysoev is at rambler-co.ru
Tue Jul 29 19:31:18 MSD 2008


On Fri, Jul 25, 2008 at 09:11:41PM +0200, Valery Kholodkov wrote:

> Скажите, патч предназначен исключительно для FreeBSD?
> 
> Потому как на линуксе 2.6.10 я справедливо получаю:
> 
> 2008/07/25 20:58:08 [crit] 4600#0: *1 pread() failed, file 
> "/usr/local/nginx/html/Synovya.i.Lubovniki.1.of.2.avi" (22: Invalid 
> argument) while sending response to client, client: 192.168.1.13, 
> server: 192.168.1.1, request: "GET /Synovya.i.Lubovniki.1.of.2.avi 
> HTTP/1.1", host: "192.168.1.1"
> 
> по очевидной причине -- приемный буфер не выровнен на границу дискового 
> блока:
> 
> Breakpoint 1, ngx_read_file (file=0x80b9ec4, buf=0x80f3970 "", 
> size=32768, offset=0)
>     at src/os/unix/ngx_files.c:16
> 16          ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
> (gdb) n
> 21          n = pread(file->fd, buf, size, offset);
> (gdb) n
> 23          if (n == -1) {
> (gdb) n
> 24              ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
> (gdb) n
> 26              return NGX_ERROR;
> (gdb) n
> 54      }

Новый патч, в котором буфера выровнены по размеру сектора.


-- 
Игорь Сысоев
http://sysoev.ru
-------------- next part --------------
Index: src/http/ngx_http_core_module.c
===================================================================
--- src/http/ngx_http_core_module.c	(revision 1445)
+++ src/http/ngx_http_core_module.c	(working copy)
@@ -353,6 +353,13 @@
       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_conf_set_off_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, directio),
+      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 +2593,7 @@
     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 +2782,7 @@
     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, 0);
     ngx_conf_merge_value(conf->tcp_nopush, prev->tcp_nopush, 0);
     ngx_conf_merge_value(conf->tcp_nodelay, prev->tcp_nodelay, 1);
 
Index: src/http/ngx_http_core_module.h
===================================================================
--- src/http/ngx_http_core_module.h	(revision 1445)
+++ src/http/ngx_http_core_module.h	(working copy)
@@ -265,6 +265,7 @@
     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: src/http/ngx_http_script.c
===================================================================
--- src/http/ngx_http_script.c	(revision 1445)
+++ src/http/ngx_http_script.c	(working copy)
@@ -996,6 +996,7 @@
 
     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: src/http/modules/ngx_http_gzip_static_module.c
===================================================================
--- src/http/modules/ngx_http_gzip_static_module.c	(revision 1445)
+++ src/http/modules/ngx_http_gzip_static_module.c	(working copy)
@@ -121,6 +121,7 @@
 
     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: src/http/modules/ngx_http_index_module.c
===================================================================
--- src/http/modules/ngx_http_index_module.c	(revision 1445)
+++ src/http/modules/ngx_http_index_module.c	(working copy)
@@ -210,6 +210,7 @@
 
         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: src/http/modules/ngx_http_static_module.c
===================================================================
--- src/http/modules/ngx_http_static_module.c	(revision 1445)
+++ src/http/modules/ngx_http_static_module.c	(working copy)
@@ -98,6 +98,7 @@
 
     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: src/http/modules/ngx_http_flv_module.c
===================================================================
--- src/http/modules/ngx_http_flv_module.c	(revision 1445)
+++ src/http/modules/ngx_http_flv_module.c	(working copy)
@@ -107,6 +107,7 @@
 
     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: src/http/modules/perl/nginx.xs
===================================================================
--- src/http/modules/perl/nginx.xs	(revision 1445)
+++ src/http/modules/perl/nginx.xs	(working copy)
@@ -652,6 +652,7 @@
 
     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: src/os/win32/ngx_files.h
===================================================================
--- src/os/win32/ngx_files.h	(revision 1445)
+++ src/os/win32/ngx_files.h	(working copy)
@@ -197,7 +197,7 @@
 
 
 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);
@@ -213,4 +213,8 @@
     off_t offset, ngx_pool_t *pool);
 
 
+#define ngx_directio(fd)            0
+#define ngx_directio_n              "ngx_directio_n"
+
+
 #endif /* _NGX_FILES_H_INCLUDED_ */
Index: src/os/unix/ngx_alloc.h
===================================================================
--- src/os/unix/ngx_alloc.h	(revision 1445)
+++ src/os/unix/ngx_alloc.h	(working copy)
@@ -21,8 +21,8 @@
 /*
  * 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: src/os/unix/ngx_files.c
===================================================================
--- src/os/unix/ngx_files.c	(revision 1445)
+++ src/os/unix/ngx_files.c	(working copy)
@@ -351,3 +351,22 @@
 
     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: src/os/unix/ngx_files.h
===================================================================
--- src/os/unix/ngx_files.h	(revision 1445)
+++ src/os/unix/ngx_files.h	(working copy)
@@ -177,4 +177,22 @@
 #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: src/core/ngx_open_file_cache.c
===================================================================
--- src/core/ngx_open_file_cache.c	(revision 1445)
+++ src/core/ngx_open_file_cache.c	(working copy)
@@ -499,6 +499,13 @@
         of->fd = fd;
     }
 
+    if (of->directio && 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:
 
     of->uniq = ngx_file_uniq(&fi);
Index: src/core/ngx_open_file_cache.h
===================================================================
--- src/core/ngx_open_file_cache.h	(revision 1445)
+++ src/core/ngx_open_file_cache.h	(working copy)
@@ -17,6 +17,7 @@
     ngx_file_uniq_t          uniq;
     time_t                   mtime;
     off_t                    size;
+    off_t                    directio;
     ngx_err_t                err;
 
     time_t                   valid;
Index: src/core/ngx_output_chain.c
===================================================================
--- src/core/ngx_output_chain.c	(revision 1445)
+++ src/core/ngx_output_chain.c	(working copy)
@@ -32,6 +32,7 @@
     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 @@
                         }
                     }
 
-                    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: src/core/ngx_palloc.c
===================================================================
--- src/core/ngx_palloc.c	(revision 1445)
+++ src/core/ngx_palloc.c	(working copy)
@@ -195,17 +195,35 @@
     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: src/core/ngx_palloc.h
===================================================================
--- src/core/ngx_palloc.h	(revision 1445)
+++ src/core/ngx_palloc.h	(working copy)
@@ -77,6 +77,7 @@
 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: auto/os/features
===================================================================
--- auto/os/features	(revision 1445)
+++ auto/os/features	(working copy)
@@ -200,3 +200,23 @@
         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


More information about the nginx-ru mailing list