diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2014-01-10 16:56:25 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-13 15:19:26 -0800 |
commit | 2315dc91a5059d7da9a8b9b9daf78d695c11383e (patch) | |
tree | 751234af7ab27daebdf18cb4b08ef8247cabb52e | |
parent | 7e11daa7c19ec319fa4b750fd249a18957f17797 (diff) | |
download | linux-stable-2315dc91a5059d7da9a8b9b9daf78d695c11383e.tar.gz linux-stable-2315dc91a5059d7da9a8b9b9daf78d695c11383e.tar.bz2 linux-stable-2315dc91a5059d7da9a8b9b9daf78d695c11383e.zip |
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) } EXPORT_SYMBOL(dev_change_flags); +static int __dev_set_mtu(struct net_device *dev, int new_mtu) +{ + const struct net_device_ops *ops = dev->netdev_ops; + + if (ops->ndo_change_mtu) + return ops->ndo_change_mtu(dev, new_mtu); + + dev->mtu = new_mtu; + return 0; +} + /** * dev_set_mtu - Change maximum transfer unit * @dev: device @@ -5309,8 +5320,7 @@ EXPORT_SYMBOL(dev_change_flags); */ int dev_set_mtu(struct net_device *dev, int new_mtu) { - const struct net_device_ops *ops = dev->netdev_ops; - int err; + int err, orig_mtu; if (new_mtu == dev->mtu) return 0; @@ -5322,14 +5332,20 @@ int dev_set_mtu(struct net_device *dev, int new_mtu) if (!netif_device_present(dev)) return -ENODEV; - err = 0; - if (ops->ndo_change_mtu) - err = ops->ndo_change_mtu(dev, new_mtu); - else - dev->mtu = new_mtu; + orig_mtu = dev->mtu; + err = __dev_set_mtu(dev, new_mtu); - if (!err) - call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); + if (!err) { + err = call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); + err = notifier_to_errno(err); + if (err) { + /* setting mtu back and notifying everyone again, + * so that they have a chance to revert changes. + */ + __dev_set_mtu(dev, orig_mtu); + call_netdevice_notifiers(NETDEV_CHANGEMTU, dev); + } + } return err; } EXPORT_SYMBOL(dev_set_mtu); |