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