2009-11-05 14:37:54

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 0/5] net: push down BKL into proto ops

This pushes one more use of the BKL from common code into specific
network protocols by killing off the proto ops wrappers.
This should cause no visible changes on the code but saves a few
kilobytes of object code in allyesconfig.

Arnd Bergmann (5):
net/appletalk: push down BKL into a atalk_dgram_ops
net/ipx: push down BKL into a ipx_dgram_ops
net/irda: push BKL into proto_ops
net/x25: push BKL usage into x25_proto
net: kill proto_ops wrapper

include/linux/net.h | 83 -------------
net/appletalk/ddp.c | 105 ++++++++++++-----
net/ipx/af_ipx.c | 54 +++++++--
net/irda/af_irda.c | 331 ++++++++++++++++++++++++++++++++++-----------------
net/x25/af_x25.c | 71 +++++++++--
5 files changed, 407 insertions(+), 237 deletions(-)


2009-11-05 14:37:46

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 1/5] 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 <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: Stephen Hemminger <[email protected]>
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
---
net/appletalk/ddp.c | 105 +++++++++++++++++++++++++++++++++++++-------------
1 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index b1a4290..3b831c0 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -1054,11 +1054,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;
}

@@ -1134,6 +1136,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))
@@ -1142,37 +1145,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 */
@@ -1182,6 +1192,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;
@@ -1206,12 +1217,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;
@@ -1219,7 +1233,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;
}

/*
@@ -1232,17 +1249,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;
@@ -1253,9 +1274,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)
@@ -1563,23 +1598,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;
@@ -1603,8 +1643,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;

@@ -1614,7 +1655,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);
@@ -1637,7 +1678,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)
@@ -1676,7 +1718,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;
@@ -1696,7 +1739,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,
@@ -1708,10 +1753,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);
@@ -1739,6 +1787,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;
}

@@ -1827,7 +1878,7 @@ static 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,
@@ -1836,7 +1887,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,
@@ -1851,8 +1902,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,
};
--
1.6.3.3

2009-11-05 14:38:02

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 2/5] net/ipx: push down BKL into a ipx_dgram_ops

Making the BKL usage explicit in ipx 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 ipx
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]>
---
net/ipx/af_ipx.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 46 insertions(+), 8 deletions(-)

diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c
index 66c7a20..f542c5b 100644
--- a/net/ipx/af_ipx.c
+++ b/net/ipx/af_ipx.c
@@ -1298,6 +1298,7 @@ static int ipx_setsockopt(struct socket *sock, int level, int optname,
int opt;
int rc = -EINVAL;

+ lock_kernel();
if (optlen != sizeof(int))
goto out;

@@ -1312,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;
}

@@ -1323,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;

@@ -1343,6 +1346,7 @@ static int ipx_getsockopt(struct socket *sock, int level, int optname,

rc = 0;
out:
+ unlock_kernel();
return rc;
}

@@ -1390,6 +1394,7 @@ static int ipx_release(struct socket *sock)
if (!sk)
goto out;

+ lock_kernel();
if (!sock_flag(sk, SOCK_DEAD))
sk->sk_state_change(sk);

@@ -1397,6 +1402,7 @@ static int ipx_release(struct socket *sock)
sock->sk = NULL;
sk_refcnt_debug_release(sk);
ipx_destroy_socket(sk);
+ unlock_kernel();
out:
return 0;
}
@@ -1424,7 +1430,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);
@@ -1519,6 +1526,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)
{
@@ -1531,6 +1549,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;
@@ -1550,7 +1569,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;
@@ -1577,6 +1596,7 @@ static int ipx_connect(struct socket *sock, struct sockaddr *uaddr,
ipxrtr_put(rt);
rc = 0;
out:
+ unlock_kernel();
return rc;
}

@@ -1592,6 +1612,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)
@@ -1626,6 +1647,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;
}

@@ -1700,6 +1734,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 */
@@ -1723,7 +1758,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;
@@ -1751,6 +1786,7 @@ static int ipx_sendmsg(struct kiocb *iocb, struct socket *sock,
if (rc >= 0)
rc = len;
out:
+ unlock_kernel();
return rc;
}

@@ -1765,6 +1801,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;
@@ -1779,7 +1816,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;
@@ -1823,6 +1860,7 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}

@@ -1834,6 +1872,7 @@ 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 - sk_wmem_alloc_get(sk);
@@ -1896,6 +1935,7 @@ static int ipx_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();

return rc;
}
@@ -1933,7 +1973,7 @@ static struct net_proto_family ipx_family_ops = {
.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,
@@ -1942,7 +1982,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,
@@ -1957,8 +1997,6 @@ 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 __read_mostly = {
.type = cpu_to_be16(ETH_P_802_3),
.func = ipx_rcv,
--
1.6.3.3

2009-11-05 14:38:31

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 3/5] net/irda: push BKL into proto_ops

The irda driver uses the BKL implicitly in its protocol
operations. Replace the wrapped proto_ops with explicit
lock_kernel() calls makes the usage more obvious and
shrinks the size of the object code.

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out

The calls t lock_kernel() should eventually all be replaced
by other serialization methods, which requires finding out
which data actually needs protection.

Cc: Samuel Ortiz <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
---
net/irda/af_irda.c | 331 +++++++++++++++++++++++++++++++++++-----------------
1 files changed, 224 insertions(+), 107 deletions(-)

diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c
index dd35641..7f84866 100644
--- a/net/irda/af_irda.c
+++ b/net/irda/af_irda.c
@@ -714,11 +714,14 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_irda saddr;
struct sock *sk = sock->sk;
struct irda_sock *self = irda_sk(sk);
+ int err;

+ lock_kernel();
memset(&saddr, 0, sizeof(saddr));
if (peer) {
+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;

saddr.sir_family = AF_IRDA;
saddr.sir_lsap_sel = self->dtsap_sel;
@@ -735,8 +738,10 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
/* uaddr_len come to us uninitialised */
*uaddr_len = sizeof (struct sockaddr_irda);
memcpy(uaddr, &saddr, *uaddr_len);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}

/*
@@ -748,21 +753,25 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr,
static int irda_listen(struct socket *sock, int backlog)
{
struct sock *sk = sock->sk;
+ int err = -EOPNOTSUPP;

IRDA_DEBUG(2, "%s()\n", __func__);

+ lock_kernel();
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM))
- return -EOPNOTSUPP;
+ goto out;

if (sk->sk_state != TCP_LISTEN) {
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;

- return 0;
+ err = 0;
}
+out:
+ unlock_kernel();

- return -EOPNOTSUPP;
+ return err;
}

/*
@@ -783,36 +792,40 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
if (addr_len != sizeof(struct sockaddr_irda))
return -EINVAL;

+ lock_kernel();
#ifdef CONFIG_IRDA_ULTRA
/* Special care for Ultra sockets */
if ((sk->sk_type == SOCK_DGRAM) &&
(sk->sk_protocol == IRDAPROTO_ULTRA)) {
self->pid = addr->sir_lsap_sel;
+ err = -EOPNOTSUPP;
if (self->pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
- return -EOPNOTSUPP;
+ goto out;
}
err = irda_open_lsap(self, self->pid);
if (err < 0)
- return err;
+ goto out;

/* Pretend we are connected */
sock->state = SS_CONNECTED;
sk->sk_state = TCP_ESTABLISHED;
+ err = 0;

- return 0;
+ goto out;
}
#endif /* CONFIG_IRDA_ULTRA */

self->ias_obj = irias_new_object(addr->sir_name, jiffies);
+ err = -ENOMEM;
if (self->ias_obj == NULL)
- return -ENOMEM;
+ goto out;

err = irda_open_tsap(self, addr->sir_lsap_sel, addr->sir_name);
if (err < 0) {
kfree(self->ias_obj->name);
kfree(self->ias_obj);
- return err;
+ goto out;
}

/* Register with LM-IAS */
@@ -820,7 +833,10 @@ static int irda_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
self->stsap_sel, IAS_KERNEL_ATTR);
irias_insert_object(self->ias_obj);

- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}

/*
@@ -839,22 +855,26 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)

IRDA_DEBUG(2, "%s()\n", __func__);

+ lock_kernel();
err = irda_create(sock_net(sk), newsock, sk->sk_protocol);
if (err)
- return err;
+ goto out;;

+ err = -EINVAL;
if (sock->state != SS_UNCONNECTED)
- return -EINVAL;
+ goto out;

if ((sk = sock->sk) == NULL)
- return -EINVAL;
+ goto out;

+ err = -EOPNOTSUPP;
if ((sk->sk_type != SOCK_STREAM) && (sk->sk_type != SOCK_SEQPACKET) &&
(sk->sk_type != SOCK_DGRAM))
- return -EOPNOTSUPP;
+ goto out;

+ err = -EINVAL;
if (sk->sk_state != TCP_LISTEN)
- return -EINVAL;
+ goto out;

/*
* The read queue this time is holding sockets ready to use
@@ -875,18 +895,20 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
break;

/* Non blocking operation */
+ err = -EWOULDBLOCK;
if (flags & O_NONBLOCK)
- return -EWOULDBLOCK;
+ goto out;

err = wait_event_interruptible(*(sk->sk_sleep),
skb_peek(&sk->sk_receive_queue));
if (err)
- return err;
+ goto out;
}

newsk = newsock->sk;
+ err = -EIO;
if (newsk == NULL)
- return -EIO;
+ goto out;

newsk->sk_state = TCP_ESTABLISHED;

@@ -894,10 +916,11 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)

/* Now attach up the new socket */
new->tsap = irttp_dup(self->tsap, new);
+ err = -EPERM; /* value does not seem to make sense. -arnd */
if (!new->tsap) {
IRDA_DEBUG(0, "%s(), dup failed!\n", __func__);
kfree_skb(skb);
- return -1;
+ goto out;
}

new->stsap_sel = new->tsap->stsap_sel;
@@ -921,8 +944,10 @@ static int irda_accept(struct socket *sock, struct socket *newsock, int flags)
newsock->state = SS_CONNECTED;

irda_connect_response(new);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}

/*
@@ -955,28 +980,34 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,

IRDA_DEBUG(2, "%s(%p)\n", __func__, self);

+ lock_kernel();
/* Don't allow connect for Ultra sockets */
+ err = -ESOCKTNOSUPPORT;
if ((sk->sk_type == SOCK_DGRAM) && (sk->sk_protocol == IRDAPROTO_ULTRA))
- return -ESOCKTNOSUPPORT;
+ goto out;

if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
- return 0; /* Connect completed during a ERESTARTSYS event */
+ err = 0;
+ goto out; /* Connect completed during a ERESTARTSYS event */
}

if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
sock->state = SS_UNCONNECTED;
- return -ECONNREFUSED;
+ err = -ECONNREFUSED;
+ goto out;
}

+ err = -EISCONN; /* No reconnect on a seqpacket socket */
if (sk->sk_state == TCP_ESTABLISHED)
- return -EISCONN; /* No reconnect on a seqpacket socket */
+ goto out;

sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;

+ err = -EINVAL;
if (addr_len != sizeof(struct sockaddr_irda))
- return -EINVAL;
+ goto out;

/* Check if user supplied any destination device address */
if ((!addr->sir_addr) || (addr->sir_addr == DEV_ADDR_ANY)) {
@@ -984,7 +1015,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_discover_daddr_and_lsap_sel(self, addr->sir_name);
if (err) {
IRDA_DEBUG(0, "%s(), auto-connect failed!\n", __func__);
- return err;
+ goto out;
}
} else {
/* Use the one provided by the user */
@@ -1000,7 +1031,7 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
err = irda_find_lsap_sel(self, addr->sir_name);
if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
- return err;
+ goto out;
}
} else {
/* Directly connect to the remote LSAP
@@ -1025,29 +1056,35 @@ static int irda_connect(struct socket *sock, struct sockaddr *uaddr,
self->max_sdu_size_rx, NULL);
if (err) {
IRDA_DEBUG(0, "%s(), connect failed!\n", __func__);
- return err;
+ goto out;
}

/* Now the loop */
+ err = -EINPROGRESS;
if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
- return -EINPROGRESS;
+ goto out;

+ err = -ERESTARTSYS;
if (wait_event_interruptible(*(sk->sk_sleep),
(sk->sk_state != TCP_SYN_SENT)))
- return -ERESTARTSYS;
+ goto out;

if (sk->sk_state != TCP_ESTABLISHED) {
sock->state = SS_UNCONNECTED;
err = sock_error(sk);
- return err? err : -ECONNRESET;
+ if (!err)
+ err = -ECONNRESET;
+ goto out;
}

sock->state = SS_CONNECTED;

/* At this point, IrLMP has assigned our source address */
self->saddr = irttp_get_saddr(self->tsap);
-
- return 0;
+ err = 0;
+out:
+ unlock_kernel();
+ return err;
}

static struct proto irda_proto = {
@@ -1192,6 +1229,7 @@ static int irda_release(struct socket *sock)
if (sk == NULL)
return 0;

+ lock_kernel();
lock_sock(sk);
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
@@ -1210,6 +1248,7 @@ static int irda_release(struct socket *sock)
/* Destroy networking socket if we are the last reference on it,
* i.e. if(sk->sk_refcnt == 0) -> sk_free(sk) */
sock_put(sk);
+ unlock_kernel();

/* Notes on socket locking and deallocation... - Jean II
* In theory we should put pairs of sock_hold() / sock_put() to
@@ -1257,28 +1296,37 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,

IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);

+ lock_kernel();
/* Note : socket.c set MSG_EOR on SEQPACKET sockets */
if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT |
- MSG_NOSIGNAL))
- return -EINVAL;
+ MSG_NOSIGNAL)) {
+ err = -EINVAL;
+ goto out;
+ }

if (sk->sk_shutdown & SEND_SHUTDOWN)
goto out_err;

- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ err = -ENOTCONN;
+ goto out;
+ }

self = irda_sk(sk);

/* Check if IrTTP is wants us to slow down */

if (wait_event_interruptible(*(sk->sk_sleep),
- (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED)))
- return -ERESTARTSYS;
+ (self->tx_flow != FLOW_STOP || sk->sk_state != TCP_ESTABLISHED))) {
+ err = -ERESTARTSYS;
+ goto out;
+ }

/* Check if we are still connected */
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ err = -ENOTCONN;
+ goto out;
+ }

/* Check that we don't send out too big frames */
if (len > self->max_data_size) {
@@ -1310,11 +1358,16 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock,
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
goto out_err;
}
+
+ unlock_kernel();
/* Tell client how much data we actually sent */
return len;

- out_err:
- return sk_stream_error(sk, msg->msg_flags, err);
+out_err:
+ err = sk_stream_error(sk, msg->msg_flags, err);
+out:
+ unlock_kernel();
+ return err;

}

@@ -1335,13 +1388,14 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,

IRDA_DEBUG(4, "%s()\n", __func__);

+ lock_kernel();
if ((err = sock_error(sk)) < 0)
- return err;
+ goto out;

skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
flags & MSG_DONTWAIT, &err);
if (!skb)
- return err;
+ goto out;

skb_reset_transport_header(skb);
copied = skb->len;
@@ -1369,8 +1423,12 @@ static int irda_recvmsg_dgram(struct kiocb *iocb, struct socket *sock,
irttp_flow_request(self->tsap, FLOW_START);
}
}
-
+ unlock_kernel();
return copied;
+
+out:
+ unlock_kernel();
+ return err;
}

/*
@@ -1388,15 +1446,19 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,

IRDA_DEBUG(3, "%s()\n", __func__);

+ lock_kernel();
if ((err = sock_error(sk)) < 0)
- return err;
+ goto out;

+ err = -EINVAL;
if (sock->flags & __SO_ACCEPTCON)
- return(-EINVAL);
+ goto out;

+ err =-EOPNOTSUPP;
if (flags & MSG_OOB)
- return -EOPNOTSUPP;
+ goto out;

+ err = 0;
target = sock_rcvlowat(sk, flags & MSG_WAITALL, size);
timeo = sock_rcvtimeo(sk, noblock);

@@ -1408,7 +1470,7 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,

if (skb == NULL) {
DEFINE_WAIT(wait);
- int ret = 0;
+ err = 0;

if (copied >= target)
break;
@@ -1418,25 +1480,25 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
/*
* POSIX 1003.1g mandates this order.
*/
- ret = sock_error(sk);
- if (ret)
+ err = sock_error(sk);
+ if (err)
;
else if (sk->sk_shutdown & RCV_SHUTDOWN)
;
else if (noblock)
- ret = -EAGAIN;
+ err = -EAGAIN;
else if (signal_pending(current))
- ret = sock_intr_errno(timeo);
+ err = sock_intr_errno(timeo);
else if (sk->sk_state != TCP_ESTABLISHED)
- ret = -ENOTCONN;
+ err = -ENOTCONN;
else if (skb_peek(&sk->sk_receive_queue) == NULL)
/* Wait process until data arrives */
schedule();

finish_wait(sk->sk_sleep, &wait);

- if (ret)
- return ret;
+ if (err)
+ goto out;
if (sk->sk_shutdown & RCV_SHUTDOWN)
break;

@@ -1489,7 +1551,9 @@ static int irda_recvmsg_stream(struct kiocb *iocb, struct socket *sock,
}
}

- return copied;
+out:
+ unlock_kernel();
+ return err ? : copied;
}

/*
@@ -1507,18 +1571,23 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb;
int err;

+ lock_kernel();
+
IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);

+ err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
- return -EINVAL;
+ goto out;

if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0);
- return -EPIPE;
+ err = -EPIPE;
+ goto out;
}

+ err = -ENOTCONN;
if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ goto out;

self = irda_sk(sk);

@@ -1535,8 +1604,9 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,

skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err);
+ err = -ENOBUFS;
if (!skb)
- return -ENOBUFS;
+ goto out;

skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb);
@@ -1546,7 +1616,7 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return err;
+ goto out;
}

/*
@@ -1556,9 +1626,13 @@ static int irda_sendmsg_dgram(struct kiocb *iocb, struct socket *sock,
err = irttp_udata_request(self->tsap, skb);
if (err) {
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
- return err;
+ goto out;
}
+ unlock_kernel();
return len;
+out:
+ unlock_kernel();
+ return err;
}

/*
@@ -1580,12 +1654,15 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,

IRDA_DEBUG(4, "%s(), len=%zd\n", __func__, len);

+ lock_kernel();
+ err = -EINVAL;
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_CMSG_COMPAT))
- return -EINVAL;
+ goto out;

+ err = -EPIPE;
if (sk->sk_shutdown & SEND_SHUTDOWN) {
send_sig(SIGPIPE, current, 0);
- return -EPIPE;
+ goto out;
}

self = irda_sk(sk);
@@ -1593,16 +1670,18 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
/* Check if an address was specified with sendto. Jean II */
if (msg->msg_name) {
struct sockaddr_irda *addr = (struct sockaddr_irda *) msg->msg_name;
+ err = -EINVAL;
/* Check address, extract pid. Jean II */
if (msg->msg_namelen < sizeof(*addr))
- return -EINVAL;
+ goto out;
if (addr->sir_family != AF_IRDA)
- return -EINVAL;
+ goto out;

pid = addr->sir_lsap_sel;
if (pid & 0x80) {
IRDA_DEBUG(0, "%s(), extension in PID not supp!\n", __func__);
- return -EOPNOTSUPP;
+ err = -EOPNOTSUPP;
+ goto out;
}
} else {
/* Check that the socket is properly bound to an Ultra
@@ -1611,7 +1690,8 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
(sk->sk_state != TCP_ESTABLISHED)) {
IRDA_DEBUG(0, "%s(), socket not bound to Ultra PID.\n",
__func__);
- return -ENOTCONN;
+ err = -ENOTCONN;
+ goto out;
}
/* Use PID from socket */
bound = 1;
@@ -1630,8 +1710,9 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,

skb = sock_alloc_send_skb(sk, len + self->max_header_size,
msg->msg_flags & MSG_DONTWAIT, &err);
+ err = -ENOBUFS;
if (!skb)
- return -ENOBUFS;
+ goto out;

skb_reserve(skb, self->max_header_size);
skb_reset_transport_header(skb);
@@ -1641,16 +1722,16 @@ static int irda_sendmsg_ultra(struct kiocb *iocb, struct socket *sock,
err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len);
if (err) {
kfree_skb(skb);
- return err;
+ goto out;
}

err = irlmp_connless_data_request((bound ? self->lsap : NULL),
skb, pid);
- if (err) {
+ if (err)
IRDA_DEBUG(0, "%s(), err=%d\n", __func__, err);
- return err;
- }
- return len;
+out:
+ unlock_kernel();
+ return err ? : len;
}
#endif /* CONFIG_IRDA_ULTRA */

@@ -1664,6 +1745,8 @@ static int irda_shutdown(struct socket *sock, int how)

IRDA_DEBUG(1, "%s(%p)\n", __func__, self);

+ lock_kernel();
+
sk->sk_state = TCP_CLOSE;
sk->sk_shutdown |= SEND_SHUTDOWN;
sk->sk_state_change(sk);
@@ -1684,6 +1767,8 @@ static int irda_shutdown(struct socket *sock, int how)
self->daddr = DEV_ADDR_ANY; /* Until we get re-connected */
self->saddr = 0x0; /* so IrLMP assign us any link */

+ unlock_kernel();
+
return 0;
}

@@ -1699,6 +1784,7 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,

IRDA_DEBUG(4, "%s()\n", __func__);

+ lock_kernel();
poll_wait(file, sk->sk_sleep, wait);
mask = 0;

@@ -1746,18 +1832,34 @@ static unsigned int irda_poll(struct file * file, struct socket *sock,
default:
break;
}
+ unlock_kernel();
return mask;
}

+static unsigned int irda_datagram_poll(struct file *file, struct socket *sock,
+ poll_table *wait)
+{
+ int err;
+
+ lock_kernel();
+ err = datagram_poll(file, sock, wait);
+ unlock_kernel();
+
+ return err;
+}
+
/*
* Function irda_ioctl (sock, cmd, arg)
*/
static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
struct sock *sk = sock->sk;
+ int err;

IRDA_DEBUG(4, "%s(), cmd=%#x\n", __func__, cmd);

+ lock_kernel();
+ err = -EINVAL;
switch (cmd) {
case TIOCOUTQ: {
long amount;
@@ -1765,9 +1867,8 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
if (amount < 0)
amount = 0;
- if (put_user(amount, (unsigned int __user *)arg))
- return -EFAULT;
- return 0;
+ err = put_user(amount, (unsigned int __user *)arg);
+ break;
}

case TIOCINQ: {
@@ -1776,15 +1877,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
/* These two are safe on a single CPU system as only user tasks fiddle here */
if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
amount = skb->len;
- if (put_user(amount, (unsigned int __user *)arg))
- return -EFAULT;
- return 0;
+ err = put_user(amount, (unsigned int __user *)arg);
+ break;
}

case SIOCGSTAMP:
if (sk != NULL)
- return sock_get_timestamp(sk, (struct timeval __user *)arg);
- return -EINVAL;
+ err = sock_get_timestamp(sk, (struct timeval __user *)arg);
+ break;

case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1796,14 +1896,14 @@ static int irda_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
case SIOCSIFNETMASK:
case SIOCGIFMETRIC:
case SIOCSIFMETRIC:
- return -EINVAL;
+ break;
default:
IRDA_DEBUG(1, "%s(), doing device ioctl!\n", __func__);
- return -ENOIOCTLCMD;
+ err = -ENOIOCTLCMD;
}
+ unlock_kernel();

- /*NOTREACHED*/
- return 0;
+ return err;
}

#ifdef CONFIG_COMPAT
@@ -1825,7 +1925,7 @@ static int irda_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lon
* Set some options for the socket
*
*/
-static int irda_setsockopt(struct socket *sock, int level, int optname,
+static int __irda_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
@@ -2083,6 +2183,18 @@ static int irda_setsockopt(struct socket *sock, int level, int optname,
return 0;
}

+static int irda_setsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
+{
+ int err;
+
+ lock_kernel();
+ err = __irda_setsockopt(sock, level, optname, optval, optlen);
+ unlock_kernel();
+
+ return err;
+}
+
/*
* Function irda_extract_ias_value(ias_opt, ias_value)
*
@@ -2135,7 +2247,7 @@ static int irda_extract_ias_value(struct irda_ias_set *ias_opt,
/*
* Function irda_getsockopt (sock, level, optname, optval, optlen)
*/
-static int irda_getsockopt(struct socket *sock, int level, int optname,
+static int __irda_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
@@ -2463,13 +2575,25 @@ bed:
return 0;
}

+static int irda_getsockopt(struct socket *sock, int level, int optname,
+ char __user *optval, int __user *optlen)
+{
+ int err;
+
+ lock_kernel();
+ err = __irda_getsockopt(sock, level, optname, optval, optlen);
+ unlock_kernel();
+
+ return err;
+}
+
static struct net_proto_family irda_family_ops = {
.family = PF_IRDA,
.create = irda_create,
.owner = THIS_MODULE,
};

-static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
+static const struct proto_ops irda_stream_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2493,7 +2617,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_stream_ops) = {
.sendpage = sock_no_sendpage,
};

-static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
+static const struct proto_ops irda_seqpacket_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2502,7 +2626,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.socketpair = sock_no_socketpair,
.accept = irda_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2517,7 +2641,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_seqpacket_ops) = {
.sendpage = sock_no_sendpage,
};

-static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
+static const struct proto_ops irda_dgram_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2526,7 +2650,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
.socketpair = sock_no_socketpair,
.accept = irda_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2542,7 +2666,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_dgram_ops) = {
};

#ifdef CONFIG_IRDA_ULTRA
-static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
+static const struct proto_ops irda_ultra_ops = {
.family = PF_IRDA,
.owner = THIS_MODULE,
.release = irda_release,
@@ -2551,7 +2675,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.getname = irda_getname,
- .poll = datagram_poll,
+ .poll = irda_datagram_poll,
.ioctl = irda_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = irda_compat_ioctl,
@@ -2567,13 +2691,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(irda_ultra_ops) = {
};
#endif /* CONFIG_IRDA_ULTRA */

-SOCKOPS_WRAP(irda_stream, PF_IRDA);
-SOCKOPS_WRAP(irda_seqpacket, PF_IRDA);
-SOCKOPS_WRAP(irda_dgram, PF_IRDA);
-#ifdef CONFIG_IRDA_ULTRA
-SOCKOPS_WRAP(irda_ultra, PF_IRDA);
-#endif /* CONFIG_IRDA_ULTRA */
-
/*
* Function irsock_init (pro)
*
--
1.6.3.3

2009-11-05 14:38:14

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 4/5] net/x25: push BKL usage into x25_proto

The x25 driver uses lock_kernel() implicitly through
its proto_ops wrapper. The makes the usage explicit
in order to get rid of that wrapper and to better document
the usage of the BKL.

The next step should be to get rid of the usage of the BKL
in x25 entirely, which requires understanding what data
structures need serialized accesses.

Cc: Henner Eisen <[email protected]>
Cc: David S. Miller <[email protected]>
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
---
net/x25/af_x25.c | 71 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
index 7fa9c7a..a7a4bc2 100644
--- a/net/x25/af_x25.c
+++ b/net/x25/af_x25.c
@@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int rc = -ENOPROTOOPT;

+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;

@@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
x25_sk(sk)->qbitincl = !!opt;
rc = 0;
out:
+ unlock_kernel();
return rc;
}

@@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
int val, len, rc = -ENOPROTOOPT;

+ lock_kernel();
if (level != SOL_X25 || optname != X25_QBITINCL)
goto out;

@@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
val = x25_sk(sk)->qbitincl;
rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
out:
+ unlock_kernel();
return rc;
}

@@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog)
struct sock *sk = sock->sk;
int rc = -EOPNOTSUPP;

+ lock_kernel();
if (sk->sk_state != TCP_LISTEN) {
memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
sk->sk_max_ack_backlog = backlog;
sk->sk_state = TCP_LISTEN;
rc = 0;
}
+ unlock_kernel();

return rc;
}
@@ -597,6 +603,7 @@ static int x25_release(struct socket *sock)
struct sock *sk = sock->sk;
struct x25_sock *x25;

+ lock_kernel();
if (!sk)
goto out;

@@ -627,6 +634,7 @@ static int x25_release(struct socket *sock)

sock_orphan(sk);
out:
+ unlock_kernel();
return 0;
}

@@ -634,18 +642,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
struct sock *sk = sock->sk;
struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
+ int rc = 0;

+ lock_kernel();
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_x25) ||
- addr->sx25_family != AF_X25)
- return -EINVAL;
+ addr->sx25_family != AF_X25) {
+ rc = -EINVAL;
+ goto out;
+ }

x25_sk(sk)->source_addr = addr->sx25_addr;
x25_insert_socket(sk);
sock_reset_flag(sk, SOCK_ZAPPED);
SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
-
- return 0;
+out:
+ unlock_kernel();
+ return rc;
}

static int x25_wait_for_connection_establishment(struct sock *sk)
@@ -686,6 +699,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
struct x25_route *rt;
int rc = 0;

+ lock_kernel();
lock_sock(sk);
if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
sock->state = SS_CONNECTED;
@@ -763,6 +777,7 @@ out_put_route:
x25_route_put(rt);
out:
release_sock(sk);
+ unlock_kernel();
return rc;
}

@@ -802,6 +817,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
struct sk_buff *skb;
int rc = -EINVAL;

+ lock_kernel();
if (!sk || sk->sk_state != TCP_LISTEN)
goto out;

@@ -829,6 +845,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
out2:
release_sock(sk);
out:
+ unlock_kernel();
return rc;
}

@@ -838,10 +855,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
struct sock *sk = sock->sk;
struct x25_sock *x25 = x25_sk(sk);
+ int rc = 0;

+ lock_kernel();
if (peer) {
- if (sk->sk_state != TCP_ESTABLISHED)
- return -ENOTCONN;
+ if (sk->sk_state != TCP_ESTABLISHED) {
+ rc = -ENOTCONN;
+ goto out;
+ }
sx25->sx25_addr = x25->dest_addr;
} else
sx25->sx25_addr = x25->source_addr;
@@ -849,7 +870,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
sx25->sx25_family = AF_X25;
*uaddr_len = sizeof(*sx25);

- return 0;
+out:
+ unlock_kernel();
+ return rc;
+}
+
+static unsigned int x25_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;
}

int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
@@ -1002,6 +1037,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
size_t size;
int qbit = 0, rc = -EINVAL;

+ lock_kernel();
if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
goto out;

@@ -1166,6 +1202,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
release_sock(sk);
rc = len;
out:
+ unlock_kernel();
return rc;
out_kfree_skb:
kfree_skb(skb);
@@ -1186,6 +1223,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
unsigned char *asmptr;
int rc = -ENOTCONN;

+ lock_kernel();
/*
* This works for seqpacket too. The receiver has ordered the queue for
* us! We do one quick check first though
@@ -1259,6 +1297,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
out_free_dgram:
skb_free_datagram(sk, skb);
out:
+ unlock_kernel();
return rc;
}

@@ -1270,6 +1309,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
void __user *argp = (void __user *)arg;
int rc;

+ lock_kernel();
switch (cmd) {
case TIOCOUTQ: {
int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
@@ -1472,6 +1512,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = -ENOIOCTLCMD;
break;
}
+ unlock_kernel();

return rc;
}
@@ -1542,15 +1583,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
break;
case SIOCGSTAMP:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestamp(sk,
(struct timeval __user*)argp);
+ unlock_kernel();
break;
case SIOCGSTAMPNS:
rc = -EINVAL;
+ lock_kernel();
if (sk)
rc = compat_sock_get_timestampns(sk,
(struct timespec __user*)argp);
+ unlock_kernel();
break;
case SIOCGIFADDR:
case SIOCSIFADDR:
@@ -1569,16 +1614,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = x25_route_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GSUBSCRIP:
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25SSUBSCRIP:
rc = -EPERM;
if (!capable(CAP_NET_ADMIN))
break;
+ lock_kernel();
rc = compat_x25_subscr_ioctl(cmd, argp);
+ unlock_kernel();
break;
case SIOCX25GFACILITIES:
case SIOCX25SFACILITIES:
@@ -1600,7 +1651,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
}
#endif

-static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
+static const struct proto_ops x25_proto_ops = {
.family = AF_X25,
.owner = THIS_MODULE,
.release = x25_release,
@@ -1609,7 +1660,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.socketpair = sock_no_socketpair,
.accept = x25_accept,
.getname = x25_getname,
- .poll = datagram_poll,
+ .poll = x25_datagram_poll,
.ioctl = x25_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = compat_x25_ioctl,
@@ -1624,8 +1675,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
.sendpage = sock_no_sendpage,
};

-SOCKOPS_WRAP(x25_proto, AF_X25);
-
static struct packet_type x25_packet_type __read_mostly = {
.type = cpu_to_be16(ETH_P_X25),
.func = x25_lapb_receive_frame,
--
1.6.3.3

2009-11-05 14:38:03

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH 5/5] net: kill proto_ops wrapper

All users of wrapped proto_ops are now gone, so we can safely remove
the wrappers as well.

Cc: David S. Miller <[email protected]>
Cc: [email protected]
Signed-off-by: Arnd Bergmann <[email protected]>
---
include/linux/net.h | 83 ---------------------------------------------------
1 files changed, 0 insertions(+), 83 deletions(-)

diff --git a/include/linux/net.h b/include/linux/net.h
index 529a093..041a8e4 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -263,89 +263,6 @@ extern int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
extern int kernel_sock_shutdown(struct socket *sock,
enum sock_shutdown_cmd how);

-#ifndef CONFIG_SMP
-#define SOCKOPS_WRAPPED(name) name
-#define SOCKOPS_WRAP(name, fam)
-#else
-
-#define SOCKOPS_WRAPPED(name) __unlocked_##name
-
-#define SOCKCALL_WRAP(name, call, parms, args) \
-static int __lock_##name##_##call parms \
-{ \
- int ret; \
- lock_kernel(); \
- ret = __unlocked_##name##_ops.call args ;\
- unlock_kernel(); \
- return ret; \
-}
-
-#define SOCKCALL_UWRAP(name, call, parms, args) \
-static unsigned int __lock_##name##_##call parms \
-{ \
- int ret; \
- lock_kernel(); \
- ret = __unlocked_##name##_ops.call args ;\
- unlock_kernel(); \
- return ret; \
-}
-
-
-#define SOCKOPS_WRAP(name, fam) \
-SOCKCALL_WRAP(name, release, (struct socket *sock), (sock)) \
-SOCKCALL_WRAP(name, bind, (struct socket *sock, struct sockaddr *uaddr, int addr_len), \
- (sock, uaddr, addr_len)) \
-SOCKCALL_WRAP(name, connect, (struct socket *sock, struct sockaddr * uaddr, \
- int addr_len, int flags), \
- (sock, uaddr, addr_len, flags)) \
-SOCKCALL_WRAP(name, socketpair, (struct socket *sock1, struct socket *sock2), \
- (sock1, sock2)) \
-SOCKCALL_WRAP(name, accept, (struct socket *sock, struct socket *newsock, \
- int flags), (sock, newsock, flags)) \
-SOCKCALL_WRAP(name, getname, (struct socket *sock, struct sockaddr *uaddr, \
- int *addr_len, int peer), (sock, uaddr, addr_len, peer)) \
-SOCKCALL_UWRAP(name, poll, (struct file *file, struct socket *sock, struct poll_table_struct *wait), \
- (file, sock, wait)) \
-SOCKCALL_WRAP(name, ioctl, (struct socket *sock, unsigned int cmd, \
- unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, compat_ioctl, (struct socket *sock, unsigned int cmd, \
- unsigned long arg), (sock, cmd, arg)) \
-SOCKCALL_WRAP(name, listen, (struct socket *sock, int len), (sock, len)) \
-SOCKCALL_WRAP(name, shutdown, (struct socket *sock, int flags), (sock, flags)) \
-SOCKCALL_WRAP(name, setsockopt, (struct socket *sock, int level, int optname, \
- char __user *optval, unsigned int optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, getsockopt, (struct socket *sock, int level, int optname, \
- char __user *optval, int __user *optlen), (sock, level, optname, optval, optlen)) \
-SOCKCALL_WRAP(name, sendmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len), \
- (iocb, sock, m, len)) \
-SOCKCALL_WRAP(name, recvmsg, (struct kiocb *iocb, struct socket *sock, struct msghdr *m, size_t len, int flags), \
- (iocb, sock, m, len, flags)) \
-SOCKCALL_WRAP(name, mmap, (struct file *file, struct socket *sock, struct vm_area_struct *vma), \
- (file, sock, vma)) \
- \
-static const struct proto_ops name##_ops = { \
- .family = fam, \
- .owner = THIS_MODULE, \
- .release = __lock_##name##_release, \
- .bind = __lock_##name##_bind, \
- .connect = __lock_##name##_connect, \
- .socketpair = __lock_##name##_socketpair, \
- .accept = __lock_##name##_accept, \
- .getname = __lock_##name##_getname, \
- .poll = __lock_##name##_poll, \
- .ioctl = __lock_##name##_ioctl, \
- .compat_ioctl = __lock_##name##_compat_ioctl, \
- .listen = __lock_##name##_listen, \
- .shutdown = __lock_##name##_shutdown, \
- .setsockopt = __lock_##name##_setsockopt, \
- .getsockopt = __lock_##name##_getsockopt, \
- .sendmsg = __lock_##name##_sendmsg, \
- .recvmsg = __lock_##name##_recvmsg, \
- .mmap = __lock_##name##_mmap, \
-};
-
-#endif
-
#define MODULE_ALIAS_NETPROTO(proto) \
MODULE_ALIAS("net-pf-" __stringify(proto))

--
1.6.3.3

2009-11-06 08:38:31

by David Miller

[permalink] [raw]
Subject: Re: [PATCH 0/5] net: push down BKL into proto ops

From: Arnd Bergmann <[email protected]>
Date: Thu, 5 Nov 2009 15:37:25 +0100

> This pushes one more use of the BKL from common code into specific
> network protocols by killing off the proto ops wrappers.
> This should cause no visible changes on the code but saves a few
> kilobytes of object code in allyesconfig.
>
> Arnd Bergmann (5):
> net/appletalk: push down BKL into a atalk_dgram_ops
> net/ipx: push down BKL into a ipx_dgram_ops
> net/irda: push BKL into proto_ops
> net/x25: push BKL usage into x25_proto
> net: kill proto_ops wrapper

Nice patch set Arnd.

As long as this passes my build validation checks it will
get pushed out to net-next-2.6

Thanks!

2009-11-12 05:18:41

by Andrew Hendry

[permalink] [raw]
Subject: Re: [PATCH 4/5] net/x25: push BKL usage into x25_proto

For anyone who looking at the next step, be aware there is an existing
bug in this area.

With single threaded x.25 processes and light X.25 traffic over time
'dead sockets' hang around. They sometimes have negative values in the
inode field and all the timers are timed out. When they exist rmmod
x25 will crash the system, even though lsmod shows 0 usage if all x.25
programs are shutdown.

# cat /proc/net/x25/socket
dest_addr src_addr dev lci st vs vr va t t2 t21 t22 t23 Snd-Q
Rcv-Q inode
0505xxxxxxxxx 0505xxxxxxxxx x25tap0 000 0 0 0 0 0 3 200 180
180 0 0 6198164303842135440
0505xxxxxxxxx 0505xxxxxxxxx x25tap0 000 0 0 0 0 0 3 200 180
180 0 0 111073138
They can be reproduced faster with threaded client/server test
programs doing connect/disconnect. No time to look further at the
moment, but I can help test.


On Fri, Nov 6, 2009 at 1:37 AM, Arnd Bergmann <[email protected]> wrote:
> The x25 driver uses lock_kernel() implicitly through
> its proto_ops wrapper. The makes the usage explicit
> in order to get rid of that wrapper and to better document
> the usage of the BKL.
>
> The next step should be to get rid of the usage of the BKL
> in x25 entirely, which requires understanding what data
> structures need serialized accesses.
>
> Cc: Henner Eisen <[email protected]>
> Cc: David S. Miller <[email protected]>
> Cc: [email protected]
> Cc: [email protected]
> Signed-off-by: Arnd Bergmann <[email protected]>
> ---
> ?net/x25/af_x25.c | ? 71 +++++++++++++++++++++++++++++++++++++++++++++--------
> ?1 files changed, 60 insertions(+), 11 deletions(-)
>
> diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c
> index 7fa9c7a..a7a4bc2 100644
> --- a/net/x25/af_x25.c
> +++ b/net/x25/af_x25.c
> @@ -415,6 +415,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?int rc = -ENOPROTOOPT;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (level != SOL_X25 || optname != X25_QBITINCL)
> ? ? ? ? ? ? ? ?goto out;
>
> @@ -429,6 +430,7 @@ static int x25_setsockopt(struct socket *sock, int level, int optname,
> ? ? ? ?x25_sk(sk)->qbitincl = !!opt;
> ? ? ? ?rc = 0;
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?}
>
> @@ -438,6 +440,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?int val, len, rc = -ENOPROTOOPT;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (level != SOL_X25 || optname != X25_QBITINCL)
> ? ? ? ? ? ? ? ?goto out;
>
> @@ -458,6 +461,7 @@ static int x25_getsockopt(struct socket *sock, int level, int optname,
> ? ? ? ?val = x25_sk(sk)->qbitincl;
> ? ? ? ?rc = copy_to_user(optval, &val, len) ? -EFAULT : 0;
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?}
>
> @@ -466,12 +470,14 @@ static int x25_listen(struct socket *sock, int backlog)
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?int rc = -EOPNOTSUPP;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (sk->sk_state != TCP_LISTEN) {
> ? ? ? ? ? ? ? ?memset(&x25_sk(sk)->dest_addr, 0, X25_ADDR_LEN);
> ? ? ? ? ? ? ? ?sk->sk_max_ack_backlog = backlog;
> ? ? ? ? ? ? ? ?sk->sk_state ? ? ? ? ? = TCP_LISTEN;
> ? ? ? ? ? ? ? ?rc = 0;
> ? ? ? ?}
> + ? ? ? unlock_kernel();
>
> ? ? ? ?return rc;
> ?}
> @@ -597,6 +603,7 @@ static int x25_release(struct socket *sock)
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?struct x25_sock *x25;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (!sk)
> ? ? ? ? ? ? ? ?goto out;
>
> @@ -627,6 +634,7 @@ static int x25_release(struct socket *sock)
>
> ? ? ? ?sock_orphan(sk);
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return 0;
> ?}
>
> @@ -634,18 +642,23 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
> ?{
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
> + ? ? ? int rc = 0;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (!sock_flag(sk, SOCK_ZAPPED) ||
> ? ? ? ? ? ?addr_len != sizeof(struct sockaddr_x25) ||
> - ? ? ? ? ? addr->sx25_family != AF_X25)
> - ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? ? ? addr->sx25_family != AF_X25) {
> + ? ? ? ? ? ? ? rc = -EINVAL;
> + ? ? ? ? ? ? ? goto out;
> + ? ? ? }
>
> ? ? ? ?x25_sk(sk)->source_addr = addr->sx25_addr;
> ? ? ? ?x25_insert_socket(sk);
> ? ? ? ?sock_reset_flag(sk, SOCK_ZAPPED);
> ? ? ? ?SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
> -
> - ? ? ? return 0;
> +out:
> + ? ? ? unlock_kernel();
> + ? ? ? return rc;
> ?}
>
> ?static int x25_wait_for_connection_establishment(struct sock *sk)
> @@ -686,6 +699,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
> ? ? ? ?struct x25_route *rt;
> ? ? ? ?int rc = 0;
>
> + ? ? ? lock_kernel();
> ? ? ? ?lock_sock(sk);
> ? ? ? ?if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
> ? ? ? ? ? ? ? ?sock->state = SS_CONNECTED;
> @@ -763,6 +777,7 @@ out_put_route:
> ? ? ? ?x25_route_put(rt);
> ?out:
> ? ? ? ?release_sock(sk);
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?}
>
> @@ -802,6 +817,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
> ? ? ? ?struct sk_buff *skb;
> ? ? ? ?int rc = -EINVAL;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (!sk || sk->sk_state != TCP_LISTEN)
> ? ? ? ? ? ? ? ?goto out;
>
> @@ -829,6 +845,7 @@ static int x25_accept(struct socket *sock, struct socket *newsock, int flags)
> ?out2:
> ? ? ? ?release_sock(sk);
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?}
>
> @@ -838,10 +855,14 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
> ? ? ? ?struct sockaddr_x25 *sx25 = (struct sockaddr_x25 *)uaddr;
> ? ? ? ?struct sock *sk = sock->sk;
> ? ? ? ?struct x25_sock *x25 = x25_sk(sk);
> + ? ? ? int rc = 0;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (peer) {
> - ? ? ? ? ? ? ? if (sk->sk_state != TCP_ESTABLISHED)
> - ? ? ? ? ? ? ? ? ? ? ? return -ENOTCONN;
> + ? ? ? ? ? ? ? if (sk->sk_state != TCP_ESTABLISHED) {
> + ? ? ? ? ? ? ? ? ? ? ? rc = -ENOTCONN;
> + ? ? ? ? ? ? ? ? ? ? ? goto out;
> + ? ? ? ? ? ? ? }
> ? ? ? ? ? ? ? ?sx25->sx25_addr = x25->dest_addr;
> ? ? ? ?} else
> ? ? ? ? ? ? ? ?sx25->sx25_addr = x25->source_addr;
> @@ -849,7 +870,21 @@ static int x25_getname(struct socket *sock, struct sockaddr *uaddr,
> ? ? ? ?sx25->sx25_family = AF_X25;
> ? ? ? ?*uaddr_len = sizeof(*sx25);
>
> - ? ? ? return 0;
> +out:
> + ? ? ? unlock_kernel();
> + ? ? ? return rc;
> +}
> +
> +static unsigned int x25_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;
> ?}
>
> ?int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
> @@ -1002,6 +1037,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
> ? ? ? ?size_t size;
> ? ? ? ?int qbit = 0, rc = -EINVAL;
>
> + ? ? ? lock_kernel();
> ? ? ? ?if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_OOB|MSG_EOR|MSG_CMSG_COMPAT))
> ? ? ? ? ? ? ? ?goto out;
>
> @@ -1166,6 +1202,7 @@ static int x25_sendmsg(struct kiocb *iocb, struct socket *sock,
> ? ? ? ?release_sock(sk);
> ? ? ? ?rc = len;
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?out_kfree_skb:
> ? ? ? ?kfree_skb(skb);
> @@ -1186,6 +1223,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
> ? ? ? ?unsigned char *asmptr;
> ? ? ? ?int rc = -ENOTCONN;
>
> + ? ? ? lock_kernel();
> ? ? ? ?/*
> ? ? ? ? * This works for seqpacket too. The receiver has ordered the queue for
> ? ? ? ? * us! We do one quick check first though
> @@ -1259,6 +1297,7 @@ static int x25_recvmsg(struct kiocb *iocb, struct socket *sock,
> ?out_free_dgram:
> ? ? ? ?skb_free_datagram(sk, skb);
> ?out:
> + ? ? ? unlock_kernel();
> ? ? ? ?return rc;
> ?}
>
> @@ -1270,6 +1309,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
> ? ? ? ?void __user *argp = (void __user *)arg;
> ? ? ? ?int rc;
>
> + ? ? ? lock_kernel();
> ? ? ? ?switch (cmd) {
> ? ? ? ? ? ? ? ?case TIOCOUTQ: {
> ? ? ? ? ? ? ? ? ? ? ? ?int amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk);
> @@ -1472,6 +1512,7 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
> ? ? ? ? ? ? ? ? ? ? ? ?rc = -ENOIOCTLCMD;
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> + ? ? ? unlock_kernel();
>
> ? ? ? ?return rc;
> ?}
> @@ -1542,15 +1583,19 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCGSTAMP:
> ? ? ? ? ? ? ? ?rc = -EINVAL;
> + ? ? ? ? ? ? ? lock_kernel();
> ? ? ? ? ? ? ? ?if (sk)
> ? ? ? ? ? ? ? ? ? ? ? ?rc = compat_sock_get_timestamp(sk,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(struct timeval __user*)argp);
> + ? ? ? ? ? ? ? unlock_kernel();
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCGSTAMPNS:
> ? ? ? ? ? ? ? ?rc = -EINVAL;
> + ? ? ? ? ? ? ? lock_kernel();
> ? ? ? ? ? ? ? ?if (sk)
> ? ? ? ? ? ? ? ? ? ? ? ?rc = compat_sock_get_timestampns(sk,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(struct timespec __user*)argp);
> + ? ? ? ? ? ? ? unlock_kernel();
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCGIFADDR:
> ? ? ? ?case SIOCSIFADDR:
> @@ -1569,16 +1614,22 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
> ? ? ? ? ? ? ? ?rc = -EPERM;
> ? ? ? ? ? ? ? ?if (!capable(CAP_NET_ADMIN))
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> + ? ? ? ? ? ? ? lock_kernel();
> ? ? ? ? ? ? ? ?rc = x25_route_ioctl(cmd, argp);
> + ? ? ? ? ? ? ? unlock_kernel();
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCX25GSUBSCRIP:
> + ? ? ? ? ? ? ? lock_kernel();
> ? ? ? ? ? ? ? ?rc = compat_x25_subscr_ioctl(cmd, argp);
> + ? ? ? ? ? ? ? unlock_kernel();
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCX25SSUBSCRIP:
> ? ? ? ? ? ? ? ?rc = -EPERM;
> ? ? ? ? ? ? ? ?if (!capable(CAP_NET_ADMIN))
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> + ? ? ? ? ? ? ? lock_kernel();
> ? ? ? ? ? ? ? ?rc = compat_x25_subscr_ioctl(cmd, argp);
> + ? ? ? ? ? ? ? unlock_kernel();
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case SIOCX25GFACILITIES:
> ? ? ? ?case SIOCX25SFACILITIES:
> @@ -1600,7 +1651,7 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
> ?}
> ?#endif
>
> -static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
> +static const struct proto_ops x25_proto_ops = {
> ? ? ? ?.family = ? ? ? AF_X25,
> ? ? ? ?.owner = ? ? ? ?THIS_MODULE,
> ? ? ? ?.release = ? ? ?x25_release,
> @@ -1609,7 +1660,7 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
> ? ? ? ?.socketpair = ? sock_no_socketpair,
> ? ? ? ?.accept = ? ? ? x25_accept,
> ? ? ? ?.getname = ? ? ?x25_getname,
> - ? ? ? .poll = ? ? ? ? datagram_poll,
> + ? ? ? .poll = ? ? ? ? x25_datagram_poll,
> ? ? ? ?.ioctl = ? ? ? ?x25_ioctl,
> ?#ifdef CONFIG_COMPAT
> ? ? ? ?.compat_ioctl = compat_x25_ioctl,
> @@ -1624,8 +1675,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(x25_proto_ops) = {
> ? ? ? ?.sendpage = ? ? sock_no_sendpage,
> ?};
>
> -SOCKOPS_WRAP(x25_proto, AF_X25);
> -
> ?static struct packet_type x25_packet_type __read_mostly = {
> ? ? ? ?.type = cpu_to_be16(ETH_P_X25),
> ? ? ? ?.func = x25_lapb_receive_frame,
> --
> 1.6.3.3
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to [email protected]
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at ?http://www.tux.org/lkml/
>