]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: xprt: add new xprt_set_idle and xprt_set_used methods
authorWilly Tarreau <w@1wt.eu>
Tue, 2 Mar 2021 16:27:58 +0000 (17:27 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 5 Mar 2021 07:30:08 +0000 (08:30 +0100)
These functions are used on the mux layer to indicate that the connection
is becoming idle and that the xprt ought to be careful before checking the
context or that it's not idle anymore and that the context is safe. The
purpose is to allow a mux which is going to release a connection to tell
the xprt to be careful when touching it. At the moment, the xprt are
always careful and that's costly so we want to have the ability to relax
this a bit.

No xprt layer uses this yet.

include/haproxy/connection-t.h
include/haproxy/connection.h
src/mux_fcgi.c
src/mux_h1.c
src/mux_h2.c

index 033f76143b4d0aa7cba9dc7d7b07b4ab6fa40cc5..9c2af7b8f90360758c4f1475facef4cec594aee6 100644 (file)
@@ -380,6 +380,8 @@ struct xprt_ops {
        void (*destroy_srv)(struct server *srv);    /* destroy a server context */
        int  (*get_alpn)(const struct connection *conn, void *xprt_ctx, const char **str, int *len); /* get application layer name */
        int (*takeover)(struct connection *conn, void *xprt_ctx, int orig_tid); /* Let the xprt know the fd have been taken over */
+       void (*set_idle)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection becomes idle. implies set_used. */
+       void (*set_used)(struct connection *conn, void *xprt_ctx); /* notify the xprt that the connection leaves idle. implies set_idle. */
        char name[8];                               /* transport layer name, zero-terminated */
        int (*subscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Subscribe <es> to events, such as "being able to send" */
        int (*unsubscribe)(struct connection *conn, void *xprt_ctx, int event_type, struct wait_event *es); /* Unsubscribe <es> from events */
index d8aff5c7bcf08b12cafac9f2235e9d669049ed0b..e00e6f820ab83bd180a1c6db760a47c60458de9e 100644 (file)
@@ -868,6 +868,25 @@ static inline int xprt_add_hs(struct connection *conn)
        return 0;
 }
 
+/* notify the next xprt that the connection is about to become idle and that it
+ * may be stolen at any time after the function returns and that any tasklet in
+ * the chain must be careful before dereferencing its context.
+ */
+static inline void xprt_set_idle(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+       if (xprt->set_idle)
+               xprt->set_idle(conn, conn->xprt_ctx);
+}
+
+/* notify the next xprt that the connection is not idle anymore and that it may
+ * not be stolen before the next xprt_set_idle().
+ */
+static inline void xprt_set_used(struct connection *conn, const struct xprt_ops *xprt, void *xprt_ctx)
+{
+       if (xprt->set_used)
+               xprt->set_used(conn, conn->xprt_ctx);
+}
+
 static inline int conn_get_alpn(const struct connection *conn, const char **str, int *len)
 {
        if (!conn_xprt_ready(conn) || !conn->xprt->get_alpn)
index be063cf403b3987acad4d1a9d1b8b27e3864a96e..b7d8e94de7f848540b1ecf4e55912259622be275 100644 (file)
@@ -3489,6 +3489,7 @@ static struct conn_stream *fcgi_attach(struct connection *conn, struct session *
 
        /* the connection is not idle anymore, let's mark this */
        HA_ATOMIC_AND(&fconn->wait_event.tasklet->state, ~TASK_F_USR1);
+       xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
 
        TRACE_LEAVE(FCGI_EV_FSTRM_NEW, conn, fstrm);
        return cs;
@@ -3620,6 +3621,8 @@ static void fcgi_detach(struct conn_stream *cs)
                                 * that the handler needs to check it under the idle conns lock.
                                 */
                                HA_ATOMIC_OR(&fconn->wait_event.tasklet->state, TASK_F_USR1);
+                               xprt_set_idle(fconn->conn, fconn->conn->xprt, fconn->conn->xprt_ctx);
+
                                if (!srv_add_to_idle_list(objt_server(fconn->conn->target), fconn->conn, 1)) {
                                        /* The server doesn't want it, let's kill the connection right away */
                                        fconn->conn->mux->destroy(fconn);
index 7d1bed48dd95d08627110c04dcc4b4ac2f530694..c8dc71c72a5e1b94547f4812ed7727ac3ded3777 100644 (file)
@@ -3007,6 +3007,7 @@ static struct conn_stream *h1_attach(struct connection *conn, struct session *se
 
        /* the connection is not idle anymore, let's mark this */
        HA_ATOMIC_AND(&h1c->wait_event.tasklet->state, ~TASK_F_USR1);
+       xprt_set_used(conn, conn->xprt, conn->xprt_ctx);
 
        TRACE_LEAVE(H1_EV_STRM_NEW, conn, h1s);
        return cs;
@@ -3106,6 +3107,8 @@ static void h1_detach(struct conn_stream *cs)
                         */
                        HA_ATOMIC_OR(&h1c->wait_event.tasklet->state, TASK_F_USR1);
                        h1c->conn->xprt->subscribe(h1c->conn, h1c->conn->xprt_ctx, SUB_RETRY_RECV, &h1c->wait_event);
+                       xprt_set_idle(h1c->conn, h1c->conn->xprt, h1c->conn->xprt_ctx);
+
                        if (!srv_add_to_idle_list(objt_server(h1c->conn->target), h1c->conn, is_not_first)) {
                                /* The server doesn't want it, let's kill the connection right away */
                                h1c->conn->mux->destroy(h1c);
index 2ac61f7ac4dcda67d5c4e716e85bcdd2a238b445..9a4660e2f923a7bcbc158e644ac9bfa8d4b91eb8 100644 (file)
@@ -4106,6 +4106,7 @@ static struct conn_stream *h2_attach(struct connection *conn, struct session *se
 
        /* the connection is not idle anymore, let's mark this */
        HA_ATOMIC_AND(&h2c->wait_event.tasklet->state, ~TASK_F_USR1);
+       xprt_set_used(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
 
        TRACE_LEAVE(H2_EV_H2S_NEW, conn, h2s);
        return cs;
@@ -4254,6 +4255,8 @@ static void h2_detach(struct conn_stream *cs)
                                         * that the handler needs to check it under the idle conns lock.
                                         */
                                        HA_ATOMIC_OR(&h2c->wait_event.tasklet->state, TASK_F_USR1);
+                                       xprt_set_idle(h2c->conn, h2c->conn->xprt, h2c->conn->xprt_ctx);
+
                                        if (!srv_add_to_idle_list(objt_server(h2c->conn->target), h2c->conn, 1)) {
                                                /* The server doesn't want it, let's kill the connection right away */
                                                h2c->conn->mux->destroy(h2c);