aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2011-01-22 17:44:59 -0500
committerArnd Bergmann <arnd@arndb.de>2011-03-05 04:55:45 -0500
commit77b2283604bdd7053494a97b0e2fee97148206c6 (patch)
tree4d5c54156d64fd80de765cc18dc7e4a68b5ec5e1
parent788257d6101d986ac8f2741aaa35974af47f574c (diff)
x25: remove the BKL
This replaces all instances of lock_kernel in x25 with lock_sock, taking care to release the socket lock around sleeping functions (sock_alloc_send_skb and skb_recv_datagram). It is not clear whether this is a correct solution, but it seem to be what other protocols do in the same situation. Includes a fix suggested by Eric Dumazet. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: David S. Miller <davem@davemloft.net> Tested-by: Andrew Hendry <andrew.hendry@gmail.com> Cc: linux-x25@vger.kernel.org Cc: netdev@vger.kernel.org Cc: Eric Dumazet <eric.dumazet@gmail.com>
-rw-r--r--net/x25/Kconfig1
-rw-r--r--net/x25/af_x25.c58
-rw-r--r--net/x25/x25_out.c7
3 files changed, 23 insertions, 43 deletions
diff --git a/net/x25/Kconfig b/net/x25/Kconfig
index 2196e55e4f61..e6759c9660bb 100644
--- a/net/x25/Kconfig
+++ b/net/x25/Kconfig
@@ -5,7 +5,6 @@
5config X25 5config X25
6 tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)" 6 tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)"
7 depends on EXPERIMENTAL 7 depends on EXPERIMENTAL
8 depends on BKL # should be fixable
9 ---help--- 8 ---help---
10 X.25 is a set of standardized network protocols, similar in scope to 9 X.25 is a set of standardized network protocols, similar in scope to
11 frame relay; the one physical line from your box to the X.25 network 10 frame relay; the one physical line from your box to the X.25 network
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index ad96ee90fe27..4680b1e4c79c 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -40,7 +40,6 @@
40#include <linux/errno.h> 40#include <linux/errno.h>
41#include <linux/kernel.h> 41#include <linux/kernel.h>
42#include <linux/sched.h> 42#include <linux/sched.h>
43#include <linux/smp_lock.h>
44#include <linux/timer.h> 43#include <linux/timer.h>
45#include <linux/string.h> 44#include <linux/string.h>
46#include <linux/net.h> 45#include <linux/net.h>
@@ -432,15 +431,6 @@ void x25_destroy_socket_from_timer(struct sock *sk)
432 sock_put(sk); 431 sock_put(sk);
433} 432}
434 433
435static void x25_destroy_socket(struct sock *sk)
436{
437 sock_hold(sk);
438 lock_sock(sk);
439 __x25_destroy_socket(sk);
440 release_sock(sk);
441 sock_put(sk);
442}
443
444/* 434/*
445 * Handling for system calls applied via the various interfaces to a 435 * Handling for system calls applied via the various interfaces to a
446 * X.25 socket object. 436 * X.25 socket object.
@@ -647,18 +637,19 @@ static int x25_release(struct socket *sock)
647 struct sock *sk = sock->sk; 637 struct sock *sk = sock->sk;
648 struct x25_sock *x25; 638 struct x25_sock *x25;
649 639
650 lock_kernel();
651 if (!sk) 640 if (!sk)
652 goto out; 641 return 0;
653 642
654 x25 = x25_sk(sk); 643 x25 = x25_sk(sk);
655 644
645 sock_hold(sk);
646 lock_sock(sk);
656 switch (x25->state) { 647 switch (x25->state) {
657 648
658 case X25_STATE_0: 649 case X25_STATE_0:
659 case X25_STATE_2: 650 case X25_STATE_2:
660 x25_disconnect(sk, 0, 0, 0); 651 x25_disconnect(sk, 0, 0, 0);
661 x25_destroy_socket(sk); 652 __x25_destroy_socket(sk);
662 goto out; 653 goto out;
663 654
664 case X25_STATE_1: 655 case X25_STATE_1:
@@ -678,7 +669,8 @@ static int x25_release(struct socket *sock)
678 669
679 sock_orphan(sk); 670 sock_orphan(sk);
680out: 671out:
681 unlock_kernel(); 672 release_sock(sk);
673 sock_put(sk);
682 return 0; 674 return 0;
683} 675}
684 676
@@ -1085,7 +1077,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
1085 size_t size; 1077 size_t size;
1086 int qbit = 0, rc = -EINVAL; 1078 int qbit = 0, rc = -EINVAL;
1087 1079
1088 lock_kernel(); 1080 lock_sock(sk);
1089 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) 1081 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
1090 goto out; 1082 goto out;
1091 1083
@@ -1148,7 +1140,9 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
1148 1140
1149 size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN; 1141 size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN;
1150 1142
1143 release_sock(sk);
1151 skb = sock_alloc_send_skb(sk, size, noblock, &rc); 1144 skb = sock_alloc_send_skb(sk, size, noblock, &rc);
1145 lock_sock(sk);
1152 if (!skb) 1146 if (!skb)
1153 goto out; 1147 goto out;
1154 X25_SKB_CB(skb)->flags = msg->msg_flags; 1148 X25_SKB_CB(skb)->flags = msg->msg_flags;
@@ -1231,26 +1225,10 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
1231 len++; 1225 len++;
1232 } 1226 }
1233 1227
1234 /*
1235 * lock_sock() is currently only used to serialize this x25_kick()
1236 * against input-driven x25_kick() calls. It currently only blocks
1237 * incoming packets for this socket and does not protect against
1238 * any other socket state changes and is not called from anywhere
1239 * else. As x25_kick() cannot block and as long as all socket
1240 * operations are BKL-wrapped, we don't need take to care about
1241 * purging the backlog queue in x25_release().
1242 *
1243 * Using lock_sock() to protect all socket operations entirely
1244 * (and making the whole x25 stack SMP aware) unfortunately would
1245 * require major changes to {send,recv}msg and skb allocation methods.
1246 * -> 2.5 ;)
1247 */
1248 lock_sock(sk);
1249 x25_kick(sk); 1228 x25_kick(sk);
1250 release_sock(sk);
1251 rc = len; 1229 rc = len;
1252out: 1230out:
1253 unlock_kernel(); 1231 release_sock(sk);
1254 return rc; 1232 return rc;
1255out_kfree_skb: 1233out_kfree_skb:
1256 kfree_skb(skb); 1234 kfree_skb(skb);
@@ -1271,7 +1249,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
1271 unsigned char *asmptr; 1249 unsigned char *asmptr;
1272 int rc = -ENOTCONN; 1250 int rc = -ENOTCONN;
1273 1251
1274 lock_kernel(); 1252 lock_sock(sk);
1275 /* 1253 /*
1276 * This works for seqpacket too. The receiver has ordered the queue for 1254 * This works for seqpacket too. The receiver has ordered the queue for
1277 * us! We do one quick check first though 1255 * us! We do one quick check first though
@@ -1300,8 +1278,10 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
1300 msg->msg_flags |= MSG_OOB; 1278 msg->msg_flags |= MSG_OOB;
1301 } else { 1279 } else {
1302 /* Now we can treat all alike */ 1280 /* Now we can treat all alike */
1281 release_sock(sk);
1303 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 1282 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
1304 flags & MSG_DONTWAIT, &rc); 1283 flags & MSG_DONTWAIT, &rc);
1284 lock_sock(sk);
1305 if (!skb) 1285 if (!skb)
1306 goto out; 1286 goto out;
1307 1287
@@ -1338,14 +1318,12 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
1338 1318
1339 msg->msg_namelen = sizeof(struct sockaddr_x25); 1319 msg->msg_namelen = sizeof(struct sockaddr_x25);
1340 1320
1341 lock_sock(sk);
1342 x25_check_rbuf(sk); 1321 x25_check_rbuf(sk);
1343 release_sock(sk);
1344 rc = copied; 1322 rc = copied;
1345out_free_dgram: 1323out_free_dgram:
1346 skb_free_datagram(sk, skb); 1324 skb_free_datagram(sk, skb);
1347out: 1325out:
1348 unlock_kernel(); 1326 release_sock(sk);
1349 return rc; 1327 return rc;
1350} 1328}
1351 1329
@@ -1581,18 +1559,18 @@ out_cud_release:
1581 1559
1582 case SIOCX25CALLACCPTAPPRV: { 1560 case SIOCX25CALLACCPTAPPRV: {
1583 rc = -EINVAL; 1561 rc = -EINVAL;
1584 lock_kernel(); 1562 lock_sock(sk);
1585 if (sk->sk_state != TCP_CLOSE) 1563 if (sk->sk_state != TCP_CLOSE)
1586 break; 1564 break;
1587 clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); 1565 clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags);
1588 unlock_kernel(); 1566 release_sock(sk);
1589 rc = 0; 1567 rc = 0;
1590 break; 1568 break;
1591 } 1569 }
1592 1570
1593 case SIOCX25SENDCALLACCPT: { 1571 case SIOCX25SENDCALLACCPT: {
1594 rc = -EINVAL; 1572 rc = -EINVAL;
1595 lock_kernel(); 1573 lock_sock(sk);
1596 if (sk->sk_state != TCP_ESTABLISHED) 1574 if (sk->sk_state != TCP_ESTABLISHED)
1597 break; 1575 break;
1598 /* must call accptapprv above */ 1576 /* must call accptapprv above */
@@ -1600,7 +1578,7 @@ out_cud_release:
1600 break; 1578 break;
1601 x25_write_internal(sk, X25_CALL_ACCEPTED); 1579 x25_write_internal(sk, X25_CALL_ACCEPTED);
1602 x25->state = X25_STATE_3; 1580 x25->state = X25_STATE_3;
1603 unlock_kernel(); 1581 release_sock(sk);
1604 rc = 0; 1582 rc = 0;
1605 break; 1583 break;
1606 } 1584 }
diff --git a/net/x25/x25_out.c b/net/x25/x25_out.c
index d00649fb251d..0144271d2184 100644
--- a/net/x25/x25_out.c
+++ b/net/x25/x25_out.c
@@ -68,8 +68,11 @@ int x25_output(struct sock *sk, struct sk_buff *skb)
68 frontlen = skb_headroom(skb); 68 frontlen = skb_headroom(skb);
69 69
70 while (skb->len > 0) { 70 while (skb->len > 0) {
71 if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 71 release_sock(sk);
72 noblock, &err)) == NULL){ 72 skbn = sock_alloc_send_skb(sk, frontlen + max_len,
73 noblock, &err);
74 lock_sock(sk);
75 if (!skbn) {
73 if (err == -EWOULDBLOCK && noblock){ 76 if (err == -EWOULDBLOCK && noblock){
74 kfree_skb(skb); 77 kfree_skb(skb);
75 return sent; 78 return sent;