mirror of
https://github.com/nginx/nginx.git
synced 2025-06-06 17:02:39 +08:00
aio sendfile
This commit is contained in:
parent
ddda411d14
commit
bfff03406d
@ -43,6 +43,12 @@ if [ $osreldate -gt 300007 ]; then
|
|||||||
CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
|
CORE_SRCS="$CORE_SRCS $FREEBSD_SENDFILE_SRCS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ $osreldate -gt 502103 ]; then
|
||||||
|
echo " + sendfile()'s SF_NODISKIO found"
|
||||||
|
|
||||||
|
have=NGX_HAVE_AIO_SENDFILE . auto/have
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
# kqueue
|
# kqueue
|
||||||
|
|
||||||
|
@ -159,6 +159,11 @@ struct ngx_connection_s {
|
|||||||
unsigned accept_context_updated:1;
|
unsigned accept_context_updated:1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
unsigned aio_sendfile:1;
|
||||||
|
ngx_buf_t *busy_sendfile;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NGX_THREADS)
|
#if (NGX_THREADS)
|
||||||
ngx_atomic_t lock;
|
ngx_atomic_t lock;
|
||||||
#endif
|
#endif
|
||||||
|
@ -209,6 +209,10 @@ struct ngx_event_aio_s {
|
|||||||
size_t nbytes;
|
size_t nbytes;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
off_t last_offset;
|
||||||
|
#endif
|
||||||
|
|
||||||
ngx_aiocb_t aiocb;
|
ngx_aiocb_t aiocb;
|
||||||
ngx_event_t event;
|
ngx_event_t event;
|
||||||
};
|
};
|
||||||
|
@ -18,6 +18,9 @@ typedef struct {
|
|||||||
static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
|
static void ngx_http_copy_aio_handler(ngx_output_chain_ctx_t *ctx,
|
||||||
ngx_file_t *file);
|
ngx_file_t *file);
|
||||||
static void ngx_http_copy_aio_event_handler(ngx_event_t *ev);
|
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
|
#endif
|
||||||
|
|
||||||
static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
|
static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
|
||||||
@ -121,6 +124,9 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
#if (NGX_HAVE_FILE_AIO)
|
#if (NGX_HAVE_FILE_AIO)
|
||||||
if (clcf->aio) {
|
if (clcf->aio) {
|
||||||
ctx->aio = ngx_http_copy_aio_handler;
|
ctx->aio = ngx_http_copy_aio_handler;
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
c->aio_sendfile = (clcf->aio == NGX_HTTP_AIO_SENDFILE);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -139,6 +145,42 @@ ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
|
|||||||
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
|
||||||
"http copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args);
|
"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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +217,26 @@ ngx_http_copy_aio_event_handler(ngx_event_t *ev)
|
|||||||
r->connection->write->handler(r->connection->write);
|
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
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,6 +104,20 @@ static ngx_conf_enum_t ngx_http_core_request_body_in_file[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#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[] = {
|
static ngx_conf_enum_t ngx_http_core_satisfy[] = {
|
||||||
{ ngx_string("all"), NGX_HTTP_SATISFY_ALL },
|
{ ngx_string("all"), NGX_HTTP_SATISFY_ALL },
|
||||||
{ ngx_string("any"), NGX_HTTP_SATISFY_ANY },
|
{ ngx_string("any"), NGX_HTTP_SATISFY_ANY },
|
||||||
@ -386,11 +400,11 @@ static ngx_command_t ngx_http_core_commands[] = {
|
|||||||
#if (NGX_HAVE_FILE_AIO)
|
#if (NGX_HAVE_FILE_AIO)
|
||||||
|
|
||||||
{ ngx_string("aio"),
|
{ ngx_string("aio"),
|
||||||
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
|
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
|
||||||
ngx_conf_set_flag_slot,
|
ngx_conf_set_enum_slot,
|
||||||
NGX_HTTP_LOC_CONF_OFFSET,
|
NGX_HTTP_LOC_CONF_OFFSET,
|
||||||
offsetof(ngx_http_core_loc_conf_t, aio),
|
offsetof(ngx_http_core_loc_conf_t, aio),
|
||||||
NULL },
|
&ngx_http_core_aio },
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -24,6 +24,11 @@
|
|||||||
#define NGX_HTTP_GZIP_PROXIED_ANY 0x0200
|
#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_ALL 0
|
||||||
#define NGX_HTTP_SATISFY_ANY 1
|
#define NGX_HTTP_SATISFY_ANY 1
|
||||||
|
|
||||||
|
@ -546,6 +546,9 @@ struct ngx_http_request_s {
|
|||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ngx_http_posted_request_t terminal_posted_request;
|
ngx_http_posted_request_t terminal_posted_request;
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
u_char preload[4];
|
||||||
|
#endif
|
||||||
} ngx_http_ephemeral_t;
|
} ngx_http_ephemeral_t;
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
* if an asked data are already in VM cache, then aio_error() returns 0,
|
* if an asked data are already in VM cache, then aio_error() returns 0,
|
||||||
* and the data are already copied in buffer;
|
* 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;
|
* aio_read/aio_error() may return EINPROGRESS for just written data;
|
||||||
*
|
*
|
||||||
@ -60,6 +61,9 @@ ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
|
|||||||
aio->event.data = aio;
|
aio->event.data = aio;
|
||||||
aio->event.ready = 1;
|
aio->event.ready = 1;
|
||||||
aio->event.log = file->log;
|
aio->event.log = file->log;
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
aio->last_offset = -1;
|
||||||
|
#endif
|
||||||
file->aio = aio;
|
file->aio = aio;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@
|
|||||||
ngx_chain_t *
|
ngx_chain_t *
|
||||||
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc, flags;
|
||||||
u_char *prev;
|
u_char *prev;
|
||||||
off_t size, send, prev_send, aligned, sent, fprev;
|
off_t size, send, prev_send, aligned, sent, fprev;
|
||||||
size_t header_size, file_size;
|
size_t header_size, file_size;
|
||||||
@ -78,6 +78,7 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||||||
|
|
||||||
send = 0;
|
send = 0;
|
||||||
eagain = 0;
|
eagain = 0;
|
||||||
|
flags = 0;
|
||||||
|
|
||||||
header.elts = headers;
|
header.elts = headers;
|
||||||
header.size = sizeof(struct iovec);
|
header.size = sizeof(struct iovec);
|
||||||
@ -261,8 +262,12 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||||||
|
|
||||||
sent = 0;
|
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,
|
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) {
|
if (rc == -1) {
|
||||||
err = ngx_errno;
|
err = ngx_errno;
|
||||||
@ -276,6 +281,12 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||||||
eintr = 1;
|
eintr = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
case NGX_EBUSY:
|
||||||
|
c->busy_sendfile = file;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
wev->error = 1;
|
wev->error = 1;
|
||||||
(void) ngx_connection_error(c, err, "sendfile() failed");
|
(void) ngx_connection_error(c, err, "sendfile() failed");
|
||||||
@ -383,6 +394,12 @@ ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NGX_HAVE_AIO_SENDFILE)
|
||||||
|
if (c->busy_sendfile) {
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (eagain) {
|
if (eagain) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user