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 struct event_handler *ehdlr = NULL; 232 struct epoll_event epevent = {0}; 233 int rc; 234 int epfd; 235 236 /* parameter checking */ 237 if (fgrp == NULL || efd < 0 || fn == NULL) { 238 return -EINVAL; 239 } 240 241 /* check if there is already one function registered for this fd */ 242 TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) { 243 if (ehdlr->fd == efd) { 244 return -EEXIST; 245 } 246 } 247 248 /* create a new event src */ 249 ehdlr = calloc(1, sizeof(*ehdlr)); 250 if (ehdlr == NULL) { 251 return -errno; 252 } 253 254 ehdlr->fd = efd; 255 ehdlr->fn = fn; 256 ehdlr->fn_arg = arg; 257 ehdlr->state = EVENT_HANDLER_STATE_WAITING; 258 ehdlr->events = EPOLLIN; 259 snprintf(ehdlr->name, sizeof(ehdlr->name), "%s", name); 260 261 if (fgrp->parent) { 262 epfd = fgrp->parent->epfd; 263 } else { 264 epfd = fgrp->epfd; 265 } 266 267 epevent.events = ehdlr->events; 268 epevent.data.ptr = ehdlr; 269 rc = epoll_ctl(epfd, EPOLL_CTL_ADD, efd, &epevent); 270 if (rc < 0) { 271 free(ehdlr); 272 return -errno; 273 } 274 275 TAILQ_INSERT_TAIL(&fgrp->event_handlers, ehdlr, next); 276 fgrp->num_fds++; 277 278 return 0; 279 } 280 281 void 282 spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd) 283 { 284 struct event_handler *ehdlr; 285 int rc; 286 int epfd; 287 288 if (fgrp == NULL || efd < 0) { 289 SPDK_ERRLOG("Invalid to remvoe efd(%d) from fd_group(%p).\n", efd, fgrp); 290 assert(0); 291 return; 292 } 293 294 295 TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) { 296 if (ehdlr->fd == efd) { 297 break; 298 } 299 } 300 301 if (ehdlr == NULL) { 302 SPDK_ERRLOG("efd(%d) is not existed in fgrp(%p)\n", efd, fgrp); 303 return; 304 } 305 306 assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED); 307 308 if (fgrp->parent) { 309 epfd = fgrp->parent->epfd; 310 } else { 311 epfd = fgrp->epfd; 312 } 313 314 rc = epoll_ctl(epfd, EPOLL_CTL_DEL, ehdlr->fd, NULL); 315 if (rc < 0) { 316 SPDK_ERRLOG("Failed to delete the fd(%d) from the epoll group(%p)\n", efd, fgrp); 317 return; 318 } 319 320 assert(fgrp->num_fds > 0); 321 fgrp->num_fds--; 322 TAILQ_REMOVE(&fgrp->event_handlers, ehdlr, next); 323 324 /* Delay ehdlr's free in case it is waiting for execution in fgrp wait loop */ 325 if (ehdlr->state == EVENT_HANDLER_STATE_RUNNING) { 326 ehdlr->state = EVENT_HANDLER_STATE_REMOVED; 327 } else { 328 free(ehdlr); 329 } 330 } 331 332 int 333 spdk_fd_group_event_modify(struct spdk_fd_group *fgrp, 334 int efd, int event_types) 335 { 336 struct epoll_event epevent; 337 struct event_handler *ehdlr; 338 int epfd; 339 340 if (fgrp == NULL || efd < 0) { 341 return -EINVAL; 342 } 343 344 TAILQ_FOREACH(ehdlr, &fgrp->event_handlers, next) { 345 if (ehdlr->fd == efd) { 346 break; 347 } 348 } 349 350 if (ehdlr == NULL) { 351 return -EINVAL; 352 } 353 354 assert(ehdlr->state != EVENT_HANDLER_STATE_REMOVED); 355 356 ehdlr->events = event_types; 357 358 if (fgrp->parent) { 359 epfd = fgrp->parent->epfd; 360 } else { 361 epfd = fgrp->epfd; 362 } 363 364 epevent.events = ehdlr->events; 365 epevent.data.ptr = ehdlr; 366 367 return epoll_ctl(epfd, EPOLL_CTL_MOD, ehdlr->fd, &epevent); 368 } 369 370 int 371 spdk_fd_group_create(struct spdk_fd_group **_egrp) 372 { 373 struct spdk_fd_group *fgrp; 374 375 if (_egrp == NULL) { 376 return -EINVAL; 377 } 378 379 fgrp = calloc(1, sizeof(*fgrp)); 380 if (fgrp == NULL) { 381 return -ENOMEM; 382 } 383 384 /* init the event source head */ 385 TAILQ_INIT(&fgrp->event_handlers); 386 387 fgrp->num_fds = 0; 388 fgrp->epfd = epoll_create1(EPOLL_CLOEXEC); 389 if (fgrp->epfd < 0) { 390 free(fgrp); 391 return -errno; 392 } 393 394 *_egrp = fgrp; 395 396 return 0; 397 } 398 399 void 400 spdk_fd_group_destroy(struct spdk_fd_group *fgrp) 401 { 402 if (fgrp == NULL || fgrp->num_fds > 0) { 403 SPDK_ERRLOG("Invalid fd_group(%p) to destroy.\n", fgrp); 404 assert(0); 405 return; 406 } 407 408 close(fgrp->epfd); 409 free(fgrp); 410 411 return; 412 } 413 414 int 415 spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout) 416 { 417 int totalfds = fgrp->num_fds; 418 struct epoll_event events[totalfds]; 419 struct event_handler *ehdlr; 420 int n; 421 int nfds; 422 423 if (fgrp->parent != NULL) { 424 if (timeout < 0) { 425 SPDK_ERRLOG("Calling spdk_fd_group_wait on a group nested in another group without a timeout will block indefinitely.\n"); 426 assert(false); 427 return -EINVAL; 428 } else { 429 SPDK_WARNLOG("Calling spdk_fd_group_wait on a group nested in another group will never find any events\n"); 430 return 0; 431 } 432 } 433 434 nfds = epoll_wait(fgrp->epfd, events, totalfds, timeout); 435 if (nfds < 0) { 436 if (errno != EINTR) { 437 SPDK_ERRLOG("fgrp epoll_wait returns with fail. errno is %d\n", errno); 438 } 439 440 return -errno; 441 } else if (nfds == 0) { 442 return 0; 443 } 444 445 for (n = 0; n < nfds; n++) { 446 /* find the event_handler */ 447 ehdlr = events[n].data.ptr; 448 449 if (ehdlr == NULL) { 450 continue; 451 } 452 453 /* Tag ehdlr as running state in case that it is removed 454 * during this wait loop but before or when it get executed. 455 */ 456 assert(ehdlr->state == EVENT_HANDLER_STATE_WAITING); 457 ehdlr->state = EVENT_HANDLER_STATE_RUNNING; 458 } 459 460 for (n = 0; n < nfds; n++) { 461 /* find the event_handler */ 462 ehdlr = events[n].data.ptr; 463 464 if (ehdlr == NULL || ehdlr->fn == NULL) { 465 continue; 466 } 467 468 /* It is possible that the ehdlr was removed 469 * during this wait loop but before it get executed. 470 */ 471 if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) { 472 free(ehdlr); 473 continue; 474 } 475 476 g_event = &events[n]; 477 /* call the interrupt response function */ 478 ehdlr->fn(ehdlr->fn_arg); 479 g_event = NULL; 480 481 /* It is possible that the ehdlr was removed 482 * during this wait loop when it get executed. 483 */ 484 if (ehdlr->state == EVENT_HANDLER_STATE_REMOVED) { 485 free(ehdlr); 486 } else { 487 ehdlr->state = EVENT_HANDLER_STATE_WAITING; 488 } 489 } 490 491 return nfds; 492 } 493 494 #else 495 496 int 497 spdk_fd_group_get_epoll_event(struct epoll_event *event) 498 { 499 return -ENOTSUP; 500 } 501 502 int 503 spdk_fd_group_add(struct spdk_fd_group *fgrp, int efd, spdk_fd_fn fn, 504 void *arg, const char *name) 505 { 506 return -ENOTSUP; 507 } 508 509 void 510 spdk_fd_group_remove(struct spdk_fd_group *fgrp, int efd) 511 { 512 } 513 514 int 515 spdk_fd_group_event_modify(struct spdk_fd_group *fgrp, 516 int efd, int event_types) 517 { 518 return -ENOTSUP; 519 } 520 521 int 522 spdk_fd_group_create(struct spdk_fd_group **fgrp) 523 { 524 return -ENOTSUP; 525 } 526 527 void 528 spdk_fd_group_destroy(struct spdk_fd_group *fgrp) 529 { 530 } 531 532 int 533 spdk_fd_group_wait(struct spdk_fd_group *fgrp, int timeout) 534 { 535 return -ENOTSUP; 536 } 537 538 int 539 spdk_fd_group_unnest(struct spdk_fd_group *parent, struct spdk_fd_group *child) 540 { 541 return -ENOTSUP; 542 } 543 544 int 545 spdk_fd_group_nest(struct spdk_fd_group *parent, struct spdk_fd_group *child) 546 { 547 return -ENOTSUP; 548 } 549 550 #endif 551