|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