* A ref to kq (obtained via kqueue_acquire) must be held. */
| 1374 | * A ref to kq (obtained via kqueue_acquire) must be held. |
| 1375 | */ |
| 1376 | static int |
| 1377 | kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, |
| 1378 | int mflag) |
| 1379 | { |
| 1380 | struct filterops *fops; |
| 1381 | struct file *fp; |
| 1382 | struct knote *kn, *tkn; |
| 1383 | struct knlist *knl; |
| 1384 | int error, filt, event; |
| 1385 | int haskqglobal, filedesc_unlock; |
| 1386 | |
| 1387 | if ((kev->flags & (EV_ENABLE | EV_DISABLE)) == (EV_ENABLE | EV_DISABLE)) |
| 1388 | return (EINVAL); |
| 1389 | |
| 1390 | fp = NULL; |
| 1391 | kn = NULL; |
| 1392 | knl = NULL; |
| 1393 | error = 0; |
| 1394 | haskqglobal = 0; |
| 1395 | filedesc_unlock = 0; |
| 1396 | |
| 1397 | filt = kev->filter; |
| 1398 | fops = kqueue_fo_find(filt); |
| 1399 | if (fops == NULL) |
| 1400 | return EINVAL; |
| 1401 | |
| 1402 | if (kev->flags & EV_ADD) { |
| 1403 | /* |
| 1404 | * Prevent waiting with locks. Non-sleepable |
| 1405 | * allocation failures are handled in the loop, only |
| 1406 | * if the spare knote appears to be actually required. |
| 1407 | */ |
| 1408 | tkn = knote_alloc(mflag); |
| 1409 | } else { |
| 1410 | tkn = NULL; |
| 1411 | } |
| 1412 | |
| 1413 | findkn: |
| 1414 | if (fops->f_isfd) { |
| 1415 | KASSERT(td != NULL, ("td is NULL")); |
| 1416 | if (kev->ident > INT_MAX) |
| 1417 | error = EBADF; |
| 1418 | else |
| 1419 | error = fget(td, kev->ident, &cap_event_rights, &fp); |
| 1420 | if (error) |
| 1421 | goto done; |
| 1422 | |
| 1423 | if ((kev->flags & EV_ADD) == EV_ADD && kqueue_expand(kq, fops, |
| 1424 | kev->ident, M_NOWAIT) != 0) { |
| 1425 | /* try again */ |
| 1426 | fdrop(fp, td); |
| 1427 | fp = NULL; |
| 1428 | error = kqueue_expand(kq, fops, kev->ident, mflag); |
| 1429 | if (error) |
| 1430 | goto done; |
| 1431 | goto findkn; |
| 1432 | } |
| 1433 |
no test coverage detected