aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUrsula Braun <ursula.braun@de.ibm.com>2012-02-07 19:19:45 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-08 18:50:19 -0500
commit7d316b9453523498246e9e19a659c423d4c5081e (patch)
tree3031f461bd53a31ade520efae13f427e1fc4c3ab
parent1ab0d2ec9aeb4489c05158e8a2b00bad89f67e03 (diff)
af_iucv: remove IUCV-pathes completely
A SEVER is missing in the callback of a receiving SEVERED. This may inhibit z/VM to remove the corresponding IUCV-path completely. This patch adds a SEVER in iucv_callback_connrej (together with additional locking. Signed-off-by: Ursula Braun <ursula.braun@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Frank Blaschka <frank.blaschka@de.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/iucv/af_iucv.c71
1 files changed, 37 insertions, 34 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index d5c5b8fd1d01..3ce0259499ed 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -90,6 +90,7 @@ do { \
90 90
91static void iucv_sock_kill(struct sock *sk); 91static void iucv_sock_kill(struct sock *sk);
92static void iucv_sock_close(struct sock *sk); 92static void iucv_sock_close(struct sock *sk);
93static void iucv_sever_path(struct sock *, int);
93 94
94static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev, 95static int afiucv_hs_rcv(struct sk_buff *skb, struct net_device *dev,
95 struct packet_type *pt, struct net_device *orig_dev); 96 struct packet_type *pt, struct net_device *orig_dev);
@@ -181,11 +182,7 @@ static int afiucv_pm_freeze(struct device *dev)
181 case IUCV_DISCONN: 182 case IUCV_DISCONN:
182 case IUCV_CLOSING: 183 case IUCV_CLOSING:
183 case IUCV_CONNECTED: 184 case IUCV_CONNECTED:
184 if (iucv->path) { 185 iucv_sever_path(sk, 0);
185 err = pr_iucv->path_sever(iucv->path, NULL);
186 iucv_path_free(iucv->path);
187 iucv->path = NULL;
188 }
189 break; 186 break;
190 case IUCV_OPEN: 187 case IUCV_OPEN:
191 case IUCV_BOUND: 188 case IUCV_BOUND:
@@ -194,6 +191,8 @@ static int afiucv_pm_freeze(struct device *dev)
194 default: 191 default:
195 break; 192 break;
196 } 193 }
194 skb_queue_purge(&iucv->send_skb_q);
195 skb_queue_purge(&iucv->backlog_skb_q);
197 } 196 }
198 read_unlock(&iucv_sk_list.lock); 197 read_unlock(&iucv_sk_list.lock);
199 return err; 198 return err;
@@ -447,10 +446,29 @@ static void iucv_sock_kill(struct sock *sk)
447 sock_put(sk); 446 sock_put(sk);
448} 447}
449 448
449/* Terminate an IUCV path */
450static void iucv_sever_path(struct sock *sk, int with_user_data)
451{
452 unsigned char user_data[16];
453 struct iucv_sock *iucv = iucv_sk(sk);
454 struct iucv_path *path = iucv->path;
455
456 if (iucv->path) {
457 iucv->path = NULL;
458 if (with_user_data) {
459 low_nmcpy(user_data, iucv->src_name);
460 high_nmcpy(user_data, iucv->dst_name);
461 ASCEBC(user_data, sizeof(user_data));
462 pr_iucv->path_sever(path, user_data);
463 } else
464 pr_iucv->path_sever(path, NULL);
465 iucv_path_free(path);
466 }
467}
468
450/* Close an IUCV socket */ 469/* Close an IUCV socket */
451static void iucv_sock_close(struct sock *sk) 470static void iucv_sock_close(struct sock *sk)
452{ 471{
453 unsigned char user_data[16];
454 struct iucv_sock *iucv = iucv_sk(sk); 472 struct iucv_sock *iucv = iucv_sk(sk);
455 unsigned long timeo; 473 unsigned long timeo;
456 int err, blen; 474 int err, blen;
@@ -494,25 +512,14 @@ static void iucv_sock_close(struct sock *sk)
494 sk->sk_state = IUCV_CLOSED; 512 sk->sk_state = IUCV_CLOSED;
495 sk->sk_state_change(sk); 513 sk->sk_state_change(sk);
496 514
497 if (iucv->path) {
498 low_nmcpy(user_data, iucv->src_name);
499 high_nmcpy(user_data, iucv->dst_name);
500 ASCEBC(user_data, sizeof(user_data));
501 pr_iucv->path_sever(iucv->path, user_data);
502 iucv_path_free(iucv->path);
503 iucv->path = NULL;
504 }
505
506 sk->sk_err = ECONNRESET; 515 sk->sk_err = ECONNRESET;
507 sk->sk_state_change(sk); 516 sk->sk_state_change(sk);
508 517
509 iucv_skb_queue_purge(&iucv->send_skb_q); 518 iucv_skb_queue_purge(&iucv->send_skb_q);
510 skb_queue_purge(&iucv->backlog_skb_q); 519 skb_queue_purge(&iucv->backlog_skb_q);
511 break;
512 520
513 default: 521 default: /* fall through */
514 /* nothing to do here */ 522 iucv_sever_path(sk, 1);
515 break;
516 } 523 }
517 524
518 /* mark socket for deletion by iucv_sock_kill() */ 525 /* mark socket for deletion by iucv_sock_kill() */
@@ -894,11 +901,8 @@ static int iucv_sock_connect(struct socket *sock, struct sockaddr *addr,
894 if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_CLOSED) 901 if (sk->sk_state == IUCV_DISCONN || sk->sk_state == IUCV_CLOSED)
895 err = -ECONNREFUSED; 902 err = -ECONNREFUSED;
896 903
897 if (err && iucv->transport == AF_IUCV_TRANS_IUCV) { 904 if (err && iucv->transport == AF_IUCV_TRANS_IUCV)
898 pr_iucv->path_sever(iucv->path, NULL); 905 iucv_sever_path(sk, 0);
899 iucv_path_free(iucv->path);
900 iucv->path = NULL;
901 }
902 906
903done: 907done:
904 release_sock(sk); 908 release_sock(sk);
@@ -1565,13 +1569,6 @@ static int iucv_sock_release(struct socket *sock)
1565 1569
1566 iucv_sock_close(sk); 1570 iucv_sock_close(sk);
1567 1571
1568 /* Unregister with IUCV base support */
1569 if (iucv_sk(sk)->path) {
1570 pr_iucv->path_sever(iucv_sk(sk)->path, NULL);
1571 iucv_path_free(iucv_sk(sk)->path);
1572 iucv_sk(sk)->path = NULL;
1573 }
1574
1575 sock_orphan(sk); 1572 sock_orphan(sk);
1576 iucv_sock_kill(sk); 1573 iucv_sock_kill(sk);
1577 return err; 1574 return err;
@@ -1750,8 +1747,7 @@ static int iucv_callback_connreq(struct iucv_path *path,
1750 path->msglim = iucv->msglimit; 1747 path->msglim = iucv->msglimit;
1751 err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk); 1748 err = pr_iucv->path_accept(path, &af_iucv_handler, nuser_data, nsk);
1752 if (err) { 1749 if (err) {
1753 err = pr_iucv->path_sever(path, user_data); 1750 iucv_sever_path(nsk, 1);
1754 iucv_path_free(path);
1755 iucv_sock_kill(nsk); 1751 iucv_sock_kill(nsk);
1756 goto fail; 1752 goto fail;
1757 } 1753 }
@@ -1828,6 +1824,7 @@ static void iucv_callback_txdone(struct iucv_path *path,
1828 struct sk_buff *list_skb = list->next; 1824 struct sk_buff *list_skb = list->next;
1829 unsigned long flags; 1825 unsigned long flags;
1830 1826
1827 bh_lock_sock(sk);
1831 if (!skb_queue_empty(list)) { 1828 if (!skb_queue_empty(list)) {
1832 spin_lock_irqsave(&list->lock, flags); 1829 spin_lock_irqsave(&list->lock, flags);
1833 1830
@@ -1849,7 +1846,6 @@ static void iucv_callback_txdone(struct iucv_path *path,
1849 iucv_sock_wake_msglim(sk); 1846 iucv_sock_wake_msglim(sk);
1850 } 1847 }
1851 } 1848 }
1852 BUG_ON(!this);
1853 1849
1854 if (sk->sk_state == IUCV_CLOSING) { 1850 if (sk->sk_state == IUCV_CLOSING) {
1855 if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) { 1851 if (skb_queue_empty(&iucv_sk(sk)->send_skb_q)) {
@@ -1857,6 +1853,7 @@ static void iucv_callback_txdone(struct iucv_path *path,
1857 sk->sk_state_change(sk); 1853 sk->sk_state_change(sk);
1858 } 1854 }
1859 } 1855 }
1856 bh_unlock_sock(sk);
1860 1857
1861} 1858}
1862 1859
@@ -1864,9 +1861,15 @@ static void iucv_callback_connrej(struct iucv_path *path, u8 ipuser[16])
1864{ 1861{
1865 struct sock *sk = path->private; 1862 struct sock *sk = path->private;
1866 1863
1864 if (sk->sk_state == IUCV_CLOSED)
1865 return;
1866
1867 bh_lock_sock(sk);
1868 iucv_sever_path(sk, 1);
1867 sk->sk_state = IUCV_DISCONN; 1869 sk->sk_state = IUCV_DISCONN;
1868 1870
1869 sk->sk_state_change(sk); 1871 sk->sk_state_change(sk);
1872 bh_unlock_sock(sk);
1870} 1873}
1871 1874
1872/* called if the other communication side shuts down its RECV direction; 1875/* called if the other communication side shuts down its RECV direction;