xref: /spdk/lib/util/fd_group.c (revision bf30e09abe1667ae2769aa367cde39c550bcac00)
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 spdk_fd_group_get_fd(struct spdk_fd_group *fgrp)
60 {
61 	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 spdk_fd_group_get_epoll_event(struct epoll_event *event)
505 {
506 	return -ENOTSUP;
507 }
508 
509 int
510 spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn,
511 		  void *arg, const char *name)
512 {
513 	return -ENOTSUP;
514 }
515 
516 int
517 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 	return -ENOTSUP;
521 }
522 
523 void
524 spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd)
525 {
526 }
527 
528 int
529 spdk_fd_group_event_modify(struct spdk_fd_group *fgrp,
530 			   int efd, int event_types)
531 {
532 	return -ENOTSUP;
533 }
534 
535 int
536 spdk_fd_group_create(struct spdk_fd_group **fgrp)
537 {
538 	return -ENOTSUP;
539 }
540 
541 void
542 spdk_fd_group_destroy(struct spdk_fd_group *fgrp)
543 {
544 }
545 
546 int
547 spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout)
548 {
549 	return -ENOTSUP;
550 }
551 
552 int
553 spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
554 {
555 	return -ENOTSUP;
556 }
557 
558 int
559 spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child)
560 {
561 	return -ENOTSUP;
562 }
563 
564 #endif
565