mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 12:16:20 +00:00
[ECONET]: Convert away from SOCKOPS_WRAPPED
Just use a local econet_mutex instead. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
f6c90b71a3
commit
1d1818316f
1 changed files with 85 additions and 55 deletions
|
@ -42,6 +42,7 @@
|
||||||
#include <linux/spinlock.h>
|
#include <linux/spinlock.h>
|
||||||
#include <linux/rcupdate.h>
|
#include <linux/rcupdate.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
|
@ -49,6 +50,7 @@
|
||||||
static const struct proto_ops econet_ops;
|
static const struct proto_ops econet_ops;
|
||||||
static struct hlist_head econet_sklist;
|
static struct hlist_head econet_sklist;
|
||||||
static DEFINE_RWLOCK(econet_lock);
|
static DEFINE_RWLOCK(econet_lock);
|
||||||
|
static DEFINE_MUTEX(econet_mutex);
|
||||||
|
|
||||||
/* Since there are only 256 possible network numbers (or fewer, depends
|
/* Since there are only 256 possible network numbers (or fewer, depends
|
||||||
how you count) it makes sense to use a simple lookup table. */
|
how you count) it makes sense to use a simple lookup table. */
|
||||||
|
@ -124,6 +126,8 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
|
|
||||||
msg->msg_namelen = sizeof(struct sockaddr_ec);
|
msg->msg_namelen = sizeof(struct sockaddr_ec);
|
||||||
|
|
||||||
|
mutex_lock(&econet_mutex);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call the generic datagram receiver. This handles all sorts
|
* Call the generic datagram receiver. This handles all sorts
|
||||||
* of horrible races and re-entrancy so we can forget about it
|
* of horrible races and re-entrancy so we can forget about it
|
||||||
|
@ -174,6 +178,7 @@ static int econet_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
out_free:
|
out_free:
|
||||||
skb_free_datagram(sk, skb);
|
skb_free_datagram(sk, skb);
|
||||||
out:
|
out:
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,8 +189,8 @@ out:
|
||||||
static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||||
{
|
{
|
||||||
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
|
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
|
||||||
struct sock *sk=sock->sk;
|
struct sock *sk;
|
||||||
struct econet_sock *eo = ec_sk(sk);
|
struct econet_sock *eo;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check legality
|
* Check legality
|
||||||
|
@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len
|
||||||
sec->sec_family != AF_ECONET)
|
sec->sec_family != AF_ECONET)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
mutex_lock(&econet_mutex);
|
||||||
|
|
||||||
|
sk = sock->sk;
|
||||||
|
eo = ec_sk(sk);
|
||||||
|
|
||||||
eo->cb = sec->cb;
|
eo->cb = sec->cb;
|
||||||
eo->port = sec->port;
|
eo->port = sec->port;
|
||||||
eo->station = sec->addr.station;
|
eo->station = sec->addr.station;
|
||||||
eo->net = sec->addr.net;
|
eo->net = sec->addr.net;
|
||||||
|
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
* Get and verify the address.
|
* Get and verify the address.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
mutex_lock(&econet_mutex);
|
||||||
|
|
||||||
if (saddr == NULL) {
|
if (saddr == NULL) {
|
||||||
struct econet_sock *eo = ec_sk(sk);
|
struct econet_sock *eo = ec_sk(sk);
|
||||||
|
|
||||||
|
@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
port = eo->port;
|
port = eo->port;
|
||||||
cb = eo->cb;
|
cb = eo->cb;
|
||||||
} else {
|
} else {
|
||||||
if (msg->msg_namelen < sizeof(struct sockaddr_ec))
|
if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
addr.station = saddr->addr.station;
|
addr.station = saddr->addr.station;
|
||||||
addr.net = saddr->addr.net;
|
addr.net = saddr->addr.net;
|
||||||
port = saddr->port;
|
port = saddr->port;
|
||||||
|
@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
dev = net2dev_map[addr.net];
|
dev = net2dev_map[addr.net];
|
||||||
|
|
||||||
/* If not directly reachable, use some default */
|
/* If not directly reachable, use some default */
|
||||||
if (dev == NULL)
|
if (dev == NULL) {
|
||||||
{
|
|
||||||
dev = net2dev_map[0];
|
dev = net2dev_map[0];
|
||||||
/* No interfaces at all? */
|
/* No interfaces at all? */
|
||||||
if (dev == NULL)
|
if (dev == NULL) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return -ENETDOWN;
|
return -ENETDOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len + 15 > dev->mtu)
|
if (len + 15 > dev->mtu) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return -EMSGSIZE;
|
return -EMSGSIZE;
|
||||||
|
}
|
||||||
|
|
||||||
if (dev->type == ARPHRD_ECONET)
|
if (dev->type == ARPHRD_ECONET) {
|
||||||
{
|
|
||||||
/* Real hardware Econet. We're not worthy etc. */
|
/* Real hardware Econet. We're not worthy etc. */
|
||||||
#ifdef CONFIG_ECONET_NATIVE
|
#ifdef CONFIG_ECONET_NATIVE
|
||||||
unsigned short proto = 0;
|
unsigned short proto = 0;
|
||||||
|
@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
|
|
||||||
dev_queue_xmit(skb);
|
dev_queue_xmit(skb);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return(len);
|
return(len);
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
|
@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
#else
|
#else
|
||||||
err = -EPROTOTYPE;
|
err = -EPROTOTYPE;
|
||||||
#endif
|
#endif
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ECONET_AUNUDP
|
#ifdef CONFIG_ECONET_AUNUDP
|
||||||
/* AUN virtual Econet. */
|
/* AUN virtual Econet. */
|
||||||
|
|
||||||
if (udpsock == NULL)
|
if (udpsock == NULL) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return -ENETDOWN; /* No socket - can't send */
|
return -ENETDOWN; /* No socket - can't send */
|
||||||
|
}
|
||||||
|
|
||||||
/* Make up a UDP datagram and hand it off to some higher intellect. */
|
/* Make up a UDP datagram and hand it off to some higher intellect. */
|
||||||
|
|
||||||
|
@ -438,8 +461,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
void __user *base = msg->msg_iov[i].iov_base;
|
void __user *base = msg->msg_iov[i].iov_base;
|
||||||
size_t len = msg->msg_iov[i].iov_len;
|
size_t len = msg->msg_iov[i].iov_len;
|
||||||
/* Check it now since we switch to KERNEL_DS later. */
|
/* Check it now since we switch to KERNEL_DS later. */
|
||||||
if (!access_ok(VERIFY_READ, base, len))
|
if (!access_ok(VERIFY_READ, base, len)) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
}
|
||||||
iov[i+1].iov_base = base;
|
iov[i+1].iov_base = base;
|
||||||
iov[i+1].iov_len = len;
|
iov[i+1].iov_len = len;
|
||||||
size += len;
|
size += len;
|
||||||
|
@ -447,8 +472,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
|
|
||||||
/* Get a skbuff (no data, just holds our cb information) */
|
/* Get a skbuff (no data, just holds our cb information) */
|
||||||
if ((skb = sock_alloc_send_skb(sk, 0,
|
if ((skb = sock_alloc_send_skb(sk, 0,
|
||||||
msg->msg_flags & MSG_DONTWAIT, &err)) == NULL)
|
msg->msg_flags & MSG_DONTWAIT,
|
||||||
|
&err)) == NULL) {
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return err;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
eb = (struct ec_cb *)&skb->cb;
|
eb = (struct ec_cb *)&skb->cb;
|
||||||
|
|
||||||
|
@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
#else
|
#else
|
||||||
err = -EPROTOTYPE;
|
err = -EPROTOTYPE;
|
||||||
#endif
|
#endif
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -485,18 +515,25 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
|
||||||
static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
|
static int econet_getname(struct socket *sock, struct sockaddr *uaddr,
|
||||||
int *uaddr_len, int peer)
|
int *uaddr_len, int peer)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk;
|
||||||
struct econet_sock *eo = ec_sk(sk);
|
struct econet_sock *eo;
|
||||||
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
|
struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;
|
||||||
|
|
||||||
if (peer)
|
if (peer)
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
mutex_lock(&econet_mutex);
|
||||||
|
|
||||||
|
sk = sock->sk;
|
||||||
|
eo = ec_sk(sk);
|
||||||
|
|
||||||
sec->sec_family = AF_ECONET;
|
sec->sec_family = AF_ECONET;
|
||||||
sec->port = eo->port;
|
sec->port = eo->port;
|
||||||
sec->addr.station = eo->station;
|
sec->addr.station = eo->station;
|
||||||
sec->addr.net = eo->net;
|
sec->addr.net = eo->net;
|
||||||
|
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
|
|
||||||
*uaddr_len = sizeof(*sec);
|
*uaddr_len = sizeof(*sec);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data)
|
||||||
|
|
||||||
static int econet_release(struct socket *sock)
|
static int econet_release(struct socket *sock)
|
||||||
{
|
{
|
||||||
struct sock *sk = sock->sk;
|
struct sock *sk;
|
||||||
|
|
||||||
|
mutex_lock(&econet_mutex);
|
||||||
|
|
||||||
|
sk = sock->sk;
|
||||||
if (!sk)
|
if (!sk)
|
||||||
return 0;
|
goto out_unlock;
|
||||||
|
|
||||||
econet_remove_socket(&econet_sklist, sk);
|
econet_remove_socket(&econet_sklist, sk);
|
||||||
|
|
||||||
|
@ -549,10 +589,14 @@ static int econet_release(struct socket *sock)
|
||||||
sk->sk_timer.expires = jiffies + HZ;
|
sk->sk_timer.expires = jiffies + HZ;
|
||||||
sk->sk_timer.function = econet_destroy_timer;
|
sk->sk_timer.function = econet_destroy_timer;
|
||||||
add_timer(&sk->sk_timer);
|
add_timer(&sk->sk_timer);
|
||||||
return 0;
|
|
||||||
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_free(sk);
|
sk_free(sk);
|
||||||
|
|
||||||
|
out_unlock:
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,6 +652,7 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
|
||||||
struct ec_device *edev;
|
struct ec_device *edev;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
struct sockaddr_ec *sec;
|
struct sockaddr_ec *sec;
|
||||||
|
int err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Fetch the caller's info block into kernel space
|
* Fetch the caller's info block into kernel space
|
||||||
|
@ -621,38 +666,35 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
|
||||||
|
|
||||||
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
|
sec = (struct sockaddr_ec *)&ifr.ifr_addr;
|
||||||
|
|
||||||
switch (cmd)
|
mutex_lock(&econet_mutex);
|
||||||
{
|
|
||||||
|
err = 0;
|
||||||
|
switch (cmd) {
|
||||||
case SIOCSIFADDR:
|
case SIOCSIFADDR:
|
||||||
edev = dev->ec_ptr;
|
edev = dev->ec_ptr;
|
||||||
if (edev == NULL)
|
if (edev == NULL) {
|
||||||
{
|
|
||||||
/* Magic up a new one. */
|
/* Magic up a new one. */
|
||||||
edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
|
edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);
|
||||||
if (edev == NULL) {
|
if (edev == NULL) {
|
||||||
printk("af_ec: memory squeeze.\n");
|
err = -ENOMEM;
|
||||||
dev_put(dev);
|
break;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
}
|
||||||
memset(edev, 0, sizeof(struct ec_device));
|
memset(edev, 0, sizeof(struct ec_device));
|
||||||
dev->ec_ptr = edev;
|
dev->ec_ptr = edev;
|
||||||
}
|
} else
|
||||||
else
|
|
||||||
net2dev_map[edev->net] = NULL;
|
net2dev_map[edev->net] = NULL;
|
||||||
edev->station = sec->addr.station;
|
edev->station = sec->addr.station;
|
||||||
edev->net = sec->addr.net;
|
edev->net = sec->addr.net;
|
||||||
net2dev_map[sec->addr.net] = dev;
|
net2dev_map[sec->addr.net] = dev;
|
||||||
if (!net2dev_map[0])
|
if (!net2dev_map[0])
|
||||||
net2dev_map[0] = dev;
|
net2dev_map[0] = dev;
|
||||||
dev_put(dev);
|
break;
|
||||||
return 0;
|
|
||||||
|
|
||||||
case SIOCGIFADDR:
|
case SIOCGIFADDR:
|
||||||
edev = dev->ec_ptr;
|
edev = dev->ec_ptr;
|
||||||
if (edev == NULL)
|
if (edev == NULL) {
|
||||||
{
|
err = -ENODEV;
|
||||||
dev_put(dev);
|
break;
|
||||||
return -ENODEV;
|
|
||||||
}
|
}
|
||||||
memset(sec, 0, sizeof(struct sockaddr_ec));
|
memset(sec, 0, sizeof(struct sockaddr_ec));
|
||||||
sec->addr.station = edev->station;
|
sec->addr.station = edev->station;
|
||||||
|
@ -660,12 +702,19 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
|
||||||
sec->sec_family = AF_ECONET;
|
sec->sec_family = AF_ECONET;
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
|
if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
|
||||||
return -EFAULT;
|
err = -EFAULT;
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
err = -EINVAL;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&econet_mutex);
|
||||||
|
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
return -EINVAL;
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -693,26 +742,13 @@ static int econet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
static int econet_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* All ioctls provided by econet are standard. There is one gotcha, sockaddr_ec
|
|
||||||
* differs between 32bit and 64bit. Fortunately nobody in kernel uses portion
|
|
||||||
* of sockaddr which differs between 32bit and 64bit, so we do not need special
|
|
||||||
* handling.
|
|
||||||
*/
|
|
||||||
return -ENOIOCTLCMD;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static struct net_proto_family econet_family_ops = {
|
static struct net_proto_family econet_family_ops = {
|
||||||
.family = PF_ECONET,
|
.family = PF_ECONET,
|
||||||
.create = econet_create,
|
.create = econet_create,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
|
static const struct proto_ops econet_ops = {
|
||||||
.family = PF_ECONET,
|
.family = PF_ECONET,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.release = econet_release,
|
.release = econet_release,
|
||||||
|
@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
|
||||||
.getname = econet_getname,
|
.getname = econet_getname,
|
||||||
.poll = datagram_poll,
|
.poll = datagram_poll,
|
||||||
.ioctl = econet_ioctl,
|
.ioctl = econet_ioctl,
|
||||||
#ifdef CONFIG_COMPAT
|
|
||||||
.compat_ioctl = econet_compat_ioctl,
|
|
||||||
#endif
|
|
||||||
.listen = sock_no_listen,
|
.listen = sock_no_listen,
|
||||||
.shutdown = sock_no_shutdown,
|
.shutdown = sock_no_shutdown,
|
||||||
.setsockopt = sock_no_setsockopt,
|
.setsockopt = sock_no_setsockopt,
|
||||||
|
@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
|
||||||
.sendpage = sock_no_sendpage,
|
.sendpage = sock_no_sendpage,
|
||||||
};
|
};
|
||||||
|
|
||||||
#include <linux/smp_lock.h>
|
|
||||||
SOCKOPS_WRAP(econet, PF_ECONET);
|
|
||||||
|
|
||||||
#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
|
#if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)
|
||||||
/*
|
/*
|
||||||
* Find the listening socket, if any, for the given data.
|
* Find the listening socket, if any, for the given data.
|
||||||
|
|
Loading…
Reference in a new issue