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