|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