From patchwork Fri Sep 22 17:14:40 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 13396056 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 64C1BCD484D for ; Fri, 22 Sep 2023 17:14:54 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232653AbjIVRO5 (ORCPT ); Fri, 22 Sep 2023 13:14:57 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60516 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231976AbjIVRO4 (ORCPT ); Fri, 22 Sep 2023 13:14:56 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id A01FF194; Fri, 22 Sep 2023 10:14:50 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id CA976C433C7; Fri, 22 Sep 2023 17:14:48 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695402890; bh=cUbyQ02nAM2bDvq0/ZZw9DgAYz7d/0LKnQxo6skOJKg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=JWmI052TpN/1zeBKhJEITS/FzWyMl+R8Jm+YxEHcIcSq7ru2a/hKzbFK6trpGeY4u zEyPHaFAY2W0ba4eG5EOHPNnXZy4fPsVEvkv2rRGYwMbTzae+8JOR9dHgO3h02c+Dd 713ZyDVzemx/wNXW59rWlBOuKu44GvGlhzicISQpEmcaEOq1IDyDZ/3BGdE6yqpQCz Di4miLVrLg+G2ggUzYOirruMlXShKjk7Hv3BrvtMk3IPfl2EuRvxV+Twwa2BhPBDvo KP9IomE/7l2cKAPRTH1HBNFA28lqPGnnQF5IhWVva1BKv1aQhN20m2EzrtDvDmlwFV MMYum+HnUwSoQ== From: Jeff Layton Date: Fri, 22 Sep 2023 13:14:40 -0400 Subject: [PATCH v8 1/5] fs: add infrastructure for multigrain timestamps MIME-Version: 1.0 Message-Id: <20230922-ctime-v8-1-45f0c236ede1@kernel.org> References: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> In-Reply-To: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> To: Alexander Viro , Christian Brauner , Chuck Lever , Neil Brown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chandan Babu R , "Darrick J. Wong" , Dave Chinner , Jan Kara , Linus Torvalds Cc: Kent Overstreet , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-xfs@vger.kernel.org, Jeff Layton X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=10541; i=jlayton@kernel.org; h=from:subject:message-id; bh=cUbyQ02nAM2bDvq0/ZZw9DgAYz7d/0LKnQxo6skOJKg=; b=owEBbAKT/ZANAwAIAQAOaEEZVoIVAcsmYgBlDcuGMnEkF766+TKP5OeKelTU7JOsYVGshI7co T3NWwjqPR2JAjIEAAEIAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCZQ3LhgAKCRAADmhBGVaC FR0vD/Y8MwOWZPsG9CllTA7k4QfI+psEycaO9S7W1HfqxihNE2Czqn/TocjGzyIxsYGz8YoDmql sUrenu3sO4dLy1MbuFkHING6C5r+xldNxg4d8cTWLGjhbfjTK1Y6KjQMXNsBlhpBXHCFC44cmWx WRad6Snvx+56tRYTHDPltA407w/tQb7xEKWMNfyS46WfERd0ZFvw9LJ4nTuXZNbQxRJSMUoswRi b/3sP2a0Bkj23drO3C5Ck4Ts7bvlkXi85MNf5F+AU+3ZaP2MNo2WNtbO6YeqnExc6G+05mxwpKQ vsa0Uc2C3WWbll6ncc7SvdFxWKSv0Enhn6fSRjGA4OBp8zVMs0RqNS/QrQpCjg4dJ+on4Qps+1D J153sgdC/304pMyTnZeIiocM2h5UWLjWQ4P9Jwr9BZ5a1CiGAJgZ6kjMZ8aE6EXDC1VLOfa5++X vdKKG136dvbN/wzzntK5hj29mJUTsUu+ldp63kjnyLOJbTex76Q3kMtXJxZKLgDGbtusjLcQnci m34FzYb81ubU9AaiQRhxqBXMhk9jTlOyHMYLL819S9y9a82rAuymd3IcNugYRkB8q7EJ99sTxEN GBJQovu7GClU1JHo0QEGKCZ7vek8yEzs2+rT/5zHXbbZp/vTzmYRZiA2SbVEcKiimHZ7CBpJzqk NzZVyAhxOBZbU X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org The VFS always uses coarse-grained timestamps when updating the ctime and mtime after a change. This has the benefit of allowing filesystems to optimize away a lot metadata updates, down to around 1 per jiffy, even when a file is under heavy writes. Unfortunately, this has always been an issue when we're exporting via NFS, which traditionally relied on timestamps to validate caches. A lot of changes can happen in a jiffy, and that can lead to cache-coherency issues between hosts. NFSv4 added a dedicated change attribute that must change value after any change to an inode. Some filesystems (btrfs, ext4 and tmpfs) utilize the i_version field for this, but the NFSv4 spec allows a server to generate this value from the inode's ctime. What we need is a way to only use fine-grained timestamps when they are being actively queried. POSIX generally mandates that when the the mtime changes, the ctime must also change. The kernel always stores normalized ctime values, so only the first 30 bits of the tv_nsec field are ever used. Use the 31st bit of the ctime tv_nsec field to indicate that something has queried the inode for the mtime or ctime. When this flag is set, on the next mtime or ctime update, the kernel will fetch a fine-grained timestamp instead of the usual coarse-grained one. Filesytems can opt into this behavior by setting the FS_MGTIME flag in the fstype. Filesystems that don't set this flag will continue to use coarse-grained timestamps. Note that there is one problem with this scheme. A file with a coarse-grained timestamp that is modified after a different file with a fine grained one can appear to have been modified before. Thus, these timestamps are not suitable for presentation to userland as-is as it could confuse some programs that depend on strict ordering via timestamps. For some use cases however (constructing change cookies), they should be fine. Signed-off-by: Jeff Layton --- fs/inode.c | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++-- include/linux/fs.h | 63 +++++++++++++++++++++++++++++++-- 2 files changed, 160 insertions(+), 5 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 84bc3c76e5cc..f3d68e4b8df7 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -168,6 +168,8 @@ int inode_init_always(struct super_block *sb, struct inode *inode) inode->i_fop = &no_open_fops; inode->i_ino = 0; inode->__i_nlink = 1; + inode->__i_ctime.tv_sec = 0; + inode->__i_ctime.tv_nsec = 0; inode->i_opflags = 0; if (sb->s_xattr) inode->i_opflags |= IOP_XATTR; @@ -2102,10 +2104,52 @@ int file_remove_privs(struct file *file) } EXPORT_SYMBOL(file_remove_privs); +/** + * current_mgtime - Return FS time (possibly fine-grained) + * @inode: inode. + * + * Return the current time truncated to the time granularity supported by + * the fs, as suitable for a ctime/mtime change. If the ctime is flagged + * as having been QUERIED, get a fine-grained timestamp. + */ +struct timespec64 current_mgtime(struct inode *inode) +{ + struct timespec64 now, ctime; + atomic_long_t *pnsec = (atomic_long_t *)&inode->__i_ctime.tv_nsec; + long nsec = atomic_long_read(pnsec); + + if (nsec & I_CTIME_QUERIED) { + ktime_get_real_ts64(&now); + return timestamp_truncate(now, inode); + } + + ktime_get_coarse_real_ts64(&now); + now = timestamp_truncate(now, inode); + + /* + * If we've recently fetched a fine-grained timestamp + * then the coarse-grained one may still be earlier than the + * existing ctime. Just keep the existing value if so. + */ + ctime = inode_get_ctime(inode); + if (timespec64_compare(&ctime, &now) > 0) + now = ctime; + + return now; +} +EXPORT_SYMBOL(current_mgtime); + +static struct timespec64 current_ctime(struct inode *inode) +{ + if (is_mgtime(inode)) + return current_mgtime(inode); + return current_time(inode); +} + static int inode_needs_update_time(struct inode *inode) { int sync_it = 0; - struct timespec64 now = current_time(inode); + struct timespec64 now = current_ctime(inode); struct timespec64 ctime; /* First try to exhaust all avenues to not sync */ @@ -2527,6 +2571,13 @@ struct timespec64 current_time(struct inode *inode) } EXPORT_SYMBOL(current_time); +/* + * Coarse timer ticks happen (roughly) every jiffy. If we see a coarse time + * more than 2 jiffies earlier than the current ctime, then we need to + * update it. This is the max delta allowed (in ns). + */ +#define COARSE_TIME_MAX_DELTA (2 / HZ * NSEC_PER_SEC) + /** * inode_set_ctime_current - set the ctime to current_time * @inode: inode @@ -2536,9 +2587,54 @@ EXPORT_SYMBOL(current_time); */ struct timespec64 inode_set_ctime_current(struct inode *inode) { - struct timespec64 now = current_time(inode); + struct timespec64 now; + struct timespec64 ctime; + + ctime.tv_nsec = READ_ONCE(inode->__i_ctime.tv_nsec); + if (!(ctime.tv_nsec & I_CTIME_QUERIED)) { + now = current_time(inode); + + /* Just copy it into place if it's not multigrain */ + if (!is_mgtime(inode)) { + inode_set_ctime_to_ts(inode, now); + return now; + } - inode_set_ctime(inode, now.tv_sec, now.tv_nsec); + /* + * If we've recently updated with a fine-grained timestamp, + * then the coarse-grained one may still be earlier than the + * existing ctime. Just keep the existing value if so. + */ + ctime.tv_sec = inode->__i_ctime.tv_sec; + if (timespec64_compare(&ctime, &now) > 0) { + struct timespec64 limit = now; + + /* + * If the current coarse-grained clock is earlier than + * it should be, then that's an indication that there + * may have been a backward clock jump, and that the + * update should not be skipped. + */ + timespec64_add_ns(&limit, COARSE_TIME_MAX_DELTA); + if (timespec64_compare(&ctime, &limit) < 0) + return ctime; + } + + /* + * Ctime updates are usually protected by the inode_lock, but + * we can still race with someone setting the QUERIED flag. + * Try to swap the new nsec value into place. If it's changed + * in the interim, then just go with a fine-grained timestamp. + */ + if (cmpxchg(&inode->__i_ctime.tv_nsec, ctime.tv_nsec, + now.tv_nsec) != ctime.tv_nsec) + goto fine_grained; + inode->__i_ctime.tv_sec = now.tv_sec; + return now; + } +fine_grained: + ktime_get_real_ts64(&now); + inode_set_ctime_to_ts(inode, timestamp_truncate(now, inode)); return now; } EXPORT_SYMBOL(inode_set_ctime_current); diff --git a/include/linux/fs.h b/include/linux/fs.h index b528f063e8ff..91239a4c1a65 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1508,18 +1508,65 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb, kgid_has_mapping(fs_userns, kgid); } +struct timespec64 current_mgtime(struct inode *inode); struct timespec64 current_time(struct inode *inode); struct timespec64 inode_set_ctime_current(struct inode *inode); +/* + * Multigrain timestamps + * + * Conditionally use fine-grained ctime and mtime timestamps when there + * are users actively observing them via getattr. The primary use-case + * for this is NFS clients that use the ctime to distinguish between + * different states of the file, and that are often fooled by multiple + * operations that occur in the same coarse-grained timer tick. + * + * The kernel always keeps normalized struct timespec64 values in the ctime, + * which means that only the first 30 bits of the value are used. Use the + * 31st bit of the ctime's tv_nsec field as a flag to indicate that the value + * has been queried since it was last updated. + */ +#define I_CTIME_QUERIED (1L<<30) + /** * inode_get_ctime - fetch the current ctime from the inode * @inode: inode from which to fetch ctime * - * Grab the current ctime from the inode and return it. + * Grab the current ctime from the inode, mask off the I_CTIME_QUERIED + * flag and return it. This is mostly intended for use by internal consumers + * of the ctime that aren't concerned with ensuring a fine-grained update on + * the next change (e.g. when preparing to store the value in the backing store + * for later retrieval). + * + * This is safe to call regardless of whether the underlying filesystem + * is using multigrain timestamps. */ static inline struct timespec64 inode_get_ctime(const struct inode *inode) { - return inode->__i_ctime; + struct timespec64 ctime; + + ctime.tv_sec = inode->__i_ctime.tv_sec; + ctime.tv_nsec = inode->__i_ctime.tv_nsec & ~I_CTIME_QUERIED; + + return ctime; +} + +/** + * inode_query_ctime - fetch the current ctime from inode and flag it + * @inode: inode from which to fetch and flag + * + * Grab the current ctime from the inode, mask off the I_CTIME_QUERIED + * flag and return it. This version also marks the inode as needing a fine + * grained timestamp update in the future. + */ +static inline struct timespec64 inode_query_ctime(const struct inode *inode) +{ + struct timespec64 ctime; + atomic_long_t *pnsec = (atomic_long_t *)&inode->__i_ctime.tv_nsec; + + ctime.tv_sec = inode->__i_ctime.tv_sec; + ctime.tv_nsec = atomic_long_fetch_or(I_CTIME_QUERIED, pnsec) & ~I_CTIME_QUERIED; + return ctime; } /** @@ -2305,6 +2352,7 @@ struct file_system_type { #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ #define FS_DISALLOW_NOTIFY_PERM 16 /* Disable fanotify permission events */ #define FS_ALLOW_IDMAP 32 /* FS has been updated to handle vfs idmappings. */ +#define FS_MGTIME 64 /* FS uses multigrain timestamps */ #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ int (*init_fs_context)(struct fs_context *); const struct fs_parameter_spec *parameters; @@ -2328,6 +2376,17 @@ struct file_system_type { #define MODULE_ALIAS_FS(NAME) MODULE_ALIAS("fs-" NAME) +/** + * is_mgtime: is this inode using multigrain timestamps + * @inode: inode to test for multigrain timestamps + * + * Return true if the inode uses multigrain timestamps, false otherwise. + */ +static inline bool is_mgtime(const struct inode *inode) +{ + return inode->i_sb->s_type->fs_flags & FS_MGTIME; +} + extern struct dentry *mount_bdev(struct file_system_type *fs_type, int flags, const char *dev_name, void *data, int (*fill_super)(struct super_block *, void *, int)); From patchwork Fri Sep 22 17:14:41 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 13396057 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 81462CD4847 for ; Fri, 22 Sep 2023 17:15:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232906AbjIVRPJ (ORCPT ); Fri, 22 Sep 2023 13:15:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232713AbjIVRO6 (ORCPT ); Fri, 22 Sep 2023 13:14:58 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62A4B194; Fri, 22 Sep 2023 10:14:52 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 89086C433C8; Fri, 22 Sep 2023 17:14:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695402892; bh=NFFb0wVC4vDGCm6mY4DnCN3YW9JLtiM6/cGSNjSGNLw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=Ee3OQFc5mhZe1schuj2Ih0PMVeXCVOQ3jJbk6mkpkHqUvFyCYgmLbaFUfPz8T0xVr 8XWz8aNjM5x+uJZqbFmG2DFYpUjSiAg3XGbpz9gQhX5Jn+HLjfBfDsSZjtekZtQG48 H58DlqfyBf1pyFSWFW5e2H46HPsyysJ7FQuD68Vr07jSfC0nxQxHcNL7d/BxZWpMYz LPGZ8GqY8mTUZwyxCoN8Gs8WeGS/QOHv9X8cQnf0s+lj347LzVxbhty0WZVaNQ1FFG Xlas3vwdlUaQahQYXYT9TYUXACjQLNEkvGath6bu3qIE4pZjNrOzN4l0IHdPNlqQUk +zM1D52EdmIIw== From: Jeff Layton Date: Fri, 22 Sep 2023 13:14:41 -0400 Subject: [PATCH v8 2/5] fs: optimize away some fine-grained timestamp updates MIME-Version: 1.0 Message-Id: <20230922-ctime-v8-2-45f0c236ede1@kernel.org> References: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> In-Reply-To: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> To: Alexander Viro , Christian Brauner , Chuck Lever , Neil Brown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chandan Babu R , "Darrick J. Wong" , Dave Chinner , Jan Kara , Linus Torvalds Cc: Kent Overstreet , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-xfs@vger.kernel.org, Jeff Layton X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2334; i=jlayton@kernel.org; h=from:subject:message-id; bh=NFFb0wVC4vDGCm6mY4DnCN3YW9JLtiM6/cGSNjSGNLw=; b=owEBbQKS/ZANAwAIAQAOaEEZVoIVAcsmYgBlDcuGy850TGCImFzlW6PaszASwhbcFpoXM/ofY mgISIxoW3mJAjMEAAEIAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCZQ3LhgAKCRAADmhBGVaC Fbm7D/9b6VZ7YR1N2txLfMMfe4SCyQf5HfHYV7PpyTnWpiDh8onAt/YB/WbCt/TFe+4FhArKbZq gN8yNNikbV/qcZkMZuQKOqGAUbVN4+1ofFU8eng0N2edA1OZ+0wjhFA8HGeixTDp2mX9DtteXz5 8tP9IA7sN6UjqteyWHs47DoVjwDaGA5Tnt1G96cPa4N0jRcyBzj7SrR/SH7nbYsdAT1UcWYBbbM 82CLjSC+lxhh4iWt4yumKI6OIMQZM+h7dbfL5Pcd8fJyf4L5rqrOhlPyam+4LbSDiX7JxKkGL+w 5+8lpQBYQcHWhbRM5CL+WZzY1Iz170Rsl5qHA78yxnwE/s56NUTDsWczHQ++XSa+racTYnjlqiF VJrZWTVX/ABjhoQ+JLNmHJd/jj3aXzbHAz41voa/acsWryBYQHXIQ1V41+QJxpkinDkB6qUUr/w txr0/PHEb3l5lgVrPBzRMZqAFbKKhWwCpOz+Ib0kD1CbcZFd3xrd8tzwB+G34QUASXY42wj8HRv cB2hrWaueCN+xHOqWyherjGOJMalNfwRYcAEZuE1JVhIZEv00Bq7Q0lXvXLVmECOh986lTt5Pvn 0fU63wLR4lslFnItiJ/YVdyENPY3iZ12IRNN04z42uSy4DAu2SyPdKwVC5QuRh0rR37pGL1bZiR LRvQ2MzaluEzK/g== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org When updating the ctime and the QUERIED bit is set, we can still use the coarse-grained clock if the next coarse time tick has already happened. Only use the fine grained clock if the coarse grained one is equal to or earlier than the old ctime. Signed-off-by: Jeff Layton --- fs/inode.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index f3d68e4b8df7..293f9ba623d1 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2587,26 +2587,35 @@ EXPORT_SYMBOL(current_time); */ struct timespec64 inode_set_ctime_current(struct inode *inode) { - struct timespec64 now; + struct timespec64 now = current_time(inode); struct timespec64 ctime; + bool queried; + int tscomp; + /* Just copy it into place if it's not multigrain */ + if (!is_mgtime(inode)) { + inode_set_ctime_to_ts(inode, now); + return now; + } + + ctime.tv_sec = inode->__i_ctime.tv_sec; ctime.tv_nsec = READ_ONCE(inode->__i_ctime.tv_nsec); - if (!(ctime.tv_nsec & I_CTIME_QUERIED)) { - now = current_time(inode); + queried = ctime.tv_nsec & I_CTIME_QUERIED; + ctime.tv_nsec &= ~I_CTIME_QUERIED; - /* Just copy it into place if it's not multigrain */ - if (!is_mgtime(inode)) { - inode_set_ctime_to_ts(inode, now); - return now; - } + tscomp = timespec64_compare(&ctime, &now); + /* + * We can use a coarse-grained timestamp if no one has queried for it, + * or coarse time is already later than the existing ctime. + */ + if (!queried || tscomp < 0) { /* * If we've recently updated with a fine-grained timestamp, * then the coarse-grained one may still be earlier than the * existing ctime. Just keep the existing value if so. */ - ctime.tv_sec = inode->__i_ctime.tv_sec; - if (timespec64_compare(&ctime, &now) > 0) { + if (tscomp > 0) { struct timespec64 limit = now; /* @@ -2620,6 +2629,10 @@ struct timespec64 inode_set_ctime_current(struct inode *inode) return ctime; } + /* Put back the queried bit if we stripped it before */ + if (queried) + ctime.tv_nsec |= I_CTIME_QUERIED; + /* * Ctime updates are usually protected by the inode_lock, but * we can still race with someone setting the QUERIED flag. From patchwork Fri Sep 22 17:14:42 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 13396058 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3AFD3CD4848 for ; Fri, 22 Sep 2023 17:15:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232972AbjIVRPK (ORCPT ); Fri, 22 Sep 2023 13:15:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60578 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232804AbjIVRPA (ORCPT ); Fri, 22 Sep 2023 13:15:00 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1DC17199; Fri, 22 Sep 2023 10:14:54 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 48015C433CC; Fri, 22 Sep 2023 17:14:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695402893; bh=fUxZuWZUND6whtfSXS6cbk4dZFYYjP9h1aQMSYrQkf8=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=rBTSD5KCp99SdJZqsG3zOYy+AdArnEo24hL2QnlNNWA+rKd1uSMkLvysYgASAy8nk 0bbFIkNgBgvgbU6sAOFtzG8gk4ZsxaREY53V7g3eHNwfXbEq1lkcdapAwrdViQaT/k VybJ+BJ43c6IBag3RVLgPWv06U40KwYdJ8Ioud2e5unfr+FUyD7mIJHHgIwXPqxgVf y+SwAq2s6t5VVWHcNNkUPRjfi7Gapjlq2PvqQpUprYxExjc72PfhZ6Bh9cP7axAQj4 HmyUf2kpRcyIMpzHzmKDgWaHMPnzUidPabG+MyH68FApeyLyLjaO3IXolT7e8BpPLH PN3yx8F2/QmyQ== From: Jeff Layton Date: Fri, 22 Sep 2023 13:14:42 -0400 Subject: [PATCH v8 3/5] fs: have setattr_copy handle multigrain timestamps appropriately MIME-Version: 1.0 Message-Id: <20230922-ctime-v8-3-45f0c236ede1@kernel.org> References: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> In-Reply-To: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> To: Alexander Viro , Christian Brauner , Chuck Lever , Neil Brown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chandan Babu R , "Darrick J. Wong" , Dave Chinner , Jan Kara , Linus Torvalds Cc: Kent Overstreet , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-xfs@vger.kernel.org, Jeff Layton X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3299; i=jlayton@kernel.org; h=from:subject:message-id; bh=fUxZuWZUND6whtfSXS6cbk4dZFYYjP9h1aQMSYrQkf8=; b=owEBbQKS/ZANAwAIAQAOaEEZVoIVAcsmYgBlDcuGMi53UoH/W19WSq89zn8S9TZbYu1oTRu0z xom55+Yu6WJAjMEAAEIAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCZQ3LhgAKCRAADmhBGVaC FandEACrYrCK4mEHxIf2BJs2N6vjBIybMKu/4Io+i4XF+mOOk6726NojyEhKuk2vcXIZDgoSvko 4sKNNH5HJsvVR4C/pSNdKBjr9POUoEZoVvbpAVLy2iu2ejCm9nZwOl2xLwDOHmVWpuGOaEC99N8 slbJjXsc6mQhW4YtY8aiyIe2vWAUJiApGFxe76Xq4LVXwpvlLE59HrPesc8OTs9DlWw1gGcJgBI aGZ5e552ciqXH6M3W0TigkkwuRC/pE4PgFzY4IceN8aQ751zXiaRcePJlCTd8vw48smmMTyIduB 7R0BBtYMOIFAIQLtYFAAzTOA1FXJEm9Z0fj5jaoxBcZKF1dn3wxU5v3JpQzPYlIwiW6Ew2/vE2Y ItlRJO5Cp9KTKFfB/bQQ/DGUJ1QIk9HjeA3wfhGKAJXOajJuBnt0uoMmUn5DMDSweylV3tiMO83 xA84OiIS3hYeTXK1raunHowGVvoXZAK7H+ozYd9dMdvcMfJKrPBUy9YYl5z7l/hYT+OAZUvOkNc VWGpdW7tpulAckFRkllgmsfnvbNszaNeWX483WFWsz6X6Zfv6zQe+mX8S8T9UE4XqE6ZYjDhYKn tE/ezJ+p8Zn6pmB2fWYo7O0PYpLLmzwY9kcFm3H2MawZtSwNtcpY1I8f1CBDtMzSw3qgeoYiOhq kKQ6H5ktDrpyWUQ== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org The setattr codepath is still using coarse-grained timestamps, even on multigrain filesystems. To fix this, we need to fetch the timestamp for ctime updates later, at the point where the assignment occurs in setattr_copy. On a multigrain inode, ignore the ia_ctime in the attrs, and always update the ctime to the current clock value. Update the atime and mtime with the same value (if needed) unless they are being set to other specific values, a'la utimes(). Note that we don't want to do this universally however, as some filesystems (e.g. most networked fs) want to do an explicit update elsewhere before updating the local inode. Signed-off-by: Jeff Layton --- fs/attr.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/fs/attr.c b/fs/attr.c index a8ae5f6d9b16..8ba330e6a582 100644 --- a/fs/attr.c +++ b/fs/attr.c @@ -275,6 +275,42 @@ int inode_newsize_ok(const struct inode *inode, loff_t offset) } EXPORT_SYMBOL(inode_newsize_ok); +/** + * setattr_copy_mgtime - update timestamps for mgtime inodes + * @inode: inode timestamps to be updated + * @attr: attrs for the update + * + * With multigrain timestamps, we need to take more care to prevent races + * when updating the ctime. Always update the ctime to the very latest + * using the standard mechanism, and use that to populate the atime and + * mtime appropriately (unless we're setting those to specific values). + */ +static void setattr_copy_mgtime(struct inode *inode, const struct iattr *attr) +{ + unsigned int ia_valid = attr->ia_valid; + struct timespec64 now; + + /* + * If the ctime isn't being updated then nothing else should be + * either. + */ + if (!(ia_valid & ATTR_CTIME)) { + WARN_ON_ONCE(ia_valid & (ATTR_ATIME|ATTR_MTIME)); + return; + } + + now = inode_set_ctime_current(inode); + if (ia_valid & ATTR_ATIME_SET) + inode->i_atime = attr->ia_atime; + else if (ia_valid & ATTR_ATIME) + inode->i_atime = now; + + if (ia_valid & ATTR_MTIME_SET) + inode->i_mtime = attr->ia_mtime; + else if (ia_valid & ATTR_MTIME) + inode->i_mtime = now; +} + /** * setattr_copy - copy simple metadata updates into the generic inode * @idmap: idmap of the mount the inode was found from @@ -307,12 +343,6 @@ void setattr_copy(struct mnt_idmap *idmap, struct inode *inode, i_uid_update(idmap, attr, inode); i_gid_update(idmap, attr, inode); - if (ia_valid & ATTR_ATIME) - inode->i_atime = attr->ia_atime; - if (ia_valid & ATTR_MTIME) - inode->i_mtime = attr->ia_mtime; - if (ia_valid & ATTR_CTIME) - inode_set_ctime_to_ts(inode, attr->ia_ctime); if (ia_valid & ATTR_MODE) { umode_t mode = attr->ia_mode; if (!in_group_or_capable(idmap, inode, @@ -320,6 +350,16 @@ void setattr_copy(struct mnt_idmap *idmap, struct inode *inode, mode &= ~S_ISGID; inode->i_mode = mode; } + + if (is_mgtime(inode)) + return setattr_copy_mgtime(inode, attr); + + if (ia_valid & ATTR_ATIME) + inode->i_atime = attr->ia_atime; + if (ia_valid & ATTR_MTIME) + inode->i_mtime = attr->ia_mtime; + if (ia_valid & ATTR_CTIME) + inode_set_ctime_to_ts(inode, attr->ia_ctime); } EXPORT_SYMBOL(setattr_copy); From patchwork Fri Sep 22 17:14:43 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 13396060 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1ECE9CD4850 for ; Fri, 22 Sep 2023 17:15:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232883AbjIVRPM (ORCPT ); Fri, 22 Sep 2023 13:15:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60556 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232846AbjIVRPJ (ORCPT ); Fri, 22 Sep 2023 13:15:09 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D345F1A4; Fri, 22 Sep 2023 10:14:55 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 06A00C433CA; Fri, 22 Sep 2023 17:14:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695402895; bh=v6UdIy3iF2gwyGe6YE1xuhC9UXQ7IzgYePWcUL4vSGA=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=nobLkZ57CkeLUrk9Gn+1rf8m7nE+tgakmBWN28qsQYbPxKtomzJEXpnLPmWeiWBHd wYTswOnh2rBSClEgAN8YJ7iddAPu/ln8TdSlY98dSmDWgT8mSyHHGNPrxrqrggf8g2 TyvO3JswgOAnMLrprnEmCnW2JpN0OrcRZQR08buWuiphHcIvV/jKELnN2V9cWhnxDO wcpPcNMESNGHDbERV/J3m2WiUZduLG4GMdPJ88PvbJhK+I0XYaJCd0d7MCJLgLMHrN Gp3Wqyuv86lHct+I7JFQvvRUx3x352t720UkdCF/9YzCbE/5kBf5d3N60S6q5WEsdq cWxgL7jwI7d0A== From: Jeff Layton Date: Fri, 22 Sep 2023 13:14:43 -0400 Subject: [PATCH v8 4/5] fs: add timestamp_truncate_to_gran helper MIME-Version: 1.0 Message-Id: <20230922-ctime-v8-4-45f0c236ede1@kernel.org> References: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> In-Reply-To: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> To: Alexander Viro , Christian Brauner , Chuck Lever , Neil Brown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chandan Babu R , "Darrick J. Wong" , Dave Chinner , Jan Kara , Linus Torvalds Cc: Kent Overstreet , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-xfs@vger.kernel.org, Jeff Layton X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=2766; i=jlayton@kernel.org; h=from:subject:message-id; bh=v6UdIy3iF2gwyGe6YE1xuhC9UXQ7IzgYePWcUL4vSGA=; b=owEBbQKS/ZANAwAIAQAOaEEZVoIVAcsmYgBlDcuGcqJPwl78fHiagrBrxmzVPer9aG3oaERZI pqSNpvoC8aJAjMEAAEIAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCZQ3LhgAKCRAADmhBGVaC FakdD/9KgrOQOhGZ14ptFQspbpO6fxuNVSJ/rqEaSG7uELQqBbcBcguVCQO1J3wIoEBUiEp4inf gHZLXxlDNDD/4PQh9lxCHPs6stqfiR/OIeZwe36cujXOjv5XrNdGCAznIcOjEM40Px/btRNrYC/ XJrmlw9gEU4IeAtZ9AIokdyalPTIGX7ECHLceGsMjNHU4B1zSi380XFB0r3xJsegyqiOXoY5Cta E7r6m8zgxedClqgOOBKcYq5FUjoh+7UfDXTciJ66u5BrlrpT/JjEisrReLys3w8xK8JyKTwHab6 +xgn3pkVoT4O1FrXmzbstaOO1YixyuzvOazHEs9WmY/kYehP8yOB5a0wCGcXM3SrLuWNNPIEDQy rxfHvOoPYKWWffYf1LDuaFSMasfjUa0OPm+XY8sulTaBaMw4afqlyyRr8r4skmNpGYnAvntL39O /urlIhaynyYw9Mr2rF+QJ66bl8x+qgmM7l/YtOvFxQ20hCsdol8XU2DfAzgKZBtE0zlTHTVvO1J Q1WAUaPKZTBJMQzhgVElGkua+KRcD9EvagHXdXWiq+iV4P7ZxMF1bEjKrBZAKgzj7Rg+W2Ec1A2 yBTVWzmA323AGRYnPvTn4+37r3SNAHo6Fs1q8y+LCauOb8Fga99iYMaleYsMUe95bWIY1u9AGYQ qpHGgQNLqWzi2Cw== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org In a future patch, we're going to need to truncate fine-grained timestamps down to jiffies granularity. Add a new helper that allows truncating down to an arbitrary granularity. Signed-off-by: Jeff Layton --- fs/inode.c | 38 +++++++++++++++++++++++++++----------- include/linux/fs.h | 1 + 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/fs/inode.c b/fs/inode.c index 293f9ba623d1..ae6baa5b17c5 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -2521,6 +2521,29 @@ void inode_nohighmem(struct inode *inode) } EXPORT_SYMBOL(inode_nohighmem); +/** + * timestamp_truncate_to_gran - Truncate timespec to a granularity + * @t: Timespec + * @gran: the specified granularity (in ns) + * + * Truncate a timespec to the specified granularity. Always rounds down. + * gran must not be 0 nor greater than a second (NSEC_PER_SEC, or 10^9 ns). + */ +struct timespec64 timestamp_truncate_to_gran(struct timespec64 t, unsigned int gran) +{ + /* Avoid division in the common cases 1 ns and 1 s. */ + if (gran == 1) + ; /* nothing */ + else if (gran == NSEC_PER_SEC) + t.tv_nsec = 0; + else if (gran > 1 && gran < NSEC_PER_SEC) + t.tv_nsec -= t.tv_nsec % gran; + else + WARN(1, "invalid file time granularity: %u", gran); + return t; +} +EXPORT_SYMBOL(timestamp_truncate_to_gran); + /** * timestamp_truncate - Truncate timespec to a granularity * @t: Timespec @@ -2536,19 +2559,12 @@ struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode) unsigned int gran = sb->s_time_gran; t.tv_sec = clamp(t.tv_sec, sb->s_time_min, sb->s_time_max); - if (unlikely(t.tv_sec == sb->s_time_max || t.tv_sec == sb->s_time_min)) + if (unlikely(t.tv_sec == sb->s_time_max || t.tv_sec == sb->s_time_min)) { t.tv_nsec = 0; + return t; + } - /* Avoid division in the common cases 1 ns and 1 s. */ - if (gran == 1) - ; /* nothing */ - else if (gran == NSEC_PER_SEC) - t.tv_nsec = 0; - else if (gran > 1 && gran < NSEC_PER_SEC) - t.tv_nsec -= t.tv_nsec % gran; - else - WARN(1, "invalid file time granularity: %u", gran); - return t; + return timestamp_truncate_to_gran(t, gran); } EXPORT_SYMBOL(timestamp_truncate); diff --git a/include/linux/fs.h b/include/linux/fs.h index 91239a4c1a65..fa696322dae3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -748,6 +748,7 @@ struct inode { void *i_private; /* fs or device private pointer */ } __randomize_layout; +struct timespec64 timestamp_truncate_to_gran(struct timespec64 t, unsigned int gran); struct timespec64 timestamp_truncate(struct timespec64 t, struct inode *inode); static inline unsigned int i_blocksize(const struct inode *node) From patchwork Fri Sep 22 17:14:44 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 13396059 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3BBE9CD484E for ; Fri, 22 Sep 2023 17:15:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232931AbjIVRPL (ORCPT ); Fri, 22 Sep 2023 13:15:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35046 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232919AbjIVRPJ (ORCPT ); Fri, 22 Sep 2023 13:15:09 -0400 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 99ACB1AC; Fri, 22 Sep 2023 10:14:57 -0700 (PDT) Received: by smtp.kernel.org (Postfix) with ESMTPSA id BC254C43391; Fri, 22 Sep 2023 17:14:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1695402897; bh=+R/VqH2Y/BEqxszA0QoLfX//cyFS9olgivR+kesE1J4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=iGdFCLfI45oIdGjAhse2hgGufxXf/0O9SoobCZ6Kp6qHR1lsFNhsfggdoO1vAEJvZ j0GX5+d9ed6zhcWBLoAl5hu3jSIRsO8inXCWlLV0lmUbmhiC9eCtC76g6Etga6E+Ie Nrf2E1UFJMh5ywRWYITq/jmTTOfrNOn5eQKSSD0NDEm5KOUmkp8tGQ0PFY2uSX/o90 x+VDNzKOXIf0sA590jm77bZHd3kXVDR72243VI9CHIinaVCHFk6+Km85a7m3OmUXho K74Rhs19YyfibVFsrRX7Owth2bWG1g0PJfI77BB5GgROv30noUCzMzgaOT80BrnheI fFmak1i1pLV/A== From: Jeff Layton Date: Fri, 22 Sep 2023 13:14:44 -0400 Subject: [PATCH v8 5/5] xfs: switch to multigrain timestamps MIME-Version: 1.0 Message-Id: <20230922-ctime-v8-5-45f0c236ede1@kernel.org> References: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> In-Reply-To: <20230922-ctime-v8-0-45f0c236ede1@kernel.org> To: Alexander Viro , Christian Brauner , Chuck Lever , Neil Brown , Olga Kornievskaia , Dai Ngo , Tom Talpey , Chandan Babu R , "Darrick J. Wong" , Dave Chinner , Jan Kara , Linus Torvalds Cc: Kent Overstreet , linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, linux-nfs@vger.kernel.org, linux-xfs@vger.kernel.org, Jeff Layton X-Mailer: b4 0.12.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3811; i=jlayton@kernel.org; h=from:subject:message-id; bh=+R/VqH2Y/BEqxszA0QoLfX//cyFS9olgivR+kesE1J4=; b=owEBbQKS/ZANAwAIAQAOaEEZVoIVAcsmYgBlDcuGzq6LFTw1GidIFjabFRhWirpLN8lq0xa2T gnnQgk9RM6JAjMEAAEIAB0WIQRLwNeyRHGyoYTq9dMADmhBGVaCFQUCZQ3LhgAKCRAADmhBGVaC FfNoEACpYILGJNZCCiYdPFl9vpwrP0Gd3cZHvHbgH4D15ySNal9OtCw43Yy73I2bXKZswiSHYpw JOa3X5lqXVv1WBBqS6prbYRFyHwXFNiSVsaR0m2bqI4e1tDPXih3ZsGi4KXxOYlZ0ZpLYXH9NTG 1IQropOz8tvmWj6k17+FkE8SxnJnObC4MQlqXNnf4CJazo0XbR/Qwrka5nJYSwChIinIFAm9u3D nhJgi4sqE3dFSgqRbwsijCHLwMjr32mOL+hMQflJcNmAvFheM6Dj2h3c3e6Zyjt1J58b3anm8io qYGmBD8mxoFehTM2MRdF/1qpy+kfOefCJUWSIeZq6TTI+4eWMaHA9PfKeEPyLAzMp5tn6rMOQ5R bOLyDLKlzLzGVJdJOUJmbxt0JBpxzPq2o5e5eDhvn0JYS5ddIY1uBzuM4/y98SvT1HIPCXrM+4a XYJMrnwA2ppdom2a6MyFjjFPDT5QbfUPDKV6zk/IJFH4+dLyV2054kvF2JfhE7agsvixgpLbSaD WbCGhhfbuRKVKhPXqWkYmx5lPrGxzwKVcXnBFtYMn5W7r0TCQ6g7mnPJ/hiecqTkfov5NGm/dWh XbL4Z2/MFMT2nwD37eOzM5dtLPlEgC3iCqDJZtAD8h2W/xBIlSxI8uCODGbBPj/klSDQZdM+Y2P DH6+jV6szK/A5XA== X-Developer-Key: i=jlayton@kernel.org; a=openpgp; fpr=4BC0D7B24471B2A184EAF5D3000E684119568215 Precedence: bulk List-ID: X-Mailing-List: linux-nfs@vger.kernel.org Enable multigrain timestamps, which should ensure that there is an apparent change to the internal ctime value whenever a file has been written after being actively observed via getattr. Anytime the mtime changes, the ctime must also change, and those are the only two options for xfs_trans_ichgtime. Have that function unconditionally bump the ctime, and ASSERT that XFS_ICHGTIME_CHG is always set. In getattr, truncate the mtime and ctime at the number of nanoseconds per jiffy, which should ensure that ordering is preserved. Use the fine grained ctime to fake up a STATX_CHANGE_COOKIE if one was requested. Signed-off-by: Jeff Layton --- fs/xfs/libxfs/xfs_trans_inode.c | 6 +++--- fs/xfs/xfs_iops.c | 26 +++++++++++++++++++------- fs/xfs/xfs_super.c | 2 +- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/fs/xfs/libxfs/xfs_trans_inode.c b/fs/xfs/libxfs/xfs_trans_inode.c index 6b2296ff248a..ad22656376d3 100644 --- a/fs/xfs/libxfs/xfs_trans_inode.c +++ b/fs/xfs/libxfs/xfs_trans_inode.c @@ -62,12 +62,12 @@ xfs_trans_ichgtime( ASSERT(tp); ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); - tv = current_time(inode); + /* If the mtime changes, then ctime must also change */ + ASSERT(flags & XFS_ICHGTIME_CHG); + tv = inode_set_ctime_current(inode); if (flags & XFS_ICHGTIME_MOD) inode->i_mtime = tv; - if (flags & XFS_ICHGTIME_CHG) - inode_set_ctime_to_ts(inode, tv); if (flags & XFS_ICHGTIME_CREATE) ip->i_crtime = tv; } diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index 1c1e6171209d..af4a54756113 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c @@ -559,6 +559,7 @@ xfs_vn_getattr( struct xfs_mount *mp = ip->i_mount; vfsuid_t vfsuid = i_uid_into_vfsuid(idmap, inode); vfsgid_t vfsgid = i_gid_into_vfsgid(idmap, inode); + struct timespec64 ctime; trace_xfs_getattr(ip); @@ -573,8 +574,23 @@ xfs_vn_getattr( stat->gid = vfsgid_into_kgid(vfsgid); stat->ino = ip->i_ino; stat->atime = inode->i_atime; - stat->mtime = inode->i_mtime; - stat->ctime = inode_get_ctime(inode); + stat->mtime = timestamp_truncate_to_gran(inode->i_mtime, NSEC_PER_SEC/HZ); + + /* + * Don't bother flagging the inode for a fine-grained update unless + * STATX_CHANGE_COOKIE is set, in which case, use the fine-grained + * value to fake up a change_cookie. + */ + if (request_mask & STATX_CHANGE_COOKIE) { + ctime = inode_query_ctime(inode); + stat->change_cookie = time_to_chattr(&ctime); + stat->result_mask |= STATX_CHANGE_COOKIE; + } else { + ctime = inode_get_ctime(inode); + } + + stat->ctime = timestamp_truncate_to_gran(ctime, NSEC_PER_SEC/HZ); + stat->blocks = XFS_FSB_TO_BB(mp, ip->i_nblocks + ip->i_delayed_blks); if (xfs_has_v3inodes(mp)) { @@ -914,12 +930,8 @@ xfs_setattr_size( * these flags set. For all other operations the VFS set these flags * explicitly if it wants a timestamp update. */ - if (newsize != oldsize && - !(iattr->ia_valid & (ATTR_CTIME | ATTR_MTIME))) { - iattr->ia_ctime = iattr->ia_mtime = - current_time(inode); + if (newsize != oldsize) iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME; - } /* * The first thing we do is set the size to new_size permanently on diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index b5c202f5d96c..1f77014c6e1a 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c @@ -2065,7 +2065,7 @@ static struct file_system_type xfs_fs_type = { .init_fs_context = xfs_init_fs_context, .parameters = xfs_fs_parameters, .kill_sb = xfs_kill_sb, - .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, + .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP | FS_MGTIME, }; MODULE_ALIAS_FS("xfs");