summaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_options.c
diff options
context:
space:
mode:
authorVlad Yasevich2017-05-27 16:14:35 +0200
committerDavid S. Miller2017-05-28 00:51:41 +0200
commit7a7e96e09d463c7c3d51a51c539ae4352085ed18 (patch)
treee71e607d845b7a87f50eace22efa40f63621081e /drivers/net/bonding/bond_options.c
parentrtnl: Add support for netdev event to link messages (diff)
downloadkernel-qcow2-linux-7a7e96e09d463c7c3d51a51c539ae4352085ed18.tar.gz
kernel-qcow2-linux-7a7e96e09d463c7c3d51a51c539ae4352085ed18.tar.xz
kernel-qcow2-linux-7a7e96e09d463c7c3d51a51c539ae4352085ed18.zip
bonding: Prevent duplicate userspace notification
Whenever a user changes bonding options, a NETDEV_CHANGEINFODATA notificatin is generated which results in a rtnelink message to be sent. While runnig 'ip monitor', we can actually see 2 messages, one a result of the event, and the other a result of state change that is generated bo netdev_state_change(). However, this is not always the case. If bonding changes were done via sysfs or ifenslave (old ioctl interface), then only 1 message is seen. This patch removes duplicate messages in the case of using netlink to configure bonding. It introduceds a separte function that triggers a netdev event and uses that function in the syfs and ioctl cases. This was discovered while auditing all the different envents and continues the effort of cleaning up duplicated netlink messages. CC: David Ahern <dsa@cumulusnetworks.com> CC: Jiri Pirko <jiri@resnulli.us> Signed-off-by: Vladislav Yasevich <vyasevic@redhat.com> Acked-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_options.c')
-rw-r--r--drivers/net/bonding/bond_options.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/drivers/net/bonding/bond_options.c b/drivers/net/bonding/bond_options.c
index 1bcbb8913e17..8ca683396fcc 100644
--- a/drivers/net/bonding/bond_options.c
+++ b/drivers/net/bonding/bond_options.c
@@ -673,7 +673,30 @@ int __bond_opt_set(struct bonding *bond,
out:
if (ret)
bond_opt_error_interpret(bond, opt, ret, val);
- else if (bond->dev->reg_state == NETREG_REGISTERED)
+
+ return ret;
+}
+/**
+ * __bond_opt_set_notify - set a bonding option
+ * @bond: target bond device
+ * @option: option to set
+ * @val: value to set it to
+ *
+ * This function is used to change the bond's option value and trigger
+ * a notification to user sapce. It can be used for both enabling/changing
+ * an option and for disabling it. RTNL lock must be obtained before calling
+ * this function.
+ */
+int __bond_opt_set_notify(struct bonding *bond,
+ unsigned int option, struct bond_opt_value *val)
+{
+ int ret = -ENOENT;
+
+ ASSERT_RTNL();
+
+ ret = __bond_opt_set(bond, option, val);
+
+ if (!ret && (bond->dev->reg_state == NETREG_REGISTERED))
call_netdevice_notifiers(NETDEV_CHANGEINFODATA, bond->dev);
return ret;
@@ -696,7 +719,7 @@ int bond_opt_tryset_rtnl(struct bonding *bond, unsigned int option, char *buf)
if (!rtnl_trylock())
return restart_syscall();
bond_opt_initstr(&optval, buf);
- ret = __bond_opt_set(bond, option, &optval);
+ ret = __bond_opt_set_notify(bond, option, &optval);
rtnl_unlock();
return ret;