Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation. All rights reserved.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk_internal/usdt.h"
7 : :
8 : : #include "spdk/env.h"
9 : : #include "spdk/log.h"
10 : : #include "spdk/queue.h"
11 : : #include "spdk/util.h"
12 : :
13 : : #include "spdk/fd_group.h"
14 : :
15 : : #define SPDK_MAX_EVENT_NAME_LEN 256
16 : :
17 : : enum event_handler_state {
18 : : /* The event_handler is added into an fd_group waiting for event,
19 : : * but not currently in the execution of a wait loop.
20 : : */
21 : : EVENT_HANDLER_STATE_WAITING,
22 : :
23 : : /* The event_handler is currently in the execution of a wait loop. */
24 : : EVENT_HANDLER_STATE_RUNNING,
25 : :
26 : : /* The event_handler was removed during the execution of a wait loop. */
27 : : EVENT_HANDLER_STATE_REMOVED,
28 : : };
29 : :
30 : : /* Taking "ehdlr" as short name for file descriptor handler of the interrupt event. */
31 : : struct event_handler {
32 : : TAILQ_ENTRY(event_handler) next;
33 : : enum event_handler_state state;
34 : :
35 : : spdk_fd_fn fn;
36 : : void *fn_arg;
37 : : /* file descriptor of the interrupt event */
38 : : int fd;
39 : : uint32_t events;
40 : : uint32_t fd_type;
41 : : char name[SPDK_MAX_EVENT_NAME_LEN + 1];
42 : : };
43 : :
44 : : struct spdk_fd_group {
45 : : int epfd;
46 : :
47 : : /* Number of fds registered in this group. The epoll file descriptor of this fd group
48 : : * i.e. epfd waits for interrupt event on all the fds from its interrupt sources list, as
49 : : * well as from all its children fd group interrupt sources list.
50 : : */
51 : : uint32_t num_fds;
52 : :
53 : : struct spdk_fd_group *parent;
54 : :
55 : : /* interrupt sources list */
56 : : TAILQ_HEAD(, event_handler) event_handlers;
57 : : };
58 : :
59 : : int
60 : 2 : spdk_fd_group_get_fd(struct spdk_fd_group *fgrp)
61 : : {
62 [ # # # # ]: 2 : return fgrp->epfd;
63 : : }
64 : :
65 : : #ifdef __linux__
66 : :
67 : : static __thread struct epoll_event *g_event = NULL;
68 : :
69 : : int
70 : 0 : spdk_fd_group_get_epoll_event(struct epoll_event *event)
71 : : {
72 [ # # ]: 0 : if (g_event == NULL) {
73 : 0 : return -EINVAL;
74 : : }
75 : 0 : *event = *g_event;
76 : 0 : return 0;
77 : 0 : }
78 : :
79 : : static int
80 : 274 : _fd_group_del_all(int epfd, struct spdk_fd_group *grp)
81 : : {
82 : 274 : struct event_handler *ehdlr = NULL;
83 : 274 : struct epoll_event epevent = {0};
84 : : int rc;
85 : 274 : int ret = 0;
86 : :
87 [ + + # # : 575 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
# # # # #
# # # #
# ]
88 [ # # # # ]: 301 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
89 [ - + ]: 301 : if (rc < 0) {
90 [ # # # # ]: 0 : if (errno == ENOENT) {
91 : : /* This is treated as success. It happens if there are multiple
92 : : * attempts to remove fds from the group.
93 : : */
94 : 0 : continue;
95 : : }
96 : :
97 [ # # # # ]: 0 : ret = -errno;
98 [ # # # # : 0 : SPDK_ERRLOG("Failed to remove fd: %d from group: %s\n",
# # ]
99 : : ehdlr->fd, strerror(errno));
100 : 0 : goto recover;
101 : : }
102 [ # # ]: 301 : ret++;
103 : 0 : }
104 : :
105 : 274 : return ret;
106 : :
107 : 0 : recover:
108 : : /* We failed to remove everything. Let's try to put everything back into
109 : : * the original group. */
110 [ # # # # : 0 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
# # # # #
# # # #
# ]
111 [ # # # # ]: 0 : epevent.events = ehdlr->events;
112 [ # # ]: 0 : epevent.data.ptr = ehdlr;
113 [ # # # # ]: 0 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, ehdlr->fd, &epevent);
114 [ # # ]: 0 : if (rc < 0) {
115 [ # # # # ]: 0 : if (errno == EEXIST) {
116 : : /* This is fine. Keep going. */
117 : 0 : continue;
118 : : }
119 : :
120 : : /* Continue on even though we've failed. But indicate
121 : : * this is a fatal error. */
122 [ # # ]: 0 : SPDK_ERRLOG("Failed to recover fd_group_del_all: %s\n", strerror(errno));
123 : 0 : ret = -ENOTRECOVERABLE;
124 : 0 : }
125 : 0 : }
126 : :
127 : 0 : return ret;
128 : 0 : }
129 : :
130 : : static int
131 : 274 : _fd_group_add_all(int epfd, struct spdk_fd_group *grp)
132 : : {
133 : 274 : struct event_handler *ehdlr = NULL;
134 : 274 : struct epoll_event epevent = {0};
135 : : int rc;
136 : 274 : int ret = 0;
137 : :
138 : : /* Hoist the fds from the child up into the parent */
139 [ + + # # : 575 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
# # # # #
# # # #
# ]
140 [ # # # # ]: 301 : epevent.events = ehdlr->events;
141 [ # # ]: 301 : epevent.data.ptr = ehdlr;
142 [ # # # # ]: 301 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, ehdlr->fd, &epevent);
143 [ - + ]: 301 : if (rc < 0) {
144 [ # # # # ]: 0 : if (errno == EEXIST) {
145 : : /* This is treated as success */
146 : 0 : continue;
147 : : }
148 : :
149 [ # # # # ]: 0 : ret = -errno;
150 [ # # # # : 0 : SPDK_ERRLOG("Failed to add fd: %d to fd group: %s\n",
# # ]
151 : : ehdlr->fd, strerror(errno));
152 : 0 : goto recover;
153 : : }
154 [ # # ]: 301 : ret++;
155 : 0 : }
156 : :
157 : 274 : return ret;
158 : :
159 : 0 : recover:
160 : : /* We failed to add everything, so try to remove what we did add. */
161 [ # # # # : 0 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
# # # # #
# # # #
# ]
162 [ # # # # ]: 0 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
163 [ # # ]: 0 : if (rc < 0) {
164 [ # # # # ]: 0 : if (errno == ENOENT) {
165 : : /* This is treated as success. */
166 : 0 : continue;
167 : : }
168 : :
169 : :
170 : : /* Continue on even though we've failed. But indicate
171 : : * this is a fatal error. */
172 [ # # ]: 0 : SPDK_ERRLOG("Failed to recover fd_group_del_all: %s\n", strerror(errno));
173 : 0 : ret = -ENOTRECOVERABLE;
174 : 0 : }
175 : 0 : }
176 : :
177 : 0 : return ret;
178 : 0 : }
179 : :
180 : : int
181 : 140 : spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
182 : : {
183 : : int rc;
184 : :
185 [ + - - + ]: 140 : if (parent == NULL || child == NULL) {
186 : 0 : return -EINVAL;
187 : : }
188 : :
189 [ + + # # : 140 : if (child->parent != parent) {
# # ]
190 : 3 : return -EINVAL;
191 : : }
192 : :
193 [ # # # # ]: 137 : rc = _fd_group_del_all(parent->epfd, child);
194 [ - + ]: 137 : if (rc < 0) {
195 : 0 : return rc;
196 : : } else {
197 [ - + # # : 137 : assert(parent->num_fds >= (uint32_t)rc);
# # # # ]
198 [ # # # # ]: 137 : parent->num_fds -= rc;
199 : : }
200 : :
201 [ # # # # ]: 137 : child->parent = NULL;
202 : :
203 [ # # # # ]: 137 : rc = _fd_group_add_all(child->epfd, child);
204 [ - + ]: 137 : if (rc < 0) {
205 : 0 : return rc;
206 : : } else {
207 [ # # # # ]: 137 : child->num_fds += rc;
208 : : }
209 : :
210 : 137 : return 0;
211 : 0 : }
212 : :
213 : : int
214 : 137 : spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
215 : : {
216 : : int rc;
217 : :
218 [ + - - + ]: 137 : if (parent == NULL || child == NULL) {
219 : 0 : return -EINVAL;
220 : : }
221 : :
222 [ - + # # : 137 : if (child->parent) {
# # ]
223 : 0 : return -EINVAL;
224 : : }
225 : :
226 [ - + # # : 137 : if (parent->parent) {
# # ]
227 : : /* More than one layer of nesting is currently not supported */
228 [ # # ]: 0 : assert(false);
229 : : return -ENOTSUP;
230 : : }
231 : :
232 [ # # # # ]: 137 : rc = _fd_group_del_all(child->epfd, child);
233 [ - + ]: 137 : if (rc < 0) {
234 : 0 : return rc;
235 : : } else {
236 [ - + # # : 137 : assert(child->num_fds >= (uint32_t)rc);
# # # # ]
237 [ # # # # ]: 137 : child->num_fds -= rc;
238 : : }
239 : :
240 [ # # # # ]: 137 : child->parent = parent;
241 : :
242 [ # # # # ]: 137 : rc = _fd_group_add_all(parent->epfd, child);
243 [ - + ]: 137 : if (rc < 0) {
244 : 0 : return rc;
245 : : } else {
246 [ # # # # ]: 137 : parent->num_fds += rc;
247 : : }
248 : :
249 : 137 : return 0;
250 : 0 : }
251 : :
252 : : void
253 : 18084 : spdk_fd_group_get_default_event_handler_opts(struct spdk_event_handler_opts *opts,
254 : : size_t opts_size)
255 : : {
256 [ + + ]: 18084 : if (!opts) {
257 : 0 : SPDK_ERRLOG("opts should not be NULL\n");
258 : 0 : return;
259 : : }
260 : :
261 [ + + ]: 18084 : if (!opts_size) {
262 : 0 : SPDK_ERRLOG("opts_size should not be zero value\n");
263 : 0 : return;
264 : : }
265 : :
266 [ + + ]: 18084 : memset(opts, 0, opts_size);
267 [ + - + - ]: 18084 : opts->opts_size = opts_size;
268 : :
269 : : #define FIELD_OK(field) \
270 : : offsetof(struct spdk_event_handler_opts, field) + sizeof(opts->field) <= opts_size
271 : :
272 : : #define SET_FIELD(field, value) \
273 : : if (FIELD_OK(field)) { \
274 : : opts->field = value; \
275 : : } \
276 : :
277 [ + + + - : 18084 : SET_FIELD(events, EPOLLIN);
+ - ]
278 [ + + + - : 18084 : SET_FIELD(fd_type, SPDK_FD_TYPE_DEFAULT);
+ - ]
279 : :
280 : : #undef FIELD_OK
281 : : #undef SET_FIELD
282 : 332 : }
283 : :
284 : : static void
285 : 9042 : event_handler_opts_copy(const struct spdk_event_handler_opts *src,
286 : : struct spdk_event_handler_opts *dst)
287 : : {
288 [ + + + - : 9042 : if (!src->opts_size) {
+ - ]
289 : 0 : SPDK_ERRLOG("opts_size should not be zero value\n");
290 [ # # ]: 0 : assert(false);
291 : : }
292 : :
293 : : #define FIELD_OK(field) \
294 : : offsetof(struct spdk_event_handler_opts, field) + sizeof(src->field) <= src->opts_size
295 : :
296 : : #define SET_FIELD(field) \
297 : : if (FIELD_OK(field)) { \
298 : : dst->field = src->field; \
299 : : } \
300 : :
301 [ + - + - : 9042 : SET_FIELD(events);
- + + - +
- + - +
- ]
302 [ + - + - : 9042 : SET_FIELD(fd_type);
- + + - +
- + - +
- ]
303 : :
304 [ + - + - : 9042 : dst->opts_size = src->opts_size;
+ - + - ]
305 : :
306 : : /* You should not remove this statement, but need to update the assert statement
307 : : * if you add a new field, and also add a corresponding SET_FIELD statement */
308 : : SPDK_STATIC_ASSERT(sizeof(struct spdk_event_handler_opts) == 16, "Incorrect size");
309 : :
310 : : #undef FIELD_OK
311 : : #undef SET_FIELD
312 : 9042 : }
313 : :
314 : : int
315 : 7330 : spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
316 : : void *arg, const char *name)
317 : : {
318 : 7330 : return spdk_fd_group_add_for_events(fgrp, efd, EPOLLIN, fn, arg, name);
319 : : }
320 : :
321 : : int
322 : 7330 : spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events,
323 : : spdk_fd_fn fn, void *arg, const char *name)
324 : : {
325 : 7330 : struct spdk_event_handler_opts opts = {};
326 : :
327 : 7330 : spdk_fd_group_get_default_event_handler_opts(&opts, sizeof(opts));
328 [ + - ]: 7330 : opts.events = events;
329 [ + - ]: 7330 : opts.fd_type = SPDK_FD_TYPE_DEFAULT;
330 : :
331 : 7330 : return spdk_fd_group_add_ext(fgrp, efd, fn, arg, name, &opts);
332 : : }
333 : :
334 : : int
335 : 9042 : spdk_fd_group_add_ext(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, void *arg,
336 : : const char *name, struct spdk_event_handler_opts *opts)
337 : : {
338 : 9042 : struct event_handler *ehdlr = NULL;
339 : 9042 : struct epoll_event epevent = {0};
340 : 9042 : struct spdk_event_handler_opts eh_opts = {};
341 : : int rc;
342 : : int epfd;
343 : :
344 : : /* parameter checking */
345 [ + - + - : 9042 : if (fgrp == NULL || efd < 0 || fn == NULL) {
- + ]
346 : 0 : return -EINVAL;
347 : : }
348 : :
349 : 9042 : spdk_fd_group_get_default_event_handler_opts(&eh_opts, sizeof(eh_opts));
350 [ + - ]: 9042 : if (opts) {
351 : 9042 : event_handler_opts_copy(opts, &eh_opts);
352 : 166 : }
353 : :
354 : : /* check if there is already one function registered for this fd */
355 [ + + + - : 20121 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
+ - + + +
- + - +
- ]
356 [ + + + - : 11079 : if (ehdlr->fd == efd) {
+ - ]
357 : 0 : return -EEXIST;
358 : : }
359 : 83 : }
360 : :
361 : : /* create a new event src */
362 : 9042 : ehdlr = calloc(1, sizeof(*ehdlr));
363 [ + + ]: 9042 : if (ehdlr == NULL) {
364 [ # # # # ]: 0 : return -errno;
365 : : }
366 : :
367 [ + - + - ]: 9042 : ehdlr->fd = efd;
368 [ + - + - ]: 9042 : ehdlr->fn = fn;
369 [ + - + - ]: 9042 : ehdlr->fn_arg = arg;
370 [ + - + - ]: 9042 : ehdlr->state = EVENT_HANDLER_STATE_WAITING;
371 [ + - + - : 9042 : ehdlr->events = eh_opts.events;
+ - ]
372 [ + - + - : 9042 : ehdlr->fd_type = eh_opts.fd_type;
+ - ]
373 [ + - ]: 9042 : snprintf(ehdlr->name, sizeof(ehdlr->name), "%s", name);
374 : :
375 [ + + + - : 9042 : if (fgrp->parent) {
- + ]
376 [ # # # # : 1711 : epfd = fgrp->parent->epfd;
# # # # ]
377 : 0 : } else {
378 [ + - + - ]: 7331 : epfd = fgrp->epfd;
379 : : }
380 : :
381 [ + - + - ]: 9042 : epevent.events = ehdlr->events;
382 [ + - ]: 9042 : epevent.data.ptr = ehdlr;
383 : 9042 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent);
384 [ + + ]: 9042 : if (rc < 0) {
385 [ # # ]: 0 : SPDK_ERRLOG("Failed to add fd: %d to fd group(%p): %s\n",
386 : : efd, fgrp, strerror(errno));
387 : 0 : free(ehdlr);
388 [ # # # # ]: 0 : return -errno;
389 : : }
390 : :
391 [ + - + - : 9042 : TAILQ_INSERT_TAIL(&fgrp->event_handlers, ehdlr, next);
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ]
392 [ + + + - : 9042 : if (fgrp->parent) {
- + ]
393 [ # # # # : 1711 : fgrp->parent->num_fds++;
# # ]
394 : 0 : } else {
395 [ - + ]: 7331 : fgrp->num_fds++;
396 : : }
397 : :
398 : 9042 : return 0;
399 : 166 : }
400 : :
401 : : void
402 : 9009 : spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
403 : : {
404 : : struct event_handler *ehdlr;
405 : : int rc;
406 : : int epfd;
407 : :
408 [ + - - + ]: 9009 : if (fgrp == NULL || efd < 0) {
409 : 0 : SPDK_ERRLOG("Cannot remove fd: %d from fd group(%p)\n", efd, fgrp);
410 [ # # ]: 0 : assert(0);
411 : : return;
412 : : }
413 : :
414 : :
415 [ + - + - : 18878 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
+ - + - +
- + - +
- ]
416 [ + + + - : 18878 : if (ehdlr->fd == efd) {
+ + ]
417 : 9009 : break;
418 : : }
419 : 83 : }
420 : :
421 [ + + ]: 9009 : if (ehdlr == NULL) {
422 : 0 : SPDK_ERRLOG("fd: %d doesn't exist in fd group(%p)\n", efd, fgrp);
423 : 0 : return;
424 : : }
425 : :
426 [ + + + - : 9009 : assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED);
+ - # # ]
427 : :
428 [ + + + - : 9009 : if (fgrp->parent) {
- + ]
429 [ # # # # : 1708 : epfd = fgrp->parent->epfd;
# # # # ]
430 : 0 : } else {
431 [ + - + - ]: 7301 : epfd = fgrp->epfd;
432 : : }
433 : :
434 [ + - + - ]: 9009 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
435 [ + + ]: 9009 : if (rc < 0) {
436 [ # # # # : 0 : SPDK_ERRLOG("Failed to remove fd: %d from fd group(%p): %s\n",
# # ]
437 : : ehdlr->fd, fgrp, strerror(errno));
438 : 0 : return;
439 : : }
440 : :
441 [ + + + - : 9009 : if (fgrp->parent) {
- + ]
442 [ - + # # : 1708 : assert(fgrp->parent->num_fds > 0);
# # # # #
# # # ]
443 [ # # # # : 1708 : fgrp->parent->num_fds--;
# # ]
444 : 0 : } else {
445 [ + + + - : 7301 : assert(fgrp->num_fds > 0);
+ - # # ]
446 [ + - ]: 7301 : fgrp->num_fds--;
447 : : }
448 [ + + + - : 9009 : TAILQ_REMOVE(&fgrp->event_handlers, ehdlr, next);
+ - - + #
# # # # #
# # # # #
# # # # #
# # + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ]
449 : :
450 : : /* Delay ehdlr's free in case it is waiting for execution in fgrp wait loop */
451 [ + + + - : 9009 : if (ehdlr->state == EVENT_HANDLER_STATE_RUNNING) {
- + ]
452 [ # # # # ]: 451 : ehdlr->state = EVENT_HANDLER_STATE_REMOVED;
453 : 0 : } else {
454 : 8558 : free(ehdlr);
455 : : }
456 : 166 : }
457 : :
458 : : int
459 : 3 : spdk_fd_group_event_modify(struct spdk_fd_group *fgrp,
460 : : int efd, int event_types)
461 : : {
462 : 3 : struct epoll_event epevent;
463 : : struct event_handler *ehdlr;
464 : : int epfd;
465 : :
466 [ + - - + ]: 3 : if (fgrp == NULL || efd < 0) {
467 : 0 : return -EINVAL;
468 : : }
469 : :
470 [ + - # # : 3 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
# # # # #
# # # #
# ]
471 [ + - # # : 3 : if (ehdlr->fd == efd) {
# # ]
472 : 3 : break;
473 : : }
474 : 0 : }
475 : :
476 [ - + ]: 3 : if (ehdlr == NULL) {
477 : 0 : return -EINVAL;
478 : : }
479 : :
480 [ - + # # : 3 : assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED);
# # # # ]
481 : :
482 [ # # # # ]: 3 : ehdlr->events = event_types;
483 : :
484 [ - + # # : 3 : if (fgrp->parent) {
# # ]
485 [ # # # # : 0 : epfd = fgrp->parent->epfd;
# # # # ]
486 : 0 : } else {
487 [ # # # # ]: 3 : epfd = fgrp->epfd;
488 : : }
489 : :
490 [ # # # # ]: 3 : epevent.events = ehdlr->events;
491 [ # # ]: 3 : epevent.data.ptr = ehdlr;
492 : :
493 [ # # # # ]: 3 : return epoll_ctl(epfd, EPOLL_CTL_MOD, ehdlr->fd, &epevent);
494 : 0 : }
495 : :
496 : : int
497 : 6142 : spdk_fd_group_create(struct spdk_fd_group **_egrp)
498 : : {
499 : : struct spdk_fd_group *fgrp;
500 : :
501 [ + + ]: 6142 : if (_egrp == NULL) {
502 : 0 : return -EINVAL;
503 : : }
504 : :
505 : 6142 : fgrp = calloc(1, sizeof(*fgrp));
506 [ + + ]: 6142 : if (fgrp == NULL) {
507 : 0 : return -ENOMEM;
508 : : }
509 : :
510 : : /* init the event source head */
511 [ + - + - : 6142 : TAILQ_INIT(&fgrp->event_handlers);
+ - + - +
- + - + -
+ - ]
512 : :
513 [ + - + - ]: 6142 : fgrp->num_fds = 0;
514 [ + - + - ]: 6142 : fgrp->epfd = epoll_create1(EPOLL_CLOEXEC);
515 [ + + + - : 6142 : if (fgrp->epfd < 0) {
+ - ]
516 : 0 : free(fgrp);
517 [ # # # # ]: 0 : return -errno;
518 : : }
519 : :
520 [ + - ]: 6142 : *_egrp = fgrp;
521 : :
522 : 6142 : return 0;
523 : 84 : }
524 : :
525 : : void
526 : 6136 : spdk_fd_group_destroy(struct spdk_fd_group *fgrp)
527 : : {
528 [ + - + + : 6136 : if (fgrp == NULL || fgrp->num_fds > 0) {
+ - ]
529 [ # # ]: 0 : if (!fgrp) {
530 : 0 : SPDK_ERRLOG("fd_group doesn't exist.\n");
531 : 0 : } else {
532 [ # # # # ]: 0 : SPDK_ERRLOG("Cannot delete fd group(%p) as (%u) fds are still registered to it.\n",
533 : : fgrp, fgrp->num_fds);
534 : : }
535 [ # # ]: 0 : assert(0);
536 : : return;
537 : : }
538 : :
539 : : /* Check if someone tried to delete the fd group before unnesting it */
540 [ + + + - : 6136 : if (!TAILQ_EMPTY(&fgrp->event_handlers)) {
+ - + - ]
541 : 0 : SPDK_ERRLOG("Interrupt sources list not empty.\n");
542 [ # # ]: 0 : assert(0);
543 : : return;
544 : : }
545 : :
546 [ + - + - ]: 6136 : close(fgrp->epfd);
547 : 6136 : free(fgrp);
548 : :
549 : 6136 : return;
550 : : }
551 : :
552 : : int
553 : 130352162 : spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
554 : 130347544 : {
555 [ + - + - ]: 130352162 : uint32_t totalfds = fgrp->num_fds;
556 [ + + ]: 130352162 : struct epoll_event events[totalfds];
557 : : struct event_handler *ehdlr;
558 : 30996 : uint64_t count;
559 : : int n;
560 : : int nfds;
561 : : int bytes_read;
562 : : int read_errno;
563 : :
564 [ + + + - : 130352162 : if (fgrp->parent != NULL) {
- + ]
565 [ # # ]: 0 : if (timeout < 0) {
566 : 0 : SPDK_ERRLOG("Calling spdk_fd_group_wait on a group nested in another group without a timeout will block indefinitely.\n");
567 [ # # ]: 0 : assert(false);
568 : : return -EINVAL;
569 : : } else {
570 : 0 : SPDK_WARNLOG("Calling spdk_fd_group_wait on a group nested in another group will never find any events.\n");
571 : 0 : return 0;
572 : : }
573 : : }
574 : :
575 [ + + + - : 130352162 : nfds = epoll_wait(fgrp->epfd, events, totalfds, timeout);
+ - ]
576 [ + + ]: 130352156 : if (nfds < 0) {
577 [ - + # # ]: 19 : if (errno != EINTR) {
578 [ # # ]: 0 : SPDK_ERRLOG("fd group(%p) epoll_wait failed: %s\n",
579 : : fgrp, strerror(errno));
580 : 0 : }
581 : :
582 [ # # # # ]: 19 : return -errno;
583 [ + + ]: 130352137 : } else if (nfds == 0) {
584 : 567 : return 0;
585 : : }
586 : :
587 [ + + + - ]: 356449208 : for (n = 0; n < nfds; n++) {
588 : : /* find the event_handler */
589 [ + - + - : 226097638 : ehdlr = events[n].data.ptr;
+ - + - +
- ]
590 : :
591 [ + + ]: 226097638 : if (ehdlr == NULL) {
592 : 0 : continue;
593 : : }
594 : :
595 : : /* Tag ehdlr as running state in case that it is removed
596 : : * during this wait loop but before or when it get executed.
597 : : */
598 [ + + + - : 226097638 : assert(ehdlr->state == EVENT_HANDLER_STATE_WAITING);
+ - # # ]
599 [ + - + - ]: 226097638 : ehdlr->state = EVENT_HANDLER_STATE_RUNNING;
600 : 4621 : }
601 : :
602 [ + + + - ]: 356449208 : for (n = 0; n < nfds; n++) {
603 : : /* find the event_handler */
604 [ + - + - : 226097638 : ehdlr = events[n].data.ptr;
+ - + - +
- ]
605 : :
606 [ + - + + : 226097638 : if (ehdlr == NULL || ehdlr->fn == NULL) {
+ - - + ]
607 : 0 : continue;
608 : : }
609 : :
610 : : /* It is possible that the ehdlr was removed
611 : : * during this wait loop but before it get executed.
612 : : */
613 [ + + + - : 226097638 : if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) {
- + ]
614 : 15 : free(ehdlr);
615 : 15 : continue;
616 : : }
617 : :
618 [ + - + - ]: 226097623 : g_event = &events[n];
619 : :
620 : : /* read fd to reset the internal eventfd object counter value to 0 */
621 [ + + + - : 226097623 : if (ehdlr->fd_type == SPDK_FD_TYPE_EVENTFD) {
+ - ]
622 [ # # # # ]: 125654 : bytes_read = read(ehdlr->fd, &count, sizeof(count));
623 [ - + ]: 125654 : if (bytes_read < 0) {
624 : 0 : g_event = NULL;
625 [ # # # # : 0 : if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
# # # # #
# # # ]
626 : 0 : continue;
627 : : }
628 [ # # ]: 0 : read_errno = errno;
629 : : /* TODO: Device is buggy. Handle this properly */
630 [ # # # # : 0 : SPDK_ERRLOG("Failed to read fd (%d) %s\n",
# # ]
631 : : ehdlr->fd, strerror(errno));
632 [ # # ]: 0 : return -read_errno;
633 [ - + ]: 125654 : } else if (bytes_read == 0) {
634 [ # # # # ]: 0 : SPDK_ERRLOG("Read nothing from fd (%d)\n", ehdlr->fd);
635 : 0 : g_event = NULL;
636 : 0 : return -EINVAL;
637 : : }
638 : 0 : }
639 : :
640 : : /* call the interrupt response function */
641 [ + - + - : 226097623 : ehdlr->fn(ehdlr->fn_arg);
- + + - +
- + - ]
642 : 226097623 : g_event = NULL;
643 : :
644 : : /* It is possible that the ehdlr was removed
645 : : * during this wait loop when it get executed.
646 : : */
647 [ + + + - : 226097623 : if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) {
- + ]
648 : 436 : free(ehdlr);
649 : 0 : } else {
650 [ + - + - ]: 226097187 : ehdlr->state = EVENT_HANDLER_STATE_WAITING;
651 : : }
652 : 4621 : }
653 : :
654 : 130351570 : return nfds;
655 : 4618 : }
656 : :
657 : : #else /* !__linux__ */
658 : :
659 : : int
660 : : spdk_fd_group_get_epoll_event(struct epoll_event *event)
661 : : {
662 : : return -ENOTSUP;
663 : : }
664 : :
665 : : int
666 : : spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
667 : : void *arg, const char *name)
668 : : {
669 : : return -ENOTSUP;
670 : : }
671 : :
672 : : int
673 : : spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events, spdk_fd_fn fn,
674 : : void *arg, const char *name)
675 : : {
676 : : return -ENOTSUP;
677 : : }
678 : :
679 : : int
680 : : spdk_fd_group_add_ext(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, void *arg,
681 : : const char *name, struct spdk_event_handler_opts *opts)
682 : : {
683 : : return -ENOTSUP;
684 : : }
685 : :
686 : : void
687 : : spdk_fd_group_get_default_event_handler_opts(struct spdk_event_handler_opts *opts,
688 : : size_t opts_size)
689 : : {
690 : : assert(false);
691 : : }
692 : :
693 : : void
694 : : spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
695 : : {
696 : : }
697 : :
698 : : int
699 : : spdk_fd_group_event_modify(struct spdk_fd_group *fgrp,
700 : : int efd, int event_types)
701 : : {
702 : : return -ENOTSUP;
703 : : }
704 : :
705 : : int
706 : : spdk_fd_group_create(struct spdk_fd_group **fgrp)
707 : : {
708 : : return -ENOTSUP;
709 : : }
710 : :
711 : : void
712 : : spdk_fd_group_destroy(struct spdk_fd_group *fgrp)
713 : : {
714 : : }
715 : :
716 : : int
717 : : spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
718 : : {
719 : : return -ENOTSUP;
720 : : }
721 : :
722 : : int
723 : : spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
724 : : {
725 : : return -ENOTSUP;
726 : : }
727 : :
728 : : int
729 : : spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
730 : : {
731 : : return -ENOTSUP;
732 : : }
733 : :
734 : : #endif /* __linux__ */
|