Re: [PATCH net-next v5 04/15] ibmveth: Refactor buffer pool management for per-queue MQ RX

mingming cao <[email protected]>
Newsgroups gmane.linux.ports.ppc.embedded
Message-ID <ca132b73-5fd9-428f-af41-cfabedf0e0b4__17395.0316080422$1788200482$gmane$org@linux.ibm.com>
On 8/17/26 6:47 PM, Jakub Kicinski wrote:
> This is an AI-generated review of your patch. The human sending this
> email has considered the AI review valid, or at least plausible.
> ---
> ibmveth: Refactor buffer pool management for per-queue MQ RX
>
> This moves the five RX buffer pools to a per-queue array and introduces
> ibmveth_alloc_buffer_pools() / ibmveth_free_buffer_pools() plus the
> per-queue helpers, wiring them into open() and close(). Queue 0 stays the
> template for pool geometry and activation, and runtime is still
> single-queue.
>
> A few questions below about the new unwind paths and about two of the
> new comments.
>
>> diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
>> index 168940bfa1094..1a428ee60d58c 100644
>> --- a/drivers/net/ethernet/ibm/ibmveth.c
>> +++ b/drivers/net/ethernet/ibm/ibmveth.c
>> @@ -627,6 +627,142 @@ static void ibmveth_free_buffer_pool(struct ibmveth_adapter *adapter,
>>   	}
>>   }
>>   
>> +/**
>> + * ibmveth_free_queue_buffer_pools - Free buffer pools for a single queue
> [ ... ]
>
>> +/**
>> + * ibmveth_alloc_queue_buffer_pools - Allocate buffer pools for a single queue
>> + * @adapter: ibmveth adapter structure
>> + * @queue: queue index
>> + *
>> + * Allocates backing storage for each active pool on @queue.
>> + * Inactive pools (!active) are skipped. Pool metadata must be
>> + * initialized before calling this function.
>> + *
>> + * Return: 0 on success, negative error code on failure
>> + */
>> +static int ibmveth_alloc_queue_buffer_pools(struct ibmveth_adapter *adapter,
>> +					    int queue)
>> +{
>> +	struct net_device *netdev = adapter->netdev;
>> +	int i;
>> +
>> +	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
>> +		struct ibmveth_buff_pool *bpool =
>> +			&adapter->rx_buff_pool[queue][i];
>> +
>> +		if (!bpool->active)
>> +			continue;
>> +
>> +		if (ibmveth_alloc_buffer_pool(bpool)) {
>> +			netdev_err(netdev,
>> +				   "queue %d pool %d alloc failed (size=%u count=%u)\n",
>> +				   queue, i,
>> +				   bpool->buff_size,
>> +				   bpool->size);
>> +			bpool->active = 0;
>> +			/* Free by allocation presence, not active — the
>> +			 * failing pool cleared active first and would be
>> +			 * skipped by an active-only unwind.
>> +			 */
> [Severity: Low]
> Is the stated rationale in this comment accurate?  Freeing by allocation
> presence is a fine policy for the later resize paths, but the specific
> claim that an active-only unwind would skip the failing pool and leak it
> does not seem to hold here, because ibmveth_alloc_buffer_pool() already
> undoes its own partial allocations before returning -1:
>
> drivers/net/ethernet/ibm/ibmveth.c:ibmveth_alloc_buffer_pool() {
> 	pool->dma_addr = kzalloc_objs(dma_addr_t, pool->size);
> 	if (!pool->dma_addr) {
> 		kfree(pool->free_map);
> 		pool->free_map = NULL;
> 		return -1;
> 	}
>
> 	pool->skbuff = kcalloc(pool->size, sizeof(void *), GFP_KERNEL);
>
> 	if (!pool->skbuff) {
> 		kfree(pool->dma_addr);
> 		pool->dma_addr = NULL;
>
> 		kfree(pool->free_map);
> 		pool->free_map = NULL;
> 		return -1;
> 	}
> 	...
> }
>
> By the time bpool->active = 0 runs, free_map/dma_addr/skbuff are all NULL
> for the failing pool, so there is nothing for an active-only unwind to
> miss.  The same claim appears in the changelog ("v4 fail path freed by
> active and skipped the failing pool", "open-fail cannot leak partially
> allocated pools").  Could the comment and changelog instead justify
> free-by-presence purely in terms of the later resize paths?
Agreed. v6 retargets the comment and changelog to the later resize
paths. Policy is unchanged.
>> +			ibmveth_free_queue_buffer_pools(adapter, queue);
>> +			return -ENOMEM;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
> [ ... ]
>
>> +	/* Allocate actual buffers for all queues */
>> +	for (q = 0; q < adapter->num_rx_queues; q++) {
>> +		rc = ibmveth_alloc_queue_buffer_pools(adapter, q);
>> +		if (rc) {
>> +			/* Free pools for all previous queues */
>> +			while (--q >= 0)
>> +				ibmveth_free_queue_buffer_pools(adapter, q);
>> +			return rc;
>> +		}
>> +	}
>> +
>> +	netdev_dbg(netdev, "allocated buffer pools for %d queue(s)\n",
>> +		   adapter->num_rx_queues);
> [Severity: Low]
> This isn't a bug, but adapter->num_rx_queues is declared as
> "unsigned int num_rx_queues;" in drivers/net/ethernet/ibm/ibmveth.h, so
> should these two new messages use %u rather than %d?  The same applies to
> the netdev_dbg() in ibmveth_free_buffer_pools() below.
Yes,  Both count prints use %u in v6.
>> +	return 0;
>> +}
>> +
>> +/**
>> + * ibmveth_free_buffer_pools - Free buffer pools for all queues
>> + * @adapter: ibmveth adapter structure
>> + *
>> + * Frees buffer pools for all queues using the helper function.
>> + */
>> +static void
>> +ibmveth_free_buffer_pools(struct ibmveth_adapter *adapter)
>> +{
>> +	int q;
>> +
>> +	/* Free buffer pools for all queues */
>> +	for (q = 0; q < adapter->num_rx_queues; q++)
>> +		ibmveth_free_queue_buffer_pools(adapter, q);
>> +
>> +	netdev_dbg(adapter->netdev, "freed buffer pools for %d queue(s)\n",
>> +		   adapter->num_rx_queues);
>> +}
>> +
>>   /**
>>    * ibmveth_remove_buffer_from_pool - remove a buffer from a pool
>>    * @adapter: adapter instance
>> @@ -851,16 +987,9 @@ static int ibmveth_open(struct net_device *netdev)
>>   		goto out_free_tx_ltb;
>>   	}
>>   
>> -	for (i = 0; i < IBMVETH_NUM_BUFF_POOLS; i++) {
>> -		if (!adapter->rx_buff_pool[0][i].active)
>> -			continue;
>> -		if (ibmveth_alloc_buffer_pool(&adapter->rx_buff_pool[0][i])) {
>> -			netdev_err(netdev, "unable to alloc pool\n");
>> -			adapter->rx_buff_pool[0][i].active = 0;
>> -			rc = -ENOMEM;
>> -			goto out_free_buffer_pools;
>> -		}
>> -	}
>> +	rc = ibmveth_alloc_buffer_pools(adapter);
>> +	if (rc)
>> +		goto out_free_tx_ltb;
> [Severity: Medium]
> This isn't a gap introduced by this patch (the old inline pool loop fell
> through to the same labels), but since the edge is being rewritten here:
> this goto is taken after ibmveth_register_logical_lan() has already
> succeeded, and the unwind it lands on never issues h_free_logical_lan():
>
> out_free_tx_ltb:
> 	while (--i >= 0)
> 		ibmveth_free_tx_ltb(adapter, i);
> 	ibmveth_cleanup_rx_resources(adapter);
> out_free_filter_list:
> 	ibmveth_free_filter_list(adapter);
>
> ibmveth_cleanup_rx_resources() does the dma_unmap_single() of
> buffer_list_dma[], the dma_free_coherent() of the RX completion queue and
> the free_page() of the buffer-list page, and ibmveth_free_filter_list()
> releases the filter list, all while PHYP still holds those addresses.  The
> adjacent request_irq() failure path does perform the handshake the driver
> otherwise considers mandatory:
>
> 		do {
> 			lpar_rc = h_free_logical_lan(adapter->vdev->unit_address);
> 		} while (H_IS_LONG_BUSY(lpar_rc) || (lpar_rc == H_BUSY));
>
> Can PHYP write the rx_no_buffer counter into the freed buffer-list page, or
> post a completion into the freed RX queue, after this path returns?  The
> h_vio_signal(VIO_IRQ_DISABLE) issued just before registration also is not
> rebalanced here.
>
> Later patches in this series do repair this: "ibmveth: Refactor TX resource
> allocation in open/close paths" retargets this edge to out_unregister_lan,
> and by the end of the series ibmveth_open() allocates the pools before
> ibmveth_register_rx_queues() and routes post-registration failures through
> ibmveth_free_all_queues() -> h_free_logical_lan().  Would it be reasonable
> to point this goto at a label that unregisters the logical LAN already in
> this patch, so the intermediate commit is not bisect-visible?

Yes it can, at this point. Not retargeted here: the missing hcall
belongs with the TX open/close unwind (patch 6), and pools-before-
register is the register-helpers patch (7). Pointing this goto at a
new unregister label here would just be removed again in patch 6 when
out_unregister_lan replaces it — churn for no net gain. The
intermediate state is real but not a bisect hazard: num_rx_queues is
still 1 and this path is only reachable after a successful
h_register_logical_lan(), which is the same exposure the baseline had.

>>   
>>   	netdev_dbg(netdev, "registering irq 0x%x\n", netdev->irq);
>>   	rc = request_irq(netdev->irq, ibmveth_interrupt, 0, netdev->name,
>> @@ -885,11 +1014,7 @@ static int ibmveth_open(struct net_device *netdev)
>>   	return 0;
>>   
>>   out_free_buffer_pools:
>> -	while (--i >= 0) {
>> -		if (adapter->rx_buff_pool[0][i].active)
>> -			ibmveth_free_buffer_pool(adapter,
>> -						 &adapter->rx_buff_pool[0][i]);
>> -	}
>> +	ibmveth_free_buffer_pools(adapter);
>>   out_free_tx_ltb:
>>   	while (--i >= 0)
>>   		ibmveth_free_tx_ltb(adapter, i);
> [Severity: Medium]
> This is a pre-existing issue rather than one introduced here, but does this
> hunk silently fix a TX long-term-buffer leak?
>
> In the parent commit the pool unwind consumed i:
>
> out_free_buffer_pools:
> 	while (--i >= 0) {
> 		if (adapter->rx_buff_pool[0][i].active)
> 			ibmveth_free_buffer_pool(adapter,
> 						 &adapter->rx_buff_pool[0][i]);
> 	}
> out_free_tx_ltb:
> 	while (--i >= 0)
> 		ibmveth_free_tx_ltb(adapter, i);
>
> so on reaching out_free_tx_ltb by fall-through, i was already -1 and the
> first test of --i evaluated to -2, meaning no tx_ltb_ptr[]/tx_ltb_dma[]
> buffer was released.  With the pool unwind now a helper call that does not
> touch i, i still holds the TX queue count from the completed TX allocation
> loop, so the TX LTBs are freed.
>
> Every PAGE_ALIGN(IBMVETH_MAX_TX_BUF_SIZE) TX buffer plus its DMA mapping was
> leaked on each failing open, and it repeats per attempt ("ip link set <dev>
> up" under memory pressure, or the close+open pair inside veth_pool_store(),
> ibmveth_change_mtu() and ibmveth_reset()).
>
> Would it make sense to split this out as its own patch with a Fixes: tag so
> stable trees pick it up, or at least describe it in the changelog?

Yes, as a side effect of pulling the pool loop out. v6 names it in the
commit message. Not split out: adding it at the head would make the
series 16 patches, exceeding the netdev limit.

Thanks,

Mingming
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.