Skip to content

Commit

Permalink
net/appletalk: push down BKL into a atalk_dgram_ops
Browse files Browse the repository at this point in the history
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 <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: Stephen Hemminger <[email protected]>
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
arndb authored and davem330 committed Nov 7, 2009
1 parent c6060be commit ecced8b
Showing 1 changed file with 77 additions and 28 deletions.
105 changes: 77 additions & 28 deletions net/appletalk/ddp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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))
Expand All @@ -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 */
Expand All @@ -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;
Expand All @@ -1207,20 +1218,26 @@ 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;
at->dest_node = addr->sat_addr.s_node;

sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
return 0;
err = 0;
out:
unlock_kernel();
return err;
}

/*
Expand All @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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);
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
};
Expand Down

0 comments on commit ecced8b

Please sign in to comment.