Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751154AbdFCGUN (ORCPT ); Sat, 3 Jun 2017 02:20:13 -0400 Received: from zeniv.linux.org.uk ([195.92.253.2]:35860 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750753AbdFCGUL (ORCPT ); Sat, 3 Jun 2017 02:20:11 -0400 Date: Sat, 3 Jun 2017 07:20:09 +0100 From: Al Viro To: Khazhismel Kumykov Cc: linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org, Miklos Szeredi Subject: Re: Hang/soft lockup in d_invalidate with simultaneous calls Message-ID: <20170603062009.GI6365@ZenIV.linux.org.uk> References: <20170603011241.GH6365@ZenIV.linux.org.uk> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.8.0 (2017-02-23) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 1955 Lines: 58 On Fri, Jun 02, 2017 at 10:22:39PM -0700, Khazhismel Kumykov wrote: > On Fri, Jun 2, 2017 at 6:12 PM, Al Viro wrote: > > Part of that could be relieved if we turned check_and_drop() into > > static void check_and_drop(void *_data) > > { > > struct detach_data *data = _data; > > > > if (!data->mountpoint && list_empty(&data->select.dispose)) > > __d_drop(data->select.start); > > } > > So with this change, d_invalidate will drop the starting dentry before > all it's children are dropped? Would it make sense to just drop it > right off the bat, and let one task handle shrinking all it's > children? We can't - not until we know that there's nothing mounted under it. The thing is, unlike shrink_dcache_parent() we *can* bugger off as soon as we'd found no victims, nothing mounted and dentry itself is unhashed. We can't do anything in select_collect() (we would've broken shrink_dcache_parent() that way), but we can do unhashing in check_and_drop() in "really nothing to do" case and we can return from d_invalidate() after that. So how about this: diff --git a/fs/dcache.c b/fs/dcache.c index cddf39777835..a9f995f6859e 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1494,7 +1494,7 @@ static void check_and_drop(void *_data) { struct detach_data *data = _data; - if (!data->mountpoint && !data->select.found) + if (!data->mountpoint && list_empty(&data->select.dispose)) __d_drop(data->select.start); } @@ -1536,17 +1536,15 @@ void d_invalidate(struct dentry *dentry) d_walk(dentry, &data, detach_and_collect, check_and_drop); - if (data.select.found) + if (!list_empty(&data.select.dispose)) shrink_dentry_list(&data.select.dispose); + else if (!data.mountpoint) + return; if (data.mountpoint) { detach_mounts(data.mountpoint); dput(data.mountpoint); } - - if (!data.mountpoint && !data.select.found) - break; - cond_resched(); } }