aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Garzik <jgarzik@redhat.com>2007-10-08 03:06:32 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:54:49 -0400
commit14e3e07979c4384e45e751882292d3b38477e855 (patch)
treea99004a45287f943ffa69428ceb0d516f1bc9458
parentcfcabdcc2d5a810208e5bb3974121b7ed60119aa (diff)
[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 <jgarzik@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/dev.c88
1 files changed, 58 insertions, 30 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 13a1bc5d3bfd..1aa07047826e 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)
3083} 3083}
3084 3084
3085/* 3085/*
3086 * Perform the SIOCxIFxxx calls. 3086 * Perform the SIOCxIFxxx calls, inside read_lock(dev_base_lock)
3087 */ 3087 */
3088static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) 3088static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cmd)
3089{ 3089{
3090 int err; 3090 int err;
3091 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name); 3091 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)
3098 ifr->ifr_flags = dev_get_flags(dev); 3098 ifr->ifr_flags = dev_get_flags(dev);
3099 return 0; 3099 return 0;
3100 3100
3101 case SIOCSIFFLAGS: /* Set interface flags */
3102 return dev_change_flags(dev, ifr->ifr_flags);
3103
3104 case SIOCGIFMETRIC: /* Get the metric on the interface 3101 case SIOCGIFMETRIC: /* Get the metric on the interface
3105 (currently unused) */ 3102 (currently unused) */
3106 ifr->ifr_metric = 0; 3103 ifr->ifr_metric = 0;
3107 return 0; 3104 return 0;
3108 3105
3109 case SIOCSIFMETRIC: /* Set the metric on the interface
3110 (currently unused) */
3111 return -EOPNOTSUPP;
3112
3113 case SIOCGIFMTU: /* Get the MTU of a device */ 3106 case SIOCGIFMTU: /* Get the MTU of a device */
3114 ifr->ifr_mtu = dev->mtu; 3107 ifr->ifr_mtu = dev->mtu;
3115 return 0; 3108 return 0;
3116 3109
3117 case SIOCSIFMTU: /* Set the MTU of a device */
3118 return dev_set_mtu(dev, ifr->ifr_mtu);
3119
3120 case SIOCGIFHWADDR: 3110 case SIOCGIFHWADDR:
3121 if (!dev->addr_len) 3111 if (!dev->addr_len)
3122 memset(ifr->ifr_hwaddr.sa_data, 0, sizeof ifr->ifr_hwaddr.sa_data); 3112 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)
3126 ifr->ifr_hwaddr.sa_family = dev->type; 3116 ifr->ifr_hwaddr.sa_family = dev->type;
3127 return 0; 3117 return 0;
3128 3118
3119 case SIOCGIFSLAVE:
3120 err = -EINVAL;
3121 break;
3122
3123 case SIOCGIFMAP:
3124 ifr->ifr_map.mem_start = dev->mem_start;
3125 ifr->ifr_map.mem_end = dev->mem_end;
3126 ifr->ifr_map.base_addr = dev->base_addr;
3127 ifr->ifr_map.irq = dev->irq;
3128 ifr->ifr_map.dma = dev->dma;
3129 ifr->ifr_map.port = dev->if_port;
3130 return 0;
3131
3132 case SIOCGIFINDEX:
3133 ifr->ifr_ifindex = dev->ifindex;
3134 return 0;
3135
3136 case SIOCGIFTXQLEN:
3137 ifr->ifr_qlen = dev->tx_queue_len;
3138 return 0;
3139
3140 default:
3141 /* dev_ioctl() should ensure this case
3142 * is never reached
3143 */
3144 WARN_ON(1);
3145 err = -EINVAL;
3146 break;
3147
3148 }
3149 return err;
3150}
3151
3152/*
3153 * Perform the SIOCxIFxxx calls, inside rtnl_lock()
3154 */
3155static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3156{
3157 int err;
3158 struct net_device *dev = __dev_get_by_name(net, ifr->ifr_name);
3159
3160 if (!dev)
3161 return -ENODEV;
3162
3163 switch (cmd) {
3164 case SIOCSIFFLAGS: /* Set interface flags */
3165 return dev_change_flags(dev, ifr->ifr_flags);
3166
3167 case SIOCSIFMETRIC: /* Set the metric on the interface
3168 (currently unused) */
3169 return -EOPNOTSUPP;
3170
3171 case SIOCSIFMTU: /* Set the MTU of a device */
3172 return dev_set_mtu(dev, ifr->ifr_mtu);
3173
3129 case SIOCSIFHWADDR: 3174 case SIOCSIFHWADDR:
3130 return dev_set_mac_address(dev, &ifr->ifr_hwaddr); 3175 return dev_set_mac_address(dev, &ifr->ifr_hwaddr);
3131 3176
@@ -3137,15 +3182,6 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3137 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 3182 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
3138 return 0; 3183 return 0;
3139 3184
3140 case SIOCGIFMAP:
3141 ifr->ifr_map.mem_start = dev->mem_start;
3142 ifr->ifr_map.mem_end = dev->mem_end;
3143 ifr->ifr_map.base_addr = dev->base_addr;
3144 ifr->ifr_map.irq = dev->irq;
3145 ifr->ifr_map.dma = dev->dma;
3146 ifr->ifr_map.port = dev->if_port;
3147 return 0;
3148
3149 case SIOCSIFMAP: 3185 case SIOCSIFMAP:
3150 if (dev->set_config) { 3186 if (dev->set_config) {
3151 if (!netif_device_present(dev)) 3187 if (!netif_device_present(dev))
@@ -3172,14 +3208,6 @@ static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd)
3172 return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data, 3208 return dev_mc_delete(dev, ifr->ifr_hwaddr.sa_data,
3173 dev->addr_len, 1); 3209 dev->addr_len, 1);
3174 3210
3175 case SIOCGIFINDEX:
3176 ifr->ifr_ifindex = dev->ifindex;
3177 return 0;
3178
3179 case SIOCGIFTXQLEN:
3180 ifr->ifr_qlen = dev->tx_queue_len;
3181 return 0;
3182
3183 case SIOCSIFTXQLEN: 3211 case SIOCSIFTXQLEN:
3184 if (ifr->ifr_qlen < 0) 3212 if (ifr->ifr_qlen < 0)
3185 return -EINVAL; 3213 return -EINVAL;
@@ -3290,7 +3318,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg)
3290 case SIOCGIFTXQLEN: 3318 case SIOCGIFTXQLEN:
3291 dev_load(net, ifr.ifr_name); 3319 dev_load(net, ifr.ifr_name);
3292 read_lock(&dev_base_lock); 3320 read_lock(&dev_base_lock);
3293 ret = dev_ifsioc(net, &ifr, cmd); 3321 ret = dev_ifsioc_locked(net, &ifr, cmd);
3294 read_unlock(&dev_base_lock); 3322 read_unlock(&dev_base_lock);
3295 if (!ret) { 3323 if (!ret) {
3296 if (colon) 3324 if (colon)