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.
This commit is contained in:
Amaury Denoyelle 2021-12-22 11:29:05 +01:00
parent d6b166787c
commit 250ac42754
1 changed files with 14 additions and 5 deletions

View File

@ -3863,6 +3863,8 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt,
struct quic_conn *qc = NULL; struct quic_conn *qc = NULL;
struct ebmb_node *node; struct ebmb_node *node;
struct quic_connection_id *id; 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); HA_RWLOCK_RDLOCK(QUIC_LOCK, &l->rx.cids_lock);
@ -3892,15 +3894,22 @@ static struct quic_conn *retrieve_qc_conn_from_cid(struct quic_rx_packet *pkt,
id = ebmb_entry(node, struct quic_connection_id, node); id = ebmb_entry(node, struct quic_connection_id, node);
qc = id->qc; qc = id->qc;
found_in_dcid = 1;
/* If found in DCIDs tree, remove the quic_conn from the ODCIDs tree.
* If already done, this is a noop.
*/
ebmb_delete(&qc->odcid_node);
end: end:
HA_RWLOCK_RDUNLOCK(QUIC_LOCK, &l->rx.cids_lock); 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.
*/
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; return qc;
} }