From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202512 header.b=jODLj9KT; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 3CE0F5A0623 for ; Fri, 09 Jan 2026 00:34:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202512; t=1767915239; bh=234iiQkmgsZ3cv0mWripb2/SLxWeQNmHwwO73EMM+Yo=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=jODLj9KTZqmbvIrAqCjmy65Okyp0wV2S7wgurDFoOF8YZeWmgOc1wWeoW0XGEJ/Ds AhyBG2KaK/wvDmryIyC5HzKrgYYmPO+/q3bgaAeZvOlBavlxEJiFYtE15GkWhun0JE LN+1qwVLgX6LjoIeL5/pPXsWzs1i3QqDv6KvXNOfKufZzDiEhDPf890qUFHxlJY6uC tXEPFO5Ngre6FAV5vD7S5fL2NNwPzB1BGSRaH7YFbyDEkQD19HP0Xo6k6hGV//t1XG lGEQUF74wltxyXQVbrXpsq1Hy58ENJubtgpn2vt2nBxBFZyemS3v7CN7cUDb1jNcEB wL6sofNWaEYeA== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4dnLnz6MSbz4wRG; Fri, 09 Jan 2026 10:33:59 +1100 (AEDT) Date: Fri, 9 Jan 2026 10:33:55 +1100 From: David Gibson To: Laurent Vivier Subject: Re: [PATCH v2 5/5] flow: Introduce flow_epoll_set() to centralize epoll operations Message-ID: References: <20260108140119.1204797-1-lvivier@redhat.com> <20260108140119.1204797-6-lvivier@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha512; protocol="application/pgp-signature"; boundary="oIhO7wCta1UTVS//" Content-Disposition: inline In-Reply-To: <20260108140119.1204797-6-lvivier@redhat.com> Message-ID-Hash: QWG7EEZZMHFGZAQKWD6FWEWWU4TBP64U X-Message-ID-Hash: QWG7EEZZMHFGZAQKWD6FWEWWU4TBP64U X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --oIhO7wCta1UTVS// Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Thu, Jan 08, 2026 at 03:01:19PM +0100, Laurent Vivier wrote: > Currently, each flow type (TCP, TCP_SPLICE, PING, UDP) has its own > code to add or modify file descriptors in epoll. This leads to > duplicated boilerplate code across icmp.c, tcp.c, tcp_splice.c, and > udp_flow.c, each setting up epoll_ref unions and calling epoll_ctl() > with flow-type-specific details. >=20 > Introduce flow_epoll_set() in flow.c to handle epoll operations for > all flow types in a unified way. The function takes an explicit epoll > type parameter, allowing it to handle not only flow socket types but > also the TCP timer (EPOLL_TYPE_TCP_TIMER). >=20 > This will be needed to migrate queue pair from an epollfd to another. >=20 > Signed-off-by: Laurent Vivier I'm not totally convinced if folding in TCP timers with the socket fds makes sense. I think there's still room for improving consistency of the epoll lifecycle (removing the in_epoll flag equivalent). But both of those can be looked at later. So, Reviewed-by: David Gibson > --- > flow.c | 33 ++++++++++++++++++++ > flow.h | 3 ++ > icmp.c | 11 +++---- > tcp.c | 64 ++++++++++++++++++++------------------ > tcp_splice.c | 86 +++++++++++++++++++++++++--------------------------- > udp_flow.c | 12 +++----- > 6 files changed, 119 insertions(+), 90 deletions(-) >=20 > diff --git a/flow.c b/flow.c > index 4f53486586cd..73d24f9d3765 100644 > --- a/flow.c > +++ b/flow.c > @@ -20,6 +20,7 @@ > #include "flow.h" > #include "flow_table.h" > #include "repair.h" > +#include "epoll_ctl.h" > =20 > const char *flow_state_str[] =3D { > [FLOW_STATE_FREE] =3D "FREE", > @@ -390,6 +391,38 @@ void flow_epollid_clear(struct flow_common *f) > f->epollid =3D EPOLLFD_ID_INVALID; > } > =20 > +/** > + * flow_epoll_set() - Add or modify epoll registration for a flow socket > + * @command: epoll_ctl() command: EPOLL_CTL_ADD or EPOLL_CTL_MOD > + * @type: epoll type > + * @f: Flow to register socket for > + * @events: epoll events to watch for > + * @fd: File descriptor to register > + * @sidei: Side index of the flow > + * > + * Return: 0 on success, -1 on error (from epoll_ctl()) > + */ > +int flow_epoll_set(int command, enum epoll_type type, > + const struct flow_common *f, uint32_t events, int fd, > + unsigned int sidei) > +{ > + struct epoll_event ev; > + union epoll_ref ref; > + > + ref.type =3D type; > + ref.fd =3D fd; > + > + if (type =3D=3D EPOLL_TYPE_TCP_TIMER) > + ref.flow =3D flow_idx(f); > + else > + ref.flowside =3D flow_sidx(f, sidei); > + > + ev.events =3D events; > + ev.data.u64 =3D ref.u64; > + > + return epoll_ctl(flow_epollfd(f), command, fd, &ev); > +} > + > /** > * flow_epollid_register() - Initialize the epoll id -> fd mapping > * @epollid: epoll id to associate to > diff --git a/flow.h b/flow.h > index b43b0b1dd7f2..bd5c6d90322b 100644 > --- a/flow.h > +++ b/flow.h > @@ -265,6 +265,9 @@ bool flow_in_epoll(const struct flow_common *f); > int flow_epollfd(const struct flow_common *f); > void flow_epollid_set(struct flow_common *f, int epollid); > void flow_epollid_clear(struct flow_common *f); > +int flow_epoll_set(int command, enum epoll_type type, > + const struct flow_common *f, uint32_t events, int fd, > + unsigned int sidei); > void flow_epollid_register(int epollid, int epollfd); > void flow_defer_handler(const struct ctx *c, const struct timespec *now); > int flow_migrate_source_early(struct ctx *c, const struct migrate_stage = *stage, > diff --git a/icmp.c b/icmp.c > index 9564c4963f7b..b6bb36d80715 100644 > --- a/icmp.c > +++ b/icmp.c > @@ -177,7 +177,6 @@ static struct icmp_ping_flow *icmp_ping_new(const str= uct ctx *c, > union flow *flow =3D flow_alloc(); > struct icmp_ping_flow *pingf; > const struct flowside *tgt; > - union epoll_ref ref; > =20 > if (!flow) > return NULL; > @@ -211,13 +210,11 @@ static struct icmp_ping_flow *icmp_ping_new(const s= truct ctx *c, > goto cancel; > =20 > flow_epollid_set(&pingf->f, EPOLLFD_ID_DEFAULT); > - > - ref.type =3D EPOLL_TYPE_PING; > - ref.flowside =3D FLOW_SIDX(flow, TGTSIDE); > - ref.fd =3D pingf->sock; > - > - if (epoll_add(flow_epollfd(&pingf->f), EPOLLIN, ref) < 0) { > + if (flow_epoll_set(EPOLL_CTL_ADD, EPOLL_TYPE_PING, &pingf->f, > + EPOLLIN, pingf->sock, > + TGTSIDE) < 0) { > close(pingf->sock); > + flow_epollid_clear(&pingf->f); > goto cancel; > } > =20 > diff --git a/tcp.c b/tcp.c > index 5141cdc7e839..d8cc11b377de 100644 > --- a/tcp.c > +++ b/tcp.c > @@ -523,34 +523,44 @@ static uint32_t tcp_conn_epoll_events(uint8_t event= s, uint8_t conn_flags) > =20 > /** > * tcp_epoll_ctl() - Add/modify/delete epoll state from connection events > - * @c: Execution context > * @conn: Connection pointer > * > * Return: 0 on success, negative error code on failure (not on deletion) > */ > -static int tcp_epoll_ctl(const struct ctx *c, struct tcp_tap_conn *conn) > +static int tcp_epoll_ctl(struct tcp_tap_conn *conn) > { > - int m =3D flow_in_epoll(&conn->f) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; > - union epoll_ref ref =3D { .type =3D EPOLL_TYPE_TCP, .fd =3D conn->sock, > - .flowside =3D FLOW_SIDX(conn, !TAPSIDE(conn)), }; > - struct epoll_event ev =3D { .data.u64 =3D ref.u64 }; > - int epollfd =3D flow_in_epoll(&conn->f) ? flow_epollfd(&conn->f) > - : c->epollfd; > + uint32_t events; > + int m; > =20 > if (conn->events =3D=3D CLOSED) { > - if (flow_in_epoll(&conn->f)) > + if (flow_in_epoll(&conn->f)) { > + int epollfd =3D flow_epollfd(&conn->f); > + > epoll_del(epollfd, conn->sock); > - if (conn->timer !=3D -1) > - epoll_del(epollfd, conn->timer); > + if (conn->timer !=3D -1) > + epoll_del(epollfd, conn->timer); > + } > + > return 0; > } > =20 > - ev.events =3D tcp_conn_epoll_events(conn->events, conn->flags); > + events =3D tcp_conn_epoll_events(conn->events, conn->flags); > =20 > - if (epoll_ctl(epollfd, m, conn->sock, &ev)) > - return -errno; > + if (flow_in_epoll(&conn->f)) { > + m =3D EPOLL_CTL_MOD; > + } else { > + flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT); > + m =3D EPOLL_CTL_ADD; > + } > + > + if (flow_epoll_set(m, EPOLL_TYPE_TCP, &conn->f, events, conn->sock, > + !TAPSIDE(conn)) < 0) { > + int ret =3D -errno; > =20 > - flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT); > + if (m =3D=3D EPOLL_CTL_ADD) > + flow_epollid_clear(&conn->f); > + return ret; > + } > =20 > return 0; > } > @@ -569,11 +579,6 @@ static void tcp_timer_ctl(const struct ctx *c, struc= t tcp_tap_conn *conn) > return; > =20 > if (conn->timer =3D=3D -1) { > - union epoll_ref ref =3D { .type =3D EPOLL_TYPE_TCP_TIMER, > - .flow =3D FLOW_IDX(conn) }; > - struct epoll_event ev =3D { .data.u64 =3D ref.u64, > - .events =3D EPOLLIN | EPOLLET }; > - int epollfd =3D flow_epollfd(&conn->f); > int fd; > =20 > fd =3D timerfd_create(CLOCK_MONOTONIC, 0); > @@ -581,18 +586,17 @@ static void tcp_timer_ctl(const struct ctx *c, stru= ct tcp_tap_conn *conn) > flow_dbg_perror(conn, "failed to get timer"); > if (fd > -1) > close(fd); > - conn->timer =3D -1; > return; > } > - conn->timer =3D fd; > - ref.fd =3D conn->timer; > =20 > - if (epoll_ctl(epollfd, EPOLL_CTL_ADD, conn->timer, &ev)) { > + if (flow_epoll_set(EPOLL_CTL_ADD, EPOLL_TYPE_TCP_TIMER, > + &conn->f, EPOLLIN | EPOLLET, fd, 0) < 0) { > flow_dbg_perror(conn, "failed to add timer"); > - close(conn->timer); > - conn->timer =3D -1; > + close(fd); > return; > } > + > + conn->timer =3D fd; > } > =20 > if (conn->flags & ACK_TO_TAP_DUE) { > @@ -669,7 +673,7 @@ void conn_flag_do(const struct ctx *c, struct tcp_tap= _conn *conn, > } > =20 > if (flag =3D=3D STALLED || flag =3D=3D ~STALLED) > - tcp_epoll_ctl(c, conn); > + tcp_epoll_ctl(conn); > =20 > if (flag =3D=3D ACK_FROM_TAP_DUE || flag =3D=3D ACK_TO_TAP_DUE || > (flag =3D=3D ~ACK_FROM_TAP_DUE && (conn->flags & ACK_TO_TAP_DUE)) || > @@ -726,7 +730,7 @@ void conn_event_do(const struct ctx *c, struct tcp_ta= p_conn *conn, > } else { > if (event =3D=3D CLOSED) > flow_hash_remove(c, TAP_SIDX(conn)); > - tcp_epoll_ctl(c, conn); > + tcp_epoll_ctl(conn); > } > =20 > if (CONN_HAS(conn, SOCK_FIN_SENT | TAP_FIN_ACKED)) > @@ -1742,7 +1746,7 @@ static void tcp_conn_from_tap(const struct ctx *c, = sa_family_t af, > conn_event(c, conn, TAP_SYN_ACK_SENT); > } > =20 > - tcp_epoll_ctl(c, conn); > + tcp_epoll_ctl(conn); > =20 > if (c->mode =3D=3D MODE_VU) { /* To rebind to same oport after migratio= n */ > socklen_t sl =3D sizeof(sa); > @@ -3984,7 +3988,7 @@ int tcp_flow_migrate_target_ext(struct ctx *c, stru= ct tcp_tap_conn *conn, int fd > tcp_send_flag(c, conn, ACK); > tcp_data_from_sock(c, conn); > =20 > - if ((rc =3D tcp_epoll_ctl(c, conn))) { > + if ((rc =3D tcp_epoll_ctl(conn))) { > flow_dbg(conn, > "Failed to subscribe to epoll for migrated socket: %s", > strerror_(-rc)); > diff --git a/tcp_splice.c b/tcp_splice.c > index bf4ff466de07..26e9845c39ee 100644 > --- a/tcp_splice.c > +++ b/tcp_splice.c > @@ -135,37 +135,35 @@ static uint32_t tcp_splice_conn_epoll_events(uint16= _t events, unsigned sidei) > =20 > /** > * tcp_splice_epoll_ctl() - Add/modify/delete epoll state from connectio= n events > - * @c: Execution context > * @conn: Connection pointer > * > * Return: 0 on success, negative error code on failure (not on deletion) > */ > -static int tcp_splice_epoll_ctl(const struct ctx *c, > - struct tcp_splice_conn *conn) > +static int tcp_splice_epoll_ctl(struct tcp_splice_conn *conn) > { > - int epollfd =3D flow_in_epoll(&conn->f) ? flow_epollfd(&conn->f) > - : c->epollfd; > - int m =3D flow_in_epoll(&conn->f) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; > - const union epoll_ref ref[SIDES] =3D { > - { .type =3D EPOLL_TYPE_TCP_SPLICE, .fd =3D conn->s[0], > - .flowside =3D FLOW_SIDX(conn, 0) }, > - { .type =3D EPOLL_TYPE_TCP_SPLICE, .fd =3D conn->s[1], > - .flowside =3D FLOW_SIDX(conn, 1) } > - }; > - struct epoll_event ev[SIDES] =3D { { .data.u64 =3D ref[0].u64 }, > - { .data.u64 =3D ref[1].u64 } }; > - > - ev[0].events =3D tcp_splice_conn_epoll_events(conn->events, 0); > - ev[1].events =3D tcp_splice_conn_epoll_events(conn->events, 1); > - > - > - if (epoll_ctl(epollfd, m, conn->s[0], &ev[0]) || > - epoll_ctl(epollfd, m, conn->s[1], &ev[1])) { > + uint32_t events[2]; > + int m; > + > + if (flow_in_epoll(&conn->f)) { > + m =3D EPOLL_CTL_MOD; > + } else { > + flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT); > + m =3D EPOLL_CTL_ADD; > + } > + > + events[0] =3D tcp_splice_conn_epoll_events(conn->events, 0); > + events[1] =3D tcp_splice_conn_epoll_events(conn->events, 1); > + > + if (flow_epoll_set(m, EPOLL_TYPE_TCP_SPLICE, &conn->f, events[0], > + conn->s[0], 0) || > + flow_epoll_set(m, EPOLL_TYPE_TCP_SPLICE, &conn->f, events[1], > + conn->s[1], 1)) { > int ret =3D -errno; > flow_perror(conn, "ERROR on epoll_ctl()"); > + if (m =3D=3D EPOLL_CTL_ADD) > + flow_epollid_clear(&conn->f); > return ret; > } > - flow_epollid_set(&conn->f, EPOLLFD_ID_DEFAULT); > =20 > return 0; > } > @@ -205,7 +203,7 @@ static void conn_flag_do(struct tcp_splice_conn *conn, > } > } > =20 > -#define conn_flag(c, conn, flag) \ > +#define conn_flag(conn, flag) \ > do { \ > flow_trace(conn, "flag at %s:%i", __func__, __LINE__); \ > conn_flag_do(conn, flag); \ > @@ -213,12 +211,10 @@ static void conn_flag_do(struct tcp_splice_conn *co= nn, > =20 > /** > * conn_event_do() - Set and log connection events, update epoll state > - * @c: Execution context > * @conn: Connection pointer > * @event: Connection event > */ > -static void conn_event_do(const struct ctx *c, struct tcp_splice_conn *c= onn, > - unsigned long event) > +static void conn_event_do(struct tcp_splice_conn *conn, unsigned long ev= ent) > { > if (event & (event - 1)) { > int flag_index =3D fls(~event); > @@ -240,14 +236,14 @@ static void conn_event_do(const struct ctx *c, stru= ct tcp_splice_conn *conn, > flow_dbg(conn, "%s", tcp_splice_event_str[flag_index]); > } > =20 > - if (tcp_splice_epoll_ctl(c, conn)) > - conn_flag(c, conn, CLOSING); > + if (tcp_splice_epoll_ctl(conn)) > + conn_flag(conn, CLOSING); > } > =20 > -#define conn_event(c, conn, event) \ > +#define conn_event(conn, event) \ > do { \ > flow_trace(conn, "event at %s:%i",__func__, __LINE__); \ > - conn_event_do(c, conn, event); \ > + conn_event_do(conn, event); \ > } while (0) > =20 > =20 > @@ -315,7 +311,7 @@ static int tcp_splice_connect_finish(const struct ctx= *c, > if (pipe2(conn->pipe[sidei], O_NONBLOCK | O_CLOEXEC)) { > flow_perror(conn, "cannot create %d->%d pipe", > sidei, !sidei); > - conn_flag(c, conn, CLOSING); > + conn_flag(conn, CLOSING); > return -EIO; > } > =20 > @@ -329,7 +325,7 @@ static int tcp_splice_connect_finish(const struct ctx= *c, > } > =20 > if (!(conn->events & SPLICE_ESTABLISHED)) > - conn_event(c, conn, SPLICE_ESTABLISHED); > + conn_event(conn, SPLICE_ESTABLISHED); > =20 > return 0; > } > @@ -376,7 +372,7 @@ static int tcp_splice_connect(const struct ctx *c, st= ruct tcp_splice_conn *conn) > =20 > pif_sockaddr(c, &sa, tgtpif, &tgt->eaddr, tgt->eport); > =20 > - conn_event(c, conn, SPLICE_CONNECT); > + conn_event(conn, SPLICE_CONNECT); > =20 > if (connect(conn->s[1], &sa.sa, socklen_inany(&sa))) { > if (errno !=3D EINPROGRESS) { > @@ -385,7 +381,7 @@ static int tcp_splice_connect(const struct ctx *c, st= ruct tcp_splice_conn *conn) > return -errno; > } > } else { > - conn_event(c, conn, SPLICE_ESTABLISHED); > + conn_event(conn, SPLICE_ESTABLISHED); > return tcp_splice_connect_finish(c, conn); > } > =20 > @@ -445,7 +441,7 @@ void tcp_splice_conn_from_sock(const struct ctx *c, u= nion flow *flow, int s0) > flow_trace(conn, "failed to set TCP_QUICKACK on %i", s0); > =20 > if (tcp_splice_connect(c, conn)) > - conn_flag(c, conn, CLOSING); > + conn_flag(conn, CLOSING); > =20 > FLOW_ACTIVATE(conn); > } > @@ -494,14 +490,14 @@ void tcp_splice_sock_handler(struct ctx *c, union e= poll_ref ref, > =20 > if (events & EPOLLOUT) { > fromsidei =3D !evsidei; > - conn_event(c, conn, ~OUT_WAIT(evsidei)); > + conn_event(conn, ~OUT_WAIT(evsidei)); > } else { > fromsidei =3D evsidei; > } > =20 > if (events & EPOLLRDHUP) > /* For side 0 this is fake, but implied */ > - conn_event(c, conn, FIN_RCVD(evsidei)); > + conn_event(conn, FIN_RCVD(evsidei)); > =20 > swap: > eof =3D 0; > @@ -536,7 +532,7 @@ retry: > more =3D SPLICE_F_MORE; > =20 > if (conn->flags & lowat_set_flag) > - conn_flag(c, conn, lowat_act_flag); > + conn_flag(conn, lowat_act_flag); > } > =20 > do > @@ -568,8 +564,8 @@ retry: > "Setting SO_RCVLOWAT %i: %s", > lowat, strerror_(errno)); > } else { > - conn_flag(c, conn, lowat_set_flag); > - conn_flag(c, conn, lowat_act_flag); > + conn_flag(conn, lowat_set_flag); > + conn_flag(conn, lowat_act_flag); > } > } > =20 > @@ -583,7 +579,7 @@ retry: > if (conn->read[fromsidei] =3D=3D conn->written[fromsidei]) > break; > =20 > - conn_event(c, conn, OUT_WAIT(!fromsidei)); > + conn_event(conn, OUT_WAIT(!fromsidei)); > break; > } > =20 > @@ -605,7 +601,7 @@ retry: > if ((conn->events & FIN_RCVD(sidei)) && > !(conn->events & FIN_SENT(!sidei))) { > shutdown(conn->s[!sidei], SHUT_WR); > - conn_event(c, conn, FIN_SENT(!sidei)); > + conn_event(conn, FIN_SENT(!sidei)); > } > } > } > @@ -626,7 +622,7 @@ retry: > return; > =20 > close: > - conn_flag(c, conn, CLOSING); > + conn_flag(conn, CLOSING); > } > =20 > /** > @@ -762,10 +758,10 @@ void tcp_splice_timer(struct tcp_splice_conn *conn) > flow_trace(conn, "can't set SO_RCVLOWAT on %d", > conn->s[sidei]); > } > - conn_flag(c, conn, ~RCVLOWAT_SET(sidei)); > + conn_flag(conn, ~RCVLOWAT_SET(sidei)); > } > } > =20 > flow_foreach_sidei(sidei) > - conn_flag(c, conn, ~RCVLOWAT_ACT(sidei)); > + conn_flag(conn, ~RCVLOWAT_ACT(sidei)); > } > diff --git a/udp_flow.c b/udp_flow.c > index c4cf35c2c89d..b016a8095ec6 100644 > --- a/udp_flow.c > +++ b/udp_flow.c > @@ -74,7 +74,6 @@ static int udp_flow_sock(const struct ctx *c, > { > const struct flowside *side =3D &uflow->f.side[sidei]; > uint8_t pif =3D uflow->f.pif[sidei]; > - union epoll_ref ref; > int rc; > int s; > =20 > @@ -84,14 +83,11 @@ static int udp_flow_sock(const struct ctx *c, > return s; > } > =20 > - ref.type =3D EPOLL_TYPE_UDP; > - ref.flowside =3D FLOW_SIDX(uflow, sidei); > - ref.fd =3D s; > - > flow_epollid_set(&uflow->f, EPOLLFD_ID_DEFAULT); > - > - rc =3D epoll_add(flow_epollfd(&uflow->f), EPOLLIN, ref); > - if (rc < 0) { > + if (flow_epoll_set(EPOLL_CTL_ADD, EPOLL_TYPE_UDP, &uflow->f, > + EPOLLIN, s, sidei) < 0) { > + rc =3D -errno; > + flow_epollid_clear(&uflow->f); > close(s); > return rc; > } > --=20 > 2.52.0 >=20 --=20 David Gibson (he or they) | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you, not the other way | around. http://www.ozlabs.org/~dgibson --oIhO7wCta1UTVS// Content-Type: application/pgp-signature; name=signature.asc -----BEGIN PGP SIGNATURE----- iQIzBAEBCgAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmlgPuIACgkQzQJF27ox 2Gc7JhAAo7qsu+p6J2sNv2sLXGyWWnysLAzaVpbTTBUC0U2BnkMeJGPnt0c1jKDn bWePVf5mo16VYB3svWfnppF9cpnkmFwFxLTJWEN0gqAiiqxmAlwOkBDpSYgP4VH/ AGnLBu2E1nTAKPIuBvsCt5cVw/UcSbPTwMqqacf5vOoAej80Sdxccw0wEBKTFILP Ka7xQiIXdodnEi1rq49t56SHexT2QncTCnMju70zBHPF9aFOxvlmy09xBz7+PKWq x8+XM2LDHOD/tViQyt8H5QI0ggNPUyECEGqAQjcQN/nXKag2+ABs0+EH/pHhNrms pV3YPPNuH1WqYoRVaZaUjaaKZru8WYwMDw4jw2kQZwaMJvlZmqOT2hS5u15pzMxV REHISClUU11pijqV9jWX9IVm3kXSBsMEPF9KLb12Hm2TKA3x/z8KAh/67ppHKD5h 5qBeQbhmJoXyeVCxMj6E5898xtumJGCh5TrY2irsjYNat1uroKWLoR8Q3C20Jqms rDvi1Ml7u3X9GInKJA5riERPW7R8XzpqGBHbMwBDy4CESZq3tVZL+xJbCC78/tlK Bp2N5VC9R1Y+ioZjpPx+iwDPqm2DVPxEXUZnSG22Z4lcWcrphk/o1lEFUEcrjEwP JMZKR0oeV5CAcN4sONEthAeXUJo1qIsd+KEk3e8fbZfjc1dS3F0= =xWzd -----END PGP SIGNATURE----- --oIhO7wCta1UTVS//--