diff options
| author | David S. Miller <davem@sunset.davemloft.net> | 2006-03-28 00:01:55 -0800 | 
|---|---|---|
| committer | David S. Miller <davem@sunset.davemloft.net> | 2006-03-28 17:02:43 -0800 | 
| commit | 1d1818316f0b61e0997a159680e1e631a23a407e (patch) | |
| tree | fe79294a13661c75f2c5e311dfa62b2ba5ac8f67 /net/econet | |
| parent | f6c90b71a355a0a4a22e1cfee5748617adc25a53 (diff) | |
[ECONET]: Convert away from SOCKOPS_WRAPPED
Just use a local econet_mutex instead.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/econet')
| -rw-r--r-- | net/econet/af_econet.c | 140 | 
1 files changed, 85 insertions, 55 deletions
| diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 0c4c83bb2a59..868265619dbb 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -42,6 +42,7 @@  #include <linux/spinlock.h>  #include <linux/rcupdate.h>  #include <linux/bitops.h> +#include <linux/mutex.h>  #include <asm/uaccess.h>  #include <asm/system.h> @@ -49,6 +50,7 @@  static const struct proto_ops econet_ops;  static struct hlist_head econet_sklist;  static DEFINE_RWLOCK(econet_lock); +static DEFINE_MUTEX(econet_mutex);  /* Since there are only 256 possible network numbers (or fewer, depends     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); +	mutex_lock(&econet_mutex); +  	/*  	 *	Call the generic datagram receiver. This handles all sorts  	 *	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:  	skb_free_datagram(sk, skb);  out: +	mutex_unlock(&econet_mutex);  	return err;  } @@ -184,8 +189,8 @@ out:  static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)  {  	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr; -	struct sock *sk=sock->sk; -	struct econet_sock *eo = ec_sk(sk); +	struct sock *sk; +	struct econet_sock *eo;  	/*  	 *	Check legality @@ -195,11 +200,18 @@ static int econet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len  	    sec->sec_family != AF_ECONET)  		return -EINVAL; +	mutex_lock(&econet_mutex); + +	sk = sock->sk; +	eo = ec_sk(sk); +  	eo->cb	    = sec->cb;  	eo->port    = sec->port;  	eo->station = sec->addr.station;  	eo->net	    = sec->addr.net; +	mutex_unlock(&econet_mutex); +  	return 0;  } @@ -284,6 +296,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  	 *	Get and verify the address.   	 */ +	mutex_lock(&econet_mutex); +  	if (saddr == NULL) {  		struct econet_sock *eo = ec_sk(sk); @@ -292,8 +306,10 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  		port	     = eo->port;  		cb	     = eo->cb;  	} else { -		if (msg->msg_namelen < sizeof(struct sockaddr_ec))  +		if (msg->msg_namelen < sizeof(struct sockaddr_ec)) { +			mutex_unlock(&econet_mutex);  			return -EINVAL; +		}  		addr.station = saddr->addr.station;  		addr.net = saddr->addr.net;  		port = saddr->port; @@ -304,19 +320,21 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  	dev = net2dev_map[addr.net];  	/* If not directly reachable, use some default */ -	if (dev == NULL) -	{ +	if (dev == NULL) {  		dev = net2dev_map[0];  		/* No interfaces at all? */ -		if (dev == NULL) +		if (dev == NULL) { +			mutex_unlock(&econet_mutex);  			return -ENETDOWN; +		}  	} -	if (len + 15 > dev->mtu) +	if (len + 15 > dev->mtu) { +		mutex_unlock(&econet_mutex);  		return -EMSGSIZE; +	} -	if (dev->type == ARPHRD_ECONET) -	{ +	if (dev->type == ARPHRD_ECONET) {  		/* Real hardware Econet.  We're not worthy etc. */  #ifdef CONFIG_ECONET_NATIVE  		unsigned short proto = 0; @@ -374,6 +392,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  		dev_queue_xmit(skb);  		dev_put(dev); +		mutex_unlock(&econet_mutex);  		return(len);  	out_free: @@ -384,14 +403,18 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  #else  		err = -EPROTOTYPE;  #endif +		mutex_unlock(&econet_mutex); +  		return err;  	}  #ifdef CONFIG_ECONET_AUNUDP  	/* AUN virtual Econet. */ -	if (udpsock == NULL) +	if (udpsock == NULL) { +		mutex_unlock(&econet_mutex);  		return -ENETDOWN;		/* No socket - can't send */ +	}  	/* 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;  		size_t len = msg->msg_iov[i].iov_len;  		/* 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; +		}  		iov[i+1].iov_base = base;  		iov[i+1].iov_len = 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) */  	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; +	}  	eb = (struct ec_cb *)&skb->cb; @@ -475,6 +503,8 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,  #else  	err = -EPROTOTYPE;  #endif +	mutex_unlock(&econet_mutex); +  	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,  			  int *uaddr_len, int peer)  { -	struct sock *sk = sock->sk; -	struct econet_sock *eo = ec_sk(sk); +	struct sock *sk; +	struct econet_sock *eo;  	struct sockaddr_ec *sec = (struct sockaddr_ec *)uaddr;  	if (peer)  		return -EOPNOTSUPP; +	mutex_lock(&econet_mutex); + +	sk = sock->sk; +	eo = ec_sk(sk); +  	sec->sec_family	  = AF_ECONET;  	sec->port	  = eo->port;  	sec->addr.station = eo->station;  	sec->addr.net	  = eo->net; +	mutex_unlock(&econet_mutex); +  	*uaddr_len = sizeof(*sec);  	return 0;  } @@ -522,10 +559,13 @@ static void econet_destroy_timer(unsigned long data)  static int econet_release(struct socket *sock)  { -	struct sock *sk = sock->sk; +	struct sock *sk; +	mutex_lock(&econet_mutex); + +	sk = sock->sk;  	if (!sk) -		return 0; +		goto out_unlock;  	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.function = econet_destroy_timer;  		add_timer(&sk->sk_timer); -		return 0; + +		goto out_unlock;  	}  	sk_free(sk); + +out_unlock: +	mutex_unlock(&econet_mutex);  	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 net_device *dev;  	struct sockaddr_ec *sec; +	int err;  	/*  	 *	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; -	switch (cmd) -	{ +	mutex_lock(&econet_mutex); + +	err = 0; +	switch (cmd) {  	case SIOCSIFADDR:  		edev = dev->ec_ptr; -		if (edev == NULL) -		{ +		if (edev == NULL) {  			/* Magic up a new one. */  			edev = kmalloc(sizeof(struct ec_device), GFP_KERNEL);  			if (edev == NULL) { -				printk("af_ec: memory squeeze.\n"); -				dev_put(dev); -				return -ENOMEM; +				err = -ENOMEM; +				break;  			}  			memset(edev, 0, sizeof(struct ec_device));  			dev->ec_ptr = edev; -		} -		else +		} else  			net2dev_map[edev->net] = NULL;  		edev->station = sec->addr.station;  		edev->net = sec->addr.net;  		net2dev_map[sec->addr.net] = dev;  		if (!net2dev_map[0])  			net2dev_map[0] = dev; -		dev_put(dev); -		return 0; +		break;  	case SIOCGIFADDR:  		edev = dev->ec_ptr; -		if (edev == NULL) -		{ -			dev_put(dev); -			return -ENODEV; +		if (edev == NULL) { +			err = -ENODEV; +			break;  		}  		memset(sec, 0, sizeof(struct sockaddr_ec));  		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;  		dev_put(dev);  		if (copy_to_user(arg, &ifr, sizeof(struct ifreq))) -			return -EFAULT; -		return 0; +			err = -EFAULT; +		break; + +	default: +		err = -EINVAL; +		break;  	} +	mutex_unlock(&econet_mutex); +  	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;  } -#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 = {  	.family =	PF_ECONET,  	.create =	econet_create,  	.owner	=	THIS_MODULE,  }; -static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = { +static const struct proto_ops econet_ops = {  	.family =	PF_ECONET,  	.owner =	THIS_MODULE,  	.release =	econet_release, @@ -723,9 +759,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {  	.getname =	econet_getname,   	.poll =		datagram_poll,  	.ioctl =	econet_ioctl, -#ifdef CONFIG_COMPAT -	.compat_ioctl =	econet_compat_ioctl, -#endif  	.listen =	sock_no_listen,  	.shutdown =	sock_no_shutdown,  	.setsockopt =	sock_no_setsockopt, @@ -736,9 +769,6 @@ static const struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {  	.sendpage =	sock_no_sendpage,  }; -#include <linux/smp_lock.h> -SOCKOPS_WRAP(econet, PF_ECONET); -  #if defined(CONFIG_ECONET_AUNUDP) || defined(CONFIG_ECONET_NATIVE)  /*   *	Find the listening socket, if any, for the given data. | 
