Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

qeth: improve ip_list administration after deregister failures

1. ip_list handling after deregister failure of multicast address:
If error code "MC Address not found" is returned do not re-add
multicast address to ip_list.
For other error codes readd multicast address at the end of
function qeth_delete_all_mc.
2. ip_list handling after deregister failure or normal ip address:
If error code "IP Address not found" is returned do not re-add
multicast address to ip list.
This is especially important in IP address takeover scenarios,
to enable re-takeover of a taken over IP address.

Signed-off-by: Ursula Braun <braunu@de.ibm.com>
Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>

authored by

Ursula Braun and committed by
Jeff Garzik
2d921c32 cef8c793

+11 -7
+1 -1
drivers/s390/net/qeth_core_mpc.c
··· 195 195 {IPA_RC_SETIP_NO_STARTLAN, "Setip no startlan received"}, 196 196 {IPA_RC_SETIP_ALREADY_RECEIVED, "Setip already received"}, 197 197 {IPA_RC_IP_ADDR_ALREADY_USED, "IP address already in use on LAN"}, 198 - {IPA_RC_MULTICAST_FULL, "No task available, multicast full"}, 198 + {IPA_RC_MC_ADDR_NOT_FOUND, "Multicast address not found"}, 199 199 {IPA_RC_SETIP_INVALID_VERSION, "SETIP invalid IP version"}, 200 200 {IPA_RC_UNSUPPORTED_SUBCMD, "Unsupported assist subcommand"}, 201 201 {IPA_RC_ARP_ASSIST_NO_ENABLE, "Only partial success, no enable"},
+1 -1
drivers/s390/net/qeth_core_mpc.h
··· 182 182 IPA_RC_SETIP_NO_STARTLAN = 0xe008, 183 183 IPA_RC_SETIP_ALREADY_RECEIVED = 0xe009, 184 184 IPA_RC_IP_ADDR_ALREADY_USED = 0xe00a, 185 - IPA_RC_MULTICAST_FULL = 0xe00b, 185 + IPA_RC_MC_ADDR_NOT_FOUND = 0xe00b, 186 186 IPA_RC_SETIP_INVALID_VERSION = 0xe00d, 187 187 IPA_RC_UNSUPPORTED_SUBCMD = 0xe00e, 188 188 IPA_RC_ARP_ASSIST_NO_ENABLE = 0xe00f,
+9 -5
drivers/s390/net/qeth_l3_main.c
··· 401 401 static void __qeth_l3_delete_all_mc(struct qeth_card *card, 402 402 unsigned long *flags) 403 403 { 404 + struct list_head fail_list; 404 405 struct qeth_ipaddr *addr, *tmp; 405 406 int rc; 407 + 408 + INIT_LIST_HEAD(&fail_list); 406 409 again: 407 410 list_for_each_entry_safe(addr, tmp, &card->ip_list, entry) { 408 411 if (addr->is_multicast) { ··· 413 410 spin_unlock_irqrestore(&card->ip_lock, *flags); 414 411 rc = qeth_l3_deregister_addr_entry(card, addr); 415 412 spin_lock_irqsave(&card->ip_lock, *flags); 416 - if (!rc) { 413 + if (!rc || (rc == IPA_RC_MC_ADDR_NOT_FOUND)) 417 414 kfree(addr); 418 - goto again; 419 - } else 420 - list_add(&addr->entry, &card->ip_list); 415 + else 416 + list_add_tail(&addr->entry, &fail_list); 417 + goto again; 421 418 } 422 419 } 420 + list_splice(&fail_list, &card->ip_list); 423 421 } 424 422 425 423 static void qeth_l3_set_ip_addr_list(struct qeth_card *card) ··· 471 467 spin_unlock_irqrestore(&card->ip_lock, flags); 472 468 rc = qeth_l3_deregister_addr_entry(card, addr); 473 469 spin_lock_irqsave(&card->ip_lock, flags); 474 - if (!rc) 470 + if (!rc || (rc == IPA_RC_PRIMARY_ALREADY_DEFINED)) 475 471 kfree(addr); 476 472 else 477 473 list_add_tail(&addr->entry, &card->ip_list);