|WARNING| [v4, 2/2] net/sfc: provide cached dev info to use in secondary process
dpdklab at iol.unh.edu
dpdklab at iol.unh.edu
Mon Aug 24 18:59:39 CEST 2026
Test-Label: ai-code-review
Test-Status: WARNING
https://dpdk.org/patch/168265
_AI Code Review_
=== Patch Review: series.patch (via Claude) ===
Review date: 2026-08-24
# DPDK Patch Review
## Patch 1/2: net/sfc: fix shared adapter pointer set in secondary process
### Errors
None identified.
### Warnings
None identified.
### Info
None.
---
## Patch 2/2: net/sfc: provide cached dev info to use in secondary process
### Errors
**1. Race condition: dev_info_cache written without synchronization**
In `sfc_eth_dev_pci_probe()`, the `dev_info_cache` structure is populated and then its validity flag is set with `rte_memory_order_release`. However, the `rte_eth_dev_info_get()` call that fills the cache writes to `sas->dev_info_cache` without atomic operations. If the secondary process calls `sfc_dev_infos_get_secondary()` concurrently while the primary is still inside `rte_eth_dev_info_get()`, the secondary may observe a partially-written structure (torn reads).
The `rte_memory_order_release` store of the validity flag only orders operations *before* the store; it does not prevent the secondary from reading `dev_info_cache` during the `rte_eth_dev_info_get()` call if that call takes non-trivial time.
**Suggested fix:**
Either:
1. Use a separate staging buffer, fill it, then `memcpy` to the cache before setting the flag, OR
2. Document that `rte_eth_dev_info_get()` completes before any secondary process could possibly call the getter (if this is guaranteed by DPDK attach order), OR
3. Add a comment explaining why concurrent access cannot occur (if hotplug or secondary attach timing guarantees this).
If concurrent access during init is impossible due to DPDK's process attach sequencing, add a comment stating this assumption.
---
**2. Pointer in shared memory not zeroed (device field)**
The code sets `sas->dev_info_cache.device = NULL` after caching, but does not zero `sas->dev_info_cache.switch_info.name` (which is also a process-local pointer). The getter restores `switch_info.name` from `dev->device->driver->name`, but if the primary process cached a non-NULL `switch_info.name` and then the getter restores it, the pointer could be stale if `dev->device->driver->name` differs between processes.
More critically: if `rte_eth_dev_info_get()` populates `dev_info.switch_info.name` with a pointer to a string in the primary's address space, that pointer is meaningless in the secondary. The current code tries to "restore" it in the getter, but the conditional `if (dev_info->switch_info.name != NULL)` checks the *cached* pointer (from the primary) before overwriting it.
**Suggested fix:**
In the caching code, zero all process-local pointers:
```c
sas->dev_info_cache.device = NULL;
sas->dev_info_cache.switch_info.name = NULL;
```
And in the getter, unconditionally assign the process-local value:
```c
dev_info->device = dev->device;
if (dev->device != NULL && dev->device->driver != NULL)
dev_info->switch_info.name = dev->device->driver->name;
```
This ensures the cached pointer is never trusted.
---
### Warnings
**1. Error path does not release resources on cache population failure**
If `rte_eth_dev_info_get()` fails (`rc != 0`), the code logs a warning and continues. However, the validity flag remains `false`, which will cause all secondary process `dev_infos_get` calls to return `-EAGAIN` indefinitely. The primary process continues with representor creation and reports success.
This means the port is partially initialized: representors are created, but secondaries cannot get dev info. This is inconsistent behavior.
**Suggested fix:**
Consider whether cache population failure should fail the probe entirely (return `rc` before representor creation) or whether `-EAGAIN` from secondaries is acceptable. If the latter, add a comment documenting this is a known limitation. If the former, change to:
```c
if (rc != 0) {
sfc_err(sa, "failed to cache dev info: %s", rte_strerror(-rc));
goto fail_cache_dev_info;
}
```
and add cleanup label.
---
**2. Missing release notes**
This patch adds a new behavior (secondary process `dev_infos_get` support) but does not update release notes. This is a visible change for applications using secondary processes.
**Suggested fix:**
Add an entry to the current release notes (`doc/guides/rel_notes/release_XX_YY.rst`) documenting that the sfc PMD now supports `dev_infos_get` in secondary processes.
---
### Info
**1. Comment on cache staleness could be more specific**
The comment in `sfc.h` says "Some driver-computed fields derived from mutable post-attach state are knowingly stale" but does not list which fields. This makes it hard for future maintainers to know if a change to `rte_eth_dev_info` breaks this assumption.
**Suggestion:**
Add examples of known-stale fields (e.g., "fields like `nb_rx_queues` and `nb_tx_queues` reflect primary's state at attach time").
---
**2. Use of `RTE_ATOMIC(bool)` is correct**
The patch correctly uses `RTE_ATOMIC(bool)` and explicit memory ordering (`rte_memory_order_acquire`/`release`) for the validity flag. This follows DPDK C11 atomic guidelines.
---
## Summary
**Patch 1/2**: Clean fix, no issues.
**Patch 2/2**: Two **Errors** related to potential race condition during cache population and incomplete pointer sanitization in shared memory. Two **Warnings** about error handling and missing release notes.
More information about the test-report
mailing list