[teamd] prevent re-entrance of port priv change handler (#2723)
When adding a lag member dynamically after system boots up, teamd port priv change handler could re-entrant itself and causing adding operation to fail. While handling PORT_CHANGE event, teamd_per_port.c port priv change handler was called, it will then call runner_lacp to add port to lag, the later causes IFINFO_CHANGE to be notified and calls the priv change handler again, this re-entrance would cause runner_lacp port_added to be called again and messes up with the previous adding sequence. Then fails the lag member adding operation. Prevent per port priv change handler re-entrance solves the problem. Signed-off-by: Ying Xie <ying.xie@microsoft.com>
This commit is contained in:
parent
13a643bb3e
commit
bc98f9fe64
@ -0,0 +1,90 @@
|
|||||||
|
From fb00b070482dc587eec7b4e34acec094be1af00d Mon Sep 17 00:00:00 2001
|
||||||
|
From: Ying Xie <ying.xie@microsoft.com>
|
||||||
|
Date: Fri, 29 Mar 2019 20:54:49 +0000
|
||||||
|
Subject: [PATCH 10/11] [teamd] prevent private change handler reentrance
|
||||||
|
|
||||||
|
While handling PORT_CHANGE, teamd could casue an INTERFACE_CHANGE in the
|
||||||
|
same context. Which will interfere with the PORT_CHANGE handling and
|
||||||
|
causing it to fail.
|
||||||
|
|
||||||
|
Lock is not needed because the re-entrance happened in the same thread
|
||||||
|
context.
|
||||||
|
|
||||||
|
This issue was noticed while dynamically adding a port into a lag.
|
||||||
|
|
||||||
|
Signed-off-by: Ying Xie <ying.xie@microsoft.com>
|
||||||
|
---
|
||||||
|
teamd/teamd.c | 2 ++
|
||||||
|
teamd/teamd.h | 2 ++
|
||||||
|
teamd/teamd_per_port.c | 13 +++++++++++--
|
||||||
|
3 files changed, 15 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/teamd/teamd.c b/teamd/teamd.c
|
||||||
|
index e28aa7d..140b98b 100644
|
||||||
|
--- a/teamd/teamd.c
|
||||||
|
+++ b/teamd/teamd.c
|
||||||
|
@@ -1255,6 +1255,8 @@ static int teamd_init(struct teamd_context *ctx)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
+ ctx->reentrant = false;
|
||||||
|
+
|
||||||
|
ctx->th = team_alloc();
|
||||||
|
if (!ctx->th) {
|
||||||
|
teamd_log_err("Team alloc failed.");
|
||||||
|
diff --git a/teamd/teamd.h b/teamd/teamd.h
|
||||||
|
index 622c365..7cd3266 100644
|
||||||
|
--- a/teamd/teamd.h
|
||||||
|
+++ b/teamd/teamd.h
|
||||||
|
@@ -160,6 +160,8 @@ struct teamd_context {
|
||||||
|
int pipe_r;
|
||||||
|
int pipe_w;
|
||||||
|
} workq;
|
||||||
|
+
|
||||||
|
+ bool reentrant;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct teamd_port {
|
||||||
|
diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c
|
||||||
|
index 137da57..8b4a457 100644
|
||||||
|
--- a/teamd/teamd_per_port.c
|
||||||
|
+++ b/teamd/teamd_per_port.c
|
||||||
|
@@ -250,6 +250,10 @@ static int port_priv_change_handler_func(struct team_handle *th, void *priv,
|
||||||
|
struct port_obj *port_obj;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
+ if (ctx->reentrant) {
|
||||||
|
+ return 0;
|
||||||
|
+ }
|
||||||
|
+ ctx->reentrant = true;
|
||||||
|
team_for_each_port(port, th) {
|
||||||
|
uint32_t ifindex = team_get_port_ifindex(port);
|
||||||
|
|
||||||
|
@@ -258,17 +262,22 @@ static int port_priv_change_handler_func(struct team_handle *th, void *priv,
|
||||||
|
if (team_is_port_removed(port))
|
||||||
|
continue;
|
||||||
|
err = port_obj_create(ctx, &port_obj, ifindex, port);
|
||||||
|
- if (err)
|
||||||
|
+ if (err) {
|
||||||
|
+ ctx->reentrant = false;
|
||||||
|
return err;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (team_is_port_changed(port)) {
|
||||||
|
err = teamd_event_port_changed(ctx, _port(port_obj));
|
||||||
|
- if (err)
|
||||||
|
+ if (err) {
|
||||||
|
+ ctx->reentrant = false;
|
||||||
|
return err;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
if (team_is_port_removed(port))
|
||||||
|
port_obj_remove(ctx, port_obj);
|
||||||
|
}
|
||||||
|
+ ctx->reentrant = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.7.4
|
||||||
|
|
@ -6,3 +6,4 @@
|
|||||||
0006-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch
|
0006-Fix-ifinfo_link_with_port-race-condition-with-newlink.patch
|
||||||
0007-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch
|
0007-Skip-setting-the-same-hwaddr-to-lag-port-to-avoid-di.patch
|
||||||
0008-teamd-register-change-handler-for-TEAM_IFINFO_CHANGE.patch
|
0008-teamd-register-change-handler-for-TEAM_IFINFO_CHANGE.patch
|
||||||
|
0009-teamd-prevent-private-change-handler-reentrance.patch
|
||||||
|
Loading…
Reference in New Issue
Block a user