From patchwork Thu Oct 31 23:46:17 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Chinner X-Patchwork-Id: 11222119 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 A2446912 for ; Thu, 31 Oct 2019 23:47:11 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 780172087F for ; Thu, 31 Oct 2019 23:47:11 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 780172087F Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=fromorbit.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id 52DDF6B0274; Thu, 31 Oct 2019 19:46:30 -0400 (EDT) Delivered-To: linux-mm-outgoing@kvack.org Received: by kanga.kvack.org (Postfix, from userid 40) id E06376B0275; Thu, 31 Oct 2019 19:46:29 -0400 (EDT) X-Original-To: int-list-linux-mm@kvack.org X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B99486B026A; Thu, 31 Oct 2019 19:46:29 -0400 (EDT) X-Original-To: linux-mm@kvack.org X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0036.hostedemail.com [216.40.44.36]) by kanga.kvack.org (Postfix) with ESMTP id 4C9436B0277 for ; Thu, 31 Oct 2019 19:46:29 -0400 (EDT) Received: from smtpin14.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with SMTP id 06476180A5DEE for ; Thu, 31 Oct 2019 23:46:29 +0000 (UTC) X-FDA: 76105716498.14.dress21_559d38162f320 X-Spam-Summary: 2,0,0,e3a291fea47d3466,d41d8cd98f00b204,david@fromorbit.com,:linux-xfs@vger.kernel.org:linux-fsdevel@vger.kernel.org::linux-kernel@vger.kernel.org,RULES_HIT:41:355:379:541:800:960:966:973:988:989:1260:1261:1311:1314:1345:1359:1437:1515:1534:1543:1711:1730:1747:1777:1792:2196:2199:2393:2559:2562:2693:2901:3138:3139:3140:3141:3142:3354:3865:3866:3867:3868:3870:3871:3872:3874:4250:4321:4385:5007:6119:6261:7576:7875:7903:10004:11026:11658:11914:12043:12291:12296:12297:12438:12517:12519:12555:12679:12895:13161:13229:13894:14096:14181:14394:14721:21080:21324:21433:21451:21627:30054:30070,0,RBL:211.29.132.249:@fromorbit.com:.lbl8.mailshell.net-62.8.32.100 66.201.201.201,CacheIP:none,Bayesian:0.5,0.5,0.5,Netcheck:none,DomainCache:0,MSF:not bulk,SPF:fn,MSBL:0,DNSBL:neutral,Custom_rules:0:0:0,LFtime:2,LUA_SUMMARY:none X-HE-Tag: dress21_559d38162f320 X-Filterd-Recvd-Size: 4948 Received: from mail105.syd.optusnet.com.au (mail105.syd.optusnet.com.au [211.29.132.249]) by imf23.hostedemail.com (Postfix) with ESMTP for ; Thu, 31 Oct 2019 23:46:28 +0000 (UTC) Received: from dread.disaster.area (pa49-180-67-183.pa.nsw.optusnet.com.au [49.180.67.183]) by mail105.syd.optusnet.com.au (Postfix) with ESMTPS id 20C713A2710; Fri, 1 Nov 2019 10:46:25 +1100 (AEDT) Received: from discord.disaster.area ([192.168.253.110]) by dread.disaster.area with esmtp (Exim 4.92.3) (envelope-from ) id 1iQK8x-0007Cm-TS; Fri, 01 Nov 2019 10:46:19 +1100 Received: from dave by discord.disaster.area with local (Exim 4.92.3) (envelope-from ) id 1iQK8x-00042T-RH; Fri, 01 Nov 2019 10:46:19 +1100 From: Dave Chinner To: linux-xfs@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH 27/28] rwsem: introduce down/up_write_non_owner Date: Fri, 1 Nov 2019 10:46:17 +1100 Message-Id: <20191031234618.15403-28-david@fromorbit.com> X-Mailer: git-send-email 2.24.0.rc0 In-Reply-To: <20191031234618.15403-1-david@fromorbit.com> References: <20191031234618.15403-1-david@fromorbit.com> MIME-Version: 1.0 X-Optus-CM-Score: 0 X-Optus-CM-Analysis: v=2.2 cv=G6BsK5s5 c=1 sm=1 tr=0 a=3wLbm4YUAFX2xaPZIabsgw==:117 a=3wLbm4YUAFX2xaPZIabsgw==:17 a=jpOVt7BSZ2e4Z31A5e1TngXxSK0=:19 a=MeAgGD-zjQ4A:10 a=20KFwNOVAAAA:8 a=PQ_rIYW8ek-NpEnsdwgA:9 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: From: Dave Chinner To serialise freeing of inodes against unreferenced lookups, XFS wants to hold the inode locked from the reclaim context that queues it from RCU freeing until the grace period that actually frees the inode. THis means the inode is being unlocked by a context that didn't lock it, and that makes lockdep unhappy. This is a very special use case - inodes can be found once marked for reclaim because of lockless RCU lookups, so we need some synchronisation that will prevent such inodes from being locked. To access an unreferenced inode we need to take the ILOCK rwsem without blocking and still under rcu_read_lock() to hold off reclaim of the inode. If the inode has been reclaimed and is queued for freeing, holding the ILOCK rwsem until the RCU grace period expires means no lookup that finds it in that grace period will be able to lock it and use it. Once the grace period expires we are guaranteed that nothing will ever find the inode again, and we can unlock it and free it. This requires down_write_trylock_non_owner() in the reclaim context before we mark the inode as reclaimed and run call_rcu() to free it. It require up_write_non_owner() in the RCU callback before we free the inode. Signed-off-by: Dave Chinner --- include/linux/rwsem.h | 6 ++++++ kernel/locking/rwsem.c | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h index 00d6054687dd..e557bd994d0e 100644 --- a/include/linux/rwsem.h +++ b/include/linux/rwsem.h @@ -191,6 +191,9 @@ do { \ */ extern void down_read_non_owner(struct rw_semaphore *sem); extern void up_read_non_owner(struct rw_semaphore *sem); +extern void down_write_non_owner(struct rw_semaphore *sem); +extern int down_write_trylock_non_owner(struct rw_semaphore *sem); +extern void up_write_non_owner(struct rw_semaphore *sem); #else # define down_read_nested(sem, subclass) down_read(sem) # define down_write_nest_lock(sem, nest_lock) down_write(sem) @@ -198,6 +201,9 @@ extern void up_read_non_owner(struct rw_semaphore *sem); # define down_write_killable_nested(sem, subclass) down_write_killable(sem) # define down_read_non_owner(sem) down_read(sem) # define up_read_non_owner(sem) up_read(sem) +# define down_write_non_owner(sem) down_write(sem) +# define down_write_trylock_non_owner(sem) down_write_trylock(sem) +# define up_write_non_owner(sem) up_write(sem) #endif #endif /* _LINUX_RWSEM_H */ diff --git a/kernel/locking/rwsem.c b/kernel/locking/rwsem.c index eef04551eae7..36162d42fe09 100644 --- a/kernel/locking/rwsem.c +++ b/kernel/locking/rwsem.c @@ -1654,4 +1654,27 @@ void up_read_non_owner(struct rw_semaphore *sem) } EXPORT_SYMBOL(up_read_non_owner); +void down_write_non_owner(struct rw_semaphore *sem) +{ + might_sleep(); + __down_write(sem); +} +EXPORT_SYMBOL(down_write_non_owner); + +/* + * trylock for writing -- returns 1 if successful, 0 if contention + */ +int down_write_trylock_non_owner(struct rw_semaphore *sem) +{ + return __down_write_trylock(sem); +} +EXPORT_SYMBOL(down_write_trylock_non_owner); + +void up_write_non_owner(struct rw_semaphore *sem) +{ + rwsem_set_owner(sem); + __up_write(sem); +} +EXPORT_SYMBOL(up_write_non_owner); + #endif