svn commit: r307839 - head/sys/dev/hyperv/netvsc

Sepherosa Ziehau sephe at FreeBSD.org
Mon Oct 24 03:34:20 UTC 2016


Author: sephe
Date: Mon Oct 24 03:34:19 2016
New Revision: 307839
URL: https://svnweb.freebsd.org/changeset/base/307839

Log:
  hyperv/hn: Fix chimney sending buffer leakage upon NVS sending failure.
  
  This will not happen in real world, since TX consumption of the vmbus
  TX bufring is limitted.  Better safe than sorry.
  
  MFC after:	1 week
  Sponsored by:	Microsoft
  Differential Revision:	https://reviews.freebsd.org/D8309

Modified:
  head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c

Modified: head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c
==============================================================================
--- head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Mon Oct 24 03:26:34 2016	(r307838)
+++ head/sys/dev/hyperv/netvsc/hv_netvsc_drv_freebsd.c	Mon Oct 24 03:34:19 2016	(r307839)
@@ -951,6 +951,8 @@ hn_txdesc_dmamap_load(struct hn_tx_ring 
 	struct mbuf *m = *m_head;
 	int error;
 
+	KASSERT(txd->chim_index == HN_NVS_CHIM_IDX_INVALID, ("txd uses chim"));
+
 	error = bus_dmamap_load_mbuf_sg(txr->hn_tx_data_dtag, txd->data_dmap,
 	    m, segs, nsegs, BUS_DMA_NOWAIT);
 	if (error == EFBIG) {
@@ -974,19 +976,6 @@ hn_txdesc_dmamap_load(struct hn_tx_ring 
 	return error;
 }
 
-static __inline void
-hn_txdesc_dmamap_unload(struct hn_tx_ring *txr, struct hn_txdesc *txd)
-{
-
-	if (txd->flags & HN_TXD_FLAG_DMAMAP) {
-		bus_dmamap_sync(txr->hn_tx_data_dtag,
-		    txd->data_dmap, BUS_DMASYNC_POSTWRITE);
-		bus_dmamap_unload(txr->hn_tx_data_dtag,
-		    txd->data_dmap);
-		txd->flags &= ~HN_TXD_FLAG_DMAMAP;
-	}
-}
-
 static __inline int
 hn_txdesc_put(struct hn_tx_ring *txr, struct hn_txdesc *txd)
 {
@@ -998,14 +987,25 @@ hn_txdesc_put(struct hn_tx_ring *txr, st
 	if (atomic_fetchadd_int(&txd->refs, -1) != 1)
 		return 0;
 
-	hn_txdesc_dmamap_unload(txr, txd);
+	if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID) {
+		KASSERT((txd->flags & HN_TXD_FLAG_DMAMAP) == 0,
+		    ("chim txd uses dmamap"));
+		hn_chim_free(txr->hn_sc, txd->chim_index);
+		txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
+	} else if (txd->flags & HN_TXD_FLAG_DMAMAP) {
+		bus_dmamap_sync(txr->hn_tx_data_dtag,
+		    txd->data_dmap, BUS_DMASYNC_POSTWRITE);
+		bus_dmamap_unload(txr->hn_tx_data_dtag,
+		    txd->data_dmap);
+		txd->flags &= ~HN_TXD_FLAG_DMAMAP;
+	}
+
 	if (txd->m != NULL) {
 		m_freem(txd->m);
 		txd->m = NULL;
 	}
 
 	txd->flags |= HN_TXD_FLAG_ONLIST;
-
 #ifndef HN_USE_TXDESC_BUFRING
 	mtx_lock_spin(&txr->hn_txlist_spin);
 	KASSERT(txr->hn_txdesc_avail >= 0 &&
@@ -1046,7 +1046,9 @@ hn_txdesc_get(struct hn_tx_ring *txr)
 		atomic_subtract_int(&txr->hn_txdesc_avail, 1);
 #endif
 		KASSERT(txd->m == NULL && txd->refs == 0 &&
-		    (txd->flags & HN_TXD_FLAG_ONLIST), ("invalid txd"));
+		    txd->chim_index == HN_NVS_CHIM_IDX_INVALID &&
+		    (txd->flags & HN_TXD_FLAG_ONLIST) &&
+		    (txd->flags & HN_TXD_FLAG_DMAMAP) == 0, ("invalid txd"));
 		txd->flags &= ~HN_TXD_FLAG_ONLIST;
 		txd->refs = 1;
 	}
@@ -1093,9 +1095,6 @@ hn_tx_done(struct hn_send_ctx *sndc, str
 	struct hn_txdesc *txd = sndc->hn_cbarg;
 	struct hn_tx_ring *txr;
 
-	if (txd->chim_index != HN_NVS_CHIM_IDX_INVALID)
-		hn_chim_free(sc, txd->chim_index);
-
 	txr = txd->txr;
 	KASSERT(txr->hn_chan == chan,
 	    ("channel mismatch, on chan%u, should be chan%u",
@@ -2820,6 +2819,7 @@ hn_create_tx_ring(struct hn_softc *sc, i
 		struct hn_txdesc *txd = &txr->hn_txdesc[i];
 
 		txd->txr = txr;
+		txd->chim_index = HN_NVS_CHIM_IDX_INVALID;
 
 		/*
 		 * Allocate and load RNDIS packet message.


More information about the svn-src-head mailing list