ioq.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Linux AIO request queue
  3. *
  4. * Copyright 2012 IBM, Corp.
  5. * Copyright 2012 Red Hat, Inc. and/or its affiliates
  6. *
  7. * Authors:
  8. * Stefan Hajnoczi <stefanha@redhat.com>
  9. *
  10. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  11. * See the COPYING file in the top-level directory.
  12. *
  13. */
  14. #include "hw/dataplane/ioq.h"
  15. void ioq_init(IOQueue *ioq, int fd, unsigned int max_reqs)
  16. {
  17. int rc;
  18. ioq->fd = fd;
  19. ioq->max_reqs = max_reqs;
  20. memset(&ioq->io_ctx, 0, sizeof ioq->io_ctx);
  21. rc = io_setup(max_reqs, &ioq->io_ctx);
  22. if (rc != 0) {
  23. fprintf(stderr, "ioq io_setup failed %d\n", rc);
  24. exit(1);
  25. }
  26. rc = event_notifier_init(&ioq->io_notifier, 0);
  27. if (rc != 0) {
  28. fprintf(stderr, "ioq io event notifier creation failed %d\n", rc);
  29. exit(1);
  30. }
  31. ioq->freelist = g_malloc0(sizeof ioq->freelist[0] * max_reqs);
  32. ioq->freelist_idx = 0;
  33. ioq->queue = g_malloc0(sizeof ioq->queue[0] * max_reqs);
  34. ioq->queue_idx = 0;
  35. }
  36. void ioq_cleanup(IOQueue *ioq)
  37. {
  38. g_free(ioq->freelist);
  39. g_free(ioq->queue);
  40. event_notifier_cleanup(&ioq->io_notifier);
  41. io_destroy(ioq->io_ctx);
  42. }
  43. EventNotifier *ioq_get_notifier(IOQueue *ioq)
  44. {
  45. return &ioq->io_notifier;
  46. }
  47. struct iocb *ioq_get_iocb(IOQueue *ioq)
  48. {
  49. /* Underflow cannot happen since ioq is sized for max_reqs */
  50. assert(ioq->freelist_idx != 0);
  51. struct iocb *iocb = ioq->freelist[--ioq->freelist_idx];
  52. ioq->queue[ioq->queue_idx++] = iocb;
  53. return iocb;
  54. }
  55. void ioq_put_iocb(IOQueue *ioq, struct iocb *iocb)
  56. {
  57. /* Overflow cannot happen since ioq is sized for max_reqs */
  58. assert(ioq->freelist_idx != ioq->max_reqs);
  59. ioq->freelist[ioq->freelist_idx++] = iocb;
  60. }
  61. struct iocb *ioq_rdwr(IOQueue *ioq, bool read, struct iovec *iov,
  62. unsigned int count, long long offset)
  63. {
  64. struct iocb *iocb = ioq_get_iocb(ioq);
  65. if (read) {
  66. io_prep_preadv(iocb, ioq->fd, iov, count, offset);
  67. } else {
  68. io_prep_pwritev(iocb, ioq->fd, iov, count, offset);
  69. }
  70. io_set_eventfd(iocb, event_notifier_get_fd(&ioq->io_notifier));
  71. return iocb;
  72. }
  73. int ioq_submit(IOQueue *ioq)
  74. {
  75. int rc = io_submit(ioq->io_ctx, ioq->queue_idx, ioq->queue);
  76. ioq->queue_idx = 0; /* reset */
  77. return rc;
  78. }
  79. int ioq_run_completion(IOQueue *ioq, IOQueueCompletion *completion,
  80. void *opaque)
  81. {
  82. struct io_event events[ioq->max_reqs];
  83. int nevents, i;
  84. do {
  85. nevents = io_getevents(ioq->io_ctx, 0, ioq->max_reqs, events, NULL);
  86. } while (nevents < 0 && errno == EINTR);
  87. if (nevents < 0) {
  88. return nevents;
  89. }
  90. for (i = 0; i < nevents; i++) {
  91. ssize_t ret = ((uint64_t)events[i].res2 << 32) | events[i].res;
  92. completion(events[i].obj, ret, opaque);
  93. ioq_put_iocb(ioq, events[i].obj);
  94. }
  95. return nevents;
  96. }