aio sendfile
diff --git a/auto/os/freebsd b/auto/os/freebsd
index 596aaa0..2098529 100644
--- a/auto/os/freebsd
+++ b/auto/os/freebsd
@@ -43,6 +43,12 @@
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
diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h
index 689b5f0..ebc0c4c 100644
--- a/src/core/ngx_connection.h
+++ b/src/core/ngx_connection.h
@@ -159,6 +159,11 @@
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
diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h
index ab38546..778da52 100644
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -209,6 +209,10 @@
size_t nbytes;
#endif
+#if (NGX_HAVE_AIO_SENDFILE)
+ off_t last_offset;
+#endif
+
ngx_aiocb_t aiocb;
ngx_event_t event;
};
diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c
index 61c3cb2..f3d0f11 100644
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -18,6 +18,9 @@
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);
@@ -121,6 +124,9 @@
#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
@@ -139,6 +145,42 @@
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 @@
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
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index cd2d774..e8484ee 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -104,6 +104,20 @@
};
+#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 @@
#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
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 826b403..9946c4f 100644
--- 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
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 425737a..2ca2153 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -546,6 +546,9 @@
typedef struct {
ngx_http_posted_request_t terminal_posted_request;
+#if (NGX_HAVE_AIO_SENDFILE)
+ u_char preload[4];
+#endif
} ngx_http_ephemeral_t;
diff --git a/src/os/unix/ngx_file_aio_read.c b/src/os/unix/ngx_file_aio_read.c
index bf089ec..19a7589 100644
--- 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 @@
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;
}
diff --git a/src/os/unix/ngx_freebsd_sendfile_chain.c b/src/os/unix/ngx_freebsd_sendfile_chain.c
index 26e3863..976b6d0 100644
--- 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 @@
send = 0;
eagain = 0;
+ flags = 0;
header.elts = headers;
header.size = sizeof(struct iovec);
@@ -261,8 +262,12 @@
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;
@@ -276,6 +281,12 @@
eintr = 1;
break;
+#if (NGX_HAVE_AIO_SENDFILE)
+ case NGX_EBUSY:
+ c->busy_sendfile = file;
+ break;
+#endif
+
default:
wev->error = 1;
(void) ngx_connection_error(c, err, "sendfile() failed");
@@ -383,6 +394,12 @@
break;
}
+#if (NGX_HAVE_AIO_SENDFILE)
+ if (c->busy_sendfile) {
+ return cl;
+ }
+#endif
+
if (eagain) {
/*