diff --git a/auto/os/features b/auto/os/features index 8efed75a2..5fcbf7f6b 100644 --- a/auto/os/features +++ b/auto/os/features @@ -182,6 +182,10 @@ ngx_feature_test="fcntl(0, F_SETFL, O_DIRECT);" . auto/feature +if [ $ngx_found = yes -a "$NGX_SYSTEM" = "Linux" ]; then + have=NGX_HAVE_ALIGNED_DIRECTIO . auto/have +fi + ngx_feature="F_NOCACHE" ngx_feature_name="NGX_HAVE_F_NOCACHE" ngx_feature_run=no diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h index d16656d6b..ce26c630e 100644 --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -79,6 +79,9 @@ typedef struct { unsigned sendfile; unsigned directio; +#if (NGX_HAVE_ALIGNED_DIRECTIO) + unsigned unaligned; +#endif unsigned need_in_memory; unsigned need_in_temp; diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index ecb0f31bf..391852ffe 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -355,6 +355,10 @@ ngx_output_chain_align_file_buf(ngx_output_chain_ctx_t *ctx, off_t bsize) * to reuse the buf via ctx->free list */ +#if (NGX_HAVE_ALIGNED_DIRECTIO) + ctx->unaligned = 1; +#endif + return NGX_OK; } @@ -491,8 +495,41 @@ ngx_output_chain_copy_buf(ngx_output_chain_ctx_t *ctx) } } else { + +#if (NGX_HAVE_ALIGNED_DIRECTIO) + + if (ctx->unaligned) { + if (ngx_directio_off(src->file->fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno, + ngx_directio_off_n " \"%s\" failed", + src->file->name.data); + } + } + +#endif + n = ngx_read_file(src->file, dst->pos, (size_t) size, src->file_pos); +#if (NGX_HAVE_ALIGNED_DIRECTIO) + + if (ctx->unaligned) { + ngx_err_t err; + + err = ngx_errno; + + if (ngx_directio_on(src->file->fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, ctx->pool->log, ngx_errno, + ngx_directio_on_n " \"%s\" failed", + src->file->name.data); + } + + ngx_set_errno(err); + + ctx->unaligned = 0; + } + +#endif + if (n == NGX_ERROR) { return (ngx_int_t) n; } diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c index ab861467e..661ecaa4e 100644 --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -389,7 +389,7 @@ ngx_unlock_fd(ngx_fd_t fd) #if (NGX_HAVE_O_DIRECT) ngx_int_t -ngx_directio(ngx_fd_t fd) +ngx_directio_on(ngx_fd_t fd) { int flags; @@ -402,4 +402,19 @@ ngx_directio(ngx_fd_t fd) return fcntl(fd, F_SETFL, flags | O_DIRECT); } + +ngx_int_t +ngx_directio_off(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 diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h index 9988bcc30..d7a38d95a 100644 --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -222,23 +222,26 @@ ngx_err_t ngx_unlock_fd(ngx_fd_t fd); #if (NGX_HAVE_O_DIRECT) -ngx_int_t ngx_directio(ngx_fd_t fd); -#define ngx_directio_n "fcntl(O_DIRECT)" +ngx_int_t ngx_directio_on(ngx_fd_t fd); +#define ngx_directio_on_n "fcntl(O_DIRECT)" + +ngx_int_t ngx_directio_off(ngx_fd_t fd); +#define ngx_directio_off_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)" +#define ngx_directio_on(fd) fcntl(fd, F_NOCACHE, 1) +#define ngx_directio_on_n "fcntl(F_NOCACHE, 1)" #elif (NGX_HAVE_DIRECTIO) -#define ngx_directio(fd) directio(fd, DIRECTIO_ON) -#define ngx_directio_n "directio(DIRECTIO_ON)" +#define ngx_directio_on(fd) directio(fd, DIRECTIO_ON) +#define ngx_directio_on_n "directio(DIRECTIO_ON)" #else -#define ngx_directio(fd) 0 -#define ngx_directio_n "ngx_directio_n" +#define ngx_directio_on(fd) 0 +#define ngx_directio_on_n "ngx_directio_on_n" #endif diff --git a/src/os/win32/ngx_files.c b/src/os/win32/ngx_files.c index 20b528668..cbba0bbfb 100644 --- a/src/os/win32/ngx_files.c +++ b/src/os/win32/ngx_files.c @@ -505,7 +505,13 @@ ngx_file_append_mode(ngx_fd_t fd) ngx_int_t -ngx_directio(ngx_fd_t fd) +ngx_directio_on(ngx_fd_t fd) +{ + return 0; +} + +ngx_int_t +ngx_directio_off(ngx_fd_t fd) { return 0; } diff --git a/src/os/win32/ngx_files.h b/src/os/win32/ngx_files.h index 9f4f68199..95ea65b67 100644 --- a/src/os/win32/ngx_files.h +++ b/src/os/win32/ngx_files.h @@ -232,8 +232,11 @@ ssize_t ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *ce, off_t offset, ngx_pool_t *pool); -ngx_int_t ngx_directio(ngx_fd_t fd); -#define ngx_directio_n "ngx_directio_n" +ngx_int_t ngx_directio_on(ngx_fd_t fd); +#define ngx_directio_on_n "ngx_directio_on_n" + +ngx_int_t ngx_directio_off(ngx_fd_t fd); +#define ngx_directio_off_n "ngx_directio_off_n" #endif /* _NGX_FILES_H_INCLUDED_ */