changeset 531:d41628eb4d0a NGINX_0_8_12

nginx 0.8.12 *) Feature: the "sendfile" parameter in the "aio" directive on FreeBSD. *) Bugfix: in try_files; the bug had appeared in 0.8.11. *) Bugfix: in memcached; the bug had appeared in 0.8.11.
author Igor Sysoev <http://sysoev.ru>
date Mon, 31 Aug 2009 00:00:00 +0400
parents 1fd1b769cd78
children 9917c53346ac
files CHANGES CHANGES.ru auto/os/freebsd src/core/nginx.h src/core/ngx_connection.h src/event/ngx_event.h src/http/modules/ngx_http_memcached_module.c src/http/modules/perl/nginx.pm src/http/ngx_http.h src/http/ngx_http_copy_filter_module.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_postpone_filter_module.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/os/unix/ngx_darwin_sendfile_chain.c src/os/unix/ngx_file_aio_read.c src/os/unix/ngx_freebsd_sendfile_chain.c src/os/unix/ngx_linux_sendfile_chain.c src/os/unix/ngx_solaris_sendfilev_chain.c src/os/unix/ngx_writev_chain.c
diffstat 21 files changed, 280 insertions(+), 99 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,8 +1,17 @@
 
+Changes with nginx 0.8.12                                        31 Aug 2009
+
+    *) Feature: the "sendfile" parameter in the "aio" directive on FreeBSD.
+
+    *) Bugfix: in try_files; the bug had appeared in 0.8.11.
+
+    *) Bugfix: in memcached; the bug had appeared in 0.8.11.
+
+
 Changes with nginx 0.8.11                                        28 Aug 2009
 
-    *) Change: directive "gzip_disable msie6" enables gzipping for 
-       MSIE 6.0 SV1.
+    *) Change: now directive "gzip_disable msie6" does not disable gzipping 
+       for MSIE 6.0 SV1.
 
     *) Feature: file AIO support on FreeBSD and Linux.
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,8 +1,19 @@
 
+Изменения в nginx 0.8.12                                          31.08.2009
+
+    *) Добавление: параметр sendfile в директиве aio во FreeBSD.
+
+    *) Исправление: ошибки при использовании try_files; ошибка появилась в 
+       0.8.11.
+
+    *) Исправление: ошибки при использовании memcached; ошибка появилась в 
+       0.8.11.
+
+
 Изменения в nginx 0.8.11                                          28.08.2009
 
-    *) Изменение: директива "gzip_disable msie6" разрешает сжатие для 
-       MSIE 6.0 SV1.
+    *) Изменение: теперь директива "gzip_disable msie6" не запрещает сжатие 
+       для MSIE 6.0 SV1.
 
     *) Добавление: поддержка файлового AIO во FreeBSD и Linux.
 
--- a/auto/os/freebsd
+++ b/auto/os/freebsd
@@ -43,6 +43,12 @@ if [ $osreldate -gt 300007 ]; then
     CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
 fi
 
+if [ $osreldate -gt 502103 ]; then
+    echo " + sendfile()'s SF_NODISKIO found"
+
+    have=NGX_HAVE_AIO_SENDFILE . auto/have
+fi
+
 
 # kqueue
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         8011
-#define NGINX_VERSION      "0.8.11"
+#define nginx_version         8012
+#define NGINX_VERSION      "0.8.12"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -159,6 +159,11 @@ struct ngx_connection_s {
     unsigned            accept_context_updated:1;
 #endif
 
+#if (NGX_HAVE_AIO_SENDFILE)
+    unsigned            aio_sendfile:1;
+    ngx_buf_t          *busy_sendfile;
+#endif
+
 #if (NGX_THREADS)
     ngx_atomic_t        lock;
 #endif
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -209,6 +209,10 @@ struct ngx_event_aio_s {
     size_t                     nbytes;
 #endif
 
+#if (NGX_HAVE_AIO_SENDFILE)
+    off_t                      last_offset;
+#endif
+
     ngx_aiocb_t                aiocb;
     ngx_event_t                event;
 };
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -211,6 +211,8 @@ ngx_http_memcached_handler(ngx_http_requ
     u->input_filter = ngx_http_memcached_filter;
     u->input_filter_ctx = ctx;
 
+    r->main->count++;
+
     ngx_http_upstream_init(r);
 
     return NGX_DONE;
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.8.11';
+our $VERSION = '0.8.12';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -84,13 +84,17 @@ ngx_int_t ngx_http_find_server_conf(ngx_
 void ngx_http_update_location_config(ngx_http_request_t *r);
 void ngx_http_handler(ngx_http_request_t *r);
 void ngx_http_run_posted_requests(ngx_connection_t *c);
-ngx_int_t ngx_http_post_request(ngx_http_request_t *r);
+ngx_int_t ngx_http_post_request(ngx_http_request_t *r,
+    ngx_http_posted_request_t *pr);
 void ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc);
 
 void ngx_http_empty_handler(ngx_event_t *wev);
 void ngx_http_request_empty_handler(ngx_http_request_t *r);
 
 
+#define ngx_http_ephemeral(r)  (ngx_http_ephemeral_t *) (&r->uri_start)
+
+
 #define NGX_HTTP_LAST   1
 #define NGX_HTTP_FLUSH  2
 
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -18,6 +18,9 @@ typedef struct {
 static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
     ngx_file_t *file);
 static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
+#if (NGX_HAVE_AIO_SENDFILE)
+static void ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev);
+#endif
 #endif
 
 static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
@@ -89,7 +92,7 @@ ngx_http_copy_filter(ngx_http_request_t 
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                   "copy filter: \"%V?%V\"", &r->uri, &r->args);
+                   "http copy filter: \"%V?%V\"", &r->uri, &r->args);
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_copy_filter_module);
 
@@ -121,6 +124,9 @@ ngx_http_copy_filter(ngx_http_request_t 
 #if (NGX_HAVE_FILE_AIO)
         if (clcf->aio) {
             ctx->aio = ngx_http_copy_aio_handler;
+#if (NGX_HAVE_AIO_SENDFILE)
+            c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
+#endif
         }
 #endif
 
@@ -136,8 +142,44 @@ ngx_http_copy_filter(ngx_http_request_t 
         r->buffered |= NGX_HTTP_COPY_BUFFERED;
     }
 
-    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
+
+#if (NGX_HAVE_AIO_SENDFILE)
+
+    if (c->busy_sendfile) {
+        off_t                  offset;
+        ngx_file_t            *file;
+        ngx_http_ephemeral_t  *e;
+
+        file = c->busy_sendfile->file;
+        offset = c->busy_sendfile->file_pos;
+
+        if (file->aio) {
+            c->aio_sendfile = (offset != file->aio->last_offset);
+            file->aio->last_offset = offset;
+
+            if (c->aio_sendfile == 0) {
+                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+                              "sendfile(%V) returned busy again", &file->name);
+            }
+        }
+
+        c->busy_sendfile = NULL;
+        e = (ngx_http_ephemeral_t *) &r->uri_start;
+
+        (void) ngx_file_aio_read(file, e->preload, 4, offset, r->pool);
+
+        if (file->aio) {
+            file->aio->data = r;
+            file->aio->handler = ngx_http_copy_aio_sendfile_event_handler;
+
+            r->main->blocked++;
+            r->aio = 1;
+        }
+    }
+
+#endif
 
     return rc;
 }
@@ -175,6 +217,26 @@ ngx_http_copy_aio_event_handler(ngx_even
     r->connection->write->handler(r->connection->write);
 }
 
+
+#if (NGX_HAVE_AIO_SENDFILE)
+
+static void
+ngx_http_copy_aio_sendfile_event_handler(ngx_event_t *ev)
+{
+    ngx_event_aio_t     *aio;
+    ngx_http_request_t  *r;
+
+    aio = ev->data;
+    r = aio->data;
+
+    r->main->blocked--;
+    r->aio = 0;
+    ev->complete = 0;
+
+    r->connection->write->handler(r->connection->write);
+}
+
+#endif
 #endif
 
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -104,6 +104,20 @@ static ngx_conf_enum_t  ngx_http_core_re
 };
 
 
+#if (NGX_HAVE_FILE_AIO)
+
+static ngx_conf_enum_t  ngx_http_core_aio[] = {
+    { ngx_string("off"), NGX_HTTP_AIO_OFF  },
+    { ngx_string("on"), NGX_HTTP_AIO_ON },
+#if (NGX_HAVE_AIO_SENDFILE)
+    { ngx_string("sendfile"), NGX_HTTP_AIO_SENDFILE },
+#endif
+    { ngx_null_string, 0 }
+};
+
+#endif
+
+
 static ngx_conf_enum_t  ngx_http_core_satisfy[] = {
     { ngx_string("all"), NGX_HTTP_SATISFY_ALL },
     { ngx_string("any"), NGX_HTTP_SATISFY_ANY },
@@ -386,11 +400,11 @@ static ngx_command_t  ngx_http_core_comm
 #if (NGX_HAVE_FILE_AIO)
 
     { ngx_string("aio"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_enum_slot,
       NGX_HTTP_LOC_CONF_OFFSET,
       offsetof(ngx_http_core_loc_conf_t, aio),
-      NULL },
+      &ngx_http_core_aio },
 
 #endif
 
@@ -1201,6 +1215,7 @@ ngx_http_core_try_files_phase(ngx_http_r
                 (void) ngx_http_internal_redirect(r, &path, &args);
             }
 
+            ngx_http_finalize_request(r, NGX_DONE);
             return NGX_OK;
         }
 
@@ -2139,7 +2154,7 @@ ngx_http_subrequest(ngx_http_request_t *
 
     *psr = sr;
 
-    return ngx_http_post_request(sr);
+    return ngx_http_post_request(sr, NULL);
 }
 
 
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -24,6 +24,11 @@
 #define NGX_HTTP_GZIP_PROXIED_ANY       0x0200
 
 
+#define NGX_HTTP_AIO_OFF                0
+#define NGX_HTTP_AIO_ON                 1
+#define NGX_HTTP_AIO_SENDFILE           2
+
+
 #define NGX_HTTP_SATISFY_ALL            0
 #define NGX_HTTP_SATISFY_ANY            1
 
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -102,7 +102,7 @@ ngx_http_postpone_filter(ngx_http_reques
 
             c->data = pr->request;
 
-            return ngx_http_post_request(pr->request);
+            return ngx_http_post_request(pr->request, NULL);
         }
 
         if (pr->out == NULL) {
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -1810,13 +1810,15 @@ ngx_http_run_posted_requests(ngx_connect
 
 
 ngx_int_t
-ngx_http_post_request(ngx_http_request_t *r)
+ngx_http_post_request(ngx_http_request_t *r, ngx_http_posted_request_t *pr)
 {
-    ngx_http_posted_request_t  *pr, **p;
-
-    pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
+    ngx_http_posted_request_t  **p;
+
     if (pr == NULL) {
-        return NGX_ERROR;
+        pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
+        if (pr == NULL) {
+            return NGX_ERROR;
+        }
     }
 
     pr->request = r;
@@ -1965,7 +1967,7 @@ ngx_http_finalize_request(ngx_http_reque
             }
         }
 
-        if (ngx_http_post_request(pr) != NGX_OK) {
+        if (ngx_http_post_request(pr, NULL) != NGX_OK) {
             r->main->count++;
             ngx_http_terminate_request(r, 0);
             return;
@@ -2025,8 +2027,9 @@ ngx_http_finalize_request(ngx_http_reque
 static void
 ngx_http_terminate_request(ngx_http_request_t *r, ngx_int_t rc)
 {
-    ngx_http_cleanup_t  *cln;
-    ngx_http_request_t  *mr;
+    ngx_http_cleanup_t    *cln;
+    ngx_http_request_t    *mr;
+    ngx_http_ephemeral_t  *e;
 
     mr = r->main;
 
@@ -2054,9 +2057,10 @@ ngx_http_terminate_request(ngx_http_requ
             return;
         }
 
+        e = ngx_http_ephemeral(mr);
         mr->posted_requests = NULL;
         mr->write_event_handler = ngx_http_terminate_handler;
-        (void) ngx_http_post_request(mr);
+        (void) ngx_http_post_request(mr, &e->terminal_posted_request);
         return;
     }
 
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -510,6 +510,21 @@ struct ngx_http_request_s {
     /* used to parse HTTP headers */
 
     ngx_uint_t                        state;
+
+    ngx_uint_t                        header_hash;
+    ngx_uint_t                        lowcase_index;
+    u_char                            lowcase_header[NGX_HTTP_LC_HEADER_LEN];
+
+    u_char                           *header_name_start;
+    u_char                           *header_name_end;
+    u_char                           *header_start;
+    u_char                           *header_end;
+
+    /*
+     * a memory that can be reused after parsing a request line
+     * via ngx_http_ephemeral_t
+     */
+
     u_char                           *uri_start;
     u_char                           *uri_end;
     u_char                           *uri_ext;
@@ -523,18 +538,18 @@ struct ngx_http_request_s {
     u_char                           *host_end;
     u_char                           *port_start;
     u_char                           *port_end;
-    u_char                           *header_name_start;
-    u_char                           *header_name_end;
-    u_char                           *header_start;
-    u_char                           *header_end;
 
     unsigned                          http_minor:16;
     unsigned                          http_major:16;
+};
 
-    ngx_uint_t                        header_hash;
-    ngx_uint_t                        lowcase_index;
-    u_char                            lowcase_header[NGX_HTTP_LC_HEADER_LEN];
-};
+
+typedef struct {
+    ngx_http_posted_request_t         terminal_posted_request;
+#if (NGX_HAVE_AIO_SENDFILE)
+    u_char                            preload[4];
+#endif
+} ngx_http_ephemeral_t;
 
 
 extern ngx_http_header_t       ngx_http_headers_in[];
--- a/src/os/unix/ngx_darwin_sendfile_chain.c
+++ b/src/os/unix/ngx_darwin_sendfile_chain.c
@@ -42,7 +42,7 @@ ngx_darwin_sendfile_chain(ngx_connection
     u_char          *prev;
     off_t            size, send, prev_send, aligned, sent, fprev;
     off_t            header_size, file_size;
-    ngx_uint_t       eintr, eagain, complete;
+    ngx_uint_t       eintr, complete;
     ngx_err_t        err;
     ngx_buf_t       *file;
     ngx_array_t      header, trailer;
@@ -75,7 +75,6 @@ ngx_darwin_sendfile_chain(ngx_connection
     }
 
     send = 0;
-    eagain = 0;
 
     header.elts = headers;
     header.size = sizeof(struct iovec);
@@ -238,22 +237,22 @@ ngx_darwin_sendfile_chain(ngx_connection
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
+                switch (err) {
+                case NGX_EAGAIN:
+                    break;
 
-                    } else {
-                        eagain = 1;
-                    }
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "sendfile() sent only %O bytes", sent);
-
-                } else {
+                default:
                     wev->error = 1;
                     (void) ngx_connection_error(c, err, "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "sendfile() sent only %O bytes", sent);
             }
 
             if (rc == 0 && sent == 0) {
@@ -284,19 +283,22 @@ ngx_darwin_sendfile_chain(ngx_connection
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
-                    }
+                switch (err) {
+                case NGX_EAGAIN:
+                    break;
 
-                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "writev() not ready");
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                } else {
+                default:
                     wev->error = 1;
                     ngx_connection_error(c, err, "writev() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "writev() not ready");
             }
 
             sent = rc > 0 ? rc : 0;
--- a/src/os/unix/ngx_file_aio_read.c
+++ b/src/os/unix/ngx_file_aio_read.c
@@ -15,7 +15,8 @@
  *    if an asked data are already in VM cache, then aio_error() returns 0,
  *    and the data are already copied in buffer;
  *
- *    aio_read() preread in VM cache as minimum 32K;
+ *    aio_read() preread in VM cache as minimum 16K (probably BKVASIZE);
+ *    the first AIO preload may be up to 128K;
  *
  *    aio_read/aio_error() may return EINPROGRESS for just written data;
  *
@@ -60,6 +61,9 @@ ngx_file_aio_read(ngx_file_t *file, u_ch
         aio->event.data = aio;
         aio->event.ready = 1;
         aio->event.log = file->log;
+#if (NGX_HAVE_AIO_SENDFILE)
+        aio->last_offset = -1;
+#endif
         file->aio = aio;
     }
 
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -40,7 +40,7 @@
 ngx_chain_t *
 ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
 {
-    int              rc;
+    int              rc, flags;
     u_char          *prev;
     off_t            size, send, prev_send, aligned, sent, fprev;
     size_t           header_size, file_size;
@@ -78,6 +78,7 @@ ngx_freebsd_sendfile_chain(ngx_connectio
 
     send = 0;
     eagain = 0;
+    flags = 0;
 
     header.elts = headers;
     header.size = sizeof(struct iovec);
@@ -261,28 +262,39 @@ ngx_freebsd_sendfile_chain(ngx_connectio
 
             sent = 0;
 
+#if (NGX_HAVE_AIO_SENDFILE)
+            flags = c->aio_sendfile ? SF_NODISKIO : 0;
+#endif
+
             rc = sendfile(file->file->fd, c->fd, file->file_pos,
-                          file_size + header_size, &hdtr, &sent, 0);
+                          file_size + header_size, &hdtr, &sent, flags);
 
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
+                switch (err) {
+                case NGX_EAGAIN:
+                    eagain = 1;
+                    break;
 
-                    } else {
-                        eagain = 1;
-                    }
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "sendfile() sent only %O bytes", sent);
+#if (NGX_HAVE_AIO_SENDFILE)
+                case NGX_EBUSY:
+                    c->busy_sendfile = file;
+                    break;
+#endif
 
-                } else {
+                default:
                     wev->error = 1;
                     (void) ngx_connection_error(c, err, "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "sendfile() sent only %O bytes", sent);
             }
 
             /*
@@ -318,19 +330,22 @@ ngx_freebsd_sendfile_chain(ngx_connectio
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
-                    }
+                switch (err) {
+                case NGX_EAGAIN:
+                    break;
 
-                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "writev() not ready");
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                } else {
+                default:
                     wev->error = 1;
                     ngx_connection_error(c, err, "writev() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "writev() not ready");
             }
 
             sent = rc > 0 ? rc : 0;
@@ -379,6 +394,12 @@ ngx_freebsd_sendfile_chain(ngx_connectio
             break;
         }
 
+#if (NGX_HAVE_AIO_SENDFILE)
+        if (c->busy_sendfile) {
+            return cl;
+        }
+#endif
+
         if (eagain) {
 
             /*
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -263,19 +263,22 @@ ngx_linux_sendfile_chain(ngx_connection_
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
-                    }
+                switch (err) {
+                case NGX_EAGAIN:
+                    break;
 
-                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "sendfile() is not ready");
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                } else {
+                default:
                     wev->error = 1;
                     ngx_connection_error(c, err, "sendfile() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "sendfile() is not ready");
             }
 
             sent = rc > 0 ? rc : 0;
@@ -290,19 +293,22 @@ ngx_linux_sendfile_chain(ngx_connection_
             if (rc == -1) {
                 err = ngx_errno;
 
-                if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                    if (err == NGX_EINTR) {
-                        eintr = 1;
-                    }
+                switch (err) {
+                case NGX_EAGAIN:
+                    break;
 
-                    ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                                   "writev() not ready");
+                case NGX_EINTR:
+                    eintr = 1;
+                    break;
 
-                } else {
+                default:
                     wev->error = 1;
                     ngx_connection_error(c, err, "writev() failed");
                     return NGX_CHAIN_ERROR;
                 }
+
+                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                               "writev() not ready");
             }
 
             sent = rc > 0 ? rc : 0;
--- a/src/os/unix/ngx_solaris_sendfilev_chain.c
+++ b/src/os/unix/ngx_solaris_sendfilev_chain.c
@@ -168,19 +168,22 @@ ngx_solaris_sendfilev_chain(ngx_connecti
         if (n == -1) {
             err = ngx_errno;
 
-            if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                if (err == NGX_EINTR) {
-                    eintr = 1;
-                }
+            switch (err) {
+            case NGX_EAGAIN:
+                break;
 
-                ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
-                              "sendfilev() sent only %uz bytes", sent);
+            case NGX_EINTR:
+                eintr = 1;
+                break;
 
-            } else {
+            default:
                 wev->error = 1;
                 ngx_connection_error(c, err, "sendfilev() failed");
                 return NGX_CHAIN_ERROR;
             }
+
+            ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, err,
+                          "sendfilev() sent only %uz bytes", sent);
         }
 
         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -110,19 +110,22 @@ ngx_writev_chain(ngx_connection_t *c, ng
         if (n == -1) {
             err = ngx_errno;
 
-            if (err == NGX_EAGAIN || err == NGX_EINTR) {
-                if (err == NGX_EINTR) {
-                    eintr = 1;
-                }
+            switch (err) {
+            case NGX_EAGAIN:
+                break;
 
-                ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
-                               "writev() not ready");
+            case NGX_EINTR:
+                eintr = 1;
+                break;
 
-            } else {
+            default:
                 wev->error = 1;
                 (void) ngx_connection_error(c, err, "writev() failed");
                 return NGX_CHAIN_ERROR;
             }
+
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
+                           "writev() not ready");
         }
 
         sent = n > 0 ? n : 0;