diff options
author | Jeff Garzik <jgarzik@redhat.com> | 2007-10-08 03:06:32 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:54:49 -0400 |
commit | 14e3e07979c4384e45e751882292d3b38477e855 (patch) | |
tree | a99004a45287f943ffa69428ceb0d516f1bc9458 /net/core | |
parent | cfcabdcc2d5a810208e5bb3974121b7ed60119aa (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>
Diffstat (limited to 'net/core')
-rw-r--r-- | 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 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 | */ |
3088 | static int dev_ifsioc(struct net *net, struct ifreq *ifr, unsigned int cmd) | 3088 | static 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 | */ | ||
3155 | static 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) |