Пример #1
0
//return eventfd
int AIORead(std::string path,void *buf,int epfd=-1)
{
    m_filefd = openFile(path);
    if (-1 == m_filefd) {
        return -1;
    }
    
    m_ctx = 0;
    if (io_setup(8192, &m_ctx)) {
        perror("io_setup");
        return -1;
    }

    if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
        perror("posix_memalign");
        return 5;
    }
    printf("buf: %p\n", buf);

    for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
        iocbps[i] = &iocbp->iocb;
        io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
        io_set_eventfd(&iocbp->iocb, efd);
        io_set_callback(&iocbp->iocb, aio_callback);
        iocbp->nth_request = i + 1;
    }

    if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
        perror("io_submit");
        return 6;
    }
}
Пример #2
0
static int aio_submit(struct iothread *t, http_conn_t h)
{
	struct iocb *iocb;
	size_t data_len;
	off_t data_off;
	int ret, fd;

	data_len = http_conn_data(h, &fd, &data_off);
	assert(data_len);

	iocb = hgang_alloc(aio_iocbs);
	if ( NULL == iocb )
		return 0;

	io_prep_sendfile(iocb, fd, data_len, data_off, http_conn_socket(h));
	iocb->data = h;
	io_set_eventfd(iocb, efd->fd);

	ret = io_submit(aio_ctx, 1, &iocb);
	if ( ret <= 0 ) {
		errno = -ret;
		fprintf(stderr, "io_submit: %s\n", os_err());
		return 0;
	}

	dprintf("io_submit: sendfile: %zu bytes\n", data_len);
	in_flight++;
	return 1;
}
Пример #3
0
int aio_preadv(io_context_t ctx, struct iocb *iocb, int fd, const struct iovec *iov, int iovcnt,
		off_t offset, int ev, void *param)
{
	struct iocb *ios[1] = { iocb };

	io_prep_preadv(iocb, fd, iov, iovcnt, offset);
	io_set_eventfd(iocb, ev);
	iocb->data = param;

	return io_submit(ctx, 1, ios);
}
Пример #4
0
int aio_read(int fd, void *buffer, size_t length, off_t offset, aio_callback_t cb){
	struct iocb iocb;
        struct iocb *piocb = &iocb;
        int resp;

        io_prep_pread(&iocb, fd, buffer, length, offset);
        iocb.data = cb;
	io_set_eventfd(&iocb, aio_fd);

        resp = io_submit(aio_ctx,1, &piocb);
        return resp;
}
Пример #5
0
void AsyncIO::submit(Op* op) {
  CHECK_EQ(op->state(), Op::State::INITIALIZED);
  CHECK_LT(pending_, capacity_) << "too many pending requests";
  initializeContext();  // on demand
  iocb* cb = &op->iocb_;
  cb->data = nullptr;  // unused
  if (pollFd_ != -1) {
    io_set_eventfd(cb, pollFd_);
  }
  int rc = io_submit(ctx_, 1, &cb);
  checkKernelError(rc, "AsyncIO: io_submit failed");
  DCHECK_EQ(rc, 1);
  op->start();
  ++pending_;
}
Пример #6
0
/*
 * Test whether counter overflow is detected and handled correctly.
 *
 * It is not possible to directly overflow the counter using the
 * write() syscall. Overflows occur when the counter is incremented
 * from kernel space, in an irq context, when it is not possible to
 * block the calling thread of execution.
 *
 * The AIO subsystem internally uses eventfd mechanism for
 * notification of completion of read or write requests. In this test
 * we trigger a counter overflow, by setting the counter value to the
 * max possible value initially. When the AIO subsystem notifies
 * through the eventfd counter, the counter overflows.
 *
 * NOTE: If the the counter starts from an initial value of 0, it will
 * take decades for an overflow to occur. But since we set the initial
 * value to the max possible counter value, we are able to cause it to
 * overflow with a single increment.
 *
 * When the counter overflows, the following are tested
 *   1. Check whether POLLERR event occurs in poll() for the eventfd.
 *   2. Check whether readfd_set/writefd_set is set in select() for the
        eventfd.
 *   3. The counter value is UINT64_MAX.
 */
static int trigger_eventfd_overflow(int evfd, int *fd, io_context_t * ctx)
{
    int ret;
    struct iocb iocb;
    struct iocb *iocbap[1];
    static char buf[4 * 1024];

    *ctx = 0;
    ret = io_setup(16, ctx);
    if (ret < 0) {
        errno = -ret;
        tst_resm(TINFO | TERRNO, "io_setup error");
        return -1;
    }

    *fd = open("testfile", O_RDWR | O_CREAT, 0644);
    if (*fd == -1) {
        tst_resm(TINFO | TERRNO, "open(testfile) failed");
        goto err_io_destroy;
    }

    ret = set_counter(evfd, UINT64_MAX - 1);
    if (ret == -1) {
        tst_resm(TINFO, "error setting counter to UINT64_MAX-1");
        goto err_close_file;
    }

    io_prep_pwrite(&iocb, *fd, buf, sizeof(buf), 0);
    io_set_eventfd(&iocb, evfd);

    iocbap[0] = &iocb;
    ret = io_submit(*ctx, 1, iocbap);
    if (ret < 0) {
        errno = -ret;
        tst_resm(TINFO | TERRNO, "error submitting iocb");
        goto err_close_file;
    }

    return 0;

err_close_file:
    close(*fd);

err_io_destroy:
    io_destroy(*ctx);

    return -1;
}
Пример #7
0
BlockDriverAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        BlockDriverCompletionFunc *cb, void *opaque, int type)
{
    struct qemu_laio_state *s = aio_ctx;
    struct qemu_laiocb *laiocb;
    struct iocb *iocbs;
    off_t offset = sector_num * 512;

    laiocb = qemu_aio_get(&laio_pool, bs, cb, opaque);
    if (!laiocb)
        return NULL;
    laiocb->nbytes = nb_sectors * 512;
    laiocb->ctx = s;
    laiocb->ret = -EINPROGRESS;
    laiocb->is_read = (type == QEMU_AIO_READ);
    laiocb->qiov = qiov;

    iocbs = &laiocb->iocb;

    switch (type) {
    case QEMU_AIO_WRITE:
        io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset);
	break;
    case QEMU_AIO_READ:
        io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
	break;
    /* Currently Linux kernel does not support other operations */
    default:
        fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
                        __func__, type);
        goto out_free_aiocb;
    }
    io_set_eventfd(&laiocb->iocb, s->efd);
    s->count++;

    if (io_submit(s->ctx, 1, &iocbs) < 0)
        goto out_dec_count;
    return &laiocb->common;

out_dec_count:
    s->count--;
out_free_aiocb:
    qemu_aio_release(laiocb);
    return NULL;
}
Пример #8
0
BlockAIOCB *laio_submit(BlockDriverState *bs, void *aio_ctx, int fd,
        int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
        BlockCompletionFunc *cb, void *opaque, int type)
{
    struct qemu_laio_state *s = aio_ctx;
    struct qemu_laiocb *laiocb;
    struct iocb *iocbs;
    off_t offset = sector_num * 512;

    laiocb = qemu_aio_get(&laio_aiocb_info, bs, cb, opaque);
    laiocb->nbytes = nb_sectors * 512;
    laiocb->ctx = s;
    laiocb->ret = -EINPROGRESS;
    laiocb->is_read = (type == QEMU_AIO_READ);
    laiocb->qiov = qiov;

    iocbs = &laiocb->iocb;

    switch (type) {
    case QEMU_AIO_WRITE:
        io_prep_pwritev(iocbs, fd, qiov->iov, qiov->niov, offset);
	break;
    case QEMU_AIO_READ:
        io_prep_preadv(iocbs, fd, qiov->iov, qiov->niov, offset);
	break;
    /* Currently Linux kernel does not support other operations */
    default:
        fprintf(stderr, "%s: invalid AIO request type 0x%x.\n",
                        __func__, type);
        goto out_free_aiocb;
    }
    io_set_eventfd(&laiocb->iocb, event_notifier_get_fd(&s->e));

    if (!s->io_q.plugged) {
        if (io_submit(s->ctx, 1, &iocbs) < 0) {
            goto out_free_aiocb;
        }
    } else {
        ioq_enqueue(s, iocbs);
    }
    return &laiocb->common;

out_free_aiocb:
    qemu_aio_unref(laiocb);
    return NULL;
}
Пример #9
0
int
aioperf_libaio_read(aioperf_io_task_t *io_task)
{
    struct iocb             *libaio_req = NULL;
    aioperf_repository_t    *repository = NULL;
    aioperf_conf_info_t     *conf_info = NULL;
    unsigned long            left_size = 0;
    unsigned int             count = 0;

    repository = io_task->repository;
    conf_info = repository->conf_info;
    left_size = io_task->file_size - io_task->offset;
        
    if (!(libaio_req = (struct iocb *)aioperf_memory_pool_alloc(repository->pool, 
        sizeof(struct iocb)))) {
        printf("alloc error\n");
        return AIOPERF_ERROR;
    }

    if (!(io_task->buf = (char *)aioperf_memory_memalign(512, 
        conf_info->buf_size))) {
        printf("memory memalign error\n");
    }
    

    io_task->data = libaio_req;

    if (left_size > conf_info->buf_size) {
        count = conf_info->buf_size;
    } else {
        count = left_size;
    }

    io_prep_pread(libaio_req, io_task->fd, io_task->buf, count, 
        io_task->offset);
    libaio_req->data = io_task;

    io_set_eventfd(libaio_req, io_task->repository->signal_fd);
    
    if (io_submit(*(io_context_t *)repository->mgr->data, 1, &libaio_req) < 0) {
        printf("io_submit error\n");
    }

    return AIOPERF_OK;
}
Пример #10
0
static void do_io_async(void)
{
	size_t n_files = sizeof(files) / sizeof(files[0]);
	size_t i;
	io_context_t ctx = 0;
	struct iocb *iocb;
	struct iocb **piocb;
	int n_aio_ops, rc;

	/* TODO 1 - allocate iocb and piocb */
	iocb = (struct iocb *) malloc(n_files * sizeof(*iocb));
	DIE(iocb == NULL, "malloc");

	piocb = (struct iocb **) malloc(n_files * sizeof(*piocb));
	DIE(piocb == NULL, "malloc");

	/* TODO 1 - initialiaze iocb and piocb */
	for (i = 0; i < n_files; i++) {
		io_prep_pwrite(&iocb[i], fds[i], g_buffer, BUFSIZ, 0);
		piocb[i] = &iocb[i];

#ifdef USE_EVENTFD
		/* TODO 2 - set up eventfd notification */
		io_set_eventfd(&iocb[i], efd);
#endif		
	}

	/* TODO 1 - setup aio context */
	rc = io_setup(n_files, &ctx);
	DIE(rc < 0, "io_setup");

	/* TODO 1 - submit aio */
	n_aio_ops = io_submit(ctx, n_files, piocb);
	DIE(n_aio_ops < 0, "io_submit");

	/* wait for completion*/
	wait_aio(ctx, n_files);

	/* TODO 1 - destroy aio context */
	io_destroy(ctx);
}
Пример #11
0
void AsyncIO::submit(Op* op) {
  CHECK_EQ(op->state(), Op::State::INITIALIZED);
  initializeContext();  // on demand

  // We can increment past capacity, but we'll clean up after ourselves.
  auto p = pending_.fetch_add(1, std::memory_order_acq_rel);
  if (p >= capacity_) {
    decrementPending();
    throw std::range_error("AsyncIO: too many pending requests");
  }
  iocb* cb = &op->iocb_;
  cb->data = nullptr;  // unused
  if (pollFd_ != -1) {
    io_set_eventfd(cb, pollFd_);
  }
  int rc = io_submit(ctx_, 1, &cb);
  if (rc < 0) {
    decrementPending();
    throwSystemErrorExplicit(-rc, "AsyncIO: io_submit failed");
  }
  submitted_++;
  DCHECK_EQ(rc, 1);
  op->start();
}
Пример #12
0
int main(int argc, char *argv[])
{
  int efd, fd, epfd;
  io_context_t ctx;
  struct timespec tms;
  struct io_event events[NUM_EVENTS];
  struct custom_iocb iocbs[NUM_EVENTS];
  struct iocb *iocbps[NUM_EVENTS];
  struct custom_iocb *iocbp;
  int i, j, r;
  void *buf;
  struct epoll_event epevent;

  // TODO:Used to record event?
  efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
  if (efd == -1) {
    perror("eventfd");
    return 2;
  }

  // File Open Operation
  fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
  if (fd == -1) {
    perror("open");
    return 3;
  }
  // Init the file size first.
  ftruncate(fd, TEST_FILE_SIZE);
    
  
  ctx = 0;
  //  1. io_setup: Create an asynchronous I/O context capable of receiving
  //     at least nr_events.
  //  2. 8192: It could receive at least 8192 events??
  if (io_setup(8192, &ctx)) {
    perror("io_setup");
    return 4;
  }

  // Allocate RD_WR_SIZE bytes, and places the address of the allocated memory
  // in *buf. The address of the allocated memory will be a multiple of ALIGN_SIZE,
  if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
    perror("posix_memalign");
    return 5;
  }
  printf("buf: %p\n", buf);

  
  for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
    iocbps[i] = &iocbp->iocb;
    
    // An inline convenience function designed to facilitate the initialization of the iocb for
    // an asynchronous read operation. When the function finished, the iocbp->iocb will be:
    //   iocb->u.c.nbytes= RD_WR_SIZE
    //   iocb->aio_fildes = fd
    //   iocb->u.c.buf = buf
    //   iocb->u.c.offset = i * RD_WR_SIZE
    io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
    io_set_eventfd(&iocbp->iocb, efd);

    // Set up io completion callback function.
    io_set_callback(&iocbp->iocb, aio_callback);
    iocbp->nth_request = i + 1;
  }

  // Submit asynchronous I/O blocks for processing. It will queue NUM_EVENTS
  // I/O request blocks for processing in the AIO context ctx.
  //  iocbps is an array of nr AIO control blocks, which will be submitted to context ctx.
  if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
    perror("io_submit");
    return 6;
  }

  // Open an epoll file descriptor ( epoll is I/O event notification facility).
  // It will returns a file descriptor referring to the new epoll instance.
  epfd = epoll_create(1);
  if (epfd == -1) {
    perror("epoll_create");
    return 7;
  }

  epevent.events = EPOLLIN | EPOLLET;
  epevent.data.ptr = NULL;
  // epoll_ctl: Control interface for an epoll descriptor.
  //      EPOLL_CTL_ADD:  the operation that will be performanced
  //      efd: The target file descriptor that the operation will be performed for.
  //      epevent: describle the object linked to the fle descriptor efd.
  if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent)) {
    perror("epoll_ctl");
    return 8;
  }

  i = 0;
  while (i < NUM_EVENTS) {
    uint64_t finished_aio;

    // epoll_wait: wait for an I/O event on an epoll file descriptor
    //   epfd: the file descriptor that the epoll instance refer to.
    //   epevent: points to the events that will be available for the caller.
    //   1: at most 1  are returned by the function
    //   -1: specifies the minimum number of milliseconds that epoll_wait() will block.
    //       -1 causes epoll_wait to block indefinitely.
    if (epoll_wait(epfd, &epevent, 1, -1) != 1) {
      perror("epoll_wait");
      return 9;
    }

    if (read(efd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio)) {
      perror("read");
      return 10;
    }

    printf("finished io number: %"PRIu64"\n", finished_aio);
    
    while (finished_aio > 0) {
      tms.tv_sec = 0;
      tms.tv_nsec = 0;
      // read asynchronous I/O events from the completion queue.
      r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
      if (r > 0) {
	for (j = 0; j < r; ++j) {
	  ((io_callback_t)(events[j].data))(ctx, events[j].obj, events[j].res, events[j].res2);
	}
	i += r;
	finished_aio -= r;
      }
    }
  }
    
  close(epfd);
  free(buf);

  // destroy an asynchronous I/O context
  io_destroy(ctx);
  close(fd);
  close(efd);
  remove(TEST_FILE);

  return 0;
}
Пример #13
0
int main(int argc, char *argv[])
{
    int efd, fd, epfd;
    io_context_t ctx;
    struct timespec tms;
    struct io_event events[NUM_EVENTS];
    struct custom_iocb iocbs[NUM_EVENTS];
    struct iocb *iocbps[NUM_EVENTS];
    struct custom_iocb *iocbp;
    int i, j, r;
    void *buf;
    struct epoll_event epevent;

    efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
    if (efd == -1) {
        perror("eventfd");
        return 2;
    }

    fd = open(TEST_FILE, O_RDWR | O_CREAT | O_DIRECT, 0644);
    if (fd == -1) {
        perror("open");
        return 3;
    }
    ftruncate(fd, TEST_FILE_SIZE);
    
    ctx = 0;
    if (io_setup(8192, &ctx)) {
        perror("io_setup");
        return 4;
    }

    if (posix_memalign(&buf, ALIGN_SIZE, RD_WR_SIZE)) {
        perror("posix_memalign");
        return 5;
    }
    printf("buf: %p\n", buf);

    for (i = 0, iocbp = iocbs; i < NUM_EVENTS; ++i, ++iocbp) {
        iocbps[i] = &iocbp->iocb;
        io_prep_pread(&iocbp->iocb, fd, buf, RD_WR_SIZE, i * RD_WR_SIZE);
        io_set_eventfd(&iocbp->iocb, efd);
        io_set_callback(&iocbp->iocb, aio_callback);
        iocbp->nth_request = i + 1;
    }

    if (io_submit(ctx, NUM_EVENTS, iocbps) != NUM_EVENTS) {
        perror("io_submit");
        return 6;
    }

    epfd = epoll_create(1);
    if (epfd == -1) {
        perror("epoll_create");
        return 7;
    }

    epevent.events = EPOLLIN | EPOLLET;
    epevent.data.ptr = NULL;
    if (epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent)) {
        perror("epoll_ctl");
        return 8;
    }

    i = 0;
    while (i < NUM_EVENTS) {
        uint64_t finished_aio;

        if (epoll_wait(epfd, &epevent, 1, -1) != 1) {
            perror("epoll_wait");
            return 9;
        }

        if (read(efd, &finished_aio, sizeof(finished_aio)) != sizeof(finished_aio)) {
            perror("read");
            return 10;
        }

        printf("finished io number: %"PRIu64"\n", finished_aio);
    
        while (finished_aio > 0) {
            tms.tv_sec = 0;
            tms.tv_nsec = 0;
            r = io_getevents(ctx, 1, NUM_EVENTS, events, &tms);
            if (r > 0) {
                for (j = 0; j < r; ++j) {
                    ((io_callback_t)(events[j].data))(ctx, events[j].obj, events[j].res, events[j].res2);
                }
                i += r;
                finished_aio -= r;
            }
        }
    }
    
    close(epfd);
    free(buf);
    io_destroy(ctx);
    close(fd);
    close(efd);
    remove(TEST_FILE);

    return 0;
}