| From foo@baz Thu Nov 9 09:48:01 CET 2017 |
| From: Ursula Braun <ubraun@linux.vnet.ibm.com> |
| Date: Thu, 12 Jan 2017 15:48:43 +0100 |
| Subject: s390/qeth: fix retrieval of vipa and proxy-arp addresses |
| |
| From: Ursula Braun <ubraun@linux.vnet.ibm.com> |
| |
| |
| [ Upstream commit e48b9eaaa29a0a7d5da2df136b07eefa0180d584 ] |
| |
| qeth devices in layer3 mode need a separate handling of vipa and proxy-arp |
| addresses. vipa and proxy-arp addresses processed by qeth can be read from |
| userspace. Introduced with commit 5f78e29ceebf ("qeth: optimize IP handling |
| in rx_mode callback") the retrieval of vipa and proxy-arp addresses is |
| broken, if more than one vipa or proxy-arp address are set. |
| |
| The qeth code used local variable "int i" for 2 different purposes. This |
| patch now spends 2 separate local variables of type "int". |
| While touching these functions hash_for_each_safe() is converted to |
| hash_for_each(), since there is no removal of hash entries. |
| |
| Signed-off-by: Ursula Braun <ubraun@linux.vnet.ibm.com> |
| Reviewed-by: Julian Wiedmann <jwi@linux.vnet.ibm.com> |
| Reference-ID: RQM 3524 |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Sasha Levin <alexander.levin@verizon.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/s390/net/qeth_l3_sys.c | 30 ++++++++++++++++-------------- |
| 1 file changed, 16 insertions(+), 14 deletions(-) |
| |
| --- a/drivers/s390/net/qeth_l3_sys.c |
| +++ b/drivers/s390/net/qeth_l3_sys.c |
| @@ -692,15 +692,15 @@ static ssize_t qeth_l3_dev_vipa_add_show |
| enum qeth_prot_versions proto) |
| { |
| struct qeth_ipaddr *ipaddr; |
| - struct hlist_node *tmp; |
| char addr_str[40]; |
| + int str_len = 0; |
| int entry_len; /* length of 1 entry string, differs between v4 and v6 */ |
| - int i = 0; |
| + int i; |
| |
| entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; |
| entry_len += 2; /* \n + terminator */ |
| spin_lock_bh(&card->ip_lock); |
| - hash_for_each_safe(card->ip_htable, i, tmp, ipaddr, hnode) { |
| + hash_for_each(card->ip_htable, i, ipaddr, hnode) { |
| if (ipaddr->proto != proto) |
| continue; |
| if (ipaddr->type != QETH_IP_TYPE_VIPA) |
| @@ -708,16 +708,17 @@ static ssize_t qeth_l3_dev_vipa_add_show |
| /* String must not be longer than PAGE_SIZE. So we check if |
| * string length gets near PAGE_SIZE. Then we can savely display |
| * the next IPv6 address (worst case, compared to IPv4) */ |
| - if ((PAGE_SIZE - i) <= entry_len) |
| + if ((PAGE_SIZE - str_len) <= entry_len) |
| break; |
| qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, |
| addr_str); |
| - i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); |
| + str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "%s\n", |
| + addr_str); |
| } |
| spin_unlock_bh(&card->ip_lock); |
| - i += snprintf(buf + i, PAGE_SIZE - i, "\n"); |
| + str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "\n"); |
| |
| - return i; |
| + return str_len; |
| } |
| |
| static ssize_t qeth_l3_dev_vipa_add4_show(struct device *dev, |
| @@ -854,15 +855,15 @@ static ssize_t qeth_l3_dev_rxip_add_show |
| enum qeth_prot_versions proto) |
| { |
| struct qeth_ipaddr *ipaddr; |
| - struct hlist_node *tmp; |
| char addr_str[40]; |
| + int str_len = 0; |
| int entry_len; /* length of 1 entry string, differs between v4 and v6 */ |
| - int i = 0; |
| + int i; |
| |
| entry_len = (proto == QETH_PROT_IPV4)? 12 : 40; |
| entry_len += 2; /* \n + terminator */ |
| spin_lock_bh(&card->ip_lock); |
| - hash_for_each_safe(card->ip_htable, i, tmp, ipaddr, hnode) { |
| + hash_for_each(card->ip_htable, i, ipaddr, hnode) { |
| if (ipaddr->proto != proto) |
| continue; |
| if (ipaddr->type != QETH_IP_TYPE_RXIP) |
| @@ -870,16 +871,17 @@ static ssize_t qeth_l3_dev_rxip_add_show |
| /* String must not be longer than PAGE_SIZE. So we check if |
| * string length gets near PAGE_SIZE. Then we can savely display |
| * the next IPv6 address (worst case, compared to IPv4) */ |
| - if ((PAGE_SIZE - i) <= entry_len) |
| + if ((PAGE_SIZE - str_len) <= entry_len) |
| break; |
| qeth_l3_ipaddr_to_string(proto, (const u8 *)&ipaddr->u, |
| addr_str); |
| - i += snprintf(buf + i, PAGE_SIZE - i, "%s\n", addr_str); |
| + str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "%s\n", |
| + addr_str); |
| } |
| spin_unlock_bh(&card->ip_lock); |
| - i += snprintf(buf + i, PAGE_SIZE - i, "\n"); |
| + str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "\n"); |
| |
| - return i; |
| + return str_len; |
| } |
| |
| static ssize_t qeth_l3_dev_rxip_add4_show(struct device *dev, |