Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752822AbcCHObb (ORCPT ); Tue, 8 Mar 2016 09:31:31 -0500 Received: from smtprelay4.synopsys.com ([198.182.47.9]:48671 "EHLO smtprelay.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751516AbcCHObW (ORCPT ); Tue, 8 Mar 2016 09:31:22 -0500 From: Vineet Gupta To: CC: Vineet Gupta , Christoph Lameter , Pekka Enberg , David Rientjes , Joonsoo Kim , Andrew Morton , Noam Camus , , , Subject: [PATCH] mm: slub: Ensure that slab_unlock() is atomic Date: Tue, 8 Mar 2016 20:00:57 +0530 Message-ID: <1457447457-25878-1-git-send-email-vgupta@synopsys.com> X-Mailer: git-send-email 2.5.0 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.12.197.157] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1639 Lines: 51 We observed livelocks on ARC SMP setup when running hackbench with SLUB. This hardware configuration lacks atomic instructions (LLOCK/SCOND) thus kernel resorts to a central @smp_bitops_lock to protect any R-M-W ops suh as test_and_set_bit() The spinlock itself is implemented using Atomic [EX]change instruction which is always available. The race happened when both cores tried to slab_lock() the same page. c1 c0 ----------- ----------- slab_lock slab_lock slab_unlock Not observing the unlock This in turn happened because slab_unlock() doesn't serialize properly (doesn't use atomic clear) with a concurrent running slab_lock()->test_and_set_bit() Cc: Christoph Lameter Cc: Pekka Enberg Cc: David Rientjes Cc: Joonsoo Kim Cc: Andrew Morton Cc: Noam Camus Cc: Cc: Cc: Cc: Signed-off-by: Vineet Gupta --- mm/slub.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/slub.c b/mm/slub.c index d8fbd4a6ed59..b7d345a508dc 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -345,7 +345,7 @@ static __always_inline void slab_lock(struct page *page) static __always_inline void slab_unlock(struct page *page) { VM_BUG_ON_PAGE(PageTail(page), page); - __bit_spin_unlock(PG_locked, &page->flags); + bit_spin_unlock(PG_locked, &page->flags); } static inline void set_page_slub_counters(struct page *page, unsigned long counters_new) -- 2.5.0