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

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>

+23 -43
-1
net/x25/Kconfig
··· 5 5 config X25 6 6 tristate "CCITT X.25 Packet Layer (EXPERIMENTAL)" 7 7 depends on EXPERIMENTAL 8 - depends on BKL # should be fixable 9 8 ---help--- 10 9 X.25 is a set of standardized network protocols, similar in scope to 11 10 frame relay; the one physical line from your box to the X.25 network
+18 -40
net/x25/af_x25.c
··· 40 40 #include <linux/errno.h> 41 41 #include <linux/kernel.h> 42 42 #include <linux/sched.h> 43 - #include <linux/smp_lock.h> 44 43 #include <linux/timer.h> 45 44 #include <linux/string.h> 46 45 #include <linux/net.h> ··· 431 432 sock_put(sk); 432 433 } 433 434 434 - static void x25_destroy_socket(struct sock *sk) 435 - { 436 - sock_hold(sk); 437 - lock_sock(sk); 438 - __x25_destroy_socket(sk); 439 - release_sock(sk); 440 - sock_put(sk); 441 - } 442 - 443 435 /* 444 436 * Handling for system calls applied via the various interfaces to a 445 437 * X.25 socket object. ··· 637 647 struct sock *sk = sock->sk; 638 648 struct x25_sock *x25; 639 649 640 - lock_kernel(); 641 650 if (!sk) 642 - goto out; 651 + return 0; 643 652 644 653 x25 = x25_sk(sk); 645 654 655 + sock_hold(sk); 656 + lock_sock(sk); 646 657 switch (x25->state) { 647 658 648 659 case X25_STATE_0: 649 660 case X25_STATE_2: 650 661 x25_disconnect(sk, 0, 0, 0); 651 - x25_destroy_socket(sk); 662 + __x25_destroy_socket(sk); 652 663 goto out; 653 664 654 665 case X25_STATE_1: ··· 669 678 670 679 sock_orphan(sk); 671 680 out: 672 - unlock_kernel(); 681 + release_sock(sk); 682 + sock_put(sk); 673 683 return 0; 674 684 } 675 685 ··· 1077 1085 size_t size; 1078 1086 int qbit = 0, rc = -EINVAL; 1079 1087 1080 - lock_kernel(); 1088 + lock_sock(sk); 1081 1089 if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT)) 1082 1090 goto out; 1083 1091 ··· 1140 1148 1141 1149 size = len + X25_MAX_L2_LEN + X25_EXT_MIN_LEN; 1142 1150 1151 + release_sock(sk); 1143 1152 skb = sock_alloc_send_skb(sk, size, noblock, &rc); 1153 + lock_sock(sk); 1144 1154 if (!skb) 1145 1155 goto out; 1146 1156 X25_SKB_CB(skb)->flags = msg->msg_flags; ··· 1225 1231 len++; 1226 1232 } 1227 1233 1228 - /* 1229 - * lock_sock() is currently only used to serialize this x25_kick() 1230 - * against input-driven x25_kick() calls. It currently only blocks 1231 - * incoming packets for this socket and does not protect against 1232 - * any other socket state changes and is not called from anywhere 1233 - * else. As x25_kick() cannot block and as long as all socket 1234 - * operations are BKL-wrapped, we don't need take to care about 1235 - * purging the backlog queue in x25_release(). 1236 - * 1237 - * Using lock_sock() to protect all socket operations entirely 1238 - * (and making the whole x25 stack SMP aware) unfortunately would 1239 - * require major changes to {send,recv}msg and skb allocation methods. 1240 - * -> 2.5 ;) 1241 - */ 1242 - lock_sock(sk); 1243 1234 x25_kick(sk); 1244 - release_sock(sk); 1245 1235 rc = len; 1246 1236 out: 1247 - unlock_kernel(); 1237 + release_sock(sk); 1248 1238 return rc; 1249 1239 out_kfree_skb: 1250 1240 kfree_skb(skb); ··· 1249 1271 unsigned char *asmptr; 1250 1272 int rc = -ENOTCONN; 1251 1273 1252 - lock_kernel(); 1274 + lock_sock(sk); 1253 1275 /* 1254 1276 * This works for seqpacket too. The receiver has ordered the queue for 1255 1277 * us! We do one quick check first though ··· 1278 1300 msg->msg_flags |= MSG_OOB; 1279 1301 } else { 1280 1302 /* Now we can treat all alike */ 1303 + release_sock(sk); 1281 1304 skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, 1282 1305 flags & MSG_DONTWAIT, &rc); 1306 + lock_sock(sk); 1283 1307 if (!skb) 1284 1308 goto out; 1285 1309 ··· 1318 1338 1319 1339 msg->msg_namelen = sizeof(struct sockaddr_x25); 1320 1340 1321 - lock_sock(sk); 1322 1341 x25_check_rbuf(sk); 1323 - release_sock(sk); 1324 1342 rc = copied; 1325 1343 out_free_dgram: 1326 1344 skb_free_datagram(sk, skb); 1327 1345 out: 1328 - unlock_kernel(); 1346 + release_sock(sk); 1329 1347 return rc; 1330 1348 } 1331 1349 ··· 1559 1581 1560 1582 case SIOCX25CALLACCPTAPPRV: { 1561 1583 rc = -EINVAL; 1562 - lock_kernel(); 1584 + lock_sock(sk); 1563 1585 if (sk->sk_state != TCP_CLOSE) 1564 1586 break; 1565 1587 clear_bit(X25_ACCPT_APPRV_FLAG, &x25->flags); 1566 - unlock_kernel(); 1588 + release_sock(sk); 1567 1589 rc = 0; 1568 1590 break; 1569 1591 } 1570 1592 1571 1593 case SIOCX25SENDCALLACCPT: { 1572 1594 rc = -EINVAL; 1573 - lock_kernel(); 1595 + lock_sock(sk); 1574 1596 if (sk->sk_state != TCP_ESTABLISHED) 1575 1597 break; 1576 1598 /* must call accptapprv above */ ··· 1578 1600 break; 1579 1601 x25_write_internal(sk, X25_CALL_ACCEPTED); 1580 1602 x25->state = X25_STATE_3; 1581 - unlock_kernel(); 1603 + release_sock(sk); 1582 1604 rc = 0; 1583 1605 break; 1584 1606 }
+5 -2
net/x25/x25_out.c
··· 68 68 frontlen = skb_headroom(skb); 69 69 70 70 while (skb->len > 0) { 71 - if ((skbn = sock_alloc_send_skb(sk, frontlen + max_len, 72 - noblock, &err)) == NULL){ 71 + release_sock(sk); 72 + skbn = sock_alloc_send_skb(sk, frontlen + max_len, 73 + noblock, &err); 74 + lock_sock(sk); 75 + if (!skbn) { 73 76 if (err == -EWOULDBLOCK && noblock){ 74 77 kfree_skb(skb); 75 78 return sent;