net/appletalk: push down BKL into a atalk_dgram_ops
authorArnd Bergmann <arnd@arndb.de>
Thu, 5 Nov 2009 04:37:26 +0000 (04:37 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 7 Nov 2009 08:46:37 +0000 (00:46 -0800)
Making the BKL usage explicit in appletalk makes it more
obvious where it is used, reduces code size and helps
getting rid of the BKL in common code.

I did not analyse how to kill lock_kernel from appletalk
entirely, this will involve either proving that it's not
needed, or replacing with a proper mutex or spinlock,
after finding out which data structures are protected
by the lock.

Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Cc: David S. Miller <davem@davemloft.net>
Cc: Stephen Hemminger <shemminger@vyatta.com>
Cc: netdev@vger.kernel.org
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/appletalk/ddp.c

index 7cd08b45c52b12590cf3f3c4e141b4ebb6cf1b78..31fca64d17a2b9cea30cf162834fe1cb6fea35f2 100644 (file)
@@ -1055,11 +1055,13 @@ static int atalk_release(struct socket *sock)
 {
        struct sock *sk = sock->sk;
 
+       lock_kernel();
        if (sk) {
                sock_orphan(sk);
                sock->sk = NULL;
                atalk_destroy_socket(sk);
        }
+       unlock_kernel();
        return 0;
 }
 
@@ -1135,6 +1137,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_at *addr = (struct sockaddr_at *)uaddr;
        struct sock *sk = sock->sk;
        struct atalk_sock *at = at_sk(sk);
+       int err;
 
        if (!sock_flag(sk, SOCK_ZAPPED) ||
            addr_len != sizeof(struct sockaddr_at))
@@ -1143,37 +1146,44 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        if (addr->sat_family != AF_APPLETALK)
                return -EAFNOSUPPORT;
 
+       lock_kernel();
        if (addr->sat_addr.s_net == htons(ATADDR_ANYNET)) {
                struct atalk_addr *ap = atalk_find_primary();
 
+               err = -EADDRNOTAVAIL;
                if (!ap)
-                       return -EADDRNOTAVAIL;
+                       goto out;
 
                at->src_net  = addr->sat_addr.s_net = ap->s_net;
                at->src_node = addr->sat_addr.s_node= ap->s_node;
        } else {
+               err = -EADDRNOTAVAIL;
                if (!atalk_find_interface(addr->sat_addr.s_net,
                                          addr->sat_addr.s_node))
-                       return -EADDRNOTAVAIL;
+                       goto out;
 
                at->src_net  = addr->sat_addr.s_net;
                at->src_node = addr->sat_addr.s_node;
        }
 
        if (addr->sat_port == ATADDR_ANYPORT) {
-               int n = atalk_pick_and_bind_port(sk, addr);
+               err = atalk_pick_and_bind_port(sk, addr);
 
-               if (n < 0)
-                       return n;
+               if (err < 0)
+                       goto out;
        } else {
                at->src_port = addr->sat_port;
 
+               err = -EADDRINUSE;
                if (atalk_find_or_insert_socket(sk, addr))
-                       return -EADDRINUSE;
+                       goto out;
        }
 
        sock_reset_flag(sk, SOCK_ZAPPED);
-       return 0;
+       err = 0;
+out:
+       unlock_kernel();
+       return err;
 }
 
 /* Set the address we talk to */
@@ -1183,6 +1193,7 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
        struct sock *sk = sock->sk;
        struct atalk_sock *at = at_sk(sk);
        struct sockaddr_at *addr;
+       int err;
 
        sk->sk_state   = TCP_CLOSE;
        sock->state = SS_UNCONNECTED;
@@ -1207,12 +1218,15 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 #endif
        }
 
+       lock_kernel();
+       err = -EBUSY;
        if (sock_flag(sk, SOCK_ZAPPED))
                if (atalk_autobind(sk) < 0)
-                       return -EBUSY;
+                       goto out;
 
+       err = -ENETUNREACH;
        if (!atrtr_get_dev(&addr->sat_addr))
-               return -ENETUNREACH;
+               goto out;
 
        at->dest_port = addr->sat_port;
        at->dest_net  = addr->sat_addr.s_net;
@@ -1220,7 +1234,10 @@ static int atalk_connect(struct socket *sock, struct sockaddr *uaddr,
 
        sock->state  = SS_CONNECTED;
        sk->sk_state = TCP_ESTABLISHED;
-       return 0;
+       err = 0;
+out:
+       unlock_kernel();
+       return err;
 }
 
 /*
@@ -1233,17 +1250,21 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
        struct sockaddr_at sat;
        struct sock *sk = sock->sk;
        struct atalk_sock *at = at_sk(sk);
+       int err;
 
+       lock_kernel();
+       err = -ENOBUFS;
        if (sock_flag(sk, SOCK_ZAPPED))
                if (atalk_autobind(sk) < 0)
-                       return -ENOBUFS;
+                       goto out;
 
        *uaddr_len = sizeof(struct sockaddr_at);
        memset(&sat.sat_zero, 0, sizeof(sat.sat_zero));
 
        if (peer) {
+               err = -ENOTCONN;
                if (sk->sk_state != TCP_ESTABLISHED)
-                       return -ENOTCONN;
+                       goto out;
 
                sat.sat_addr.s_net  = at->dest_net;
                sat.sat_addr.s_node = at->dest_node;
@@ -1254,9 +1275,23 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr,
                sat.sat_port        = at->src_port;
        }
 
+       err = 0;
        sat.sat_family = AF_APPLETALK;
        memcpy(uaddr, &sat, sizeof(sat));
-       return 0;
+
+out:
+       unlock_kernel();
+       return err;
+}
+
+static unsigned int atalk_poll(struct file *file, struct socket *sock,
+                          poll_table *wait)
+{
+       int err;
+       lock_kernel();
+       err = datagram_poll(file, sock, wait);
+       unlock_kernel();
+       return err;
 }
 
 #if defined(CONFIG_IPDDP) || defined(CONFIG_IPDDP_MODULE)
@@ -1564,23 +1599,28 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        if (len > DDP_MAXSZ)
                return -EMSGSIZE;
 
+       lock_kernel();
        if (usat) {
+               err = -EBUSY;
                if (sock_flag(sk, SOCK_ZAPPED))
                        if (atalk_autobind(sk) < 0)
-                               return -EBUSY;
+                               goto out;
 
+               err = -EINVAL;
                if (msg->msg_namelen < sizeof(*usat) ||
                    usat->sat_family != AF_APPLETALK)
-                       return -EINVAL;
+                       goto out;
 
+               err = -EPERM;
                /* netatalk didn't implement this check */
                if (usat->sat_addr.s_node == ATADDR_BCAST &&
                    !sock_flag(sk, SOCK_BROADCAST)) {
-                       return -EPERM;
+                       goto out;
                }
        } else {
+               err = -ENOTCONN;
                if (sk->sk_state != TCP_ESTABLISHED)
-                       return -ENOTCONN;
+                       goto out;
                usat = &local_satalk;
                usat->sat_family      = AF_APPLETALK;
                usat->sat_port        = at->dest_port;
@@ -1604,8 +1644,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
 
                rt = atrtr_find(&at_hint);
        }
+       err = ENETUNREACH;
        if (!rt)
-               return -ENETUNREACH;
+               goto out;
 
        dev = rt->dev;
 
@@ -1615,7 +1656,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        size += dev->hard_header_len;
        skb = sock_alloc_send_skb(sk, size, (flags & MSG_DONTWAIT), &err);
        if (!skb)
-               return err;
+               goto out;
 
        skb->sk = sk;
        skb_reserve(skb, ddp_dl->header_length);
@@ -1638,7 +1679,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        err = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
        if (err) {
                kfree_skb(skb);
-               return -EFAULT;
+               err = -EFAULT;
+               goto out;
        }
 
        if (sk->sk_no_check == 1)
@@ -1677,7 +1719,8 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
                        rt = atrtr_find(&at_lo);
                        if (!rt) {
                                kfree_skb(skb);
-                               return -ENETUNREACH;
+                               err = -ENETUNREACH;
+                               goto out;
                        }
                        dev = rt->dev;
                        skb->dev = dev;
@@ -1697,7 +1740,9 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        }
        SOCK_DEBUG(sk, "SK %p: Done write (%Zd).\n", sk, len);
 
-       return len;
+out:
+       unlock_kernel();
+       return err ? : len;
 }
 
 static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
@@ -1709,10 +1754,13 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        int copied = 0;
        int offset = 0;
        int err = 0;
-       struct sk_buff *skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
+       struct sk_buff *skb;
+
+       lock_kernel();
+       skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
                                                flags & MSG_DONTWAIT, &err);
        if (!skb)
-               return err;
+               goto out;
 
        /* FIXME: use skb->cb to be able to use shared skbs */
        ddp = ddp_hdr(skb);
@@ -1740,6 +1788,9 @@ static int atalk_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr
        }
 
        skb_free_datagram(sk, skb);     /* Free the datagram. */
+
+out:
+       unlock_kernel();
        return err ? : copied;
 }
 
@@ -1830,7 +1881,7 @@ static const struct net_proto_family atalk_family_ops = {
        .owner          = THIS_MODULE,
 };
 
-static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
+static const struct proto_ops atalk_dgram_ops = {
        .family         = PF_APPLETALK,
        .owner          = THIS_MODULE,
        .release        = atalk_release,
@@ -1839,7 +1890,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
        .socketpair     = sock_no_socketpair,
        .accept         = sock_no_accept,
        .getname        = atalk_getname,
-       .poll           = datagram_poll,
+       .poll           = atalk_poll,
        .ioctl          = atalk_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = atalk_compat_ioctl,
@@ -1854,8 +1905,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(atalk_dgram_ops) = {
        .sendpage       = sock_no_sendpage,
 };
 
-SOCKOPS_WRAP(atalk_dgram, PF_APPLETALK);
-
 static struct notifier_block ddp_notifier = {
        .notifier_call  = ddp_device_event,
 };