diff options
author | Mike Marciniszyn <mike.marciniszyn@intel.com> | 2013-02-07 15:47:51 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2013-02-14 20:04:18 -0500 |
commit | bcc9b67a5b65ec2e1ec5371226a729ec1b380860 (patch) | |
tree | 23edbc2c2964ee07d5c96c4ab3f5e697ad248fa6 /drivers/infiniband/hw | |
parent | 836dc9e3fbbab0c30aa6e664417225f5c1fb1c39 (diff) |
IB/qib: Fix QP locate/remove race
remove_qp() can execute concurrently with a qib_lookup_qpn() on
another CPU, which in of itself, is ok, given the RCU locking.
The issue is that remove_qp() NULLs out the qp->next field so that a
qib_lookup_qpn() might fail to find a qp if it occurs after the one
that is being deleted. This is a momentary issue and subsequent
qib_lookup_qpn() calls would find the qp's since the search restarts
from the bucket head. At scale, the issue might causes dropped
packets and unnecessary retransmissions.
The fix just deletes the qp->next NULL assignment to prevent the
remove_qp() from hiding qp's from qib_lookup_qpn().
Reviewed-by: Dean Luick <dean.luick@intel.com>
Signed-off-by: Mike Marciniszyn <mike.marciniszyn@intel.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/hw')
-rw-r--r-- | drivers/infiniband/hw/qib/qib_qp.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 35275099cafd..a6a2cc2ba260 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c | |||
@@ -268,8 +268,9 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp) | |||
268 | qpp = &q->next) | 268 | qpp = &q->next) |
269 | if (q == qp) { | 269 | if (q == qp) { |
270 | atomic_dec(&qp->refcount); | 270 | atomic_dec(&qp->refcount); |
271 | *qpp = qp->next; | 271 | rcu_assign_pointer(*qpp, |
272 | rcu_assign_pointer(qp->next, NULL); | 272 | rcu_dereference_protected(qp->next, |
273 | lockdep_is_held(&dev->qpt_lock))); | ||
273 | break; | 274 | break; |
274 | } | 275 | } |
275 | } | 276 | } |