From patchwork Fri Jun 30 17:48:49 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13298585 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 BCB91C001B3 for ; Fri, 30 Jun 2023 17:48:55 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2E4FA8E003F; Fri, 30 Jun 2023 13:48:55 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 295C08E000F; Fri, 30 Jun 2023 13:48:55 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 136448E003F; Fri, 30 Jun 2023 13:48:55 -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 0321D8E000F for ; Fri, 30 Jun 2023 13:48:55 -0400 (EDT) Received: from smtpin27.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id CE0D1160DFD for ; Fri, 30 Jun 2023 17:48:54 +0000 (UTC) X-FDA: 80960149788.27.DCE6325 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf28.hostedemail.com (Postfix) with ESMTP id CC618C000D for ; Fri, 30 Jun 2023 17:48:52 +0000 (UTC) Authentication-Results: imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HUhP0hIw; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf28.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=1688147332; 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=GmdIcql9t8areRj1qqZWXls0q4yT8NfEka5s1qckVbA=; b=T4VtVe7NKaiQ7qaJdfI0uGD4AXrg3/5Iqy9qUpmMe6WiYB/nDxCvknc8sWCXx7NTigoHxk D6lX/lkumN5DDaBPs9+CErAQnjDPB6Eg4t9USlT7AViuOZZkasgY3Wurj3Uu3V0cfVReep ya9vR2ddlApuIvE3+PBbWxJgEnekonk= ARC-Authentication-Results: i=1; imf28.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HUhP0hIw; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf28.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=1688147332; a=rsa-sha256; cv=none; b=PXN1Ofe5X4kpvj7Rf5G1RkUY3hsGY4PnVpSOjpJ6XG0aUJznOWhqpwLr53BhsEsT4sfH/8 4ifojJ9asiWupFM5VTqvV3M08xj0KNWwWkWBHh6YzNei4/QAY9Ng5lPaLuOI8RFV/8okfI RtRt5WzNoJuM64VNUC95iR8t3LEqx/g= 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 E359F617CB; Fri, 30 Jun 2023 17:48:51 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BEA7CC433C8; Fri, 30 Jun 2023 17:48:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1688147331; bh=iWqwcV+eIiSHZmsYQJ7ZBLU/vmsFktEqZ/Wrz1FYplg=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=HUhP0hIwz6AyB3wZKihKR7oYyPTxeaqu4hC+682b6AJCdhw5r9l09vt5Q2q62lEkm 3ZyhvBPwC07xag2D7GiO+rizKSmqgXuHDPM3vFE8oW6LS3EPqVUseQC5vxLLmv9MZp eQ/ndaaIb0qy8q66pudIL6eu/lNXsNQb1ZZpc0euHZLje7JZMfAgTTiDDxyh8G1CEo 0KF5qOWm2FCSEDN6+/o20ux3W7v0NvKgRWphqH8cWbqM9gFCG1fFEwEBpt+SdHLBP0 B6knsRWMigbdZqyzeusk749mHiSCbHWIi1mEZp8gdTqQOH5ldi4GPioohRhYVlF+9z ldDlkOHAN1Anw== Subject: [PATCH v7 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: Fri, 30 Jun 2023 13:48:49 -0400 Message-ID: <168814732984.530310.11190772066786107220.stgit@manet.1015granger.net> In-Reply-To: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> References: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Queue-Id: CC618C000D X-Rspam-User: X-Rspamd-Server: rspam02 X-Stat-Signature: 6xrqk94pfo3ju514jm76h7ebo9tfbzqb X-HE-Tag: 1688147332-80276 X-HE-Meta: U2FsdGVkX1+hU/pRykNs3IcHglV/HFm86y5MxOOj/fX11ChjDF+5IlgWk3SIoET3kqHyHl4F9PfBi4+DFz6zSclz+JJtMxcEfY5nvpA5di8kTDmn6qpomAB5uuAN79nxAbvScI0LtP924Zx052w/le2rh8yvqhDgJ5BRGORky3xGksrSToastYbABJVr0REN6iZWENW1Wm42dCK4bPPPpJukZhqQDyEFGe74E1Dzvv3gKXS+htsyB1kq8AZ7J4wEHiFZw8kjkZKzIAxn64mH9Cu8c0iFJtS9UBSb7wir5hyTwMaAA8gjN9JtMV5LgegGqEfcbYUZyHX4QrGRiA+M8kCAbi+HSp7kRWGTJ+h4dwGZD5CR+N/spBCjfRXhY673Ny6KI7IFDh3Gp5cPTHkHXAi1aFtQP6O9LFzeDGx0rumK8YV6g0NfsTaKXgYPxMIGKSkBPbA+0UkNRLJttooYhC0pSw2Eq+JGTeEIb7zAt2yoh3CrnBX864HaHL6KP7VNBZQWPg3z0WRYamj4TLJjvtnFupOxdIYkF/VlNaacxghw23eR8FNkiI586HKbD4SDTJpqy9GgwAMDmCIDa8ojoT3u1R89KrNMEOE4jjBxa9IitLYWVlRuiYltHJBstjZqi53zuh828EUjdOW247mFBJakFwaNcFaUeou5OPsVYpmfkRwolWiQzHSPnsqpsoydfmV0telRDrCSlPBdc3IWtuIoE37v/n38C8k5/AbZJjP+V6Zg7O8PT90sDbOuMJYFfiuDHLhOBPxzGjspFkdG/LZWCbalsS5RsfxJdJOLygOKLKIe9T+WY+Z0m4ump74j1roEiw9H8IuuT0jb5KlSQVbMWTQpg4LPcy7tEQiZ+vchyt9bd2m6TouT8+eXQTwWQJVO7Fld1mPqfH+8QFPyjT7y+ZMirErfaaFhXUDWa5C5PVrJSVKAWSt97F5XX6UmlCQ9o0Vm2vYcXrRZHTK ORl2DZe4 vhZgqeqPR7Tq1z0N+qW9E8fZ/0QdNorFjDspnm1rdBe4yBI9HpRFALO5i0HT3lLDVi63K9l3FZ8AjVbWAs0KThDJzu1Gao4gTsA6jZcVzxxm0IfqFpww3baGtutnRsr/272DU+thqqDKNIOLEWmbPHHueQURSOOuJ6qfCR88/qk93VuW2Hy1azUgakKfdEaLJY1qVJmeYUws8uwQhyVxoYvVUy+MWGQ1rK75naomqnjxI3g3TZsk00/6zXftGmsSny8eoH2FtB3KMezU09jKgZoqXEQ== 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 --- Documentation/filesystems/locking.rst | 2 Documentation/filesystems/vfs.rst | 6 + fs/libfs.c | 247 +++++++++++++++++++++++++++++++++ include/linux/fs.h | 18 ++ 4 files changed, 272 insertions(+), 1 deletion(-) diff --git a/Documentation/filesystems/locking.rst b/Documentation/filesystems/locking.rst index ed148919e11a..6a928fee3400 100644 --- a/Documentation/filesystems/locking.rst +++ b/Documentation/filesystems/locking.rst @@ -85,6 +85,7 @@ prototypes:: struct dentry *dentry, struct fileattr *fa); int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); struct posix_acl * (*get_acl)(struct mnt_idmap *, struct dentry *, int); + struct offset_ctx *(*get_offset_ctx)(struct inode *inode); locking rules: all may block @@ -115,6 +116,7 @@ atomic_open: shared (exclusive if O_CREAT is set in open flags) tmpfile: no fileattr_get: no or exclusive fileattr_set: exclusive +get_offset_ctx: no ============== ============================================= diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index cb2a97e49872..898d0b43109e 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -515,6 +515,7 @@ As of kernel 2.6.22, the following members are defined: int (*fileattr_set)(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); + struct offset_ctx *(*get_offset_ctx)(struct inode *inode); }; Again, all methods are called without any locks being held, unless @@ -675,7 +676,10 @@ otherwise noted. called on ioctl(FS_IOC_SETFLAGS) and ioctl(FS_IOC_FSSETXATTR) to change miscellaneous file flags and attributes. Callers hold i_rwsem exclusive. If unset, then fall back to f_op->ioctl(). - +``get_offset_ctx`` + called to get the offset context for a directory inode. A + filesystem must define this operation to use + simple_offset_dir_operations. The Address Space Object ======================== diff --git a/fs/libfs.c b/fs/libfs.c index 5b851315eeed..68b0000dc518 100644 --- a/fs/libfs.c +++ b/fs/libfs.c @@ -239,6 +239,253 @@ const struct inode_operations simple_dir_inode_operations = { }; EXPORT_SYMBOL(simple_dir_inode_operations); +static void offset_set(struct dentry *dentry, unsigned long offset) +{ + dentry->d_fsdata = (void *)offset; +} + +static unsigned long dentry2offset(struct dentry *dentry) +{ + return (unsigned long)dentry->d_fsdata; +} + +/** + * simple_offset_init - initialize an offset_ctx + * @octx: directory offset map to be initialized + * + */ +void simple_offset_init(struct offset_ctx *octx) +{ + xa_init_flags(&octx->xa, XA_FLAGS_ALLOC1); + + /* 0 is '.', 1 is '..', so always start with offset 2 */ + octx->next_offset = 2; +} + +/** + * simple_offset_add - Add an entry to a directory's offset map + * @octx: directory offset ctx to be updated + * @dentry: new dentry being added + * + * Returns zero on success. @so_ctx and the dentry offset are updated. + * Otherwise, a negative errno value is returned. + */ +int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry) +{ + static const struct xa_limit limit = XA_LIMIT(2, U32_MAX); + u32 offset; + int ret; + + if (dentry2offset(dentry) != 0) + return -EBUSY; + + ret = xa_alloc_cyclic(&octx->xa, &offset, dentry, limit, + &octx->next_offset, GFP_KERNEL); + if (ret < 0) + return ret; + + offset_set(dentry, offset); + return 0; +} + +/** + * simple_offset_remove - Remove an entry to a directory's offset map + * @octx: directory offset ctx to be updated + * @dentry: dentry being removed + * + */ +void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry) +{ + unsigned long index = dentry2offset(dentry); + + if (index == 0) + return; + + xa_erase(&octx->xa, index); + offset_set(dentry, 0); +} + +/** + * simple_offset_rename_exchange - exchange rename with directory offsets + * @old_dir: parent of dentry being moved + * @old_dentry: dentry being moved + * @new_dir: destination parent + * @new_dentry: destination dentry + * + * Returns zero on success. Otherwise a negative errno is returned and the + * rename is rolled back. + */ +int simple_offset_rename_exchange(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry) +{ + struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir); + struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir); + unsigned long old_index = dentry2offset(old_dentry); + unsigned long new_index = dentry2offset(new_dentry); + int ret; + + simple_offset_remove(old_ctx, old_dentry); + simple_offset_remove(new_ctx, new_dentry); + + ret = simple_offset_add(new_ctx, old_dentry); + if (ret) + goto out_restore; + + ret = simple_offset_add(old_ctx, new_dentry); + if (ret) { + simple_offset_remove(new_ctx, old_dentry); + goto out_restore; + } + + ret = simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry); + if (ret) { + simple_offset_remove(new_ctx, old_dentry); + simple_offset_remove(old_ctx, new_dentry); + goto out_restore; + } + return 0; + +out_restore: + offset_set(old_dentry, old_index); + xa_store(&old_ctx->xa, old_index, old_dentry, GFP_KERNEL); + offset_set(new_dentry, new_index); + xa_store(&new_ctx->xa, new_index, new_dentry, GFP_KERNEL); + return ret; +} + +/** + * simple_offset_destroy - Release offset map + * @octx: directory offset ctx 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 simple_offset_destroy(struct offset_ctx *octx) +{ + xa_destroy(&octx->xa); +} + +/** + * offset_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 offset_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 *offset_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 offset_dir_emit(struct dir_context *ctx, struct dentry *dentry) +{ + loff_t offset = dentry2offset(dentry); + struct inode *inode = d_inode(dentry); + + return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset, + inode->i_ino, fs_umode_to_dtype(inode->i_mode)); +} + +static void offset_iterate_dir(struct dentry *dir, struct dir_context *ctx) +{ + struct inode *inode = d_inode(dir); + struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode); + XA_STATE(xas, &so_ctx->xa, ctx->pos); + struct dentry *dentry; + + while (true) { + spin_lock(&dir->d_lock); + dentry = offset_find_next(&xas); + spin_unlock(&dir->d_lock); + if (!dentry) + break; + + if (!offset_dir_emit(ctx, dentry)) { + dput(dentry); + break; + } + + dput(dentry); + ctx->pos = xas.xa_index + 1; + } +} + +/** + * offset_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 offset_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; + + offset_iterate_dir(dir, ctx); + return 0; +} + +const struct file_operations simple_offset_dir_operations = { + .llseek = offset_dir_llseek, + .iterate_shared = offset_readdir, + .read = generic_read_dir, + .fsync = noop_fsync, +}; + static struct dentry *find_next_child(struct dentry *parent, struct dentry *prev) { struct dentry *child = NULL; diff --git a/include/linux/fs.h b/include/linux/fs.h index 6867512907d6..59a4129ce14c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1770,6 +1770,7 @@ struct dir_context { struct iov_iter; struct io_uring_cmd; +struct offset_ctx; struct file_operations { struct module *owner; @@ -1857,6 +1858,7 @@ struct inode_operations { int (*fileattr_set)(struct mnt_idmap *idmap, struct dentry *dentry, struct fileattr *fa); int (*fileattr_get)(struct dentry *dentry, struct fileattr *fa); + struct offset_ctx *(*get_offset_ctx)(struct inode *inode); } ____cacheline_aligned; static inline ssize_t call_read_iter(struct file *file, struct kiocb *kio, @@ -2971,6 +2973,22 @@ extern ssize_t simple_read_from_buffer(void __user *to, size_t count, extern ssize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos, const void __user *from, size_t count); +struct offset_ctx { + struct xarray xa; + u32 next_offset; +}; + +void simple_offset_init(struct offset_ctx *octx); +int simple_offset_add(struct offset_ctx *octx, struct dentry *dentry); +void simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry); +int simple_offset_rename_exchange(struct inode *old_dir, + struct dentry *old_dentry, + struct inode *new_dir, + struct dentry *new_dentry); +void simple_offset_destroy(struct offset_ctx *octx); + +extern const struct file_operations simple_offset_dir_operations; + extern int __generic_file_fsync(struct file *, loff_t, loff_t, int); extern int generic_file_fsync(struct file *, loff_t, loff_t, int); From patchwork Fri Jun 30 17:48:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13298586 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 D9FF5EB64DC for ; Fri, 30 Jun 2023 17:49:02 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 751A38E0040; Fri, 30 Jun 2023 13:49:02 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 7020E8E000F; Fri, 30 Jun 2023 13:49:02 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 5A2EC8E0040; Fri, 30 Jun 2023 13:49:02 -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 49C4F8E000F for ; Fri, 30 Jun 2023 13:49:02 -0400 (EDT) Received: from smtpin12.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id F196C160DE9 for ; Fri, 30 Jun 2023 17:49:01 +0000 (UTC) X-FDA: 80960150082.12.BDBE096 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf24.hostedemail.com (Postfix) with ESMTP id 2D28A180019 for ; Fri, 30 Jun 2023 17:48:58 +0000 (UTC) Authentication-Results: imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HIDO8gao; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf24.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=1688147339; 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=MQpGR3KsSrD2meRTxWtenFFXrfSzuXHiLNi59Pfwy8o=; b=qYDyTpYeVX5CjQjY4FCedtkxlKLvlFxMBLrTiW+92abZScwcq6gCkfg8ex1yxzxfDlzApp vzRApiF7CfEHwPycRdvZnVQ9mW3LuIhGXxGWhpfgywyvz7hhDwKV6V2k55tQTbbU+lgcEY 0kHOj+Eq930KOkYU/qsWViksjH1SP3Y= ARC-Authentication-Results: i=1; imf24.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=HIDO8gao; dmarc=pass (policy=none) header.from=kernel.org; spf=pass (imf24.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=1688147339; a=rsa-sha256; cv=none; b=Kc9tT4R96MWaZAi+/c/WexagViE2Qm8VbPeqw88Uq7NQC3TxEEEjrg/Sp4vgS3yxSlc4XD hbslv7LfxtMJzlWmP8sT3U7ZEims9Md8hOxrp8ZN/xF9VEK1BvFHspBPmnEQjA140KMYow 2B73c4zyuY2YOaH4ZLHCAs4TTjwbHq0= 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 4C93E617E1; Fri, 30 Jun 2023 17:48:58 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6BBCEC433CB; Fri, 30 Jun 2023 17:48:57 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1688147338; bh=lpcIrpUUhkkDjNh21WLxKZUWboCaHEQE1ZuJQA6VvY4=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=HIDO8gaorTxtlC6gS6AuM6QEXfPdbdEGL9QKN8puDoapE+HKJ9F/8+wmmTOPRCF7g PD5NHZsNRlwIg6h+JcRcEKJQ4+os8WDGbfvzi+ONC5Ood2iZQirG/WYny7xIQQs//I EQvmziJ3NjiMrJTt2q0v4ivFJ68fD6ypLe/Ik3u0S5KwZS9HutdestcxAuy3kWboQx MTq61sIYA9MOAzIsVEovyHP/ouimAbkEpfYvnr1NWwCV0+qmZQ+ol8TVCtIFcR43tG 6Fh4I9SYxJTrYkQkDbxbuDoflZ3kJV/Prljn8cWuag6T5sZjdAuMltbB4APsADiJSE sbEl0DxiHkNgA== Subject: [PATCH v7 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 , Christoph Hellwig , Chuck Lever , jlayton@redhat.com, linux-mm@kvack.org, linux-fsdevel@vger.kernel.org Date: Fri, 30 Jun 2023 13:48:56 -0400 Message-ID: <168814733654.530310.9958360833543413152.stgit@manet.1015granger.net> In-Reply-To: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> References: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Queue-Id: 2D28A180019 X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: tdrqoreg74mbbd5t1m65kdmjnp489bnp X-HE-Tag: 1688147338-180262 X-HE-Meta: U2FsdGVkX18GsNSHuy4wVbnZ6ASAS+Vnege0H88D/SQqKZtbNTWTfB5WKNNJF7k0EoKIkphyCvsL6P51AsMDwFaw0yP/cHgOJfDg6moUmdAWNgHchVjg4ijqctbga551iRzWxXC1sOE0L6C8BcYD5RAJvYPcjFoNZN0ReBtkP9ihasd90aIIMb66TlLup9cd61AI2WMZQkNk2QM/ESpgPrSsQ0vB9Td1x9h+PfrxecCSCOJR0wS3usVjW32FId3I1JaONGSYfN4Omt6/s87PEJ+H+jBU/+EEjEVjGbDlpMAjE+QKY/CAbHfp/04thtAsazB1+x7XS4LLLS8uHwpzRSwY7uTXnFJXiGmBXWCAfDkj60UiMhnOZ0iFXxzpf/Ux/Hyn6aKacCq5Qf6PmakaKzYZ2/gc6GX+nPzYjQ76xeWYmSKM+XKOx2QPN2J/n1q1jVQFlMxzvf7EVuMOm0O+cFjZuBl62h6uYq8/yKdc1RlFUFXZ7od0nCVd1g5Ytf1G1T8vp96gdQ1pF6BIG9Grjfv57O54++snjfeQVQ9YEaXDKi4R0J/vrQTU64kmFRvcAoMMgxsLPFC/1Z5X9FoVM3JX4wIVXUAEXV0gZJGBZJiWgrNFdsf9xZE7rLrG1nxzcKgimP1ifcIPVdASNblvLA5xpMjKypCcrHtbvZIeS7nVfkEBRnTtzB7CMLb4z44fjs0ZL+GLDYOZScb7EAEqM9Jft7XGY9VUsy2QRlRphkrYpZdcpNHB8hHmPs67eruU/Mecu/gvOiVGMWc6udEPRCdcBs7sePFIOG4xkFBXbDSv200hnrRQkd3jqKX16rEBvXLO2wSP5wTIhlNOuNaSa+905iMO0B5JWGkARKqChh0rGWEleOci195h1OgYYBbj0AIP76NrYUgZGZmJTFDQS/H3XcPItWbHitqFxlWXUABsgykn9XOBgcOEkqszyEyXdWCNkbgMOeav5N2FudI u7JfY8pm exRcJr2cYzm2rXcjiwprdNGJnM4wfjeAP9YSBvivHIaS+Mff6D2R9QeuqdJSgUd8R/y7VHmkS5bg3DNv61+bp5bMl+cvXxdj3yUQHIKEWjaJr8T53nEEXwLudcMvvPV5IotnC9vneoh0u/qxx55z/27oBrVUOTheZDPCSD0IDwDPSzEzG2pTJkPgbZVTusnzNYAJLaXZaawN/FTyf8IL7jnA63wlG/aH2R6m/QnuSsGe3NSLEhLbxVAdWUxbEEXqvnWhlYwtaYRW5sU9+UGAonr8Mcjy7woyL3TqcGeq8x/B30gNEkCJofv9K0WyCeO6UwjqdHk57kDAYIzkG+X+pT/D6w9gbKzK7DarKeVEatj5YsA6VTH6tGYugog== 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 Reviewed-by: Christoph Hellwig Signed-off-by: Chuck Lever --- mm/shmem.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/mm/shmem.c b/mm/shmem.c index 2f2e0e618072..ba3d7db90c9d 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3293,26 +3293,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); @@ -3327,6 +3323,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 Fri Jun 30 17:49:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Chuck Lever X-Patchwork-Id: 13298587 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 007F3EB64D7 for ; Fri, 30 Jun 2023 17:49:08 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6DC7F8E0041; Fri, 30 Jun 2023 13:49:08 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 68C7D8E000F; Fri, 30 Jun 2023 13:49:08 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 506D68E0041; Fri, 30 Jun 2023 13:49:08 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0015.hostedemail.com [216.40.44.15]) by kanga.kvack.org (Postfix) with ESMTP id 3FD928E000F for ; Fri, 30 Jun 2023 13:49:08 -0400 (EDT) Received: from smtpin06.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 005661C9048 for ; Fri, 30 Jun 2023 17:49:07 +0000 (UTC) X-FDA: 80960150376.06.62CDDAB Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by imf11.hostedemail.com (Postfix) with ESMTP id 2C45C40014 for ; Fri, 30 Jun 2023 17:49:05 +0000 (UTC) Authentication-Results: imf11.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=hYgyYYf6; spf=pass (imf11.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=1688147346; 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=8IeAq52f9TV+g7uDOeNt3cbWsk9ZjZk4oCc795bpX+U=; b=mNkBLhcPsguDa6Y99MYDdElPSd5tYXxVAICofhPiqz9KrUJPr9wtfIb//+CN2OwhHjNEMa 2SDeQKYC9OsqyPBAS+u73t4Fb4D0nGJXp8wQgkoAARNCJ5FQ5WMvimjeaO0AC38E5MdsJ0 1wRGv5luNvfXo+wQCHIJRk0LcNPmW7k= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1688147346; a=rsa-sha256; cv=none; b=vGnqPzdn397ortjtHbHyRzPeLM+rrmGTE3uo/gMVDCEK6UoyLQT1OT6UYg3jL/X93MOdfn h2H00B9awj4ULrdAfdU/2FcskfOGXUlRD+jMYk8QqtuYZiP5e2XnXhZjSGf+7l2LQzyFVa C30eyJw4urjo/8UYuVOYY5YsKnAMz60= ARC-Authentication-Results: i=1; imf11.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=hYgyYYf6; spf=pass (imf11.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 6325D617CB; Fri, 30 Jun 2023 17:49:05 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 44BDEC433C8; Fri, 30 Jun 2023 17:49:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1688147344; bh=eMmAzlgHAQ2+4ZGKGU1pc9Tr35pqzaCjMCrCctyKSSo=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=hYgyYYf6B1eksZgJh0DQQQrxHks6Q1H8QvgOjqAkEvdnpAHnQj4ZrtC5sFJdaCKJn 97/SiDzW3EdLclNQeNLaD1DXlkGX3ZFtvi6IOctIG0Ge5upz3xHF0w961+RWbge8QP BIMTaBJLlG/Q7K+slz/DZgH8HSHIeCe7lNP24FrD0FClvBPn2bPDFAEC3AkUZb4ZG8 GqkxWG+pDTs3+oyiBj4TOdjErAgmQVmRrn4DHPGRxqKk/fGTIkPoJhv1/asy8FQdHT cE/BTmC3Sw/cOeJDqxN+H9Dng4Cu0rJbieP4YZ8yNBkL3X0+Awfl75WdbHzSSu7puh xFHmZry7/MS6A== Subject: [PATCH v7 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: Fri, 30 Jun 2023 13:49:03 -0400 Message-ID: <168814734331.530310.3911190551060453102.stgit@manet.1015granger.net> In-Reply-To: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> References: <168814723481.530310.17776748558242063239.stgit@manet.1015granger.net> User-Agent: StGit/1.5 MIME-Version: 1.0 X-Rspamd-Queue-Id: 2C45C40014 X-Rspam-User: X-Stat-Signature: 5tcyifpm1m41nxkazt997tq5yew783qj X-Rspamd-Server: rspam03 X-HE-Tag: 1688147345-493982 X-HE-Meta: U2FsdGVkX1+QFBZZQtchUmgP2vPsd7p1yId9cCHkHWrjOX3LQEz6mZGbBTux8qmmukHGrRNldBHNh1fdzVNUCgEEO+mrkswvePy3I6nsIECD39MqxVixcjp22nUVQ07TIK4DiQ5gVHKog+h2oz+sGlKPte6vZznDsthOlndADTbbgSQVqN1I8V1Sju+H+ACITrm4L1qKO+wyh5VPE7syCSx4/NTmlPs4HSlei68R/ZWleRbaHB7n1eiAwgsJo2bsqzpR0Ht7XIbdgg5xcinVApXz0NGx56UX73M87maL3wE8aScpxAd/iZPfLPzoaPHjpdNPBIvl9Na0qgadF4dMcn0UuQbwt4d5gm8bi86CCCraYPpOCPhlKVAwq14PoxvoijMka3Cy+UQqu80J7+EgWrbPDqI1oXzYPUnIc0buB7P1xT9gTnri1f5MuCMaeWKQjmlv7CXZiH0YMPF7ZNsuuoyJzEt5g/5CEXIitsDdXCDvZxB8FSUGpG5x4klomk2vTkEzAACyonTQ7SZa6+cIIcpGTjlmpZG2J5lkAcuvPF+RdttGbdBJ+ZMU4D51Dkys0yhGyO2gGwTrZ9PjzY2nsSNqeJ08iHYxGsxBGOcqQ9uDXCdmvo6Okv6pp21U/aJ1A1R/2cnAO/WU6aRWfrHtnXBeZV6rOI02m9VC0izaet3N+bN37I7ZlIYZ84k1KCpCKLFrtJMB0tbM134ToSpD2PHannzlzVbdUgFj9zeqqNsYyG9QEi6Lx/uIG0UiFsAErvjZbZ/dxFj5xZamzMhwE62zhwOpN6ttenkHrJrtfnFvv4Jl+go0XLIEDG+PH88mgSkCQpOZoBs7DEY5v5AV6xJXwSsiYbFVQMFni3dF33L2e2KKuAG5NNUjgcVRwY+f1l81ZXNSZ8rlmAzKOafKWH+uh7aHPU6QD+M7zgESX7dFmbWXYZtrRMClMAKlqKchk4Z8PYqZHh8oWNtrm1X iYGGWNwz KOAquoQBPzhAbtGTOA+anrrM4SWgdeY3Z/aGzU2EE23H+6+ZrcQWmZ1kUAHWeCoqQxyO4BZb/k4TbPXXdbFFR0EbVXwbv83bO0MD2/mFh7owlaHO5Aozc3GZNavIe+um5iKTaM7FGni+F50ZaCdkR8i0jNgh6yfYAStsxwX37RA5GyH0bhglqhCbyD7fF8HV9Ju+/XGGflW9K8ABqF/02x9SuHofcXmfwmJ/qs4lGNvFarFaEGrRQO7/X8pGURUj4QAkVfjdXfVbsZGYed4YOSyXt0g== 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 --- include/linux/shmem_fs.h | 1 + mm/shmem.c | 47 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 41 insertions(+), 7 deletions(-) diff --git a/include/linux/shmem_fs.h b/include/linux/shmem_fs.h index 9029abd29b1c..a5454a80ab30 100644 --- a/include/linux/shmem_fs.h +++ b/include/linux/shmem_fs.h @@ -27,6 +27,7 @@ struct shmem_inode_info { atomic_t stop_eviction; /* hold when working on inode */ struct timespec64 i_crtime; /* file creation time */ unsigned int fsflags; /* flags for FS_IOC_[SG]ETFLAGS */ + struct offset_ctx dir_offsets; /* stable entry offsets */ struct inode vfs_inode; }; diff --git a/mm/shmem.c b/mm/shmem.c index ba3d7db90c9d..c9e6c1dd4fe8 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2355,6 +2355,11 @@ static void shmem_set_inode_flags(struct inode *inode, unsigned int fsflags) #define shmem_initxattrs NULL #endif +static struct offset_ctx *shmem_get_offset_ctx(struct inode *inode) +{ + return &SHMEM_I(inode)->dir_offsets; +} + static struct inode *shmem_get_inode(struct mnt_idmap *idmap, struct super_block *sb, struct inode *dir, umode_t mode, dev_t dev, unsigned long flags) @@ -2410,7 +2415,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 = &simple_offset_dir_operations; + simple_offset_init(shmem_get_offset_ctx(inode)); break; case S_IFLNK: /* @@ -3082,7 +3088,10 @@ shmem_mknod(struct mnt_idmap *idmap, struct inode *dir, if (error && error != -EOPNOTSUPP) goto out_iput; - error = 0; + error = simple_offset_add(shmem_get_offset_ctx(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); @@ -3159,6 +3168,13 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr goto out; } + ret = simple_offset_add(shmem_get_offset_ctx(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); @@ -3177,6 +3193,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); + simple_offset_remove(shmem_get_offset_ctx(dir), dentry); + dir->i_size -= BOGO_DIRENT_SIZE; inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode); inode_inc_iversion(dir); @@ -3235,24 +3253,29 @@ 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) - return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry); + return simple_offset_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; } + simple_offset_remove(shmem_get_offset_ctx(old_dir), old_dentry); + error = simple_offset_add(shmem_get_offset_ctx(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) { @@ -3296,19 +3319,23 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, if (error && error != -EOPNOTSUPP) goto out_iput; + error = simple_offset_add(shmem_get_offset_ctx(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); @@ -3323,6 +3350,9 @@ static int shmem_symlink(struct mnt_idmap *idmap, struct inode *dir, d_instantiate(dentry, inode); dget(dentry); return 0; + +out_remove_offset: + simple_offset_remove(shmem_get_offset_ctx(dir), dentry); out_iput: iput(inode); return error; @@ -4055,6 +4085,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)) + simple_offset_destroy(shmem_get_offset_ctx(inode)); } static void shmem_init_inode(void *foo) @@ -4135,6 +4167,7 @@ static const struct inode_operations shmem_dir_inode_operations = { .mknod = shmem_mknod, .rename = shmem_rename2, .tmpfile = shmem_tmpfile, + .get_offset_ctx = shmem_get_offset_ctx, #endif #ifdef CONFIG_TMPFS_XATTR .listxattr = shmem_listxattr,