[ofa-general] [PATCH] ipoib: racing uses of ipoib_neigh in IPoIB-CM
Yossi Etigin
yosefe at voltaire.com
Wed Jun 10 12:52:29 PDT 2009
akepner at sgi.com wrote:
> @@ -810,9 +810,6 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
> list_del(&neigh->list);
> if (neigh->ah)
> ipoib_put_ah(neigh->ah);
> - ipoib_neigh_free(dev, neigh);
> -
> - tx->neigh = NULL;
> }
>
> if (test_and_clear_bit(IPOIB_FLAG_INITIALIZED, &tx->flags)) {
Can't calling ipoib_put_ah() and keeping the neighbour alive cause neigh->ah
pointer become invalid? What about doing list_del(&neigh->list) twice?
> @@ -1316,11 +1313,22 @@ static void ipoib_cm_tx_start(struct work_struct *work)
> if (ret) {
> neigh = p->neigh;
> if (neigh) {
> + struct sk_buff *skb;
> neigh->cm = NULL;
> list_del(&neigh->list);
> if (neigh->ah)
> ipoib_put_ah(neigh->ah);
> - ipoib_neigh_free(dev, neigh);
> + *to_ipoib_neigh(neigh->neighbour) = NULL;
> + ipoib_dbg(priv, "%s: releasing ref to %pI6 "
> + "(refcnt: %d)\n", __func__,
> + neigh->dgid.raw,
> + atomic_read(&neigh->neighbour->refcnt));
> + neigh_release(neigh->neighbour);
> + while ((skb = __skb_dequeue(&neigh->queue))) {
> + ++dev->stats.tx_dropped;
> + dev_kfree_skb_any(skb);
> + }
> + kfree(neigh);
> }
> list_del(&p->list);
> kfree(p);
The piece of code that does '*to_ipoib_neigh(neigh->neighbour) = NULL' and releases
skb's will appear 3 times in ipoib. I think it can be put in a separate function.
> @@ -1343,7 +1351,23 @@ static void ipoib_cm_tx_reap(struct work_struct *work)
> spin_lock_irqsave(&priv->lock, flags);
>
> while (!list_empty(&priv->cm.reap_list)) {
> + struct ipoib_neigh *neigh;
> + struct sk_buff *skb;
> p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
> + neigh = p->neigh;
> + if (neigh) {
> + *to_ipoib_neigh(neigh->neighbour) = NULL;
> + ipoib_dbg(priv, "%s: releasing ref to %pI6 "
> + "(refcnt: %d)\n", __func__, neigh->dgid.raw,
> + atomic_read(&neigh->neighbour->refcnt));
> + neigh_release(neigh->neighbour);
> + while ((skb = __skb_dequeue(&neigh->queue))) {
> + ++dev->stats.tx_dropped;
> + dev_kfree_skb_any(skb);
> + }
> + kfree(neigh);
> + }
> + p->neigh = NULL;
> list_del(&p->list);
> spin_unlock_irqrestore(&priv->lock, flags);
> netif_tx_unlock_bh(dev);
Couldn't this race with ipoib_neigh_cleanup()?
--Yossi
More information about the general
mailing list