mirror of
https://github.com/nginx/nginx.git
synced 2026-05-28 04:12:47 -04:00
Core: directio consistency in open_file_cache and mp4
This commit is contained in:
parent
9fd94af4dd
commit
738dcbbe7a
5 changed files with 177 additions and 26 deletions
|
|
@ -41,7 +41,8 @@ static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
|
|||
ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log);
|
||||
static void ngx_open_file_cleanup(void *data);
|
||||
static void ngx_close_cached_file(ngx_open_file_cache_t *cache,
|
||||
ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log);
|
||||
ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_uint_t directio_off,
|
||||
ngx_log_t *log);
|
||||
static void ngx_open_file_del_event(ngx_cached_open_file_t *file);
|
||||
static void ngx_expire_old_cached_files(ngx_open_file_cache_t *cache,
|
||||
ngx_uint_t n, ngx_log_t *log);
|
||||
|
|
@ -51,6 +52,8 @@ static ngx_cached_open_file_t *
|
|||
ngx_open_file_lookup(ngx_open_file_cache_t *cache, ngx_str_t *name,
|
||||
uint32_t hash);
|
||||
static void ngx_open_file_cache_remove(ngx_event_t *ev);
|
||||
static ngx_open_file_cache_cleanup_t *
|
||||
ngx_open_file_cache_get_cleanup(ngx_pool_t *p, ngx_fd_t fd);
|
||||
|
||||
|
||||
ngx_open_file_cache_t *
|
||||
|
|
@ -118,7 +121,7 @@ ngx_open_file_cache_cleanup(void *data)
|
|||
if (!file->err && !file->is_dir) {
|
||||
file->close = 1;
|
||||
file->count = 0;
|
||||
ngx_close_cached_file(cache, file, 0, ngx_cycle->log);
|
||||
ngx_close_cached_file(cache, file, 0, 0, ngx_cycle->log);
|
||||
|
||||
} else {
|
||||
ngx_free(file->name);
|
||||
|
|
@ -249,6 +252,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
|
|||
of->is_link = file->is_link;
|
||||
of->is_exec = file->is_exec;
|
||||
of->is_directio = file->is_directio;
|
||||
of->is_directio_off = 0;
|
||||
|
||||
if (!file->is_dir) {
|
||||
file->count++;
|
||||
|
|
@ -313,6 +317,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
|
|||
}
|
||||
|
||||
of->is_directio = file->is_directio;
|
||||
of->is_directio_off = 0;
|
||||
|
||||
goto update;
|
||||
}
|
||||
|
|
@ -389,6 +394,7 @@ create:
|
|||
file->count = 0;
|
||||
file->use_event = 0;
|
||||
file->event = NULL;
|
||||
file->directio_off = of->is_directio_off;
|
||||
|
||||
add_event:
|
||||
|
||||
|
|
@ -442,6 +448,7 @@ found:
|
|||
ofcln->cache = cache;
|
||||
ofcln->file = file;
|
||||
ofcln->min_uses = of->min_uses;
|
||||
ofcln->directio_off = of->is_directio_off;
|
||||
ofcln->log = pool->log;
|
||||
}
|
||||
|
||||
|
|
@ -920,7 +927,11 @@ ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of,
|
|||
}
|
||||
|
||||
if (of->directio <= ngx_file_size(&fi)) {
|
||||
if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
|
||||
if (of->directio_off) {
|
||||
of->is_directio = 1;
|
||||
of->is_directio_off = 1;
|
||||
|
||||
} else if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
ngx_directio_on_n " \"%V\" failed", name);
|
||||
|
||||
|
|
@ -1021,7 +1032,8 @@ ngx_open_file_cleanup(void *data)
|
|||
|
||||
c->file->count--;
|
||||
|
||||
ngx_close_cached_file(c->cache, c->file, c->min_uses, c->log);
|
||||
ngx_close_cached_file(c->cache, c->file, c->min_uses, c->directio_off,
|
||||
c->log);
|
||||
|
||||
/* drop one or two expired open files */
|
||||
ngx_expire_old_cached_files(c->cache, 1, c->log);
|
||||
|
|
@ -1030,12 +1042,25 @@ ngx_open_file_cleanup(void *data)
|
|||
|
||||
static void
|
||||
ngx_close_cached_file(ngx_open_file_cache_t *cache,
|
||||
ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_log_t *log)
|
||||
ngx_cached_open_file_t *file, ngx_uint_t min_uses, ngx_uint_t directio_off,
|
||||
ngx_log_t *log)
|
||||
{
|
||||
ngx_log_debug5(NGX_LOG_DEBUG_CORE, log, 0,
|
||||
"close cached open file: %s, fd:%d, c:%d, u:%d, %d",
|
||||
file->name, file->fd, file->count, file->uses, file->close);
|
||||
|
||||
if (directio_off) {
|
||||
file->directio_off--;
|
||||
|
||||
if (file->directio_off == 0) {
|
||||
if (ngx_directio_on(file->fd) == NGX_FILE_ERROR) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
ngx_directio_on_n " \"%s\" failed",
|
||||
file->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!file->close) {
|
||||
|
||||
file->accessed = ngx_time();
|
||||
|
|
@ -1132,7 +1157,7 @@ ngx_expire_old_cached_files(ngx_open_file_cache_t *cache, ngx_uint_t n,
|
|||
|
||||
if (!file->err && !file->is_dir) {
|
||||
file->close = 1;
|
||||
ngx_close_cached_file(cache, file, 0, log);
|
||||
ngx_close_cached_file(cache, file, 0, 0, log);
|
||||
|
||||
} else {
|
||||
ngx_free(file->name);
|
||||
|
|
@ -1244,10 +1269,92 @@ ngx_open_file_cache_remove(ngx_event_t *ev)
|
|||
|
||||
file->close = 1;
|
||||
|
||||
ngx_close_cached_file(fev->cache, file, 0, ev->log);
|
||||
ngx_close_cached_file(fev->cache, file, 0, 0, ev->log);
|
||||
|
||||
/* free memory only when fev->cache and fev->file are already not needed */
|
||||
|
||||
ngx_free(ev->data);
|
||||
ngx_free(ev);
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_open_file_directio_on(ngx_fd_t fd, ngx_pool_t *pool)
|
||||
{
|
||||
ngx_open_file_cache_cleanup_t *c;
|
||||
|
||||
/*
|
||||
* DIRECTIO is only re-enabled on a file descriptor
|
||||
* when there are no outstanding requests to switch it off
|
||||
*/
|
||||
|
||||
c = ngx_open_file_cache_get_cleanup(pool, fd);
|
||||
|
||||
if (c) {
|
||||
if (!c->directio_off) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
c->directio_off = 0;
|
||||
c->file->directio_off--;
|
||||
|
||||
if (c->file->directio_off > 0) {
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_open_file_directio_off(ngx_fd_t fd, ngx_pool_t *pool)
|
||||
{
|
||||
ngx_open_file_cache_cleanup_t *c;
|
||||
|
||||
c = ngx_open_file_cache_get_cleanup(pool, fd);
|
||||
|
||||
if (c) {
|
||||
if (c->directio_off) {
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
c->directio_off = 1;
|
||||
c->file->directio_off++;
|
||||
|
||||
if (c->file->directio_off > 1) {
|
||||
return NGX_OK;
|
||||
}
|
||||
}
|
||||
|
||||
if (ngx_directio_off(fd) == NGX_FILE_ERROR) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
static ngx_open_file_cache_cleanup_t *
|
||||
ngx_open_file_cache_get_cleanup(ngx_pool_t *p, ngx_fd_t fd)
|
||||
{
|
||||
ngx_pool_cleanup_t *cln;
|
||||
ngx_open_file_cache_cleanup_t *c;
|
||||
|
||||
for (cln = p->cleanup; cln; cln = cln->next) {
|
||||
if (cln->handler == ngx_open_file_cleanup) {
|
||||
|
||||
c = cln->data;
|
||||
|
||||
if (c->file->fd == fd) {
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,12 +42,14 @@ typedef struct {
|
|||
unsigned log:1;
|
||||
unsigned errors:1;
|
||||
unsigned events:1;
|
||||
unsigned directio_off:1;
|
||||
|
||||
unsigned is_dir:1;
|
||||
unsigned is_file:1;
|
||||
unsigned is_link:1;
|
||||
unsigned is_exec:1;
|
||||
unsigned is_directio:1;
|
||||
unsigned is_directio_off:1;
|
||||
} ngx_open_file_info_t;
|
||||
|
||||
|
||||
|
|
@ -67,6 +69,8 @@ struct ngx_cached_open_file_s {
|
|||
off_t size;
|
||||
ngx_err_t err;
|
||||
|
||||
ngx_uint_t directio_off;
|
||||
|
||||
uint32_t uses;
|
||||
|
||||
#if (NGX_HAVE_OPENAT)
|
||||
|
|
@ -103,6 +107,7 @@ typedef struct {
|
|||
ngx_open_file_cache_t *cache;
|
||||
ngx_cached_open_file_t *file;
|
||||
ngx_uint_t min_uses;
|
||||
ngx_uint_t directio_off;
|
||||
ngx_log_t *log;
|
||||
} ngx_open_file_cache_cleanup_t;
|
||||
|
||||
|
|
@ -125,5 +130,8 @@ ngx_open_file_cache_t *ngx_open_file_cache_init(ngx_pool_t *pool,
|
|||
ngx_int_t ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
|
||||
ngx_open_file_info_t *of, ngx_pool_t *pool);
|
||||
|
||||
ngx_int_t ngx_open_file_directio_on(ngx_fd_t fd, ngx_pool_t *pool);
|
||||
ngx_int_t ngx_open_file_directio_off(ngx_fd_t fd, ngx_pool_t *pool);
|
||||
|
||||
|
||||
#endif /* _NGX_OPEN_FILE_CACHE_H_INCLUDED_ */
|
||||
|
|
|
|||
|
|
@ -564,7 +564,9 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx)
|
|||
#if (NGX_HAVE_ALIGNED_DIRECTIO)
|
||||
|
||||
if (ctx->unaligned) {
|
||||
if (ngx_directio_off(src->file->fd) == NGX_FILE_ERROR) {
|
||||
if (ngx_open_file_directio_off(src->file->fd, ctx->pool)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
|
||||
ngx_directio_off_n " \"%s\" failed",
|
||||
src->file->name.data);
|
||||
|
|
@ -611,7 +613,9 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx)
|
|||
|
||||
err = ngx_errno;
|
||||
|
||||
if (ngx_directio_on(src->file->fd) == NGX_FILE_ERROR) {
|
||||
if (ngx_open_file_directio_on(src->file->fd, ctx->pool)
|
||||
!= NGX_OK)
|
||||
{
|
||||
ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno,
|
||||
ngx_directio_on_n " \"%s\" failed",
|
||||
src->file->name.data);
|
||||
|
|
|
|||
|
|
@ -519,7 +519,8 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
|
||||
|
||||
of.read_ahead = clcf->read_ahead;
|
||||
of.directio = NGX_MAX_OFF_T_VALUE;
|
||||
of.directio = clcf->directio;
|
||||
of.directio_off = 1;
|
||||
of.valid = clcf->open_file_cache_valid;
|
||||
of.min_uses = clcf->open_file_cache_min_uses;
|
||||
of.errors = clcf->open_file_cache_errors;
|
||||
|
|
@ -614,6 +615,21 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||
if (start >= 0) {
|
||||
r->single_range = 1;
|
||||
|
||||
if (of.is_directio && !of.is_directio_off) {
|
||||
|
||||
/*
|
||||
* DIRECTIO is set on transfer only
|
||||
* to allow kernel to cache "moov" atom
|
||||
*/
|
||||
|
||||
if (ngx_open_file_directio_off(of.fd, r->pool) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
ngx_directio_off_n " \"%s\" failed", path.data);
|
||||
}
|
||||
|
||||
of.is_directio_off = 1;
|
||||
}
|
||||
|
||||
mp4 = ngx_pcalloc(r->pool, sizeof(ngx_http_mp4_file_t));
|
||||
if (mp4 == NULL) {
|
||||
return NGX_HTTP_INTERNAL_SERVER_ERROR;
|
||||
|
|
@ -622,6 +638,7 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||
mp4->file.fd = of.fd;
|
||||
mp4->file.name = path;
|
||||
mp4->file.log = r->connection->log;
|
||||
mp4->file.directio = of.is_directio;
|
||||
mp4->end = of.size;
|
||||
mp4->start = (ngx_uint_t) start;
|
||||
mp4->length = length;
|
||||
|
|
@ -656,23 +673,14 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
|
|||
|
||||
log->action = "sending mp4 to client";
|
||||
|
||||
if (clcf->directio <= of.size) {
|
||||
if (of.is_directio_off) {
|
||||
|
||||
/*
|
||||
* DIRECTIO is set on transfer only
|
||||
* to allow kernel to cache "moov" atom
|
||||
*/
|
||||
/* DIRECTIO was switched off, restore it */
|
||||
|
||||
if (ngx_directio_on(of.fd) == NGX_FILE_ERROR) {
|
||||
if (ngx_open_file_directio_on(of.fd, r->pool) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
|
||||
ngx_directio_on_n " \"%s\" failed", path.data);
|
||||
}
|
||||
|
||||
of.is_directio = 1;
|
||||
|
||||
if (mp4) {
|
||||
mp4->file.directio = 1;
|
||||
}
|
||||
}
|
||||
|
||||
r->headers_out.status = NGX_HTTP_OK;
|
||||
|
|
|
|||
|
|
@ -353,7 +353,7 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
|
|||
of.valid = clcf->open_file_cache_valid;
|
||||
of.min_uses = clcf->open_file_cache_min_uses;
|
||||
of.events = clcf->open_file_cache_events;
|
||||
of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
|
||||
of.directio = clcf->directio;
|
||||
of.read_ahead = clcf->read_ahead;
|
||||
|
||||
if (ngx_open_cached_file(clcf->open_file_cache, &c->file.name, &of, r->pool)
|
||||
|
|
@ -380,13 +380,36 @@ ngx_http_file_cache_open(ngx_http_request_t *r)
|
|||
|
||||
c->file.fd = of.fd;
|
||||
c->file.log = r->connection->log;
|
||||
c->file.directio = of.is_directio;
|
||||
c->uniq = of.uniq;
|
||||
c->length = of.size;
|
||||
c->fs_size = (of.fs_size + cache->bsize - 1) / cache->bsize;
|
||||
|
||||
c->buf = ngx_create_temp_buf(r->pool, c->body_start);
|
||||
if (c->buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
if (of.is_directio) {
|
||||
|
||||
c->body_start = ngx_align(c->body_start, clcf->directio_alignment);
|
||||
|
||||
c->buf = ngx_calloc_buf(r->pool);
|
||||
if (c->buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->buf->start = ngx_pmemalign(r->pool, c->body_start,
|
||||
clcf->directio_alignment);
|
||||
if (c->buf->start == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
c->buf->pos = c->buf->start;
|
||||
c->buf->last = c->buf->start;
|
||||
c->buf->end = c->buf->start + c->body_start;
|
||||
c->buf->temporary = 1;
|
||||
|
||||
} else {
|
||||
c->buf = ngx_create_temp_buf(r->pool, c->body_start);
|
||||
if (c->buf == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ngx_http_file_cache_read(r, c);
|
||||
|
|
@ -1663,6 +1686,7 @@ ngx_http_cache_send(ngx_http_request_t *r)
|
|||
b->file->fd = c->file.fd;
|
||||
b->file->name = c->file.name;
|
||||
b->file->log = r->connection->log;
|
||||
b->file->directio = c->file.directio;
|
||||
|
||||
out.buf = b;
|
||||
out.next = NULL;
|
||||
|
|
|
|||
Loading…
Reference in a new issue