[openib-general] [PATCH] libmthca: race condition fix in
Michael S. Tsirkin
mst at mellanox.co.il
Thu Jan 5 05:03:59 PST 2006
Jack Morgenstein has discovered the following race condition in
libmthca. We are actually hitting it in testing.
Thread A destroys QP A at the kernel side by calling ibv_cmd_destroy_qp, but its
time-slice is over before removing it from the user-space qp_table removal.
Thread B allocates QP B, receiving a QP number that matches the just-destroyed
QP A in the low 16 bits. Thread B will now over-write the slot in qp_table
which was used for QP A.
Thread A wakes up and clears qp_table slot, in effect removing QP B from
qp_table.
As a solution, remove the QP from qp_table before calling ibv_cmd_destroy_qp.
This also makes sense since operations are performed in the reverse order
in create_qp.
---
Race condition fix: keep qp_table in userspace and in kernel consistent
by performing destruction in the reverse order of construction.
Signed-off-by: Michael S. Tsirkin <mst at mellanox.co.il>
Index: openib/src/userspace/libmthca/src/verbs.c
===================================================================
--- openib.orig/src/userspace/libmthca/src/verbs.c 2005-12-14 23:29:54.000000000 +0200
+++ openib/src/userspace/libmthca/src/verbs.c 2006-01-05 14:54:29.000000000 +0200
@@ -529,10 +529,6 @@ int mthca_destroy_qp(struct ibv_qp *qp)
{
int ret;
- ret = ibv_cmd_destroy_qp(qp);
- if (ret)
- return ret;
-
mthca_cq_clean(to_mcq(qp->recv_cq), qp->qp_num,
qp->srq ? to_msrq(qp->srq) : NULL);
if (qp->send_cq != qp->recv_cq)
@@ -546,6 +542,18 @@ int mthca_destroy_qp(struct ibv_qp *qp)
pthread_spin_unlock(&to_mcq(qp->recv_cq)->lock);
pthread_spin_unlock(&to_mcq(qp->send_cq)->lock);
+ ret = ibv_cmd_destroy_qp(qp);
+ if (ret) {
+ pthread_spin_lock(&to_mcq(qp->send_cq)->lock);
+ if (qp->send_cq != qp->recv_cq)
+ pthread_spin_lock(&to_mcq(qp->recv_cq)->lock);
+ mthca_store_qp(to_mctx(qp->context), qp->qp_num, to_mqp(qp));
+ if (qp->send_cq != qp->recv_cq)
+ pthread_spin_unlock(&to_mcq(qp->recv_cq)->lock);
+ pthread_spin_unlock(&to_mcq(qp->send_cq)->lock);
+ return ret;
+ }
+
if (mthca_is_memfree(qp->context)) {
mthca_free_db(to_mctx(qp->context)->db_tab, MTHCA_DB_TYPE_RQ,
to_mqp(qp)->rq.db_index);
--
MST
More information about the general
mailing list