From patchwork Sun Nov 19 23:56:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13460708 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1DED7C072A2 for ; Sun, 19 Nov 2023 23:56:25 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id CE47A6B03A4; Sun, 19 Nov 2023 18:56:24 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id C947A6B03BA; Sun, 19 Nov 2023 18:56:24 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id B5BC36B03BE; Sun, 19 Nov 2023 18:56:24 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0010.hostedemail.com [216.40.44.10]) by kanga.kvack.org (Postfix) with ESMTP id A27496B03A4 for ; Sun, 19 Nov 2023 18:56:24 -0500 (EST) Received: from smtpin24.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 7B2A2B5592 for ; Sun, 19 Nov 2023 23:56:24 +0000 (UTC) X-FDA: 81476365488.24.05F69EB Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf10.hostedemail.com (Postfix) with ESMTP id D2FEDC000D for ; Sun, 19 Nov 2023 23:56:22 +0000 (UTC) Authentication-Results: imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Tl5mBXt2; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf10.hostedemail.com: domain of cel@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cel@kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1700438183; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:in-reply-to: references:dkim-signature; bh=+se5oZP0+gX3lDC2IkRpb24p1JDx6F3sAnNeLYgb+zw=; b=O7ebeJ+VNvM5c/qmguQwfXNICOkMoXGuldPZNu1A/zYZGPEIWEZ73CM/lTED3EKrawRS56 6QJaoLKCFTcb32s7OlZ32Ef6A9pflCaTqyDc7eHjhyajdB85OW34XvPufKeSeZqJIan1oZ z6ZyHfog+HraAwN2bKWjkxlq5EV4mYo= ARC-Authentication-Results: i=1; imf10.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Tl5mBXt2; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf10.hostedemail.com: domain of cel@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cel@kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1700438183; a=rsa-sha256; cv=none; b=dK6R/4oy988UVdc/s/BIenWYj3W2WXvTqEeTUt9n/IsMUz7vnFnsgm/83grt0R9uulJ60c xcMSgm07M1xzoahxo2GQKS26/4MMQpGZ/I0CdO2p7kapERLhHIXBTPFPRzACjo7vA5s/U9 APdOBdTOisoyLpqsuxUerTft1wY6IjY= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by dfw.source.kernel.org (Postfix) with ESMTP id A24D960C52; Sun, 19 Nov 2023 23:56:21 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id F40F1C433C7; Sun, 19 Nov 2023 23:56:18 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1700438179; bh=EtcwSMC+2X05pmB2XZm956sPJJv7BwUf2YkTNGJ38Es=; h=Subject:From:To:Cc:Date:From; b=Tl5mBXt2ZuhV2UXwJohYFa4npkQ+9I5tbjkfwdfH7ZTJ1VCuqFsw/kcXAtvycd3V2 VtuJhnRWC9unIUrLGgxnyYKsxm73qr7pHT0owU3mJQxvpq1FdB47XEnyzWSchCP+F2 c/XEP6NTBesnOquzS8lEktnLsAEF82RJnVMuK66IajcziI6+HUSqvwifKdYqkiW+8W NE5NLiHEElKQl9VBLnpvFi8kWc9SfU+XHK9ABP7MXYKxqj1i2J3chZnPlbEcSXuYd0 uLwSDQksIE7JqLL/N/esjX4GFxBB01baK+ld2lemvJx8Xtrh6NBglTSLo122A71Zv1 EivHA2HNbM16w== Subject: [PATCH v4] libfs: getdents() should return 0 after reaching EOD From: Chuck Lever To: akpm@linux-foundation.org, brauner@kernel.org, hughd@google.com, jlayton@redhat.com, viro@zeniv.linux.org.uk Cc: Tavian Barnes , Chuck Lever , linux-fsdevel@vger.kernel.org, linux-mm@kvack.org Date: Sun, 19 Nov 2023 18:56:17 -0500 Message-ID: <170043792492.4628.15646203084646716134.stgit@bazille.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Queue-Id: D2FEDC000D X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: wzozdjqsf6w7j15xxncbuqxyz8q418w5 X-HE-Tag: 1700438182-837025 X-HE-Meta: U2FsdGVkX1/e+XkftZQYqxtTzuTJJzrCQkDp7vZCpEsZvBnarm+y5WrsqcN0pDlrI79bwl9pQOJn7bNjyOVlaeWTPcDSb08JmuiEydjIquviAN/Ol+ZWRoV8rFf8aF9nRnkHZPoe0UrUUw4rT2pbnnzCLIvFdHLC2cMBMSCNtRS8HbaJUrijFRadTTnXTXdVANrjbDhB/dR5UA8fyjH9ujze1ItfJBDm3z+4yB7o43sohblYzVnIOWsXbkISbkw8MFL3nA+CJ572Ow/sDh81DVxQnwTxH5rsgKV+KGGzGQTLnOg0U8IOkIQUfoc9xB8xwLrhZWdzka3L3LxeaHjDJD/tn7IgIEP89q5iMPjgcszJCtsyacOjbxwKjwH25M4GPU3H+Xk/pQuQEaiLAPSUHkSgJ63FoCz/QXnrmF0/Y/xqCrsoAKhT5oa8JhDlhbfhiQSX2R91tPxOPKmXebyMp/0+O35/u6nSaGF9Yk9AGK4kzdbtjJt01HPwIC0vtDtNtLFZ+ZGmqMHGyRYkOwWKikAuz7GIqHCGhjrnJ1bqlA4Wuu5UQ4cpv5S/qPFJKLhHtBwaGxUXJziwChra4dk55xtu1W3ZTyAi2PjDgpasy6V0MB/TbbK4HwuvwnpJMDPhaqKGvOe77rnbp1qmRe38SGi4TKgzOm3SBeC4jz28s910qbHOW0hNbr8EzmMQFhO8R48/30H+FOVG6OhSJA04l0VGRsM77M4c2fAE/zaInwmaW8mcpSW/LdFfeuuWxdQzAKv5MAlKK6MvjlkIlPP7w5Ok43fQ82dsc/lvjQl+WRwJ5fiU/tw5sVOiLd9rT2+AOrmFclg12OZlWB3q25X7VdONRhcQqRdk5UCJkXFXncpFF0CTNJHa1Ix7e7VtWgjj3m6Mr+kkgIvI/8WcAF/76tJ+BbqW6GENzRQ5m+0kgeSpoWH51VtdHagwKFyC/qmAEovxfFNojepdcpOjmJX 5tYSZqhg ovBtHroJY767D7Cn0adLbDeinlxEv1751ud1eLw7r/SvboF5frDDDegWi9PdOOsuyOcdI+KyMyxPhCFZef1CpOS/zRRd8ljR5yN4710s8t6iBk279NzNtymAM+FGBfLbVTbSWrdK6OGSI8hHW7jEfkRa7Z6yaKhPHQN2CE/FJ38S6wU9fjLtB1ZgEd1zovcprmp8gYcnHYZJRZShKBIi0zsFz4n1yP1sirNsrxQjDpuAhZ72hnGe6zt6qlUK3lVS08BEGLENZqbds5EfuNTfewxrmsCt7W5O1nDj7 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: List-Subscribe: List-Unsubscribe: From: Chuck Lever The new directory offset helpers don't conform with the convention of getdents() returning no more entries once a directory file descriptor has reached the current end-of-directory. To address this, copy the logic from dcache_readdir() to mark the open directory file descriptor once EOD has been reached. Seeking resets the mark. Reported-by: Tavian Barnes Closes: https://lore.kernel.org/linux-fsdevel/20231113180616.2831430-1-tavianator@tavianator.com/ Fixes: 6faddda69f62 ("libfs: Add directory operations for stable offsets") Signed-off-by: Chuck Lever --- fs/libfs.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) v4 of this patch passes Tavian's reproducer and fstests over NFS and directly on a tmpfs mount. Changes since v3: - Ensure that llseek() resets the EOD mark too Changes since v2: - Go back to marking EOD in the file->private_data field Changes since RFC: - Keep file->private_data stable while directory descriptor remains open diff --git a/fs/libfs.c b/fs/libfs.c index e9440d55073c..c2aa6fd4795c 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -399,6 +399,8 @@ static loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence) return -EINVAL; } + /* In this case, ->private_data is protected by f_pos_lock */ + file->private_data = NULL; return vfs_setpos(file, offset, U32_MAX); } @@ -428,7 +430,7 @@ static bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) inode->i_ino, fs_umode_to_dtype(inode->i_mode)); } -static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) +static void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx) { struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); XA_STATE(xas, &so_ctx->xa, ctx->pos); @@ -437,7 +439,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) while (true) { dentry = offset_find_next(&xas); if (!dentry) - break; + return ERR_PTR(-ENOENT); if (!offset_dir_emit(ctx, dentry)) { dput(dentry); @@ -447,6 +449,7 @@ static void offset_iterate_dir(struct inode *inode, struct dir_context *ctx) dput(dentry); ctx->pos = xas.xa_index + 1; } + return NULL; } /** @@ -479,7 +482,12 @@ static int offset_readdir(struct file *file, struct dir_context *ctx) if (!dir_emit_dots(file, ctx)) return 0; - offset_iterate_dir(d_inode(dir), ctx); + /* In this case, ->private_data is protected by f_pos_lock */ + if (ctx->pos == 2) + file->private_data = NULL; + else if (file->private_data == ERR_PTR(-ENOENT)) + return 0; + file->private_data = offset_iterate_dir(d_inode(dir), ctx); return 0; }