net: add NETDEV_PRECHANGEMTU to notify before mtu change happens
authorVeaceslav Falico <vfalico@redhat.com>
Wed, 15 Jan 2014 23:02:18 +0000 (00:02 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 17 Jan 2014 01:15:41 +0000 (17:15 -0800)
Currently, if a device changes its mtu, first the change happens (invloving
all the side effects), and after that the NETDEV_CHANGEMTU is sent so that
other devices can catch up with the new mtu. However, if they return
NOTIFY_BAD, then the change is reverted and error returned.

This is a really long and costy operation (sometimes). To fix this, add
NETDEV_PRECHANGEMTU notification which is called prior to any change
actually happening, and if any callee returns NOTIFY_BAD - the change is
aborted. This way we're skipping all the playing with apply/revert the mtu.

CC: "David S. Miller" <davem@davemloft.net>
CC: Jiri Pirko <jiri@resnulli.us>
CC: Eric Dumazet <edumazet@google.com>
CC: Nicolas Dichtel <nicolas.dichtel@6wind.com>
CC: Cong Wang <amwang@redhat.com>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
Acked-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/netdevice.h
net/core/dev.c

index 30f6513f3b4d7e0fc072a8401fe4ab551bff9be9..d7668b881d08e214ccbe99c2ce1e2eb26bd4203a 100644 (file)
@@ -1718,7 +1718,7 @@ struct pcpu_sw_netstats {
 #define NETDEV_CHANGE  0x0004  /* Notify device state change */
 #define NETDEV_REGISTER 0x0005
 #define NETDEV_UNREGISTER      0x0006
-#define NETDEV_CHANGEMTU       0x0007
+#define NETDEV_CHANGEMTU       0x0007 /* notify after mtu change happened */
 #define NETDEV_CHANGEADDR      0x0008
 #define NETDEV_GOING_DOWN      0x0009
 #define NETDEV_CHANGENAME      0x000A
@@ -1734,6 +1734,7 @@ struct pcpu_sw_netstats {
 #define NETDEV_JOIN            0x0014
 #define NETDEV_CHANGEUPPER     0x0015
 #define NETDEV_RESEND_IGMP     0x0016
+#define NETDEV_PRECHANGEMTU    0x0017 /* notify before mtu change happened */
 
 int register_netdevice_notifier(struct notifier_block *nb);
 int unregister_netdevice_notifier(struct notifier_block *nb);
index b2c1869b04e3e37359050eddf718f379871f0eac..f87bedd51eed0abfce2d4b439ecb675c8cda93b7 100644 (file)
@@ -5392,6 +5392,11 @@ int dev_set_mtu(struct net_device *dev, int new_mtu)
        if (!netif_device_present(dev))
                return -ENODEV;
 
+       err = call_netdevice_notifiers(NETDEV_PRECHANGEMTU, dev);
+       err = notifier_to_errno(err);
+       if (err)
+               return err;
+
        orig_mtu = dev->mtu;
        err = __dev_set_mtu(dev, new_mtu);