Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753376AbdFSTRJ (ORCPT + 2 others); Mon, 19 Jun 2017 15:17:09 -0400 Received: from wtarreau.pck.nerim.net ([62.212.114.60]:52277 "EHLO 1wt.eu" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753283AbdFSSgS (ORCPT ); Mon, 19 Jun 2017 14:36:18 -0400 From: Willy Tarreau To: linux-kernel@vger.kernel.org, stable@vger.kernel.org, linux@roeck-us.net Cc: "santosh.shilimkar@oracle.com" , Wengang Wang , "David S . Miller" , Julia Lawall , Jiri Slaby , Willy Tarreau Subject: [PATCH 3.10 257/268] RDS: Fix the atomicity for congestion map update Date: Mon, 19 Jun 2017 20:32:36 +0200 Message-Id: <1497897167-14556-258-git-send-email-w@1wt.eu> X-Mailer: git-send-email 2.8.0.rc2.1.gbe9624a In-Reply-To: <1497897167-14556-1-git-send-email-w@1wt.eu> References: <1497897167-14556-1-git-send-email-w@1wt.eu> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: From: "santosh.shilimkar@oracle.com" commit e47db94e10447fc467777a40302f2b393e9af2fa upstream. Two different threads with different rds sockets may be in rds_recv_rcvbuf_delta() via receive path. If their ports both map to the same word in the congestion map, then using non-atomic ops to update it could cause the map to be incorrect. Lets use atomics to avoid such an issue. Full credit to Wengang for finding the issue, analysing it and also pointing out to offending code with spin lock based fix. Reviewed-by: Leon Romanovsky Signed-off-by: Wengang Wang Signed-off-by: Santosh Shilimkar Signed-off-by: David S. Miller Cc: Julia Lawall Signed-off-by: Jiri Slaby Signed-off-by: Willy Tarreau --- net/rds/cong.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/rds/cong.c b/net/rds/cong.c index e5b65ac..cec4c4e 100644 --- a/net/rds/cong.c +++ b/net/rds/cong.c @@ -285,7 +285,7 @@ void rds_cong_set_bit(struct rds_cong_map *map, __be16 port) i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; - __set_bit_le(off, (void *)map->m_page_addrs[i]); + set_bit_le(off, (void *)map->m_page_addrs[i]); } void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) @@ -299,7 +299,7 @@ void rds_cong_clear_bit(struct rds_cong_map *map, __be16 port) i = be16_to_cpu(port) / RDS_CONG_MAP_PAGE_BITS; off = be16_to_cpu(port) % RDS_CONG_MAP_PAGE_BITS; - __clear_bit_le(off, (void *)map->m_page_addrs[i]); + clear_bit_le(off, (void *)map->m_page_addrs[i]); } static int rds_cong_test_bit(struct rds_cong_map *map, __be16 port) -- 2.8.0.rc2.1.gbe9624a