net/ipx: push down BKL into a ipx_dgram_ops
[safe/jmp/linux-2.6] / net / ipx / af_ipx.c
index f7b4d38..975c5a3 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/netdevice.h>
 #include <linux/uio.h>
 #include <linux/skbuff.h>
+#include <linux/smp_lock.h>
 #include <linux/socket.h>
 #include <linux/sockios.h>
 #include <linux/string.h>
@@ -92,11 +93,6 @@ extern int ipxrtr_route_skb(struct sk_buff *skb);
 extern struct ipx_route *ipxrtr_lookup(__be32 net);
 extern int ipxrtr_ioctl(unsigned int cmd, void __user *arg);
 
-#undef IPX_REFCNT_DEBUG
-#ifdef IPX_REFCNT_DEBUG
-atomic_t ipx_sock_nr;
-#endif
-
 struct ipx_interface *ipx_interfaces_head(void)
 {
        struct ipx_interface *rc = NULL;
@@ -151,14 +147,7 @@ static void ipx_destroy_socket(struct sock *sk)
 {
        ipx_remove_socket(sk);
        skb_queue_purge(&sk->sk_receive_queue);
-#ifdef IPX_REFCNT_DEBUG
-       atomic_dec(&ipx_sock_nr);
-       printk(KERN_DEBUG "IPX socket %p released, %d are still alive\n", sk,
-                       atomic_read(&ipx_sock_nr));
-       if (atomic_read(&sk->sk_refcnt) != 1)
-               printk(KERN_DEBUG "Destruction sock ipx %p delayed, cnt=%d\n",
-                               sk, atomic_read(&sk->sk_refcnt));
-#endif
+       sk_refcnt_debug_dec(sk);
        sock_put(sk);
 }
 
@@ -347,6 +336,9 @@ static int ipxitf_device_event(struct notifier_block *notifier,
        struct net_device *dev = ptr;
        struct ipx_interface *i, *tmp;
 
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
        if (event != NETDEV_DOWN && event != NETDEV_UP)
                goto out;
 
@@ -986,7 +978,7 @@ static int ipxitf_create(struct ipx_interface_definition *idef)
        if (intrfc)
                ipxitf_put(intrfc);
 
-       dev = dev_get_by_name(idef->ipx_device);
+       dev = dev_get_by_name(&init_net, idef->ipx_device);
        rc = -ENODEV;
        if (!dev)
                goto out;
@@ -1094,7 +1086,7 @@ static int ipxitf_delete(struct ipx_interface_definition *idef)
        if (!dlink_type)
                goto out;
 
-       dev = __dev_get_by_name(idef->ipx_device);
+       dev = __dev_get_by_name(&init_net, idef->ipx_device);
        rc = -ENODEV;
        if (!dev)
                goto out;
@@ -1189,7 +1181,7 @@ static int ipxitf_ioctl(unsigned int cmd, void __user *arg)
                if (copy_from_user(&ifr, arg, sizeof(ifr)))
                        break;
                sipx = (struct sockaddr_ipx *)&ifr.ifr_addr;
-               dev  = __dev_get_by_name(ifr.ifr_name);
+               dev  = __dev_get_by_name(&init_net, ifr.ifr_name);
                rc   = -ENODEV;
                if (!dev)
                        break;
@@ -1300,12 +1292,13 @@ const char *ipx_device_name(struct ipx_interface *intrfc)
  * socket object. */
 
 static int ipx_setsockopt(struct socket *sock, int level, int optname,
-                         char __user *optval, int optlen)
+                         char __user *optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        int opt;
        int rc = -EINVAL;
 
+       lock_kernel();
        if (optlen != sizeof(int))
                goto out;
 
@@ -1320,6 +1313,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
        ipx_sk(sk)->type = opt;
        rc = 0;
 out:
+       unlock_kernel();
        return rc;
 }
 
@@ -1331,6 +1325,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
        int len;
        int rc = -ENOPROTOOPT;
 
+       lock_kernel();
        if (!(level == SOL_IPX && optname == IPX_TYPE))
                goto out;
 
@@ -1351,6 +1346,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,
 
        rc = 0;
 out:
+       unlock_kernel();
        return rc;
 }
 
@@ -1360,7 +1356,8 @@ static struct proto ipx_proto = {
        .obj_size = sizeof(struct ipx_sock),
 };
 
-static int ipx_create(struct net *net, struct socket *sock, int protocol)
+static int ipx_create(struct net *net, struct socket *sock, int protocol,
+                     int kern)
 {
        int rc = -ESOCKTNOSUPPORT;
        struct sock *sk;
@@ -1378,14 +1375,11 @@ static int ipx_create(struct net *net, struct socket *sock, int protocol)
                goto out;
 
        rc = -ENOMEM;
-       sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto, 1);
+       sk = sk_alloc(net, PF_IPX, GFP_KERNEL, &ipx_proto);
        if (!sk)
                goto out;
-#ifdef IPX_REFCNT_DEBUG
-       atomic_inc(&ipx_sock_nr);
-       printk(KERN_DEBUG "IPX socket %p created, now we have %d alive\n", sk,
-                       atomic_read(&ipx_sock_nr));
-#endif
+
+       sk_refcnt_debug_inc(sk);
        sock_init_data(sock, sk);
        sk->sk_no_check = 1;            /* Checksum off by default */
        sock->ops = &ipx_dgram_ops;
@@ -1401,12 +1395,15 @@ static int ipx_release(struct socket *sock)
        if (!sk)
                goto out;
 
+       lock_kernel();
        if (!sock_flag(sk, SOCK_DEAD))
                sk->sk_state_change(sk);
 
        sock_set_flag(sk, SOCK_DEAD);
        sock->sk = NULL;
+       sk_refcnt_debug_release(sk);
        ipx_destroy_socket(sk);
+       unlock_kernel();
 out:
        return 0;
 }
@@ -1434,7 +1431,8 @@ static __be16 ipx_first_free_socketnum(struct ipx_interface *intrfc)
        return htons(socketNum);
 }
 
-static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+static int __ipx_bind(struct socket *sock,
+                       struct sockaddr *uaddr, int addr_len)
 {
        struct sock *sk = sock->sk;
        struct ipx_sock *ipxs = ipx_sk(sk);
@@ -1529,6 +1527,17 @@ out:
        return rc;
 }
 
+static int ipx_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
+{
+       int rc;
+
+       lock_kernel();
+       rc = __ipx_bind(sock, uaddr, addr_len);
+       unlock_kernel();
+
+       return rc;
+}
+
 static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
        int addr_len, int flags)
 {
@@ -1541,6 +1550,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
        sk->sk_state    = TCP_CLOSE;
        sock->state     = SS_UNCONNECTED;
 
+       lock_kernel();
        if (addr_len != sizeof(*addr))
                goto out;
        addr = (struct sockaddr_ipx *)uaddr;
@@ -1560,7 +1570,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
                        IPX_NODE_LEN);
 #endif /* CONFIG_IPX_INTERN */
 
-               rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
                              sizeof(struct sockaddr_ipx));
                if (rc)
                        goto out;
@@ -1587,6 +1597,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
                ipxrtr_put(rt);
        rc = 0;
 out:
+       unlock_kernel();
        return rc;
 }
 
@@ -1602,6 +1613,7 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
        *uaddr_len = sizeof(struct sockaddr_ipx);
 
+       lock_kernel();
        if (peer) {
                rc = -ENOTCONN;
                if (sk->sk_state != TCP_ESTABLISHED)
@@ -1636,6 +1648,19 @@ static int ipx_getname(struct socket *sock, struct sockaddr *uaddr,
 
        rc = 0;
 out:
+       unlock_kernel();
+       return rc;
+}
+
+static unsigned int ipx_datagram_poll(struct file *file, struct socket *sock,
+                          poll_table *wait)
+{
+       int rc;
+
+       lock_kernel();
+       rc = datagram_poll(file, sock, wait);
+       unlock_kernel();
+
        return rc;
 }
 
@@ -1647,7 +1672,7 @@ static int ipx_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_ty
        u16 ipx_pktsize;
        int rc = 0;
 
-       if (dev->nd_net != &init_net)
+       if (!net_eq(dev_net(dev), &init_net))
                goto drop;
 
        /* Not ours */
@@ -1710,6 +1735,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
        int rc = -EINVAL;
        int flags = msg->msg_flags;
 
+       lock_kernel();
        /* Socket gets bound below anyway */
 /*     if (sk->sk_zapped)
                return -EIO; */ /* Socket not bound */
@@ -1733,7 +1759,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
                        memcpy(uaddr.sipx_node, ipxs->intrfc->if_node,
                                IPX_NODE_LEN);
 #endif
-                       rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+                       rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
                                        sizeof(struct sockaddr_ipx));
                        if (rc)
                                goto out;
@@ -1761,6 +1787,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
        if (rc >= 0)
                rc = len;
 out:
+       unlock_kernel();
        return rc;
 }
 
@@ -1775,6 +1802,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
        struct sk_buff *skb;
        int copied, rc;
 
+       lock_kernel();
        /* put the autobinding in */
        if (!ipxs->port) {
                struct sockaddr_ipx uaddr;
@@ -1789,7 +1817,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
                memcpy(uaddr.sipx_node, ipxs->intrfc->if_node, IPX_NODE_LEN);
 #endif /* CONFIG_IPX_INTERN */
 
-               rc = ipx_bind(sock, (struct sockaddr *)&uaddr,
+               rc = __ipx_bind(sock, (struct sockaddr *)&uaddr,
                              sizeof(struct sockaddr_ipx));
                if (rc)
                        goto out;
@@ -1833,6 +1861,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
 out_free:
        skb_free_datagram(sk, skb);
 out:
+       unlock_kernel();
        return rc;
 }
 
@@ -1844,9 +1873,10 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
        struct sock *sk = sock->sk;
        void __user *argp = (void __user *)arg;
 
+       lock_kernel();
        switch (cmd) {
        case TIOCOUTQ:
-               amount = sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc);
+               amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
                if (amount < 0)
                        amount = 0;
                rc = put_user(amount, (int __user *)argp);
@@ -1906,6 +1936,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                rc = -ENOIOCTLCMD;
                break;
        }
+       unlock_kernel();
 
        return rc;
 }
@@ -1937,13 +1968,13 @@ static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long
  * Socket family declarations
  */
 
-static struct net_proto_family ipx_family_ops = {
+static const struct net_proto_family ipx_family_ops = {
        .family         = PF_IPX,
        .create         = ipx_create,
        .owner          = THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
+static const struct proto_ops ipx_dgram_ops = {
        .family         = PF_IPX,
        .owner          = THIS_MODULE,
        .release        = ipx_release,
@@ -1952,7 +1983,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
        .socketpair     = sock_no_socketpair,
        .accept         = sock_no_accept,
        .getname        = ipx_getname,
-       .poll           = datagram_poll,
+       .poll           = ipx_datagram_poll,
        .ioctl          = ipx_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = ipx_compat_ioctl,
@@ -1967,15 +1998,13 @@ static const struct proto_ops SOCKOPS_WRAPPED(ipx_dgram_ops) = {
        .sendpage       = sock_no_sendpage,
 };
 
-SOCKOPS_WRAP(ipx_dgram, PF_IPX);
-
-static struct packet_type ipx_8023_packet_type = {
-       .type           = __constant_htons(ETH_P_802_3),
+static struct packet_type ipx_8023_packet_type __read_mostly = {
+       .type           = cpu_to_be16(ETH_P_802_3),
        .func           = ipx_rcv,
 };
 
-static struct packet_type ipx_dix_packet_type = {
-       .type           = __constant_htons(ETH_P_IPX),
+static struct packet_type ipx_dix_packet_type __read_mostly = {
+       .type           = cpu_to_be16(ETH_P_IPX),
        .func           = ipx_rcv,
 };
 
@@ -1986,15 +2015,15 @@ static struct notifier_block ipx_dev_notifier = {
 extern struct datalink_proto *make_EII_client(void);
 extern void destroy_EII_client(struct datalink_proto *);
 
-static unsigned char ipx_8022_type = 0xE0;
-static unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
-static char ipx_EII_err_msg[] __initdata =
+static const unsigned char ipx_8022_type = 0xE0;
+static const unsigned char ipx_snap_id[5] = { 0x0, 0x0, 0x0, 0x81, 0x37 };
+static const char ipx_EII_err_msg[] __initconst =
        KERN_CRIT "IPX: Unable to register with Ethernet II\n";
-static char ipx_8023_err_msg[] __initdata =
+static const char ipx_8023_err_msg[] __initconst =
        KERN_CRIT "IPX: Unable to register with 802.3\n";
-static char ipx_llc_err_msg[] __initdata =
+static const char ipx_llc_err_msg[] __initconst =
        KERN_CRIT "IPX: Unable to register with 802.2\n";
-static char ipx_snap_err_msg[] __initdata =
+static const char ipx_snap_err_msg[] __initconst =
        KERN_CRIT "IPX: Unable to register with SNAP\n";
 
 static int __init ipx_init(void)