Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=14e3e07979c4384e45e751882292d3b38477e855
Commit:     14e3e07979c4384e45e751882292d3b38477e855
Parent:     cfcabdcc2d5a810208e5bb3974121b7ed60119aa
Author:     Jeff Garzik <[EMAIL PROTECTED]>
AuthorDate: Mon Oct 8 00:06:32 2007 -0700
Committer:  David S. Miller <[EMAIL PROTECTED]>
CommitDate: Wed Oct 10 16:54:49 2007 -0700

    [NET]: split dev_ifsioc() according to locking
    
    This always bugged me: dev_ioctl() called dev_ifsioc() either inside
    read_lock(dev_base_lock) or rtnl_lock(), depending on the ioctl being
    executed.
    
    This change moves the ioctls executed inside dev_base_lock to a new
    function, dev_ifsioc_locked().  Now the locking context is completely
    clear to the reader.
    
    Signed-off-by: Jeff Garzik <[EMAIL PROTECTED]>
    Signed-off-by: David S. Miller <[EMAIL PROTECTED]>
---
 net/core/dev.c |   88 +++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/net/core/dev.c b/net/core/dev.c
index 13a1bc5..1aa0704 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -3083,9 +3083,9 @@ int dev_set_mac_address(struct net_device *dev, struct 
sockaddr *sa)
 }
 
 /*
- *     Perform the SIOCxIFxxx calls.
+ *     Perform the SIOCxIFxxx calls, inside read_lock(dev_base_lock)
  */
-static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int 
cmd)
 {
        int err;
        struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
@@ -3098,25 +3098,15 @@ static int dev_ifsioc(struct net *net, struct ifreq 
*ifr, unsigned int cmd)
                        ifr->ifr_flags = dev_get_flags(dev);
                        return 0;
 
-               case SIOCSIFFLAGS:      /* Set interface flags */
-                       return dev_change_flags(dev, ifr->ifr_flags);
-
                case SIOCGIFMETRIC:     /* Get the metric on the interface
                                           (currently unused) */
                        ifr->ifr_metric = 0;
                        return 0;
 
-               case SIOCSIFMETRIC:     /* Set the metric on the interface
-                                          (currently unused) */
-                       return -EOPNOTSUPP;
-
                case SIOCGIFMTU:        /* Get the MTU of a device */
                        ifr->ifr_mtu = dev->mtu;
                        return 0;
 
-               case SIOCSIFMTU:        /* Set the MTU of a device */
-                       return dev_set_mtu(dev, ifr->ifr_mtu);
-
                case SIOCGIFHWADDR:
                        if (!dev->addr_len)
                                memset(ifr->ifr_hwaddr.sa_data, 0, sizeof 
ifr->ifr_hwaddr.sa_data);
@@ -3126,6 +3116,61 @@ static int dev_ifsioc(struct net *net, struct ifreq 
*ifr, unsigned int cmd)
                        ifr->ifr_hwaddr.sa_family = dev->type;
                        return 0;
 
+               case SIOCGIFSLAVE:
+                       err = -EINVAL;
+                       break;
+
+               case SIOCGIFMAP:
+                       ifr->ifr_map.mem_start = dev->mem_start;
+                       ifr->ifr_map.mem_end   = dev->mem_end;
+                       ifr->ifr_map.base_addr = dev->base_addr;
+                       ifr->ifr_map.irq       = dev->irq;
+                       ifr->ifr_map.dma       = dev->dma;
+                       ifr->ifr_map.port      = dev->if_port;
+                       return 0;
+
+               case SIOCGIFINDEX:
+                       ifr->ifr_ifindex = dev->ifindex;
+                       return 0;
+
+               case SIOCGIFTXQLEN:
+                       ifr->ifr_qlen = dev->tx_queue_len;
+                       return 0;
+
+               default:
+                       /* dev_ioctl() should ensure this case
+                        * is never reached
+                        */
+                       WARN_ON(1);
+                       err = -EINVAL;
+                       break;
+
+       }
+       return err;
+}
+
+/*
+ *     Perform the SIOCxIFxxx calls, inside rtnl_lock()
+ */
+static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
+{
+       int err;
+       struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
+
+       if (!dev)
+               return -ENODEV;
+
+       switch (cmd) {
+               case SIOCSIFFLAGS:      /* Set interface flags */
+                       return dev_change_flags(dev, ifr->ifr_flags);
+
+               case SIOCSIFMETRIC:     /* Set the metric on the interface
+                                          (currently unused) */
+                       return -EOPNOTSUPP;
+
+               case SIOCSIFMTU:        /* Set the MTU of a device */
+                       return dev_set_mtu(dev, ifr->ifr_mtu);
+
                case SIOCSIFHWADDR:
                        return dev_set_mac_address(dev, &ifr->ifr_hwaddr);
 
@@ -3137,15 +3182,6 @@ static int dev_ifsioc(struct net *net, struct ifreq 
*ifr, unsigned int cmd)
                        call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
                        return 0;
 
-               case SIOCGIFMAP:
-                       ifr->ifr_map.mem_start = dev->mem_start;
-                       ifr->ifr_map.mem_end   = dev->mem_end;
-                       ifr->ifr_map.base_addr = dev->base_addr;
-                       ifr->ifr_map.irq       = dev->irq;
-                       ifr->ifr_map.dma       = dev->dma;
-                       ifr->ifr_map.port      = dev->if_port;
-                       return 0;
-
                case SIOCSIFMAP:
                        if (dev->set_config) {
                                if (!netif_device_present(dev))
@@ -3172,14 +3208,6 @@ static int dev_ifsioc(struct net *net, struct ifreq 
*ifr, unsigned int cmd)
                        return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data,
                                             dev->addr_len, 1);
 
-               case SIOCGIFINDEX:
-                       ifr->ifr_ifindex = dev->ifindex;
-                       return 0;
-
-               case SIOCGIFTXQLEN:
-                       ifr->ifr_qlen = dev->tx_queue_len;
-                       return 0;
-
                case SIOCSIFTXQLEN:
                        if (ifr->ifr_qlen < 0)
                                return -EINVAL;
@@ -3290,7 +3318,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void 
__user *arg)
                case SIOCGIFTXQLEN:
                        dev_load(net, ifr.ifr_name);
                        read_lock(&dev_base_lock);
-                       ret = dev_ifsioc(net, &ifr, cmd);
+                       ret = dev_ifsioc_locked(net, &ifr, cmd);
                        read_unlock(&dev_base_lock);
                        if (!ret) {
                                if (colon)
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to