From mboxrd@z Thu Jan 1 00:00:00 1970 From: Jiri Pirko Subject: [patch net] mlxsw: spectrum_router: Free LPM tree upon failure Date: Thu, 18 Jan 2018 15:42:10 +0100 Message-ID: <20180118144210.4653-1-jiri@resnulli.us> Cc: davem@davemloft.net, idosch@mellanox.com, mlxsw@mellanox.com To: netdev@vger.kernel.org Return-path: Received: from mail-wm0-f67.google.com ([74.125.82.67]:37355 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756417AbeAROmM (ORCPT ); Thu, 18 Jan 2018 09:42:12 -0500 Received: by mail-wm0-f67.google.com with SMTP id v71so23437059wmv.2 for ; Thu, 18 Jan 2018 06:42:11 -0800 (PST) Sender: netdev-owner@vger.kernel.org List-ID: From: Ido Schimmel When a new LPM tree is created, we try to replace the trees in the existing virtual routers with it. If we fail, the tree needs to be freed. Currently, this does not happen in the unlikely case where we fail to bind the tree to the first virtual router, since its reference count never transitions from 1 to 0. Fix that by taking a reference before binding the tree. Fixes: fc922bb0dd94 ("mlxsw: spectrum_router: Use one LPM tree for all virtual routers") Signed-off-by: Ido Schimmel Signed-off-by: Jiri Pirko --- .../net/ethernet/mellanox/mlxsw/spectrum_router.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 434b3922b34f..6c0391c13fe0 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -821,13 +821,18 @@ static int mlxsw_sp_vr_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_lpm_tree *old_tree = fib->lpm_tree; int err; - err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); - if (err) - return err; fib->lpm_tree = new_tree; mlxsw_sp_lpm_tree_hold(new_tree); + err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); + if (err) + goto err_tree_bind; mlxsw_sp_lpm_tree_put(mlxsw_sp, old_tree); return 0; + +err_tree_bind: + mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree); + fib->lpm_tree = old_tree; + return err; } static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, @@ -868,11 +873,14 @@ static int mlxsw_sp_vrs_lpm_tree_replace(struct mlxsw_sp *mlxsw_sp, return err; no_replace: - err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); - if (err) - return err; fib->lpm_tree = new_tree; mlxsw_sp_lpm_tree_hold(new_tree); + err = mlxsw_sp_vr_lpm_tree_bind(mlxsw_sp, fib, new_tree->id); + if (err) { + mlxsw_sp_lpm_tree_put(mlxsw_sp, new_tree); + fib->lpm_tree = NULL; + return err; + } return 0; } -- 2.14.3