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