Commit c6f59d13 authored by Anton Blanchard's avatar Anton Blanchard Committed by David S. Miller

ibmveth: Fix leak when recycling skb and hypervisor returns error

If h_add_logical_lan_buffer returns an error we need to free
the skb.
Signed-off-by: default avatarAnton Blanchard <anton@samba.org>
Cc: stable <stable@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 20e6074e
...@@ -395,7 +395,7 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada ...@@ -395,7 +395,7 @@ static inline struct sk_buff *ibmveth_rxq_get_buffer(struct ibmveth_adapter *ada
} }
/* recycle the current buffer on the rx queue */ /* recycle the current buffer on the rx queue */
static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) static int ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
{ {
u32 q_index = adapter->rx_queue.index; u32 q_index = adapter->rx_queue.index;
u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator; u64 correlator = adapter->rx_queue.queue_addr[q_index].correlator;
...@@ -403,6 +403,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) ...@@ -403,6 +403,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
unsigned int index = correlator & 0xffffffffUL; unsigned int index = correlator & 0xffffffffUL;
union ibmveth_buf_desc desc; union ibmveth_buf_desc desc;
unsigned long lpar_rc; unsigned long lpar_rc;
int ret = 1;
BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS); BUG_ON(pool >= IBMVETH_NUM_BUFF_POOLS);
BUG_ON(index >= adapter->rx_buff_pool[pool].size); BUG_ON(index >= adapter->rx_buff_pool[pool].size);
...@@ -410,7 +411,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) ...@@ -410,7 +411,7 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
if (!adapter->rx_buff_pool[pool].active) { if (!adapter->rx_buff_pool[pool].active) {
ibmveth_rxq_harvest_buffer(adapter); ibmveth_rxq_harvest_buffer(adapter);
ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]); ibmveth_free_buffer_pool(adapter, &adapter->rx_buff_pool[pool]);
return; goto out;
} }
desc.fields.flags_len = IBMVETH_BUF_VALID | desc.fields.flags_len = IBMVETH_BUF_VALID |
...@@ -423,12 +424,16 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter) ...@@ -423,12 +424,16 @@ static void ibmveth_rxq_recycle_buffer(struct ibmveth_adapter *adapter)
netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed " netdev_dbg(adapter->netdev, "h_add_logical_lan_buffer failed "
"during recycle rc=%ld", lpar_rc); "during recycle rc=%ld", lpar_rc);
ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator); ibmveth_remove_buffer_from_pool(adapter, adapter->rx_queue.queue_addr[adapter->rx_queue.index].correlator);
ret = 0;
} }
if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) { if (++adapter->rx_queue.index == adapter->rx_queue.num_slots) {
adapter->rx_queue.index = 0; adapter->rx_queue.index = 0;
adapter->rx_queue.toggle = !adapter->rx_queue.toggle; adapter->rx_queue.toggle = !adapter->rx_queue.toggle;
} }
out:
return ret;
} }
static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter) static void ibmveth_rxq_harvest_buffer(struct ibmveth_adapter *adapter)
...@@ -1084,8 +1089,9 @@ static int ibmveth_poll(struct napi_struct *napi, int budget) ...@@ -1084,8 +1089,9 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
if (rx_flush) if (rx_flush)
ibmveth_flush_buffer(skb->data, ibmveth_flush_buffer(skb->data,
length + offset); length + offset);
if (!ibmveth_rxq_recycle_buffer(adapter))
kfree_skb(skb);
skb = new_skb; skb = new_skb;
ibmveth_rxq_recycle_buffer(adapter);
} else { } else {
ibmveth_rxq_harvest_buffer(adapter); ibmveth_rxq_harvest_buffer(adapter);
skb_reserve(skb, offset); skb_reserve(skb, offset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment