src/os/unix/ngx_linux_aio_read.c - nginx source code

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. extern int            ngx_eventfd;
  9. extern aio_context_t  ngx_aio_ctx;


  10. static void ngx_file_aio_event_handler(ngx_event_t *ev);


  11. static int
  12. io_submit(aio_context_t ctx, long n, struct iocb **paiocb)
  13. {
  14.     return syscall(SYS_io_submit, ctx, n, paiocb);
  15. }


  16. ngx_int_t
  17. ngx_file_aio_init(ngx_file_t *file, ngx_pool_t *pool)
  18. {
  19.     ngx_event_aio_t  *aio;

  20.     aio = ngx_pcalloc(pool, sizeof(ngx_event_aio_t));
  21.     if (aio == NULL) {
  22.         return NGX_ERROR;
  23.     }

  24.     aio->file = file;
  25.     aio->fd = file->fd;
  26.     aio->event.data = aio;
  27.     aio->event.ready = 1;
  28.     aio->event.log = file->log;

  29.     file->aio = aio;

  30.     return NGX_OK;
  31. }


  32. ssize_t
  33. ngx_file_aio_read(ngx_file_t *file, u_char *buf, size_t size, off_t offset,
  34.     ngx_pool_t *pool)
  35. {
  36.     ngx_err_t         err;
  37.     struct iocb      *piocb[1];
  38.     ngx_event_t      *ev;
  39.     ngx_event_aio_t  *aio;

  40.     if (!ngx_file_aio) {
  41.         return ngx_read_file(file, buf, size, offset);
  42.     }

  43.     if (file->aio == NULL && ngx_file_aio_init(file, pool) != NGX_OK) {
  44.         return NGX_ERROR;
  45.     }

  46.     aio = file->aio;
  47.     ev = &aio->event;

  48.     if (!ev->ready) {
  49.         ngx_log_error(NGX_LOG_ALERT, file->log, 0,
  50.                       "second aio post for \"%V\"", &file->name);
  51.         return NGX_AGAIN;
  52.     }

  53.     ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
  54.                    "aio complete:%d @%O:%uz %V",
  55.                    ev->complete, offset, size, &file->name);

  56.     if (ev->complete) {
  57.         ev->active = 0;
  58.         ev->complete = 0;

  59.         if (aio->res >= 0) {
  60.             ngx_set_errno(0);
  61.             return aio->res;
  62.         }

  63.         ngx_set_errno(-aio->res);

  64.         ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
  65.                       "aio read \"%s\" failed", file->name.data);

  66.         return NGX_ERROR;
  67.     }

  68.     ngx_memzero(&aio->aiocb, sizeof(struct iocb));

  69.     aio->aiocb.aio_data = (uint64_t) (uintptr_t) ev;
  70.     aio->aiocb.aio_lio_opcode = IOCB_CMD_PREAD;
  71.     aio->aiocb.aio_fildes = file->fd;
  72.     aio->aiocb.aio_buf = (uint64_t) (uintptr_t) buf;
  73.     aio->aiocb.aio_nbytes = size;
  74.     aio->aiocb.aio_offset = offset;
  75.     aio->aiocb.aio_flags = IOCB_FLAG_RESFD;
  76.     aio->aiocb.aio_resfd = ngx_eventfd;

  77.     ev->handler = ngx_file_aio_event_handler;

  78.     piocb[0] = &aio->aiocb;

  79.     if (io_submit(ngx_aio_ctx, 1, piocb) == 1) {
  80.         ev->active = 1;
  81.         ev->ready = 0;
  82.         ev->complete = 0;

  83.         return NGX_AGAIN;
  84.     }

  85.     err = ngx_errno;

  86.     if (err == NGX_EAGAIN) {
  87.         return ngx_read_file(file, buf, size, offset);
  88.     }

  89.     ngx_log_error(NGX_LOG_CRIT, file->log, err,
  90.                   "io_submit(\"%V\") failed", &file->name);

  91.     if (err == NGX_ENOSYS) {
  92.         ngx_file_aio = 0;
  93.         return ngx_read_file(file, buf, size, offset);
  94.     }

  95.     return NGX_ERROR;
  96. }


  97. static void
  98. ngx_file_aio_event_handler(ngx_event_t *ev)
  99. {
  100.     ngx_event_aio_t  *aio;

  101.     aio = ev->data;

  102.     ngx_log_debug2(NGX_LOG_DEBUG_CORE, ev->log, 0,
  103.                    "aio event handler fd:%d %V", aio->fd, &aio->file->name);

  104.     aio->handler(ev);
  105. }