IPoIB: Fix crash when path record fails after path flush
Commit ee1e2c82 ("IPoIB: Refresh paths instead of flushing them on SM change events") changed how paths are flushed on an SM event. This change introduces a problem if the path record query triggered by fails, causing path->ah to become NULL. A later successful path query will then trigger WARN_ON() in path_rec_completion(), and crash because path->ah has already been freed, so the ipoib_put_ah() inside the lock in path_rec_completion() may actually drop the last reference (contrary to the comment that claims this is safe). Fix this by updating path->ah and freeing old_ah only when the path record query is successful. This prevents the neighbour AH and that path AH from getting out of sync. This fixes <https://bugs.openfabrics.org/show_bug.cgi?id=1194> Reported-by: Rabah Salem <ravah@mellanox.com> Debugged-by: Eli Cohen <eli@mellanox.co.il> Signed-off-by: Roland Dreier <rolandd@cisco.com>
This commit is contained in:
@ -404,7 +404,7 @@ static void path_rec_completion(int status,
|
||||
struct net_device *dev = path->dev;
|
||||
struct ipoib_dev_priv *priv = netdev_priv(dev);
|
||||
struct ipoib_ah *ah = NULL;
|
||||
struct ipoib_ah *old_ah;
|
||||
struct ipoib_ah *old_ah = NULL;
|
||||
struct ipoib_neigh *neigh, *tn;
|
||||
struct sk_buff_head skqueue;
|
||||
struct sk_buff *skb;
|
||||
@ -428,12 +428,12 @@ static void path_rec_completion(int status,
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
|
||||
old_ah = path->ah;
|
||||
path->ah = ah;
|
||||
|
||||
if (ah) {
|
||||
path->pathrec = *pathrec;
|
||||
|
||||
old_ah = path->ah;
|
||||
path->ah = ah;
|
||||
|
||||
ipoib_dbg(priv, "created address handle %p for LID 0x%04x, SL %d\n",
|
||||
ah, be16_to_cpu(pathrec->dlid), pathrec->sl);
|
||||
|
||||
|
Reference in New Issue
Block a user