aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUrsula Braun <ursula.braun@de.ibm.com>2012-02-07 19:19:47 -0500
committerDavid S. Miller <davem@davemloft.net>2012-02-08 18:50:19 -0500
commit800c5eb7b5eba6cb2a32738d763fd59f0fbcdde4 (patch)
tree870a32bb186b395c7e70da55a1d1b17e37342336
parent7f1b0ea42a800713a3d56e1e8ca1a845e0461ca2 (diff)
af_iucv: change net_device handling for HS transport
This patch saves the net_device in the iucv_sock structure during bind in order to fasten skb sending. In addition some other small improvements are made for HS transport: - error checking when sending skbs - locking changes in afiucv_hs_callback_txnotify - skb freeing in afiucv_hs_callback_txnotify And finally it contains code cleanup to get rid of iucv_skb_queue_purge. Signed-off-by: Ursula Braun <ursula.braun@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--include/net/iucv/af_iucv.h1
-rw-r--r--net/iucv/af_iucv.c119
2 files changed, 63 insertions, 57 deletions
diff --git a/include/net/iucv/af_iucv.h b/include/net/iucv/af_iucv.h
index 0954ec95915..a1517887aea 100644
--- a/include/net/iucv/af_iucv.h
+++ b/include/net/iucv/af_iucv.h
@@ -113,6 +113,7 @@ struct iucv_sock {
113 spinlock_t accept_q_lock; 113 spinlock_t accept_q_lock;
114 struct sock *parent; 114 struct sock *parent;
115 struct iucv_path *path; 115 struct iucv_path *path;
116 struct net_device *hs_dev;
116 struct sk_buff_head send_skb_q; 117 struct sk_buff_head send_skb_q;
117 struct sk_buff_head backlog_skb_q; 118 struct sk_buff_head backlog_skb_q;
118 struct sock_msg_q message_q; 119 struct sock_msg_q message_q;
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c
index ef6ab71921f..fbce4a3126d 100644
--- a/net/iucv/af_iucv.c
+++ b/net/iucv/af_iucv.c
@@ -131,17 +131,6 @@ static inline void low_nmcpy(unsigned char *dst, char *src)
131 memcpy(&dst[8], src, 8); 131 memcpy(&dst[8], src, 8);
132} 132}
133 133
134static void iucv_skb_queue_purge(struct sk_buff_head *list)
135{
136 struct sk_buff *skb;
137
138 while ((skb = skb_dequeue(list)) != NULL) {
139 if (skb->dev)
140 dev_put(skb->dev);
141 kfree_skb(skb);
142 }
143}
144
145static int afiucv_pm_prepare(struct device *dev) 134static int afiucv_pm_prepare(struct device *dev)
146{ 135{
147#ifdef CONFIG_PM_DEBUG 136#ifdef CONFIG_PM_DEBUG
@@ -176,7 +165,7 @@ static int afiucv_pm_freeze(struct device *dev)
176 read_lock(&iucv_sk_list.lock); 165 read_lock(&iucv_sk_list.lock);
177 sk_for_each(sk, node, &iucv_sk_list.head) { 166 sk_for_each(sk, node, &iucv_sk_list.head) {
178 iucv = iucv_sk(sk); 167 iucv = iucv_sk(sk);
179 iucv_skb_queue_purge(&iucv->send_skb_q); 168 skb_queue_purge(&iucv->send_skb_q);
180 skb_queue_purge(&iucv->backlog_skb_q); 169 skb_queue_purge(&iucv->backlog_skb_q);
181 switch (sk->sk_state) { 170 switch (sk->sk_state) {
182 case IUCV_DISCONN: 171 case IUCV_DISCONN:
@@ -337,7 +326,6 @@ static void iucv_sock_wake_msglim(struct sock *sk)
337static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, 326static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
338 struct sk_buff *skb, u8 flags) 327 struct sk_buff *skb, u8 flags)
339{ 328{
340 struct net *net = sock_net(sock);
341 struct iucv_sock *iucv = iucv_sk(sock); 329 struct iucv_sock *iucv = iucv_sk(sock);
342 struct af_iucv_trans_hdr *phs_hdr; 330 struct af_iucv_trans_hdr *phs_hdr;
343 struct sk_buff *nskb; 331 struct sk_buff *nskb;
@@ -374,10 +362,10 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
374 if (imsg) 362 if (imsg)
375 memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message)); 363 memcpy(&phs_hdr->iucv_hdr, imsg, sizeof(struct iucv_message));
376 364
377 skb->dev = dev_get_by_index(net, sock->sk_bound_dev_if); 365 skb->dev = iucv->hs_dev;
378 if (!skb->dev) 366 if (!skb->dev)
379 return -ENODEV; 367 return -ENODEV;
380 if (!(skb->dev->flags & IFF_UP)) 368 if (!(skb->dev->flags & IFF_UP) || !netif_carrier_ok(skb->dev))
381 return -ENETDOWN; 369 return -ENETDOWN;
382 if (skb->len > skb->dev->mtu) { 370 if (skb->len > skb->dev->mtu) {
383 if (sock->sk_type == SOCK_SEQPACKET) 371 if (sock->sk_type == SOCK_SEQPACKET)
@@ -392,15 +380,14 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock,
392 return -ENOMEM; 380 return -ENOMEM;
393 skb_queue_tail(&iucv->send_skb_q, nskb); 381 skb_queue_tail(&iucv->send_skb_q, nskb);
394 err = dev_queue_xmit(skb); 382 err = dev_queue_xmit(skb);
395 if (err) { 383 if (net_xmit_eval(err)) {
396 skb_unlink(nskb, &iucv->send_skb_q); 384 skb_unlink(nskb, &iucv->send_skb_q);
397 dev_put(nskb->dev);
398 kfree_skb(nskb); 385 kfree_skb(nskb);
399 } else { 386 } else {
400 atomic_sub(confirm_recv, &iucv->msg_recv); 387 atomic_sub(confirm_recv, &iucv->msg_recv);
401 WARN_ON(atomic_read(&iucv->msg_recv) < 0); 388 WARN_ON(atomic_read(&iucv->msg_recv) < 0);
402 } 389 }
403 return err; 390 return net_xmit_eval(err);
404} 391}
405 392
406static struct sock *__iucv_get_sock_by_name(char *nm) 393static struct sock *__iucv_get_sock_by_name(char *nm)
@@ -471,7 +458,8 @@ static void iucv_sock_close(struct sock *sk)
471{ 458{
472 struct iucv_sock *iucv = iucv_sk(sk); 459 struct iucv_sock *iucv = iucv_sk(sk);
473 unsigned long timeo; 460 unsigned long timeo;
474 int err, blen; 461 int err = 0;
462 int blen;
475 struct sk_buff *skb; 463 struct sk_buff *skb;
476 464
477 lock_sock(sk); 465 lock_sock(sk);
@@ -498,7 +486,7 @@ static void iucv_sock_close(struct sock *sk)
498 sk->sk_state = IUCV_CLOSING; 486 sk->sk_state = IUCV_CLOSING;
499 sk->sk_state_change(sk); 487 sk->sk_state_change(sk);
500 488
501 if (!skb_queue_empty(&iucv->send_skb_q)) { 489 if (!err && !skb_queue_empty(&iucv->send_skb_q)) {
502 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) 490 if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
503 timeo = sk->sk_lingertime; 491 timeo = sk->sk_lingertime;
504 else 492 else
@@ -515,13 +503,19 @@ static void iucv_sock_close(struct sock *sk)
515 sk->sk_err = ECONNRESET; 503 sk->sk_err = ECONNRESET;
516 sk->sk_state_change(sk); 504 sk->sk_state_change(sk);
517 505
518 iucv_skb_queue_purge(&iucv->send_skb_q); 506 skb_queue_purge(&iucv->send_skb_q);
519 skb_queue_purge(&iucv->backlog_skb_q); 507 skb_queue_purge(&iucv->backlog_skb_q);
520 508
521 default: /* fall through */ 509 default: /* fall through */
522 iucv_sever_path(sk, 1); 510 iucv_sever_path(sk, 1);
523 } 511 }
524 512
513 if (iucv->hs_dev) {
514 dev_put(iucv->hs_dev);
515 iucv->hs_dev = NULL;
516 sk->sk_bound_dev_if = 0;
517 }
518
525 /* mark socket for deletion by iucv_sock_kill() */ 519 /* mark socket for deletion by iucv_sock_kill() */
526 sock_set_flag(sk, SOCK_ZAPPED); 520 sock_set_flag(sk, SOCK_ZAPPED);
527 521
@@ -713,7 +707,6 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
713 goto done_unlock; 707 goto done_unlock;
714 708
715 /* Bind the socket */ 709 /* Bind the socket */
716
717 if (pr_iucv) 710 if (pr_iucv)
718 if (!memcmp(sa->siucv_user_id, iucv_userid, 8)) 711 if (!memcmp(sa->siucv_user_id, iucv_userid, 8))
719 goto vm_bind; /* VM IUCV transport */ 712 goto vm_bind; /* VM IUCV transport */
@@ -727,6 +720,8 @@ static int iucv_sock_bind(struct socket *sock, struct sockaddr *addr,
727 memcpy(iucv->src_name, sa->siucv_name, 8); 720 memcpy(iucv->src_name, sa->siucv_name, 8);
728 memcpy(iucv->src_user_id, sa->siucv_user_id, 8); 721 memcpy(iucv->src_user_id, sa->siucv_user_id, 8);
729 sk->sk_bound_dev_if = dev->ifindex; 722 sk->sk_bound_dev_if = dev->ifindex;
723 iucv->hs_dev = dev;
724 dev_hold(dev);
730 sk->sk_state = IUCV_BOUND; 725 sk->sk_state = IUCV_BOUND;
731 iucv->transport = AF_IUCV_TRANS_HIPER; 726 iucv->transport = AF_IUCV_TRANS_HIPER;
732 if (!iucv->msglimit) 727 if (!iucv->msglimit)
@@ -1128,8 +1123,10 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
1128 noblock, &err); 1123 noblock, &err);
1129 else 1124 else
1130 skb = sock_alloc_send_skb(sk, len, noblock, &err); 1125 skb = sock_alloc_send_skb(sk, len, noblock, &err);
1131 if (!skb) 1126 if (!skb) {
1127 err = -ENOMEM;
1132 goto out; 1128 goto out;
1129 }
1133 if (iucv->transport == AF_IUCV_TRANS_HIPER) 1130 if (iucv->transport == AF_IUCV_TRANS_HIPER)
1134 skb_reserve(skb, sizeof(struct af_iucv_trans_hdr) + ETH_HLEN); 1131 skb_reserve(skb, sizeof(struct af_iucv_trans_hdr) + ETH_HLEN);
1135 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { 1132 if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
@@ -1152,6 +1149,7 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
1152 /* increment and save iucv message tag for msg_completion cbk */ 1149 /* increment and save iucv message tag for msg_completion cbk */
1153 txmsg.tag = iucv->send_tag++; 1150 txmsg.tag = iucv->send_tag++;
1154 memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN); 1151 memcpy(CB_TAG(skb), &txmsg.tag, CB_TAG_LEN);
1152
1155 if (iucv->transport == AF_IUCV_TRANS_HIPER) { 1153 if (iucv->transport == AF_IUCV_TRANS_HIPER) {
1156 atomic_inc(&iucv->msg_sent); 1154 atomic_inc(&iucv->msg_sent);
1157 err = afiucv_hs_send(&txmsg, sk, skb, 0); 1155 err = afiucv_hs_send(&txmsg, sk, skb, 0);
@@ -1206,8 +1204,6 @@ release:
1206 return len; 1204 return len;
1207 1205
1208fail: 1206fail:
1209 if (skb->dev)
1210 dev_put(skb->dev);
1211 kfree_skb(skb); 1207 kfree_skb(skb);
1212out: 1208out:
1213 release_sock(sk); 1209 release_sock(sk);
@@ -1400,7 +1396,14 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock,
1400 } 1396 }
1401 1397
1402