aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVeaceslav Falico <vfalico@redhat.com>2014-01-10 10:56:25 -0500
committerDavid S. Miller <davem@davemloft.net>2014-01-13 18:19:26 -0500
commit2315dc91a5059d7da9a8b9b9daf78d695c11383e (patch)
tree751234af7ab27daebdf18cb4b08ef8247cabb52e
parent7e11daa7c19ec319fa4b750fd249a18957f17797 (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.c34
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}
5301EXPORT_SYMBOL(dev_change_flags); 5301EXPORT_SYMBOL(dev_change_flags);
5302 5302
5303static 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 */
5310int dev_set_mtu(struct net_device *dev, int new_mtu) 5321int 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}
5335EXPORT_SYMBOL(dev_set_mtu); 5351EXPORT_SYMBOL(dev_set_mtu);