From patchwork Mon Feb 3 11:07:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiri Pirko X-Patchwork-Id: 11362445 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 43D081398 for ; Mon, 3 Feb 2020 11:07:58 +0000 (UTC) Received: from bastion.fedoraproject.org (bastion01.fedoraproject.org [209.132.181.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0E27B20721 for ; Mon, 3 Feb 2020 11:07:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 0E27B20721 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=resnulli.us Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=libteam-bounces@lists.fedorahosted.org Received: from mailman01.phx2.fedoraproject.org (mailman01.phx2.fedoraproject.org [10.5.126.36]) by bastion01.phx2.fedoraproject.org (Postfix) with ESMTP id 44F6660745A3; Mon, 3 Feb 2020 11:07:57 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 bastion01.phx2.fedoraproject.org 44F6660745A3 Received: from mailman01.phx2.fedoraproject.org (localhost [IPv6:::1]) by mailman01.phx2.fedoraproject.org (Postfix) with ESMTP id 30B1B5CAEEF2D; Mon, 3 Feb 2020 11:07:57 +0000 (UTC) Received: by mailman01.phx2.fedoraproject.org (Postfix, from userid 991) id 88D475CAEEF27; Mon, 3 Feb 2020 11:07:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mailman01.phx2.fedoraproject.org X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=DKIM_SIGNED,DKIM_VALID, RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE autolearn=disabled version=3.4.0 Received: from smtp-mm-ib01.fedoraproject.org (smtp-mm-ib01.vpn.fedoraproject.org [192.168.1.83]) by mailman01.phx2.fedoraproject.org (Postfix) with ESMTP id AF2615CAEEF16 for ; Mon, 3 Feb 2020 11:07:52 +0000 (UTC) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (Client CN "smtp.gmail.com", Issuer "GTS CA 1O1" (verified OK)) by smtp-mm-ib01.fedoraproject.org (Postfix) with ESMTPS id 371AB605D1CC for ; Mon, 3 Feb 2020 11:07:52 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id z7so17366293wrl.13 for ; Mon, 03 Feb 2020 03:07:52 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=SUNse7pme1ygZDOaWA3n9YOCAooUb4va9x/Tl77r71k=; b=O91cVgDw0q/+/v3bj5uOT82sCUw2V09moEkJ/z5Rs40FIXLuEVZfiy1g+kP9dihM4h BsCw56A+C3Xqt8RV+Cp5J9JMjE7RDIiDxPWQvGED/C8fxgW+w3X3ucybyVn9C63J2lbn Zo0mKD7Os5U5f1v41Su0VXIRgOFDMtlpxulTruTbTtZzUa5jrhZ31JbBnFzoU8tIwTEd fG3se7QKiVh15MpApGz/UqXX4U4afsq05ofE4zY1uUoXPrziClEC6+D2QZIUT38O/5Pf a4szYzZzkmMj9HTwS92zQgI5lQioMvMOWRq45WTJXUwVlAPgSXrFP0JBPb+nKhB5p6fQ bWcw== X-Gm-Message-State: APjAAAVt5IA5FcO7ZuLveYvEpncYl+SBNlv0i7IvmfqA1njliJA/QnzD V6PCkGMn2XsD/8v8VTuT19+Pc63aKkc= X-Google-Smtp-Source: APXvYqzI7uGDatCHWQI9v8wyBxIOYTntlBfl6+C8/fZqP/UV1coOYz63JniJ+6sdzD1Mui8ZTBOPpQ== X-Received: by 2002:a5d:5708:: with SMTP id a8mr14572556wrv.79.1580728070982; Mon, 03 Feb 2020 03:07:50 -0800 (PST) Received: from localhost (ip-89-177-6-126.net.upcbroadband.cz. [89.177.6.126]) by smtp.gmail.com with ESMTPSA id t1sm24099913wma.43.2020.02.03.03.07.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 03 Feb 2020 03:07:50 -0800 (PST) From: Jiri Pirko To: libteam@lists.fedorahosted.org Subject: [patch libteam] teamd: fix possible race in master ifname callback Date: Mon, 3 Feb 2020 12:07:49 +0100 Message-Id: <20200203110749.8912-1-jiri@resnulli.us> X-Mailer: git-send-email 2.21.0 MIME-Version: 1.0 Message-ID-Hash: XILAXXZKHLSQDQUMOOUAVJVZ54NOFIEF X-Message-ID-Hash: XILAXXZKHLSQDQUMOOUAVJVZ54NOFIEF X-MailFrom: jiri@resnulli.us X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header CC: stepanb@mellanox.com, liatg@mellanox.com X-Mailman-Version: 3.1.1 Precedence: list List-Id: Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: From: Jiri Pirko In teamd the messages from kernel are processed in order: options ifinfo ports However, kernel sends the messages in a different order. See: team_upper_dev_link() which generates ifinfo notification __team_port_change_port_added() which generates ports notification __team_options_change_check() which generates options notification So there is a chance that the teamd processed only the port without options and right after that it processes ifinfo. Fix this by introducing teamd_port_enabled_check() which does not log error and ignore the port in case this call fails. This is safe as this is going to be handled by future link_watch_enabled_option_changed() call. Signed-off-by: Jiri Pirko Fixes: 5f351666409f ("teamd: add port_master_ifindex_changed for link_watch_port_watch_ops") Tested-by: Stepan Blyshchak Reviewed-by: Xin Long --- teamd/teamd.h | 2 ++ teamd/teamd_link_watch.c | 13 ++++++++++--- teamd/teamd_per_port.c | 24 +++++++++++++++++++----- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/teamd/teamd.h b/teamd/teamd.h index fb2872efd0ac..f94c918cfe52 100644 --- a/teamd/teamd.h +++ b/teamd/teamd.h @@ -325,6 +325,8 @@ int teamd_port_remove_all(struct teamd_context *ctx); void teamd_port_obj_remove_all(struct teamd_context *ctx); int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, bool *enabled); +int teamd_port_enabled_check(struct teamd_context *ctx, + struct teamd_port *tdport, bool *enabled); int teamd_port_prio(struct teamd_context *ctx, struct teamd_port *tdport); int teamd_port_check_enable(struct teamd_context *ctx, struct teamd_port *tdport, diff --git a/teamd/teamd_link_watch.c b/teamd/teamd_link_watch.c index 5c626eb3e636..cae6549d613a 100644 --- a/teamd/teamd_link_watch.c +++ b/teamd/teamd_link_watch.c @@ -423,9 +423,16 @@ static int link_watch_refresh_forced_send(struct teamd_context *ctx) int err; teamd_for_each_tdport(tdport, ctx) { - err = teamd_port_enabled(ctx, tdport, &port_enabled); - if (err) - return err; + err = teamd_port_enabled_check(ctx, tdport, &port_enabled); + if (err) { + /* Looks like the options are not ready for this port. + * This can happen when called from + * link_watch_port_master_ifindex_changed(). Skip this + * for now, let it be handled by future call of + * link_watch_enabled_option_changed(). + */ + continue; + } __set_forced_send_for_port(tdport, port_enabled); if (port_enabled) enabled_port_count++; diff --git a/teamd/teamd_per_port.c b/teamd/teamd_per_port.c index 327aefbe9a44..166da576ef7c 100644 --- a/teamd/teamd_per_port.c +++ b/teamd/teamd_per_port.c @@ -389,19 +389,21 @@ int teamd_port_remove_ifname(struct teamd_context *ctx, const char *port_name) return teamd_port_remove(ctx, tdport); } -int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, - bool *enabled) +int __teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, + bool *enabled, bool may_fail) { struct team_option *option; option = team_get_option(ctx->th, "np", "enabled", tdport->ifindex); if (!option) { - teamd_log_err("%s: Failed to find \"enabled\" option.", - tdport->ifname); + if (!may_fail) + teamd_log_err("%s: Failed to find \"enabled\" option.", + tdport->ifname); return -ENOENT; } if (team_get_option_type(option) != TEAM_OPTION_TYPE_BOOL) { - teamd_log_err("Unexpected type of \"enabled\" option."); + if (!may_fail) + teamd_log_err("Unexpected type of \"enabled\" option."); return -EINVAL; } @@ -409,6 +411,18 @@ int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, return 0; } +int teamd_port_enabled(struct teamd_context *ctx, struct teamd_port *tdport, + bool *enabled) +{ + return __teamd_port_enabled(ctx, tdport, enabled, false); +} + +int teamd_port_enabled_check(struct teamd_context *ctx, + struct teamd_port *tdport, bool *enabled) +{ + return __teamd_port_enabled(ctx, tdport, enabled, true); +} + int teamd_port_prio(struct teamd_context *ctx, struct teamd_port *tdport) { int prio;