|WARNING| net/iavf: fix reset race condition
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Thu Sep 24 11:18:10 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/169977
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-09-24
# DPDK Patch Review: net/iavf: fix reset race condition
## SUMMARY
The patch correctly identifies and fixes a race condition in concurrent reset handling.
The use of atomic operations with acquire/release ordering is appropriate for the synchronization pattern (publish/consume of reset state).
All atomic operations follow DPDK C11 atomic wrapper guidelines.
One **Error**-level issue found: a correctness bug on the release path.
No style, API, or documentation issues.
---
## ERRORS
### 1. Missing error check and release on iavf_dev_uninit failure
**File:** `drivers/net/intel/iavf/iavf_ethdev.c`
**Function:** `iavf_handle_hw_reset()`
After setting `vf->in_reset_recovery = true` via the compare-exchange at line 3488-3492,
the function calls `iavf_dev_uninit()` at line 3505.
If `iavf_dev_uninit()` fails (returns non-zero), execution continues to `iavf_dev_init()` at line 3508.
If `iavf_dev_init()` also fails, the function jumps to `error:` at line 3523,
which then jumps to `reset_done:` at line 3540.
At `reset_done:`, the function releases `in_reset_recovery` at line 3547.
However, if `iavf_dev_uninit()` succeeds and `iavf_dev_init()` fails,
there is an early return path at line 3517 (`return;`) that does NOT release `in_reset_recovery`.
**Code path:**
```c
// Line 3488-3492: acquire in_reset_recovery
rte_atomic_compare_exchange_strong_explicit(&vf->in_reset_recovery, ...)
// Line 3505: uninit succeeds
ret = iavf_dev_uninit(dev);
// Line 3508-3515: init fails
ret = iavf_dev_init(dev);
if (ret) {
PMD_DRV_LOG(ERR, "Init vf failed");
vf->pf_reset_in_progress = false;
return; // <-- BUG: in_reset_recovery still true, never released
}
```
If this path is taken, `in_reset_recovery` remains `true` permanently,
blocking all future resets (the compare-exchange at line 3488 will always fail).
**Fix:** Check `iavf_dev_uninit()` return value and jump to `reset_done` on failure,
or replace the early `return` at line 3517 with `goto reset_done`.
**Suggested change:**
```c
ret = iavf_dev_uninit(dev);
if (ret != 0) {
PMD_DRV_LOG(ERR, "Uninit vf failed during reset recovery");
goto reset_done; /* release in_reset_recovery before returning */
}
ret = iavf_dev_init(dev);
if (ret) {
PMD_DRV_LOG(ERR, "Init vf failed");
vf->pf_reset_in_progress = false;
goto reset_done; /* replace return with goto */
}
```
---
## WARNINGS
None.
---
## INFO
None.
---
## POSITIVE OBSERVATIONS
1. **Atomic operations correctly replace non-atomic `bool`:**
The change from `bool in_reset_recovery` to `RTE_ATOMIC(bool) in_reset_recovery`
and replacing all accesses with `rte_atomic_load_explicit()` / `rte_atomic_store_explicit()`
correctly fixes the data race.
2. **Memory ordering is appropriate:**
- `rte_memory_order_acquire` on the compare-exchange load side (line 3489-3490)
ensures subsequent reads in the critical section see the published state.
- `rte_memory_order_release` on the store (line 3547) ensures all prior writes
(cleanup, state changes) are visible to the next thread that acquires the flag.
- `rte_memory_order_relaxed` for simple flag checks (e.g., lines 770, 3099, 3346)
is correct -- these reads do not guard other shared data.
3. **Compare-exchange pattern correctly implements a guard:**
Using `rte_atomic_compare_exchange_strong_explicit()` with `expected = false`
ensures only one thread can enter the reset path at a time.
The `rte_memory_order_acquire` on both success and failure paths is correct
(on failure, the thread needs to observe the state left by the winning thread).
4. **Function signature change is appropriate:**
Changing `iavf_handle_hw_reset()` return type from `void` to `int`
allows callers (e.g., `rte_pmd_iavf_reinit()`) to detect and propagate failures,
including the new `-EBUSY` return when a reset is already in progress.
5. **No new resource leaks introduced:**
The atomic flag does not change resource ownership patterns;
existing cleanup paths remain valid.
---
## NOTES
- The patch does not require release notes (this is a bug fix in an existing driver feature).
- The `RTE_ATOMIC(bool)` type and `rte_atomic_*_explicit()` wrappers are the correct,
modern DPDK API for shared variable access.
- The `-EBUSY` return and INFO-level log when a concurrent reset is detected (lines 3494-3496)
is a reasonable design choice for this synchronization pattern.
More information about the test-report
mailing list