From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 872421AE87A; Tue, 16 Jul 2024 14:30:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721140242; cv=none; b=a3SsB3je3b339FgnQwIMM40EAg86v3a3W8JnSzz8HXyj3+E8Mg3nTr0aQXEiydDKWnQog4NhvgEMDEn9DtSgNQtb5mXOU7UJLlonvrDmq/TQUkk7gmuMLXBUOrtCD/DQkhVgCRqgy5upYqrAZxR9yYjImco9Dh7CcAVsuZf6YFU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721140242; c=relaxed/simple; bh=bIRcPL2wZuJ4exWw+zVHjcz+9i4U10o3hRBlr51DttQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=SE1FsGaq42OGXHrxQ5/X385zo+igevwsykYzZsLIjSw4FTI1WH33bQhO3flXeI0lM6IgDeWlBXP4D1LUWWK0E6ixV4kTrkSlqzPK2N+aP/uqEAb+M2Oz6g91nMTTw61vrGbIujF1vTSma+9qwr3SlpzOTeHhv8ustUV30/3K/EM= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pLMno+dB; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pLMno+dB" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 63CFEC116B1; Tue, 16 Jul 2024 14:30:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1721140242; bh=bIRcPL2wZuJ4exWw+zVHjcz+9i4U10o3hRBlr51DttQ=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=pLMno+dBBoKotHhW3lBRH+XBduHG/S0w7y9jivU0bZAz5tnrRwPYIwvehvwEwdhGq 40L9/te48vOTmb9LWEmFGwLtyEhPJsQyM/7YKl2Tf/orWh30DH7WTnnIj7vD6i/fWL NKPNROGd2JnHT7N5szSAhGkisaKaZklmUHeo7tFZCXxo2iQlJDSU4M8UB4CEUpDRXq eWP8O2Q9h7kkkkdiH7HHv1T0Ojvf0gkuAthMl/tjT8q6xu+nC6vtTl3b6eFaGAXLfz jO/qoJE43qwDOUQwRDumHth6FV3ajafi/vvQovDS4jdXcMLOobl/UeF0qvVArRhn48 7VJq+yHO7Yo5w== From: Sasha Levin To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Christian Brauner , Jan Kara , Linus Torvalds , Sasha Levin , viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org Subject: [PATCH AUTOSEL 5.4 7/7] fs: better handle deep ancestor chains in is_subdir() Date: Tue, 16 Jul 2024 10:30:15 -0400 Message-ID: <20240716143021.2714348-7-sashal@kernel.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20240716143021.2714348-1-sashal@kernel.org> References: <20240716143021.2714348-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 5.4.279 Content-Transfer-Encoding: 8bit From: Christian Brauner [ Upstream commit 391b59b045004d5b985d033263ccba3e941a7740 ] Jan reported that 'cd ..' may take a long time in deep directory hierarchies under a bind-mount. If concurrent renames happen it is possible to livelock in is_subdir() because it will keep retrying. Change is_subdir() from simply retrying over and over to retry once and then acquire the rename lock to handle deep ancestor chains better. The list of alternatives to this approach were less then pleasant. Change the scope of rcu lock to cover the whole walk while at it. A big thanks to Jan and Linus. Both Jan and Linus had proposed effectively the same thing just that one version ended up being slightly more elegant. Reported-by: Jan Kara Signed-off-by: Linus Torvalds Signed-off-by: Christian Brauner Signed-off-by: Sasha Levin --- fs/dcache.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 43864a276faa2..7d2e689fd3100 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -3067,28 +3067,25 @@ EXPORT_SYMBOL(d_splice_alias); bool is_subdir(struct dentry *new_dentry, struct dentry *old_dentry) { - bool result; + bool subdir; unsigned seq; if (new_dentry == old_dentry) return true; - do { - /* for restarting inner loop in case of seq retry */ - seq = read_seqbegin(&rename_lock); - /* - * Need rcu_readlock to protect against the d_parent trashing - * due to d_move - */ - rcu_read_lock(); - if (d_ancestor(old_dentry, new_dentry)) - result = true; - else - result = false; - rcu_read_unlock(); - } while (read_seqretry(&rename_lock, seq)); - - return result; + /* Access d_parent under rcu as d_move() may change it. */ + rcu_read_lock(); + seq = read_seqbegin(&rename_lock); + subdir = d_ancestor(old_dentry, new_dentry); + /* Try lockless once... */ + if (read_seqretry(&rename_lock, seq)) { + /* ...else acquire lock for progress even on deep chains. */ + read_seqlock_excl(&rename_lock); + subdir = d_ancestor(old_dentry, new_dentry); + read_sequnlock_excl(&rename_lock); + } + rcu_read_unlock(); + return subdir; } EXPORT_SYMBOL(is_subdir); -- 2.43.0