From: Amaury Denoyelle Date: Wed, 22 Dec 2021 10:29:05 +0000 (+0100) Subject: BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal X-Git-Tag: v2.6-dev1~229 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=250ac42754547ac86b9e947cc772e92aa5f3e22e;p=thirdparty%2Fhaproxy.git BUG/MINOR: quic: upgrade rdlock to wrlock for ODCID removal When a quic_conn is found in the DCID tree, it can be removed from the first ODCID tree. However, this operation must absolutely be run under a write-lock to avoid race condition. To avoid to use the lock too frequently, node.leaf_p is checked. This value is set to NULL after ebmb_delete. --- diff --git a/src/xprt_quic.c b/src/xprt_quic.c index 624cb35510..500814fd1f 100644 --- a/src/xprt_quic.c +++ b/src/xprt_quic.c @@ -3863,6 +3863,8 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, struct quic_conn *qc = NULL; struct ebmb_node *node; struct quic_connection_id *id; + /* set if the quic_conn is found in the second DCID tree */ + int found_in_dcid = 0; HA_RWLOCK_RDLOCK(QUIC_LOCK, &l->rx.cids_lock); @@ -3892,14 +3894,21 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt, id = ebmb_entry(node, struct quic_connection_id, node); qc = id->qc; + found_in_dcid = 1; + + end: + HA_RWLOCK_RDUNLOCK(QUIC_LOCK, &l->rx.cids_lock); /* If found in DCIDs tree, remove the quic_conn from the ODCIDs tree. * If already done, this is a noop. + * + * node.leaf_p is first checked to avoid unnecessary locking. */ - ebmb_delete(&qc->odcid_node); - - end: - HA_RWLOCK_RDUNLOCK(QUIC_LOCK, &l->rx.cids_lock); + if (found_in_dcid && qc->odcid_node.node.leaf_p) { + HA_RWLOCK_WRLOCK(QUIC_LOCK, &l->rx.cids_lock); + ebmb_delete(&qc->odcid_node); + HA_RWLOCK_WRUNLOCK(QUIC_LOCK, &l->rx.cids_lock); + } return qc; }