Commit ecced8ba authored by Arnd Bergmann's avatar Arnd Bergmann Committed by David S. Miller

net/appletalk: push down BKL into a atalk_dgram_ops

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