From patchwork Mon Jun 26 18:21:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13293330 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 0C45BEB64D7 for ; Mon, 26 Jun 2023 18:21:33 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id A10C48D0003; Mon, 26 Jun 2023 14:21:32 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 9C1838D0001; Mon, 26 Jun 2023 14:21:32 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 889D98D0003; Mon, 26 Jun 2023 14:21:32 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 7BB758D0001 for ; Mon, 26 Jun 2023 14:21:32 -0400 (EDT) Received: from smtpin15.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay08.hostedemail.com (Postfix) with ESMTP id 4D46D14079B for ; Mon, 26 Jun 2023 18:21:32 +0000 (UTC) X-FDA: 80945716824.15.A031969 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf14.hostedemail.com (Postfix) with ESMTP id 7D4FB100007 for ; Mon, 26 Jun 2023 18:21:30 +0000 (UTC) Authentication-Results: imf14.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="iJ/EtPCc"; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf14.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=1687803690; 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:in-reply-to:references:references:dkim-signature; bh=7JiGFgIZMBHLowUD8xCuSXRydVIwziTG9bwy3vMZ7J8=; b=4gOsYsr/Gy/BLn8pBjFKEEEhij1wacVdwxJ6zA+YACfptI9divVFcsn5S1Fy1MeUh8Eu2q UBbDVKvPuesf+CGnpHXEQElyCZkItgcAM3CP36GMeiLCDzKhAhvgyahhG3CS5tZQz5wKbT G+l3zczzDQIpwKlH0hNIDYNlx/sWdNk= ARC-Authentication-Results: i=1; imf14.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b="iJ/EtPCc"; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf14.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=1687803690; a=rsa-sha256; cv=none; b=hZVeUAvidi+IOQKpLLZyopr+tPslQX6Ude3v6aEIqdJDQkrxXqNm4rXQYZ4fX02euYM3uO T9Prwo9mj2jlxF6PzcbJspcuT8z15e+L514NHiL76yOQj+VDyDcxSg5DfO9zN60PHZ12Oi BYjLQeCLirtFBnyn7cvczK0rs5IikVQ= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 81F4B60F6B; Mon, 26 Jun 2023 18:21:29 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 60C32C433CB; Mon, 26 Jun 2023 18:21:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687803688; bh=1wHRscUWByrnZ9ONV+EzuEel/ddXYcfwzYGKwxTIgBo=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=iJ/EtPCcGyRNY0O7oTdG/ed8r9FNUIU5QbUQbLPmOq07D300LFC66jOFK1xIhRQ12 qo9DcHw8W/Pv77gIpWkwfjufhZXoNBfp7VP+4uubFwk02nbqwBJUtJ4XqHTzUa5hgg B0xClO4nSA8bTQp3yLpWrJunwMQPUhy1yTnVaSVsMz7Aefb8mb0glzmSMBbOmlD0gB GBCMH/ADbZDkJCKhaX5mV6ME+XnuVOf8xp3KIoBLSV0d5JVkhP3XdKxjV9eZ3ct/bV cOavoCOSiitED+w58+wdqPVnYqZnxk1ghKUKJJk3gJvOXMiWhY/71BjTGjKZdpn8xh ZI5SH2UajmO2A== Subject: [PATCH v4 1/3] libfs: Add directory operations for stable offsets From: Chuck Lever To: viro@zeniv.linux.org.uk, brauner@kernel.org, hughd@google.com, akpm@linux-foundation.org Cc: Chuck Lever , jlayton@redhat.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Date: Mon, 26 Jun 2023 14:21:27 -0400 Message-ID: <168780368739.2142.1909222585425739373.stgit@manet.1015granger.net> In-Reply-To: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> References: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Server: rspam09 X-Rspamd-Queue-Id: 7D4FB100007 X-Stat-Signature: 17foxdppaafjz49f9xk7nxidwn79np4q X-Rspam-User: X-HE-Tag: 1687803690-662253 X-HE-Meta: U2FsdGVkX18iGRAqk7Ek8lf3K6LNGJZ40VTm/rNNsDMvYgZ6gLmzMpbHKFXzaQA3G8mg61Vcawp9XOJiSA+iOueJM4n3ZiE0D9YJTcupuuQE3m78hgm7p9MIt/oEpkw5EYjkrFuVCr6Y1dkrLW0jVpDaQTN6VW/j5hV1j4T4iMHJRmhWMWDv3nS3K3cAkXEBZ60Ya5esmbF1ozqLvBfCZCFEsSd+LZ4bEoNsKtfriVwSKvo7tEN3kzn1Wyzxn9h4+GAjU9oz+OMIIavviO5eMwl/M+AYWlO78txiaIwyHUjXI8WstBsjK5/l4AAe+UnlMh06ypSb6jTkCr4CHftSOth3hHKRNJX6mwpGjGJoB0YWcH3HlpojQBXrVNq1S5UabLjLBowFZFeXHq3qzZKMpwNQL5qEuqJBQ7iglcjtQzr/iWvqI2PghNCKaaoMPdbxza1rasrMe/G1BeLnM9t6kMuASOZqrbSlyjqOHs1Gk659xqe+Yf3bW2a9FHz+5wtSTmUyGGmK/kmczwsYG3S5VbZ0T75DVtN7IA7iVdZ3jg6Aw7yKq1zcY3b3/1kxR29oh2oM5PoRcE+W4mBqgp5DWUN5RvjPlXYdAcc8kY4uEC4elD2jf7ytlAxoKzclRhgBjDk43qnKu22xVStulFCGfwe1/OJ9R62RWCf11WBDvt4WVEUfPlKa1B2lOsw70Y0RsdcmVEMsLBITgeZ3bZ08Zi5OlZHC3cH+1ine5srJnL9m8MIM3mCLpCF+4wap+1a4I9EWGYAIDzjQDohBrer3GWM1UgIJJwwhfOx2in1Wg/i1xuGPYNIPhO9D5qCkcgn+XuA3shMc575YEr9wYKPOU2GuADVxlgjBSUSR0V9ELVTzaURrCxwXPi7CIT2wBfo/Q0z6PuZg6EO7Vatg3TV9AmGTKYYqJIt/LtyPjVpv1aSzjdO9Zw8OvSH1UzKs855X9+0UCuzbG0PSrFwYiu7 HYLTPnHE HgR7EwpaK9uvobjX2sN4fzR57N6TVwNuSpFRTn5xxAd2fzeRvlhI/kP8dz8qMgC0QxQPT7tzwbnC9rb7lSiZ1MLLa1+GpBuXSh24+LUbmBRIuMuXNAgtwG4H68mSnPMjCiShLgFmpMnKAVVn7Q6ukQSKfzVqhrYfB9tHQxndUq3iALmlFb1ejWDX1D57WQe3XjVgchkNFkBxADhcUARRbk95RUnAZg2CGTZPIIaIT5QV/x53tntBu6XcnPWQ16/c7xk4UgkmUVTovPxYJslYfHRkD1A== 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: Chuck Lever Create a vector of directory operations in fs/libfs.c that handles directory seeks and readdir via stable offsets instead of the current cursor-based mechanism. For the moment these are unused. Signed-off-by: Chuck Lever --- fs/dcache.c | 1 fs/libfs.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/dcache.h | 1 include/linux/fs.h | 9 ++ 4 files changed, 196 insertions(+) diff --git a/fs/dcache.c b/fs/dcache.c index 52e6d5fdab6b..9c9a801f3b33 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1813,6 +1813,7 @@ static struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name) dentry->d_sb = sb; dentry->d_op = NULL; dentry->d_fsdata = NULL; + dentry->d_offset = 0; INIT_HLIST_BL_NODE(&dentry->d_hash); INIT_LIST_HEAD(&dentry->d_lru); INIT_LIST_HEAD(&dentry->d_subdirs); diff --git a/fs/libfs.c b/fs/libfs.c index 89cf614a3271..07317bbe1668 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -239,6 +239,191 @@ const struct inode_operations simple_dir_inode_operations = { }; EXPORT_SYMBOL(simple_dir_inode_operations); +/** + * stable_offset_init - initialize a parent directory + * @dir: parent directory to be initialized + * + */ +void stable_offset_init(struct inode *dir) +{ + xa_init_flags(&dir->i_doff_map, XA_FLAGS_ALLOC1); + dir->i_next_offset = 0; +} +EXPORT_SYMBOL(stable_offset_init); + +/** + * stable_offset_add - Add an entry to a directory's stable offset map + * @dir: parent directory being modified + * @dentry: new dentry being added + * + * Returns zero on success. Otherwise, a negative errno value is returned. + */ +int stable_offset_add(struct inode *dir, struct dentry *dentry) +{ + struct xa_limit limit = XA_LIMIT(2, U32_MAX); + u32 offset = 0; + int ret; + + if (dentry->d_offset) + return -EBUSY; + + ret = xa_alloc_cyclic(&dir->i_doff_map, &offset, dentry, limit, + &dir->i_next_offset, GFP_KERNEL); + if (ret < 0) + return ret; + + dentry->d_offset = offset; + return 0; +} +EXPORT_SYMBOL(stable_offset_add); + +/** + * stable_offset_remove - Remove an entry to a directory's stable offset map + * @dir: parent directory being modified + * @dentry: dentry being removed + * + */ +void stable_offset_remove(struct inode *dir, struct dentry *dentry) +{ + if (!dentry->d_offset) + return; + + xa_erase(&dir->i_doff_map, dentry->d_offset); + dentry->d_offset = 0; +} +EXPORT_SYMBOL(stable_offset_remove); + +/** + * stable_offset_destroy - Release offset map + * @dir: parent directory that is about to be destroyed + * + * During fs teardown (eg. umount), a directory's offset map might still + * contain entries. xa_destroy() cleans out anything that remains. + */ +void stable_offset_destroy(struct inode *dir) +{ + xa_destroy(&dir->i_doff_map); +} +EXPORT_SYMBOL(stable_offset_destroy); + +/** + * stable_dir_llseek - Advance the read position of a directory descriptor + * @file: an open directory whose position is to be updated + * @offset: a byte offset + * @whence: enumerator describing the starting position for this update + * + * SEEK_END, SEEK_DATA, and SEEK_HOLE are not supported for directories. + * + * Returns the updated read position if successful; otherwise a + * negative errno is returned and the read position remains unchanged. + */ +static loff_t stable_dir_llseek(struct file *file, loff_t offset, int whence) +{ + switch (whence) { + case SEEK_CUR: + offset += file->f_pos; + fallthrough; + case SEEK_SET: + if (offset >= 0) + break; + fallthrough; + default: + return -EINVAL; + } + + return vfs_setpos(file, offset, U32_MAX); +} + +static struct dentry *stable_find_next(struct xa_state *xas) +{ + struct dentry *child, *found = NULL; + + rcu_read_lock(); + child = xas_next_entry(xas, U32_MAX); + if (!child) + goto out; + spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED); + if (simple_positive(child)) + found = dget_dlock(child); + spin_unlock(&child->d_lock); +out: + rcu_read_unlock(); + return found; +} + +static bool stable_dir_emit(struct dir_context *ctx, struct dentry *dentry) +{ + struct inode *inode = d_inode(dentry); + + return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, + dentry->d_offset, inode->i_ino, + fs_umode_to_dtype(inode->i_mode)); +} + +static void stable_iterate_dir(struct dentry *dir, struct dir_context *ctx) +{ + XA_STATE(xas, &((d_inode(dir))->i_doff_map), ctx->pos); + struct dentry *dentry; + + while (true) { + spin_lock(&dir->d_lock); + dentry = stable_find_next(&xas); + spin_unlock(&dir->d_lock); + if (!dentry) + break; + + if (!stable_dir_emit(ctx, dentry)) { + dput(dentry); + break; + } + + dput(dentry); + ctx->pos = xas.xa_index + 1; + } +} + +/** + * stable_readdir - Emit entries starting at offset @ctx->pos + * @file: an open directory to iterate over + * @ctx: directory iteration context + * + * Caller must hold @file's i_rwsem to prevent insertion or removal of + * entries during this call. + * + * On entry, @ctx->pos contains an offset that represents the first entry + * to be read from the directory. + * + * The operation continues until there are no more entries to read, or + * until the ctx->actor indicates there is no more space in the caller's + * output buffer. + * + * On return, @ctx->pos contains an offset that will read the next entry + * in this directory when shmem_readdir() is called again with @ctx. + * + * Return values: + * %0 - Complete + */ +static int stable_readdir(struct file *file, struct dir_context *ctx) +{ + struct dentry *dir = file->f_path.dentry; + + lockdep_assert_held(&d_inode(dir)->i_rwsem); + + if (!dir_emit_dots(file, ctx)) + return 0; + + stable_iterate_dir(dir, ctx); + return 0; +} + +const struct file_operations stable_dir_operations = { + .llseek = stable_dir_llseek, + .iterate_shared = stable_readdir, + .read = generic_read_dir, + .fsync = noop_fsync, +}; +EXPORT_SYMBOL(stable_dir_operations); + static struct dentry *find_next_child(struct dentry *parent, struct dentry *prev) { struct dentry *child = NULL; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 6b351e009f59..579ce1800efe 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -96,6 +96,7 @@ struct dentry { struct super_block *d_sb; /* The root of the dentry tree */ unsigned long d_time; /* used by d_revalidate */ void *d_fsdata; /* fs-specific data */ + u32 d_offset; /* directory offset in parent */ union { struct list_head d_lru; /* LRU list */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 133f0640fb24..3fc2c04ed8ff 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -719,6 +719,10 @@ struct inode { #endif void *i_private; /* fs or device private pointer */ + + /* simplefs stable directory offset tracking */ + struct xarray i_doff_map; + u32 i_next_offset; } __randomize_layout; struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode); @@ -2924,6 +2928,10 @@ extern int simple_rename(struct mnt_idmap *, struct inode *, unsigned int); extern void simple_recursive_removal(struct dentry *, void (*callback)(struct dentry *)); +extern void stable_offset_init(struct inode *dir); +extern int stable_offset_add(struct inode *dir, struct dentry *dentry); +extern void stable_offset_remove(struct inode *dir, struct dentry *dentry); +extern void stable_offset_destroy(struct inode *dir); extern int noop_fsync(struct file *, loff_t, loff_t, int); extern ssize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter); extern int simple_empty(struct dentry *); @@ -2939,6 +2947,7 @@ extern const struct dentry_operations simple_dentry_operations; extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags); extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); extern const struct file_operations simple_dir_operations; +extern const struct file_operations stable_dir_operations; extern const struct inode_operations simple_dir_inode_operations; extern void make_empty_dir_inode(struct inode *inode); extern bool is_empty_dir_inode(struct inode *inode); From patchwork Mon Jun 26 18:21:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13293331 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 A2835EB64D7 for ; Mon, 26 Jun 2023 18:21:39 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 41EDD8D0005; Mon, 26 Jun 2023 14:21:39 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3CDC68D0001; Mon, 26 Jun 2023 14:21:39 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 2BD008D0005; Mon, 26 Jun 2023 14:21:39 -0400 (EDT) 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 200D08D0001 for ; Mon, 26 Jun 2023 14:21:39 -0400 (EDT) Received: from smtpin05.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id E3CF7AFE00 for ; Mon, 26 Jun 2023 18:21:38 +0000 (UTC) X-FDA: 80945717076.05.8E5C148 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf09.hostedemail.com (Postfix) with ESMTP id 1808F140005 for ; Mon, 26 Jun 2023 18:21:36 +0000 (UTC) Authentication-Results: imf09.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=K7YmwTKS; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf09.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=1687803697; 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:in-reply-to:references:references:dkim-signature; bh=HyWy4W98NhZTL9TWC2BPjccfVvBbQZVYnwl3nGeECrM=; b=6+x2/ZhHTCX/npZNZ6CBeCOKpms7o4VR5P2yU8ZcYmOBSwgtrGbHjqr18aBGrsZVXOlbmt 3J4yPqUJ2iIf651LmLj6rwTEBlnSZFM//Sqfmqy5a05xVDIfnBrEOCbM2Ty8LShAKcAJxR U2BF+vJMwTwuEmAjbfwH8k99uk0dCXU= ARC-Authentication-Results: i=1; imf09.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=K7YmwTKS; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf09.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=1687803697; a=rsa-sha256; cv=none; b=pbXNkiIfRdV7dZXOJHMxhqAuiOOWFBg+LWSKvdQRWMB46TptweAp2QxwoYVRjw1hIOEHxQ TeT4DShrFuVvQNDlDoZD+0U7HSlzH5Htq1DfZwNs3AuaITdHFCyV82/5C23XwfDa+hUbBl pxe7M/PGSyOKxcwRllI23tTQHi7VMpg= Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 41F9A60F60; Mon, 26 Jun 2023 18:21:36 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 0C29DC433C0; Mon, 26 Jun 2023 18:21:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687803695; bh=u0otBwYFQ+z8N18f7DVMp5oxjO//N2A60QgEjFLrBOg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=K7YmwTKSw768CNYcRStL5txsH8CmrKRhhVEgaVydmn577NY68l7sa7ZqGCeba8x1K jK8Xi9twCgjTsJhIOjZZYxPeIco8yb1wi4AsJacykLSYrYgybBsQ5qAvhEXv7O/0He ur4xSS5keX1wVFe0kxAtpqKm6f8MpnXMn4gW2dzJ15KaVw2BFcfAwelrNs55FvPz9T DrtebEguX4tH6NqXyQo6pLDjkhnJyxW3dCuAUsYHPw7cDwbXzMYqpBJm4NRCVqkonw RB+/x79n6VzegdWx1s/zxO/we5BDMvX68EJ24qiNPTV+x7dIM6k2b+3dBUEqDHjs6/ E0rTLSNzFEGTg== Subject: [PATCH v4 2/3] shmem: Refactor shmem_symlink() From: Chuck Lever To: viro@zeniv.linux.org.uk, brauner@kernel.org, hughd@google.com, akpm@linux-foundation.org Cc: Jeff Layton , Chuck Lever , jlayton@redhat.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Date: Mon, 26 Jun 2023 14:21:34 -0400 Message-ID: <168780369414.2142.7968970882438871429.stgit@manet.1015granger.net> In-Reply-To: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> References: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 1808F140005 X-Stat-Signature: gmokupka7gx5ny51psgk3d6xhxq7babk X-HE-Tag: 1687803696-249082 X-HE-Meta: U2FsdGVkX197GuFhpM6pa9/7u3g0pHYwX9gP+0B7UKwgoncmpeGm+Hp/8CiSwDjX4Q0me7Boqb+lXazS/ACjpMQgF7hh0+gVZe2MGrAeFKRMdUlceRMU2M06pXCQkBZZHx2mlc9xYG8D7SE1Uqq17ELi49EvlC/h+iKD3PNey9EFaywrVh7I5bZhadv0cPkgB6vhWKUTNjw/x1+0+VMsEe1Hjl7vv9+CKvGUzEo64u2ocYZAEpuiSI092mKrRy+bL/vJkyD6G6PjL3uXGpTGUgXLrIXX7XPaxFrxx4foJ7PuXNSgffoJb8Allv9/SXemzMyCMNhZRGVpUjsPrkC814TXXJEGwFRSxCQ6tzqLqH4GOgasa7vvfUrBqU6TAXkY/vcp0sqX0yoPxs9AwAJsbJ0v8trVZOU0Dxeq9OtP2pYeZ8Sc2iUPFq8FHPJNVb+od597AT8uebHAU5KdkyqejsU+1diPGD1/qsNvWP5ERqFj3sWRgLVywXnUbfKFGnThNfW3LuWoGCXyeEYVwmn6ZnsAxVWUeBhNI0Y+ZbyRwj8m9StWkY1w3yy6C6vGgXQVusNexGZaVBx1Zxnl7DT9OylPB5KB2wSpSAh5wpX4bUd7phHlYm9UflpQBFBNLL7fwOMNWGEd8Tj/QPAIIrM9pAnRn0iRAR9mjtpbqrMC47TDuLv+5bz629JGFIlLu1sglpLkIqUf6HuFdcLVMX+OhjE8exDwR8rYy9j9IIV/Py3mvLLSjkX0bukvXCKO+BAvmFwLnaYDBO7A3ouv776Z09LOY6s6dBMkF03wkETwVoDBFmhya1Abg3Zxj4BznY9r4Z+xrcc/311jJ/C+VjkZrzjwZ53LQZ51D0pYx2bVwEb3ZHGyVgLFg/UId50N8ik7nirBrILAMokaf+z/Q00QBxWw+1wnBAJh2/D2prs2NvNzI81EJ4KsLdxCFfQY3DMmq8Nmqn1ZE2rowP9KI16 MATL46J3 PFsp8FCSHN+cLhmJ9pXTIT7AKx9ntcestBFMyxEYChOaQc72gTI0CJ0vpXqgML/2ut1uRx2X0Uxdia3SRSHHqRK04mVZ9wasVBPUUkObMU7N52z5BnR9XpVPo3rtftfT9EBnzsLq+OTMiiqtcXs0XXAs11rpEz3pKj9rN4MOOXC0cm8gdn01XrDn9F4aCaq7mSKuURRmjCuC5uMK3hKMmzy8yJq90i7MZLghJm9uicgtmIDrzjlYBIk8/oO0CtTpWUTyZWFDLQKT0Utx9tuYq/vGf/SyDuKCbBqcTzG82DeznvFfZqsthntR03o99z6g2lbh/pL8oXleQfAhR4Z5cfTQUiD6ZIzRIHdqMrbTn6WJAOm2+WwLck2ja+A== 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: Chuck Lever De-duplicate the error handling paths. No change in behavior is expected. Suggested-by: Jeff Layton Signed-off-by: Chuck Lever Reviewed-by: Christoph Hellwig --- mm/shmem.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index e40a08c5c6d7..721f9fd064aa 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3161,26 +3161,22 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, error = security_inode_init_security(inode, dir, &dentry->d_name, shmem_initxattrs, NULL); - if (error && error != -EOPNOTSUPP) { - iput(inode); - return error; - } + if (error && error != -EOPNOTSUPP) + goto out_iput; inode->i_size = len-1; if (len <= SHORT_SYMLINK_LEN) { inode->i_link = kmemdup(symname, len, GFP_KERNEL); if (!inode->i_link) { - iput(inode); - return -ENOMEM; + error = -ENOMEM; + goto out_iput; } inode->i_op = &shmem_short_symlink_operations; } else { inode_nohighmem(inode); error = shmem_get_folio(inode, 0, &folio, SGP_WRITE); - if (error) { - iput(inode); - return error; - } + if (error) + goto out_iput; inode->i_mapping->a_ops = &shmem_aops; inode->i_op = &shmem_symlink_inode_operations; memcpy(folio_address(folio), symname, len); @@ -3195,6 +3191,9 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, d_instantiate(dentry, inode); dget(dentry); return 0; +out_iput: + iput(inode); + return error; } static void shmem_put_link(void *arg) From patchwork Mon Jun 26 18:21:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13293332 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 90605EB64D7 for ; Mon, 26 Jun 2023 18:21:46 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 30C458D0006; Mon, 26 Jun 2023 14:21:46 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 2BC328D0001; Mon, 26 Jun 2023 14:21:46 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 15DC78D0006; Mon, 26 Jun 2023 14:21:46 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 083038D0001 for ; Mon, 26 Jun 2023 14:21:46 -0400 (EDT) Received: from smtpin25.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay09.hostedemail.com (Postfix) with ESMTP id BA99980815 for ; Mon, 26 Jun 2023 18:21:45 +0000 (UTC) X-FDA: 80945717370.25.C122626 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf26.hostedemail.com (Postfix) with ESMTP id D18AC140002 for ; Mon, 26 Jun 2023 18:21:43 +0000 (UTC) Authentication-Results: imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=kmbTkXAg; spf=pass (imf26.hostedemail.com: domain of cel@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cel@kernel.org; dmarc=pass (policy=none) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1687803703; 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:in-reply-to:references:references:dkim-signature; bh=PgiRF7eOMMJJhSdgmMjcm5fTADSAlBQ5PzdWP/6AXR0=; b=ku4cmrtJKgCrp8y52wxcYDFG4I3t/BYEjPe/9FnYdlNW72Rmg3/ayF9TnP/Wd9wFjxhgpH KngI3xtko+fpv1TeF+++rhIf/Ji85XIpPiSEuKf0/Q4OKZRLGan9LFGIIdsVGoXjQQvB+L pX1APHR8L+RWi5AMKNCxqFy5ctxTS5I= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1687803703; a=rsa-sha256; cv=none; b=PkKRj9klM+u0iUZyDAsgXfSquOJr6vmKtKVGAdp/qY1Aze69I7U6LOykgEypfuiiQ0Myto GYLYNHos3Z21q1Yv4C6rvXIEQ5jl4hpXBszQGBr4I3hGhy/wN83zsC4Ol6hilp1qbsOqe6 bgJfx+zaDYsT3mGgtlg1A8sXxyo/rEs= ARC-Authentication-Results: i=1; imf26.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=kmbTkXAg; spf=pass (imf26.hostedemail.com: domain of cel@kernel.org designates 139.178.84.217 as permitted sender) smtp.mailfrom=cel@kernel.org; dmarc=pass (policy=none) header.from=kernel.org Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id E074D60F59; Mon, 26 Jun 2023 18:21:42 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BF055C433C8; Mon, 26 Jun 2023 18:21:41 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1687803702; bh=UKT1qjbXJ/095r7Q3G5RGYYkec8CgNh7aC+yZ74QvAA=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=kmbTkXAgmmFnlq2CWE/KuYZ1krx1nS+2xlTwHd0NOLh2Cxy2pqIlzyZ8LKTdXD6Ef ZU9IAnn/DvWiEqy484ycq0/Ao9w+/2bzgOtaV7+WTc7RygG0wwYDABenSmCxm8Sse+ eoAHZp6LEll+IcjSRWGESKr6bBK5/VmMnKdmmVo3nlNEpg3im7bymnpeyQgeDVuVW6 Ss7k47Kw5BNwQx3LRWv67kMo0AEhNstkaccwx4zk0CYQg3Sen+oMvfQSzkQlin3czV Eoq//d2TEGDkA1yP7iTcR/SMH5GmtLmU2lOS6wIgypyzu3n6NMvMa6NZjEP1y6D5dP pzBW0cZnIAQsQ== Subject: [PATCH v4 3/3] shmem: stable directory offsets From: Chuck Lever To: viro@zeniv.linux.org.uk, brauner@kernel.org, hughd@google.com, akpm@linux-foundation.org Cc: Chuck Lever , jlayton@redhat.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Date: Mon, 26 Jun 2023 14:21:40 -0400 Message-ID: <168780370085.2142.4461798321197359310.stgit@manet.1015granger.net> In-Reply-To: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> References: <168780354647.2142.537463116658872680.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Queue-Id: D18AC140002 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: 8nshhcp6fn6o5n9kazemuncerq3hahr5 X-HE-Tag: 1687803703-274737 X-HE-Meta: U2FsdGVkX19NdTDaz8KeEWdwj0i6km9CpTv+lpayJqdJFMsI9MvPsz0NwSEWmJaCmWcsrnfA/BJUHfRChjzAueYpXI3IfeuC4itlSSylpeGCpIvHxnvjwvFEXhKEet6pnmgYlFItT/kdfFgNQN4vMzQTuhrJIXJqXFgIf7pLMaXLL/zqDYWCDMkRc8M6a1YiUhugkJ+lRjVWPFpHquvP924a+4sjC0+xs8sNThuzhhMW01NkvtH8NVVjTqPwkiz2NpnDTlQfQTGE7ij6B62V30DuK2wFAEyXQQjDlrjWBOtxgoI5IopKNYbhgCHIJRLBYhsPPqZUTzpe9p4XF5jgnnVJ75hlyyLjH6g99WCVLkOnvbE+SOMjrYPgz4wdl/9o4D52zqUy3aSyONdFSahF/27G0faXIk8EvJ0j+Au/Gdq7PWzDGxTgbX78N+9VI+zP45njXuu1+Lf6uYSHqAXCzywbxfhN/Edac3auJMU9Dnw9Jq3YtPINvF3FhyngMgelLsR367LX+yLcXOGezqzwuL0phXO49MJ0C4Os8NcncvyodkRQroZoThkFLwHCilriu5dd2nwhd/67/0gfDAYQqKKG9e3dA4WBpomQAaeO2jkeVq0KNCZWHn5keL9QoDuw/NgEH12zE/b+BwYUKFxEMu/W1d2jrmTMDNws0n1SCSrhGqfzuQpnX27Il/n8z9S0tKegG8/N7GeDOqt9+YgF38Cq6CXLB7+8q7eg5MKdBFaqtifTcEhDEC23kU2nGps5zIgicuLhb6ZCJrrrk7aMOMxDISDggr01k2UgtpX9x+Mqq3ueUvXVLdTGDpIOeZ0/K+pAtyzJXfybgdrNMexWom0sTAoOOyfa5R464ZsY/2N5vXMQ2dY2/6cHgg/U7DFIc4bzakvC3Jj0wHsVXRc8IuPym8Gio4GF3l5opxz1w2AI4/v48LHBrGTasa7WhjYMwQ3bEtAQfY2i/PELyV1 XN7aS6xj mAgrMeTVycw7khfxO7/nrUb/PVnt/fk5/9Emzaq/i5Zv6jxdHOwyphjA6rFiQE/FVR4DM0VQf5LX/UCPmsfTj88kD3/g7KcOrq6xE7YaNZ33B16ubhsa+SI7GUVJgSgvnZ6lvdK/qAZN4sGzRN1IAE7EOveCnMdn4vxNj8EhqcPe4X/ShecjYCpXYhPHg9DmQrxCi6+COmyCdidG1V5uC5rWMrK70BleqpecsUchBdMVibyuyqtgXAyvAfwleqiuuVTd6ylWnhMU4jsA= 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: Chuck Lever The current cursor-based directory offset mechanism doesn't work when a tmpfs filesystem is exported via NFS. This is because NFS clients do not open directories. Each server-side READDIR operation has to open the directory, read it, then close it. The cursor state for that directory, being associated strictly with the opened struct file, is thus discarded after each NFS READDIR operation. Directory offsets are cached not only by NFS clients, but also by user space libraries on those clients. Essentially there is no way to invalidate those caches when directory offsets have changed on an NFS server after the offset-to-dentry mapping changes. Thus the whole application stack depends on unchanging directory offsets. The solution we've come up with is to make the directory offset for each file in a tmpfs filesystem stable for the life of the directory entry it represents. shmem_readdir() and shmem_dir_llseek() now use an xarray to map each directory offset (an loff_t integer) to the memory address of a struct dentry. Signed-off-by: Chuck Lever --- mm/shmem.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 721f9fd064aa..89012f3583b1 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2410,7 +2410,8 @@ static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block /* Some things misbehave if size == 0 on a directory */ inode->i_size = 2 * BOGO_DIRENT_SIZE; inode->i_op = &shmem_dir_inode_operations; - inode->i_fop = &simple_dir_operations; + inode->i_fop = &stable_dir_operations; + stable_offset_init(inode); break; case S_IFLNK: /* @@ -2950,7 +2951,10 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir, if (error && error != -EOPNOTSUPP) goto out_iput; - error = 0; + error = stable_offset_add(dir, dentry); + if (error) + goto out_iput; + dir->i_size += BOGO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = current_time(dir); inode_inc_iversion(dir); @@ -3027,6 +3031,13 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr goto out; } + ret = stable_offset_add(dir, dentry); + if (ret) { + if (inode->i_nlink) + shmem_free_inode(inode->i_sb); + goto out; + } + dir->i_size += BOGO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); inode_inc_iversion(dir); @@ -3045,6 +3056,8 @@ static int shmem_unlink(struct inode *dir, struct dentry *dentry) if (inode->i_nlink > 1 && !S_ISDIR(inode->i_mode)) shmem_free_inode(inode->i_sb); + stable_offset_remove(dir, dentry); + dir->i_size -= BOGO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); inode_inc_iversion(dir); @@ -3103,24 +3116,41 @@ static int shmem_rename2(struct mnt_idmap *idmap, { struct inode *inode = d_inode(old_dentry); int they_are_dirs = S_ISDIR(inode->i_mode); + int error; if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT)) return -EINVAL; - if (flags & RENAME_EXCHANGE) + if (flags & RENAME_EXCHANGE) { + error = stable_offset_add(new_dir, old_dentry); + if (error) + return error; + error = stable_offset_add(old_dir, new_dentry); + if (error) { + stable_offset_remove(new_dir, old_dentry); + return error; + } + stable_offset_remove(old_dir, old_dentry); + stable_offset_remove(new_dir, new_dentry); + + /* Always returns zero */ return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry); + } if (!simple_empty(new_dentry)) return -ENOTEMPTY; if (flags & RENAME_WHITEOUT) { - int error; - error = shmem_whiteout(idmap, old_dir, old_dentry); if (error) return error; } + stable_offset_remove(old_dir, old_dentry); + error = stable_offset_add(new_dir, old_dentry); + if (error) + return error; + if (d_really_is_positive(new_dentry)) { (void) shmem_unlink(new_dir, new_dentry); if (they_are_dirs) { @@ -3164,19 +3194,23 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, if (error && error != -EOPNOTSUPP) goto out_iput; + error = stable_offset_add(dir, dentry); + if (error) + goto out_iput; + inode->i_size = len-1; if (len <= SHORT_SYMLINK_LEN) { inode->i_link = kmemdup(symname, len, GFP_KERNEL); if (!inode->i_link) { error = -ENOMEM; - goto out_iput; + goto out_remove_offset; } inode->i_op = &shmem_short_symlink_operations; } else { inode_nohighmem(inode); error = shmem_get_folio(inode, 0, &folio, SGP_WRITE); if (error) - goto out_iput; + goto out_remove_offset; inode->i_mapping->a_ops = &shmem_aops; inode->i_op = &shmem_symlink_inode_operations; memcpy(folio_address(folio), symname, len); @@ -3185,12 +3219,16 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, folio_unlock(folio); folio_put(folio); } + dir->i_size += BOGO_DIRENT_SIZE; dir->i_ctime = dir->i_mtime = current_time(dir); inode_inc_iversion(dir); d_instantiate(dentry, inode); dget(dentry); return 0; + +out_remove_offset: + stable_offset_remove(dir, dentry); out_iput: iput(inode); return error; @@ -3920,6 +3958,8 @@ static void shmem_destroy_inode(struct inode *inode) { if (S_ISREG(inode->i_mode)) mpol_free_shared_policy(&SHMEM_I(inode)->policy); + if (S_ISDIR(inode->i_mode)) + stable_offset_destroy(inode); } static void shmem_init_inode(void *foo)