Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 : : */
4 : : #include "spdk/stdinc.h"
5 : : #include "spdk/util.h"
6 : : #include "spdk/log.h"
7 : : #include "aio_mgr.h"
8 : : #include <libaio.h>
9 : :
10 : : #define MAX_EVENTS 1024
11 : :
12 : : struct spdk_aio_mgr_io {
13 : : struct spdk_aio_mgr *mgr;
14 : : TAILQ_ENTRY(spdk_aio_mgr_io) link;
15 : : struct iocb io;
16 : : fsdev_aio_done_cb clb;
17 : : void *ctx;
18 : : uint32_t data_size;
19 : : int err;
20 : : };
21 : :
22 : : struct spdk_aio_mgr {
23 : : TAILQ_HEAD(, spdk_aio_mgr_io) in_flight;
24 : : io_context_t io_ctx;
25 : : struct {
26 : : struct spdk_aio_mgr_io *arr;
27 : : uint32_t size;
28 : : TAILQ_HEAD(, spdk_aio_mgr_io) pool;
29 : : } aios;
30 : : uint32_t num_completions;
31 : : };
32 : :
33 : : static struct spdk_aio_mgr_io *
34 : 524288 : aio_mgr_get_aio(struct spdk_aio_mgr *mgr, fsdev_aio_done_cb clb, void *ctx)
35 : : {
36 [ # # # # : 524288 : struct spdk_aio_mgr_io *aio = TAILQ_FIRST(&mgr->aios.pool);
# # # # ]
37 : :
38 [ + - ]: 524288 : if (aio) {
39 [ # # # # ]: 524288 : aio->mgr = mgr;
40 [ # # # # ]: 524288 : aio->clb = clb;
41 [ # # # # ]: 524288 : aio->ctx = ctx;
42 [ # # # # ]: 524288 : aio->err = 0;
43 [ # # # # ]: 524288 : aio->data_size = 0;
44 [ + - # # : 524288 : TAILQ_REMOVE(&mgr->aios.pool, aio, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
45 : 0 : }
46 : :
47 : 524288 : return aio;
48 : : }
49 : :
50 : : static inline void
51 : 524288 : aio_mgr_put_aio(struct spdk_aio_mgr *mgr, struct spdk_aio_mgr_io *aio)
52 : : {
53 [ # # # # : 524288 : TAILQ_INSERT_TAIL(&aio->mgr->aios.pool, aio, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
54 : 524288 : }
55 : :
56 : : static void
57 : 524288 : spdk_aio_mgr_io_cpl_cb(io_context_t ctx, struct iocb *iocb, long res, long res2)
58 : : {
59 : 524288 : struct spdk_aio_mgr_io *aio = SPDK_CONTAINEROF(iocb, struct spdk_aio_mgr_io, io);
60 : :
61 [ + + # # : 524288 : TAILQ_REMOVE(&aio->mgr->in_flight, aio, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
62 : :
63 [ # # # # : 524288 : aio->clb(aio->ctx, res, -res2);
# # # # #
# # # #
# ]
64 : :
65 [ # # # # : 524288 : aio->mgr->num_completions++;
# # ]
66 : :
67 [ # # # # ]: 524288 : aio_mgr_put_aio(aio->mgr, aio);
68 : 524288 : }
69 : :
70 : : static struct spdk_aio_mgr_io *
71 : 524288 : spdk_aio_mgr_submit_io(struct spdk_aio_mgr *mgr, fsdev_aio_done_cb clb, void *ctx, int fd,
72 : : uint64_t offs, uint32_t size, struct iovec *iovs, uint32_t iovcnt, bool read)
73 : : {
74 : : struct spdk_aio_mgr_io *aio;
75 : : int res;
76 : 524288 : struct iocb *ios[1];
77 : :
78 [ - + - + : 524288 : SPDK_DEBUGLOG(spdk_aio_mgr_io, "%s: fd=%d offs=%" PRIu64 " size=%" PRIu32 " iovcnt=%" PRIu32 "\n",
- - # # ]
79 : : read ? "read" : "write", fd, offs, size, iovcnt);
80 : :
81 : 524288 : aio = aio_mgr_get_aio(mgr, clb, ctx);
82 [ - + ]: 524288 : if (!aio) {
83 : 0 : SPDK_ERRLOG("Cannot get aio\n");
84 [ # # # # ]: 0 : clb(ctx, 0, EFAULT);
85 : 0 : return NULL;
86 : : }
87 : :
88 [ + + # # ]: 524288 : if (read) {
89 [ # # ]: 131040 : io_prep_preadv(&aio->io, fd, iovs, iovcnt, offs);
90 : 0 : } else {
91 [ # # ]: 393248 : io_prep_pwritev(&aio->io, fd, iovs, iovcnt, offs);
92 : : }
93 [ # # ]: 524288 : io_set_callback(&aio->io, spdk_aio_mgr_io_cpl_cb);
94 : :
95 : :
96 [ # # # # : 524288 : ios[0] = &aio->io;
# # ]
97 [ # # # # ]: 524288 : res = io_submit(mgr->io_ctx, 1, ios);
98 [ - + - + : 524288 : SPDK_DEBUGLOG(spdk_aio_mgr_io, "%s: aio=%p submitted with res=%d\n", read ? "read" : "write", aio,
- - # # ]
99 : : res);
100 [ + - ]: 524288 : if (res) {
101 [ # # # # : 524288 : TAILQ_INSERT_TAIL(&aio->mgr->in_flight, aio, link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
102 : 524288 : return aio;
103 : : } else {
104 [ # # # # : 0 : aio->clb(aio->ctx, 0, aio->err);
# # # # #
# # # # #
# # ]
105 : 0 : aio_mgr_put_aio(mgr, aio);
106 : 0 : return NULL;
107 : : }
108 : :
109 : 0 : }
110 : :
111 : : struct spdk_aio_mgr *
112 : 1 : spdk_aio_mgr_create(uint32_t max_aios)
113 : : {
114 : : struct spdk_aio_mgr *mgr;
115 : : int res;
116 : : uint32_t i;
117 : :
118 : 1 : mgr = calloc(1, sizeof(*mgr));
119 [ - + ]: 1 : if (!mgr) {
120 : 0 : SPDK_ERRLOG("cannot alloc mgr of %zu bytes\n", sizeof(*mgr));
121 : 0 : return NULL;
122 : : }
123 : :
124 [ # # ]: 1 : res = io_queue_init(max_aios, &mgr->io_ctx);
125 [ - + ]: 1 : if (res) {
126 : 0 : SPDK_ERRLOG("io_setup(%" PRIu32 ") failed with %d\n", max_aios, res);
127 : 0 : free(mgr);
128 : 0 : return NULL;
129 : : }
130 : :
131 [ # # # # : 1 : mgr->aios.arr = calloc(max_aios, sizeof(mgr->aios.arr[0]));
# # ]
132 [ - + # # : 1 : if (!mgr->aios.arr) {
# # # # ]
133 : 0 : SPDK_ERRLOG("cannot alloc aios pool of %" PRIu32 "\n", max_aios);
134 [ # # # # ]: 0 : io_queue_release(mgr->io_ctx);
135 : 0 : free(mgr);
136 : 0 : return NULL;
137 : : }
138 : :
139 [ # # # # : 1 : TAILQ_INIT(&mgr->in_flight);
# # # # #
# # # # #
# # ]
140 [ # # # # : 1 : TAILQ_INIT(&mgr->aios.pool);
# # # # #
# # # # #
# # # # #
# # # ]
141 : :
142 [ + + ]: 257 : for (i = 0; i < max_aios; i++) {
143 [ # # # # : 256 : TAILQ_INSERT_TAIL(&mgr->aios.pool, &mgr->aios.arr[i], link);
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ]
144 : 0 : }
145 : :
146 : 1 : return mgr;
147 : 0 : }
148 : :
149 : : struct spdk_aio_mgr_io *
150 : 131040 : spdk_aio_mgr_read(struct spdk_aio_mgr *mgr, fsdev_aio_done_cb clb, void *ctx,
151 : : int fd, uint64_t offs, uint32_t size, struct iovec *iovs, uint32_t iovcnt)
152 : : {
153 : 131040 : return spdk_aio_mgr_submit_io(mgr, clb, ctx, fd, offs, size, iovs, iovcnt, true);
154 : : }
155 : :
156 : : struct spdk_aio_mgr_io *
157 : 393248 : spdk_aio_mgr_write(struct spdk_aio_mgr *mgr, fsdev_aio_done_cb clb, void *ctx,
158 : : int fd, uint64_t offs, uint32_t size, const struct iovec *iovs, uint32_t iovcnt)
159 : : {
160 : 393248 : return spdk_aio_mgr_submit_io(mgr, clb, ctx, fd, offs, size, (struct iovec *)iovs, iovcnt, false);
161 : : }
162 : :
163 : : void
164 : 0 : spdk_aio_mgr_cancel(struct spdk_aio_mgr *mgr, struct spdk_aio_mgr_io *aio)
165 : : {
166 : : int res;
167 : 0 : struct io_event result;
168 : :
169 [ # # # # : 0 : assert(mgr == aio->mgr);
# # # # ]
170 : :
171 [ # # # # : 0 : res = io_cancel(mgr->io_ctx, &aio->io, &result);
# # ]
172 [ # # ]: 0 : if (res) {
173 [ # # # # : 0 : SPDK_DEBUGLOG(spdk_aio_mgr_io, "aio=%p cancelled\n", aio);
# # ]
174 [ # # # # : 0 : spdk_aio_mgr_io_cpl_cb(mgr->io_ctx, &aio->io, ECANCELED, 0);
# # ]
175 : 0 : } else {
176 : 0 : SPDK_WARNLOG("aio=%p cancellation failed with err=%d\n", aio, res);
177 : : }
178 : 0 : }
179 : :
180 : : bool
181 : 1572464 : spdk_aio_mgr_poll(struct spdk_aio_mgr *mgr)
182 : : {
183 : : int res;
184 : :
185 [ # # # # ]: 1572464 : mgr->num_completions = 0;
186 : :
187 [ # # # # ]: 1572464 : res = io_queue_run(mgr->io_ctx);
188 [ - + ]: 1572464 : if (res) {
189 : 0 : SPDK_WARNLOG("polling failed with err=%d\n", res);
190 : 0 : }
191 : :
192 [ # # # # ]: 1572464 : return mgr->num_completions ? true : false;
193 : : }
194 : :
195 : : void
196 : 1 : spdk_aio_mgr_delete(struct spdk_aio_mgr *mgr)
197 : : {
198 [ - + # # : 1 : assert(TAILQ_EMPTY(&mgr->in_flight));
# # # # #
# ]
199 [ # # # # : 1 : free(mgr->aios.arr);
# # ]
200 [ # # # # ]: 1 : io_queue_release(mgr->io_ctx);
201 : 1 : free(mgr);
202 : 1 : }
203 : :
204 : 2134 : SPDK_LOG_REGISTER_COMPONENT(spdk_aio_mgr_io)
|