aboutsummaryrefslogtreecommitdiffstats
path: root/net/iucv/af_iucv.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/iucv/af_iucv.c')
-rw-r--r--net/iucv/af_iucv.c33
1 files changed, 23 insertions, 10 deletions
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index 49c15b48408e..d985d163dcfc 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -34,7 +34,7 @@
34 34
35static char iucv_userid[80]; 35static char iucv_userid[80];
36 36
37static struct proto_ops iucv_sock_ops; 37static const struct proto_ops iucv_sock_ops;
38 38
39static struct proto iucv_proto = { 39static struct proto iucv_proto = {
40 .name = "AF_IUCV", 40 .name = "AF_IUCV",
@@ -59,8 +59,8 @@ do { \
59 DEFINE_WAIT(__wait); \ 59 DEFINE_WAIT(__wait); \
60 long __timeo = timeo; \ 60 long __timeo = timeo; \
61 ret = 0; \ 61 ret = 0; \
62 prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \
62 while (!(condition)) { \ 63 while (!(condition)) { \
63 prepare_to_wait(sk->sk_sleep, &__wait, TASK_INTERRUPTIBLE); \
64 if (!__timeo) { \ 64 if (!__timeo) { \
65 ret = -EAGAIN; \ 65 ret = -EAGAIN; \
66 break; \ 66 break; \
@@ -361,10 +361,9 @@ static void iucv_sock_cleanup_listen(struct sock *parent)
361 } 361 }
362 362
363 parent->sk_state = IUCV_CLOSED; 363 parent->sk_state = IUCV_CLOSED;
364 sock_set_flag(parent, SOCK_ZAPPED);
365} 364}
366 365
367/* Kill socket */ 366/* Kill socket (only if zapped and orphaned) */
368static void iucv_sock_kill(struct sock *sk) 367static void iucv_sock_kill(struct sock *sk)
369{ 368{
370 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) 369 if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket)
@@ -426,17 +425,18 @@ static void iucv_sock_close(struct sock *sk)
426 425
427 skb_queue_purge(&iucv->send_skb_q); 426 skb_queue_purge(&iucv->send_skb_q);
428 skb_queue_purge(&iucv->backlog_skb_q); 427 skb_queue_purge(&iucv->backlog_skb_q);
429
430 sock_set_flag(sk, SOCK_ZAPPED);
431 break; 428 break;
432 429
433 default: 430 default:
434 sock_set_flag(sk, SOCK_ZAPPED); 431 sock_set_flag(sk, SOCK_ZAPPED);
432 /* nothing to do here */
435 break; 433 break;
436 } 434 }
437 435
436 /* mark socket for deletion by iucv_sock_kill() */
437 sock_set_flag(sk, SOCK_ZAPPED);
438
438 release_sock(sk); 439 release_sock(sk);
439 iucv_sock_kill(sk);
440} 440}
441 441
442static void iucv_sock_init(struct sock *sk, struct sock *parent) 442static void iucv_sock_init(struct sock *sk, struct sock *parent)
@@ -569,6 +569,7 @@ struct sock *iucv_accept_dequeue(struct sock *parent, struct socket *newsock)
569 569
570 if (sk->sk_state == IUCV_CONNECTED || 570 if (sk->sk_state == IUCV_CONNECTED ||
571 sk->sk_state == IUCV_SEVERED || 571 sk->sk_state == IUCV_SEVERED ||
572 sk->sk_state == IUCV_DISCONN || /* due to PM restore */
572 !newsock) { 573 !newsock) {
573 iucv_accept_unlink(sk); 574 iucv_accept_unlink(sk);
574 if (newsock) 575 if (newsock)
@@ -1035,6 +1036,10 @@ out:
1035 return err; 1036 return err;
1036} 1037}
1037 1038
1039/* iucv_fragment_skb() - Fragment a single IUCV message into multiple skb's
1040 *
1041 * Locking: must be called with message_q.lock held
1042 */
1038static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len) 1043static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
1039{ 1044{
1040 int dataleft, size, copied = 0; 1045 int dataleft, size, copied = 0;
@@ -1069,6 +1074,10 @@ static int iucv_fragment_skb(struct sock *sk, struct sk_buff *skb, int len)
1069 return 0; 1074 return 0;
1070} 1075}
1071 1076
1077/* iucv_process_message() - Receive a single outstanding IUCV message
1078 *
1079 * Locking: must be called with message_q.lock held
1080 */
1072static void iucv_process_message(struct sock *sk, struct sk_buff *skb, 1081static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
1073 struct iucv_path *path, 1082 struct iucv_path *path,
1074 struct iucv_message *msg) 1083 struct iucv_message *msg)
@@ -1119,6 +1128,10 @@ static void iucv_process_message(struct sock *sk, struct sk_buff *skb,
1119 skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb); 1128 skb_queue_head(&iucv_sk(sk)->backlog_skb_q, skb);
1120} 1129}
1121 1130
1131/* iucv_process_message_q() - Process outstanding IUCV messages
1132 *
1133 * Locking: must be called with message_q.lock held
1134 */
1122static void iucv_process_message_q(struct sock *sk) 1135static void iucv_process_message_q(struct sock *sk)
1123{ 1136{
1124 struct iucv_sock *iucv = iucv_sk(sk); 1137 struct iucv_sock *iucv = iucv_sk(sk);
@@ -1209,6 +1222,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
1209 kfree_skb(skb); 1222 kfree_skb(skb);
1210 1223
1211 /* Queue backlog skbs */ 1224 /* Queue backlog skbs */
1225 spin_lock_bh(&iucv->message_q.lock);
1212 rskb = skb_dequeue(&iucv->backlog_skb_q); 1226 rskb = skb_dequeue(&iucv->backlog_skb_q);
1213 while (rskb) { 1227 while (rskb) {
1214 if (sock_queue_rcv_skb(sk, rskb)) { 1228 if (sock_queue_rcv_skb(sk, rskb)) {
@@ -1220,11 +1234,10 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
1220 } 1234 }
1221 } 1235 }
1222 if (skb_queue_empty(&iucv->backlog_skb_q)) { 1236 if (skb_queue_empty(&iucv->backlog_skb_q)) {
1223 spin_lock_bh(&iucv->message_q.lock);
1224 if (!list_empty(&iucv->message_q.list)) 1237 if (!list_empty(&iucv->message_q.list))
1225 iucv_process_message_q(sk); 1238 iucv_process_message_q(sk);
1226 spin_unlock_bh(&iucv->message_q.lock);
1227 } 1239 }
1240 spin_unlock_bh(&iucv->message_q.lock);
1228 } 1241 }
1229 1242
1230done: 1243done:
@@ -1682,7 +1695,7 @@ static void iucv_callback_shutdown(struct iucv_path *path, u8 ipuser[16])
1682 bh_unlock_sock(sk); 1695 bh_unlock_sock(sk);
1683} 1696}
1684 1697
1685static struct proto_ops iucv_sock_ops = { 1698static const struct proto_ops iucv_sock_ops = {
1686 .family = PF_IUCV, 1699 .family = PF_IUCV,
1687 .owner = THIS_MODULE, 1700 .owner = THIS_MODULE,
1688 .release = iucv_sock_release, 1701 .release = iucv_sock_release,