* Expand the kq to make sure we have storage for fops/ident pair. * * Return 0 on success (or no work necessary), return errno on failure. */
| 1694 | * Return 0 on success (or no work necessary), return errno on failure. |
| 1695 | */ |
| 1696 | static int |
| 1697 | kqueue_expand(struct kqueue *kq, struct filterops *fops, uintptr_t ident, |
| 1698 | int mflag) |
| 1699 | { |
| 1700 | struct klist *list, *tmp_knhash, *to_free; |
| 1701 | u_long tmp_knhashmask; |
| 1702 | int error, fd, size; |
| 1703 | |
| 1704 | KQ_NOTOWNED(kq); |
| 1705 | |
| 1706 | error = 0; |
| 1707 | to_free = NULL; |
| 1708 | if (fops->f_isfd) { |
| 1709 | fd = ident; |
| 1710 | if (kq->kq_knlistsize <= fd) { |
| 1711 | size = kq->kq_knlistsize; |
| 1712 | while (size <= fd) |
| 1713 | size += KQEXTENT; |
| 1714 | list = malloc(size * sizeof(*list), M_KQUEUE, mflag); |
| 1715 | if (list == NULL) |
| 1716 | return ENOMEM; |
| 1717 | KQ_LOCK(kq); |
| 1718 | if ((kq->kq_state & KQ_CLOSING) != 0) { |
| 1719 | to_free = list; |
| 1720 | error = EBADF; |
| 1721 | } else if (kq->kq_knlistsize > fd) { |
| 1722 | to_free = list; |
| 1723 | } else { |
| 1724 | if (kq->kq_knlist != NULL) { |
| 1725 | bcopy(kq->kq_knlist, list, |
| 1726 | kq->kq_knlistsize * sizeof(*list)); |
| 1727 | to_free = kq->kq_knlist; |
| 1728 | kq->kq_knlist = NULL; |
| 1729 | } |
| 1730 | bzero((caddr_t)list + |
| 1731 | kq->kq_knlistsize * sizeof(*list), |
| 1732 | (size - kq->kq_knlistsize) * sizeof(*list)); |
| 1733 | kq->kq_knlistsize = size; |
| 1734 | kq->kq_knlist = list; |
| 1735 | } |
| 1736 | KQ_UNLOCK(kq); |
| 1737 | } |
| 1738 | } else { |
| 1739 | if (kq->kq_knhashmask == 0) { |
| 1740 | tmp_knhash = hashinit_flags(KN_HASHSIZE, M_KQUEUE, |
| 1741 | &tmp_knhashmask, (mflag & M_WAITOK) != 0 ? |
| 1742 | HASH_WAITOK : HASH_NOWAIT); |
| 1743 | if (tmp_knhash == NULL) |
| 1744 | return (ENOMEM); |
| 1745 | KQ_LOCK(kq); |
| 1746 | if ((kq->kq_state & KQ_CLOSING) != 0) { |
| 1747 | to_free = tmp_knhash; |
| 1748 | error = EBADF; |
| 1749 | } else if (kq->kq_knhashmask == 0) { |
| 1750 | kq->kq_knhash = tmp_knhash; |
| 1751 | kq->kq_knhashmask = tmp_knhashmask; |
| 1752 | } else { |
| 1753 | to_free = tmp_knhash; |
no test coverage detected