diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2014-01-10 10:56:25 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-13 18:19:26 -0500 |
commit | 2315dc91a5059d7da9a8b9b9daf78d695c11383e (patch) | |
tree | 751234af7ab27daebdf18cb4b08ef8247cabb52e | |
parent | 7e11daa7c19ec319fa4b750fd249a18957f17797 (diff) |
net: make dev_set_mtu() honor notification return code
Currently, after changing the MTU for a device, dev_set_mtu() calls
NETDEV_CHANGEMTU notification, however doesn't verify it's return code -
which can be NOTIFY_BAD - i.e. some of the net notifier blocks refused this
change, and continues nevertheless.
To fix this, verify the return code, and if it's an error - then revert the
MTU to the original one, notify again and pass the error code.
CC: Jiri Pirko <jiri@resnulli.us>
CC: "David S. Miller" <davem@davemloft.net>
CC: Eric Dumazet <edumazet@google.com>
CC: Alexander Duyck <alexander.h.duyck@intel.com>
CC: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
Reviewed-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/dev.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index a8280154c42a..87312dcf0aa8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -5300,6 +5300,17 @@ int dev_change_flags(struct net_device *dev, unsigned int flags) | |||
5300 | } | 5300 | } |
5301 | EXPORT_SYMBOL(dev_change_flags); | 5301 | EXPORT_SYMBOL(dev_change_flags); |
5302 | 5302 | ||
5303 | static int __dev_set_mtu(struct net_device *dev, int new_mtu) | ||
5304 | { | ||
5305 | const struct net_device_ops *ops = dev->netdev_ops; | ||
5306 | |||
5307 | if (ops->ndo_change_mtu) | ||
5308 | return ops->ndo_change_mtu(dev, new_mtu); | ||
5309 | |||
5310 | dev->mtu = new_mtu; | ||
5311 | return 0; | ||
5312 | } | ||
5313 | |||
5303 | /** | 5314 | /** |
5304 | * dev_set_mtu - Change maximum transfer unit | 5315 | * dev_set_mtu - Change maximum transfer unit |
5305 | * @dev: device | 5316 | * @dev: device |
@@ -5309,8 +5320,7 @@ EXPORT_SYMBOL(dev_change_flags); | |||
5309 | */ | 5320 | */ |
5310 | int dev_set_mtu(struct net_device *dev, int new_mtu) | 5321 | int dev_set_mtu(struct net_device *dev, int new_mtu) |
5311 | { | 5322 | { |
5312 | const struct net_device_ops *ops = dev->netdev_ops; | 5323 | int err, orig_mtu; |
5313 | int err; | ||
5314 | 5324 | ||
5315 | if (new_mtu == dev->mtu) | 5325 | if (new_mtu == dev->mtu) |
5316 | return 0; | 5326 | return 0; |
@@ -5322,14 +5332,20 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) | |||
5322 | if (!netif_device_present(dev)) | 5332 | if (!netif_device_present(dev)) |
5323 | return -ENODEV; | 5333 | return -ENODEV; |
5324 | 5334 | ||
5325 | err = 0; | 5335 | orig_mtu = dev->mtu; |
5326 | if (ops->ndo_change_mtu) | 5336 | err = __dev_set_mtu(dev, new_mtu); |
5327 | err = ops->ndo_change_mtu(dev, new_mtu); | ||
5328 | else | ||
5329 | dev->mtu = new_mtu; | ||
5330 | 5337 | ||
5331 | if (!err) | 5338 | if (!err) { |
5332 | call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); | 5339 | err = call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); |
5340 | err = notifier_to_errno(err); | ||
5341 | if (err) { | ||
5342 | /* setting mtu back and notifying everyone again, | ||
5343 | * so that they have a chance to revert changes. | ||
5344 | */ | ||
5345 | __dev_set_mtu(dev, orig_mtu); | ||
5346 | call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); | ||
5347 | } | ||
5348 | } | ||
5333 | return err; | 5349 | return err; |
5334 | } | 5350 | } |
5335 | EXPORT_SYMBOL(dev_set_mtu); | 5351 | EXPORT_SYMBOL(dev_set_mtu); |