git: 66b107e82b2f - main - ctld: Use kevent(2) for socket events rather than select(2)
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 30 Jan 2025 15:49:11 UTC
The branch main has been updated by jhb:
URL: https://cgit.FreeBSD.org/src/commit/?id=66b107e82b2f4be2e9b648897e04ffd675a43469
commit 66b107e82b2f4be2e9b648897e04ffd675a43469
Author: John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-01-30 15:48:44 +0000
Commit: John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-01-30 15:48:44 +0000
ctld: Use kevent(2) for socket events rather than select(2)
Reviewed by: asomers
Sponsored by: Chelsio Communications
Differential Revision: https://reviews.freebsd.org/D48597
---
usr.sbin/ctld/ctld.c | 136 ++++++++++++++++++++++++++++-----------------------
1 file changed, 74 insertions(+), 62 deletions(-)
diff --git a/usr.sbin/ctld/ctld.c b/usr.sbin/ctld/ctld.c
index d5e4547179d9..06307d6cdd9a 100644
--- a/usr.sbin/ctld/ctld.c
+++ b/usr.sbin/ctld/ctld.c
@@ -30,6 +30,7 @@
*/
#include <sys/types.h>
+#include <sys/event.h>
#include <sys/nv.h>
#include <sys/time.h>
#include <sys/socket.h>
@@ -65,6 +66,7 @@ static volatile bool sighup_received = false;
static volatile bool sigterm_received = false;
static volatile bool sigalrm_received = false;
+static int kqfd;
static int nchildren = 0;
static uint16_t last_portal_group_tag = 0xff;
@@ -1781,10 +1783,31 @@ conf_verify(struct conf *conf)
return (0);
}
+static bool
+portal_reuse_socket(struct portal *oldp, struct portal *newp)
+{
+ struct kevent kev;
+
+ if (strcmp(newp->p_listen, oldp->p_listen) != 0)
+ return (false);
+
+ if (oldp->p_socket <= 0)
+ return (false);
+
+ EV_SET(&kev, oldp->p_socket, EVFILT_READ, EV_ADD, 0, 0, newp);
+ if (kevent(kqfd, &kev, 1, NULL, 0, NULL) == -1)
+ return (false);
+
+ newp->p_socket = oldp->p_socket;
+ oldp->p_socket = 0;
+ return (true);
+}
+
static bool
portal_init_socket(struct portal *p)
{
struct portal_group *pg = p->p_portal_group;
+ struct kevent kev;
int error, sockbuf;
int one = 1;
@@ -1870,6 +1893,14 @@ portal_init_socket(struct portal *p)
p->p_socket = 0;
return (false);
}
+ EV_SET(&kev, p->p_socket, EVFILT_READ, EV_ADD, 0, 0, p);
+ error = kevent(kqfd, &kev, 1, NULL, 0, NULL);
+ if (error == -1) {
+ log_warn("kevent(2) failed to register for %s", p->p_listen);
+ close(p->p_socket);
+ p->p_socket = 0;
+ return (false);
+ }
return (true);
}
@@ -2116,16 +2147,11 @@ conf_apply(struct conf *oldconf, struct conf *newconf)
pg_next) {
TAILQ_FOREACH(oldp, &oldpg->pg_portals,
p_next) {
- if (strcmp(newp->p_listen,
- oldp->p_listen) == 0 &&
- oldp->p_socket > 0) {
- newp->p_socket =
- oldp->p_socket;
- oldp->p_socket = 0;
- break;
- }
+ if (portal_reuse_socket(oldp, newp))
+ goto reused;
}
}
+ reused:
if (newp->p_socket > 0) {
/*
* We're done with this portal.
@@ -2354,26 +2380,10 @@ handle_connection(struct portal *portal, int fd,
exit(0);
}
-static int
-fd_add(int fd, fd_set *fdset, int nfds)
-{
-
- /*
- * Skip sockets which we failed to bind.
- */
- if (fd <= 0)
- return (nfds);
-
- FD_SET(fd, fdset);
- if (fd > nfds)
- nfds = fd;
- return (nfds);
-}
-
static void
main_loop(struct conf *conf, bool dont_fork)
{
- struct portal_group *pg;
+ struct kevent kev;
struct portal *portal;
struct sockaddr_storage client_sa;
socklen_t client_salen;
@@ -2381,8 +2391,7 @@ main_loop(struct conf *conf, bool dont_fork)
int connection_id;
int portal_id;
#endif
- fd_set fdset;
- int error, nfds, client_fd;
+ int error, client_fd;
pidfile_write(conf->conf_pidfh);
@@ -2417,38 +2426,34 @@ found:
#endif
assert(proxy_mode == false);
- FD_ZERO(&fdset);
- nfds = 0;
- TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- TAILQ_FOREACH(portal, &pg->pg_portals, p_next)
- nfds = fd_add(portal->p_socket, &fdset, nfds);
- }
- error = select(nfds + 1, &fdset, NULL, NULL, NULL);
- if (error <= 0) {
+ error = kevent(kqfd, NULL, 0, &kev, 1, NULL);
+ if (error == -1) {
if (errno == EINTR)
- return;
- log_err(1, "select");
+ continue;
+ log_err(1, "kevent");
}
- TAILQ_FOREACH(pg, &conf->conf_portal_groups, pg_next) {
- TAILQ_FOREACH(portal, &pg->pg_portals, p_next) {
- if (!FD_ISSET(portal->p_socket, &fdset))
- continue;
- client_salen = sizeof(client_sa);
- client_fd = accept(portal->p_socket,
- (struct sockaddr *)&client_sa,
- &client_salen);
- if (client_fd < 0) {
- if (errno == ECONNABORTED)
- continue;
- log_err(1, "accept");
- }
- assert(client_salen >= client_sa.ss_len);
- handle_connection(portal, client_fd,
- (struct sockaddr *)&client_sa,
- dont_fork);
- break;
+ switch (kev.filter) {
+ case EVFILT_READ:
+ portal = kev.udata;
+ assert(portal->p_socket == (int)kev.ident);
+
+ client_salen = sizeof(client_sa);
+ client_fd = accept(portal->p_socket,
+ (struct sockaddr *)&client_sa,
+ &client_salen);
+ if (client_fd < 0) {
+ if (errno == ECONNABORTED)
+ continue;
+ log_err(1, "accept");
}
+ assert(client_salen >= client_sa.ss_len);
+
+ handle_connection(portal, client_fd,
+ (struct sockaddr *)&client_sa, dont_fork);
+ break;
+ default:
+ __assert_unreachable();
}
#ifdef ICL_KERNEL_PROXY
}
@@ -2734,13 +2739,6 @@ main(int argc, char **argv)
if (new_pports_from_conf(newconf, &kports))
log_errx(1, "Error associating physical ports; exiting");
- error = conf_apply(oldconf, newconf);
- if (error != 0)
- log_errx(1, "failed to apply configuration; exiting");
-
- conf_delete(oldconf);
- oldconf = NULL;
-
if (dont_daemonize == false) {
log_debugx("daemonizing");
if (daemon(0, 0) == -1) {
@@ -2750,6 +2748,20 @@ main(int argc, char **argv)
}
}
+ kqfd = kqueue();
+ if (kqfd == -1) {
+ log_warn("Cannot create kqueue");
+ pidfile_remove(newconf->conf_pidfh);
+ exit(1);
+ }
+
+ error = conf_apply(oldconf, newconf);
+ if (error != 0)
+ log_errx(1, "failed to apply configuration; exiting");
+
+ conf_delete(oldconf);
+ oldconf = NULL;
+
/* Schedule iSNS update */
if (!TAILQ_EMPTY(&newconf->conf_isns))
set_timeout((newconf->conf_isns_period + 2) / 3, false);