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 :
12 : #include "spdk/fd_group.h"
13 :
14 : #ifdef __linux__
15 : #include <sys/epoll.h>
16 : #endif
17 :
18 : #define SPDK_MAX_EVENT_NAME_LEN 256
19 :
20 : enum event_handler_state {
21 : /* The event_handler is added into an fd_group waiting for event,
22 : * but not currently in the execution of a wait loop.
23 : */
24 : EVENT_HANDLER_STATE_WAITING,
25 :
26 : /* The event_handler is currently in the execution of a wait loop. */
27 : EVENT_HANDLER_STATE_RUNNING,
28 :
29 : /* The event_handler was removed during the execution of a wait loop. */
30 : EVENT_HANDLER_STATE_REMOVED,
31 : };
32 :
33 : /* file descriptor of the interrupt event */
34 :
35 : /* Taking "ehdlr" as short name for file descriptor handler of the interrupt event. */
36 : struct event_handler {
37 : TAILQ_ENTRY(event_handler) next;
38 : enum event_handler_state state;
39 :
40 : spdk_fd_fn fn;
41 : void *fn_arg;
42 : /* file descriptor of the interrupt event */
43 : int fd;
44 : uint32_t events;
45 : char name[SPDK_MAX_EVENT_NAME_LEN + 1];
46 : };
47 :
48 : struct spdk_fd_group {
49 : int epfd;
50 : int num_fds; /* Number of fds registered in this group. */
51 :
52 : struct spdk_fd_group *parent;
53 :
54 : /* interrupt sources list */
55 : TAILQ_HEAD(, event_handler) event_handlers;
56 : };
57 :
58 : int
59 0 : spdk_fd_group_get_fd(struct spdk_fd_group *fgrp)
60 : {
61 0 : return fgrp->epfd;
62 : }
63 :
64 : #ifdef __linux__
65 :
66 : static __thread struct epoll_event *g_event = NULL;
67 :
68 : int
69 : spdk_fd_group_get_epoll_event(struct epoll_event *event)
70 : {
71 : if (g_event == NULL) {
72 : return -EINVAL;
73 : }
74 : *event = *g_event;
75 : return 0;
76 : }
77 :
78 : static int
79 : _fd_group_del_all(int epfd, struct spdk_fd_group *grp)
80 : {
81 : struct event_handler *ehdlr = NULL;
82 : struct epoll_event epevent = {0};
83 : int rc;
84 : int ret = 0;
85 :
86 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
87 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
88 : if (rc < 0) {
89 : if (errno == ENOENT) {
90 : /* This is treated as success. It happens if there are multiple
91 : * attempts to remove fds from the group.
92 : */
93 : continue;
94 : }
95 :
96 : ret = -errno;
97 : SPDK_ERRLOG("Failed to remove fd %d from group: %s\n", ehdlr->fd, strerror(errno));
98 : goto recover;
99 : }
100 : }
101 :
102 : return 0;
103 :
104 : recover:
105 : /* We failed to remove everything. Let's try to get everything put back into
106 : * the original group. */
107 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
108 : epevent.events = ehdlr->events;
109 : epevent.data.ptr = ehdlr;
110 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, ehdlr->fd, &epevent);
111 : if (rc < 0) {
112 : if (errno == EEXIST) {
113 : /* This is fine. Keep going. */
114 : continue;
115 : }
116 :
117 : /* Continue on even though we've failed. But indicate
118 : * this is a fatal error. */
119 : SPDK_ERRLOG("Failed to recover fd_group_del_all: %s\n", strerror(errno));
120 : ret = -ENOTRECOVERABLE;
121 : }
122 : }
123 :
124 : return ret;
125 : }
126 :
127 : static int
128 : _fd_group_add_all(int epfd, struct spdk_fd_group *grp)
129 : {
130 : struct event_handler *ehdlr = NULL;
131 : struct epoll_event epevent = {0};
132 : int rc;
133 : int ret = 0;
134 :
135 : /* Hoist the fds from the child up into the parent */
136 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
137 : epevent.events = ehdlr->events;
138 : epevent.data.ptr = ehdlr;
139 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, ehdlr->fd, &epevent);
140 : if (rc < 0) {
141 : if (errno == EEXIST) {
142 : /* This is treated as success */
143 : continue;
144 : }
145 :
146 : ret = -errno;
147 : SPDK_ERRLOG("Failed to add fd to fd group: %s\n", strerror(errno));
148 : goto recover;
149 : }
150 : }
151 :
152 : return 0;
153 :
154 : recover:
155 : /* We failed to add everything, so try to remove what we did add. */
156 : TAILQ_FOREACH(ehdlr, &grp->event_handlers, next) {
157 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
158 : if (rc < 0) {
159 : if (errno == ENOENT) {
160 : /* This is treated as success. */
161 : continue;
162 : }
163 :
164 :
165 : /* Continue on even though we've failed. But indicate
166 : * this is a fatal error. */
167 : SPDK_ERRLOG("Failed to recover fd_group_del_all: %s\n", strerror(errno));
168 : ret = -ENOTRECOVERABLE;
169 : }
170 : }
171 :
172 : return ret;
173 : }
174 :
175 : int
176 : spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
177 : {
178 : int rc;
179 :
180 : if (parent == NULL || child == NULL) {
181 : return -EINVAL;
182 : }
183 :
184 : if (child->parent != parent) {
185 : return -EINVAL;
186 : }
187 :
188 : rc = _fd_group_del_all(parent->epfd, child);
189 : if (rc < 0) {
190 : return rc;
191 : }
192 :
193 : child->parent = NULL;
194 :
195 : return _fd_group_add_all(child->epfd, child);
196 : }
197 :
198 : int
199 : spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
200 : {
201 : int rc;
202 :
203 : if (parent == NULL || child == NULL) {
204 : return -EINVAL;
205 : }
206 :
207 : if (child->parent) {
208 : return -EINVAL;
209 : }
210 :
211 : if (parent->parent) {
212 : /* More than one layer of nesting is not currently supported */
213 : assert(false);
214 : return -ENOTSUP;
215 : }
216 :
217 : rc = _fd_group_del_all(child->epfd, child);
218 : if (rc < 0) {
219 : return rc;
220 : }
221 :
222 : child->parent = parent;
223 :
224 : return _fd_group_add_all(parent->epfd, child);
225 : }
226 :
227 : int
228 : spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
229 : void *arg, const char *name)
230 : {
231 : return spdk_fd_group_add_for_events(fgrp, efd, EPOLLIN, fn, arg, name);
232 : }
233 :
234 : int
235 : spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events,
236 : spdk_fd_fn fn, void *arg, const char *name)
237 : {
238 : struct event_handler *ehdlr = NULL;
239 : struct epoll_event epevent = {0};
240 : int rc;
241 : int epfd;
242 :
243 : /* parameter checking */
244 : if (fgrp == NULL || efd < 0 || fn == NULL) {
245 : return -EINVAL;
246 : }
247 :
248 : /* check if there is already one function registered for this fd */
249 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
250 : if (ehdlr->fd == efd) {
251 : return -EEXIST;
252 : }
253 : }
254 :
255 : /* create a new event src */
256 : ehdlr = calloc(1, sizeof(*ehdlr));
257 : if (ehdlr == NULL) {
258 : return -errno;
259 : }
260 :
261 : ehdlr->fd = efd;
262 : ehdlr->fn = fn;
263 : ehdlr->fn_arg = arg;
264 : ehdlr->state = EVENT_HANDLER_STATE_WAITING;
265 : ehdlr->events = events;
266 : snprintf(ehdlr->name, sizeof(ehdlr->name), "%s", name);
267 :
268 : if (fgrp->parent) {
269 : epfd = fgrp->parent->epfd;
270 : } else {
271 : epfd = fgrp->epfd;
272 : }
273 :
274 : epevent.events = ehdlr->events;
275 : epevent.data.ptr = ehdlr;
276 : rc = epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent);
277 : if (rc < 0) {
278 : free(ehdlr);
279 : return -errno;
280 : }
281 :
282 : TAILQ_INSERT_TAIL(&fgrp->event_handlers, ehdlr, next);
283 : fgrp->num_fds++;
284 :
285 : return 0;
286 : }
287 :
288 : void
289 : spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
290 : {
291 : struct event_handler *ehdlr;
292 : int rc;
293 : int epfd;
294 :
295 : if (fgrp == NULL || efd < 0) {
296 : SPDK_ERRLOG("Invalid to remove efd(%d) from fd_group(%p).\n", efd, fgrp);
297 : assert(0);
298 : return;
299 : }
300 :
301 :
302 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
303 : if (ehdlr->fd == efd) {
304 : break;
305 : }
306 : }
307 :
308 : if (ehdlr == NULL) {
309 : SPDK_ERRLOG("efd(%d) is not existed in fgrp(%p)\n", efd, fgrp);
310 : return;
311 : }
312 :
313 : assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED);
314 :
315 : if (fgrp->parent) {
316 : epfd = fgrp->parent->epfd;
317 : } else {
318 : epfd = fgrp->epfd;
319 : }
320 :
321 : rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL);
322 : if (rc < 0) {
323 : SPDK_ERRLOG("Failed to delete the fd(%d) from the epoll group(%p)\n", efd, fgrp);
324 : return;
325 : }
326 :
327 : assert(fgrp->num_fds > 0);
328 : fgrp->num_fds--;
329 : TAILQ_REMOVE(&fgrp->event_handlers, ehdlr, next);
330 :
331 : /* Delay ehdlr's free in case it is waiting for execution in fgrp wait loop */
332 : if (ehdlr->state == EVENT_HANDLER_STATE_RUNNING) {
333 : ehdlr->state = EVENT_HANDLER_STATE_REMOVED;
334 : } else {
335 : free(ehdlr);
336 : }
337 : }
338 :
339 : int
340 : spdk_fd_group_event_modify(struct spdk_fd_group *fgrp,
341 : int efd, int event_types)
342 : {
343 : struct epoll_event epevent;
344 : struct event_handler *ehdlr;
345 : int epfd;
346 :
347 : if (fgrp == NULL || efd < 0) {
348 : return -EINVAL;
349 : }
350 :
351 : TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) {
352 : if (ehdlr->fd == efd) {
353 : break;
354 : }
355 : }
356 :
357 : if (ehdlr == NULL) {
358 : return -EINVAL;
359 : }
360 :
361 : assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED);
362 :
363 : ehdlr->events = event_types;
364 :
365 : if (fgrp->parent) {
366 : epfd = fgrp->parent->epfd;
367 : } else {
368 : epfd = fgrp->epfd;
369 : }
370 :
371 : epevent.events = ehdlr->events;
372 : epevent.data.ptr = ehdlr;
373 :
374 : return epoll_ctl(epfd, EPOLL_CTL_MOD, ehdlr->fd, &epevent);
375 : }
376 :
377 : int
378 : spdk_fd_group_create(struct spdk_fd_group **_egrp)
379 : {
380 : struct spdk_fd_group *fgrp;
381 :
382 : if (_egrp == NULL) {
383 : return -EINVAL;
384 : }
385 :
386 : fgrp = calloc(1, sizeof(*fgrp));
387 : if (fgrp == NULL) {
388 : return -ENOMEM;
389 : }
390 :
391 : /* init the event source head */
392 : TAILQ_INIT(&fgrp->event_handlers);
393 :
394 : fgrp->num_fds = 0;
395 : fgrp->epfd = epoll_create1(EPOLL_CLOEXEC);
396 : if (fgrp->epfd < 0) {
397 : free(fgrp);
398 : return -errno;
399 : }
400 :
401 : *_egrp = fgrp;
402 :
403 : return 0;
404 : }
405 :
406 : void
407 : spdk_fd_group_destroy(struct spdk_fd_group *fgrp)
408 : {
409 : if (fgrp == NULL || fgrp->num_fds > 0) {
410 : SPDK_ERRLOG("Invalid fd_group(%p) to destroy.\n", fgrp);
411 : assert(0);
412 : return;
413 : }
414 :
415 : close(fgrp->epfd);
416 : free(fgrp);
417 :
418 : return;
419 : }
420 :
421 : int
422 : spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
423 : {
424 : int totalfds = fgrp->num_fds;
425 : struct epoll_event events[totalfds];
426 : struct event_handler *ehdlr;
427 : int n;
428 : int nfds;
429 :
430 : if (fgrp->parent != NULL) {
431 : if (timeout < 0) {
432 : SPDK_ERRLOG("Calling spdk_fd_group_wait on a group nested in another group without a timeout will block indefinitely.\n");
433 : assert(false);
434 : return -EINVAL;
435 : } else {
436 : SPDK_WARNLOG("Calling spdk_fd_group_wait on a group nested in another group will never find any events\n");
437 : return 0;
438 : }
439 : }
440 :
441 : nfds = epoll_wait(fgrp->epfd, events, totalfds, timeout);
442 : if (nfds < 0) {
443 : if (errno != EINTR) {
444 : SPDK_ERRLOG("fgrp epoll_wait returns with fail. errno is %d\n", errno);
445 : }
446 :
447 : return -errno;
448 : } else if (nfds == 0) {
449 : return 0;
450 : }
451 :
452 : for (n = 0; n < nfds; n++) {
453 : /* find the event_handler */
454 : ehdlr = events[n].data.ptr;
455 :
456 : if (ehdlr == NULL) {
457 : continue;
458 : }
459 :
460 : /* Tag ehdlr as running state in case that it is removed
461 : * during this wait loop but before or when it get executed.
462 : */
463 : assert(ehdlr->state == EVENT_HANDLER_STATE_WAITING);
464 : ehdlr->state = EVENT_HANDLER_STATE_RUNNING;
465 : }
466 :
467 : for (n = 0; n < nfds; n++) {
468 : /* find the event_handler */
469 : ehdlr = events[n].data.ptr;
470 :
471 : if (ehdlr == NULL || ehdlr->fn == NULL) {
472 : continue;
473 : }
474 :
475 : /* It is possible that the ehdlr was removed
476 : * during this wait loop but before it get executed.
477 : */
478 : if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) {
479 : free(ehdlr);
480 : continue;
481 : }
482 :
483 : g_event = &events[n];
484 : /* call the interrupt response function */
485 : ehdlr->fn(ehdlr->fn_arg);
486 : g_event = NULL;
487 :
488 : /* It is possible that the ehdlr was removed
489 : * during this wait loop when it get executed.
490 : */
491 : if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) {
492 : free(ehdlr);
493 : } else {
494 : ehdlr->state = EVENT_HANDLER_STATE_WAITING;
495 : }
496 : }
497 :
498 : return nfds;
499 : }
500 :
501 : #else
502 :
503 : int
504 0 : spdk_fd_group_get_epoll_event(struct epoll_event *event)
505 : {
506 0 : return -ENOTSUP;
507 : }
508 :
509 : int
510 0 : spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
511 : void *arg, const char *name)
512 : {
513 0 : return -ENOTSUP;
514 : }
515 :
516 : int
517 0 : spdk_fd_group_add_for_events(struct spdk_fd_group *fgrp, int efd, uint32_t events, spdk_fd_fn fn,
518 : void *arg, const char *name)
519 : {
520 0 : return -ENOTSUP;
521 : }
522 :
523 : void
524 0 : spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
525 : {
526 0 : }
527 :
528 : int
529 0 : spdk_fd_group_event_modify(struct spdk_fd_group *fgrp,
530 : int efd, int event_types)
531 : {
532 0 : return -ENOTSUP;
533 : }
534 :
535 : int
536 0 : spdk_fd_group_create(struct spdk_fd_group **fgrp)
537 : {
538 0 : return -ENOTSUP;
539 : }
540 :
541 : void
542 0 : spdk_fd_group_destroy(struct spdk_fd_group *fgrp)
543 : {
544 0 : }
545 :
546 : int
547 0 : spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
548 : {
549 0 : return -ENOTSUP;
550 : }
551 :
552 : int
553 0 : spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
554 : {
555 0 : return -ENOTSUP;
556 : }
557 :
558 : int
559 0 : spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
560 : {
561 0 : return -ENOTSUP;
562 : }
563 :
564 : #endif
|