patch-2.3.15 linux/net/econet/econet.c

Next file: linux/net/ipv4/Config.in
Previous file: linux/net/decnet/sysctl_net_decnet.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.14/linux/net/econet/econet.c linux/net/econet/econet.c
@@ -115,6 +115,8 @@
 
 /*
  *	Find an Econet device given its `dev' pointer.  This is IRQ safe.
+ *
+ *	Against what is it safe? --ANK
  */
 
 static struct ec_device *edev_get(struct net_device *dev)
@@ -329,7 +331,7 @@
 	{
 		/* Real hardware Econet.  We're not worthy etc. */
 #ifdef CONFIG_ECONET_NATIVE
-		dev_lock_list();
+		atomic_inc(&dev->refcnt);
 		
 		skb = sock_alloc_send_skb(sk, len+dev->hard_header_len+15, 0, 
 					  msg->msg_flags & MSG_DONTWAIT, &err);
@@ -372,14 +374,15 @@
 		 *	Now send it
 		 */
 		
-		dev_unlock_list();
 		dev_queue_xmit(skb);
+		dev_put(dev);
 		return(len);
 
 	out_free:
 		kfree_skb(skb);
 	out_unlock:
-		dev_unlock_list();
+		if (dev)
+			dev_put(dev);
 #else
 		err = -EPROTOTYPE;
 #endif
@@ -402,9 +405,16 @@
 	   y.x maps to IP a.b.c.x.  This should be replaced with something
 	   more flexible and more aware of subnet masks.  */
 	{
-		struct in_device *idev = (struct in_device *)dev->ip_ptr;
-		unsigned long network = ntohl(idev->ifa_list->ifa_address) & 
-			0xffffff00;		/* !!! */
+		struct in_device *idev = in_dev_get(dev);
+		unsigned long network = 0;
+		if (idev) {
+			read_lock(&idev->lock);
+			if (idev->ifa_list)
+				network = ntohl(idev->ifa_list->ifa_address) & 
+					0xffffff00;		/* !!! */
+			read_unlock(&idev->lock);
+			in_dev_put(idev);
+		}
 		udpdest.sin_addr.s_addr = htonl(network | addr.station);
 	}
 
@@ -502,7 +512,7 @@
  *	Close an econet socket.
  */
 
-static int econet_release(struct socket *sock, struct socket *peersock)
+static int econet_release(struct socket *sock)
 {
 	struct sk_buff	*skb;
 	struct sock *sk = sock->sk;
@@ -602,7 +612,7 @@
 	if (copy_from_user(&ifr, arg, sizeof(struct ifreq)))
 		return -EFAULT;
 
-	if ((dev = dev_get(ifr.ifr_name)) == NULL) 
+	if ((dev = dev_get_by_name(ifr.ifr_name)) == NULL) 
 		return -ENODEV;
 
 	sec = (struct sockaddr_ec *)&ifr.ifr_addr;
@@ -615,10 +625,19 @@
 		if (edev == NULL)
 		{
 			/* Magic up a new one. */
+			printk("Get fascist grenade!!!\n");
+			*(int*)0 = 0;
+			/* Note to author: please, remove this spinlock.
+			   You do not change edevlist from interrupts,
+			   so that such aggressive protection is redundant.
+
+			   BTW not all scans of edev_list are protected.
+			 */
 			edev = kmalloc(GFP_KERNEL, sizeof(struct ec_device));
 			if (edev == NULL) {
 				printk("af_ec: memory squeeze.\n");
 				spin_unlock_irqrestore(&edevlist_lock, flags);
+				dev_put(dev);
 				return -ENOMEM;
 			}
 			memset(edev, 0, sizeof(struct ec_device));
@@ -629,6 +648,7 @@
 		edev->station = sec->addr.station;
 		edev->net = sec->addr.net;
 		spin_unlock_irqrestore(&edevlist_lock, flags);
+		dev_put(dev);
 		return 0;
 
 	case SIOCGIFADDR:
@@ -637,6 +657,7 @@
 		if (edev == NULL)
 		{
 			spin_unlock_irqrestore(&edevlist_lock, flags);
+			dev_put(dev);
 			return -ENODEV;
 		}
 		memset(sec, 0, sizeof(struct sockaddr_ec));
@@ -644,11 +665,13 @@
 		sec->addr.net = edev->net;
 		sec->sec_family = AF_ECONET;
 		spin_unlock_irqrestore(&edevlist_lock, flags);
+		dev_put(dev);
 		if (copy_to_user(arg, &ifr, sizeof(struct ifreq)))
 			return -EFAULT;
 		return 0;
 	}
 
+	dev_put(dev);
 	return -EINVAL;
 }
 
@@ -722,10 +745,9 @@
 	econet_create
 };
 
-static struct proto_ops econet_ops = {
+static struct proto_ops SOCKOPS_WRAPPED(econet_ops) = {
 	PF_ECONET,
 
-	sock_no_dup,
 	econet_release,
 	econet_bind,
 	sock_no_connect,
@@ -740,8 +762,12 @@
 	sock_no_getsockopt,
 	sock_no_fcntl,
 	econet_sendmsg,
-	econet_recvmsg
+	econet_recvmsg,
+	sock_no_mmap
 };
+
+#include <linux/smp_lock.h>
+SOCKOPS_WRAP(econet, PF_ECONET);
 
 /*
  *	Find the listening socket, if any, for the given data.

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)