aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2021-11-19 07:56:30 +0000
committerAndriy Gapon <avg@FreeBSD.org>2021-12-10 12:32:37 +0000
commit5f24d2a82c1fa6555e550dcda99d0c1aae1e44b3 (patch)
tree4653ad64883c29001f8b8e2adb75667e34da07c1
parent0f048f199e69da73936665c72550a3a5fe8c4f1d (diff)
downloadsrc-5f24d2a82c1fa6555e550dcda99d0c1aae1e44b3.tar.gz
src-5f24d2a82c1fa6555e550dcda99d0c1aae1e44b3.zip
iflib_stop: drain rx tasks to prevent any data races
iflib_stop modifies iflib data structures that are used by _task_fn_rx, most prominently the free lists. So, iflib_stop has to ensure that the rx task threads are not active. This should help to fix a crash seen when iflib_if_ioctl (e.g., SIOCSIFCAP) is called while there is already traffic flowing. The crash has been seen on VMWare guests with vmxnet3 driver. My guess is that on physical hardware the couple of 1ms delays that iflib_stop has after disabling interrupts are enough for the queued work to be completed before any iflib state is touched. But on busy hypervisors the guests might not get enough CPU time to complete the work, thus there can be a race between the taskqueue threads and the work done to handle an ioctl, specifically in iflib_stop and iflib_init_locked. PR: 259458 (cherry picked from commit 1bfdb812c786ac2607a82633f9c84a5d16f54079)
-rw-r--r--sys/net/iflib.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/sys/net/iflib.c b/sys/net/iflib.c
index 55ba1895a059..85da3e77f037 100644
--- a/sys/net/iflib.c
+++ b/sys/net/iflib.c
@@ -2612,7 +2612,8 @@ iflib_stop(if_ctx_t ctx)
bzero((void *)di->idi_vaddr, di->idi_size);
}
for (i = 0; i < scctx->isc_nrxqsets; i++, rxq++) {
- /* make sure all transmitters have completed before proceeding XXX */
+ gtaskqueue_drain(rxq->ifr_task.gt_taskqueue,
+ &rxq->ifr_task.gt_task);
rxq->ifr_cq_cidx = 0;
for (j = 0, di = rxq->ifr_ifdi; j < sctx->isc_nrxqs; j++, di++)