]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
fs: add a ->sync_lazytime method
authorChristoph Hellwig <hch@lst.de>
Thu, 8 Jan 2026 14:19:07 +0000 (15:19 +0100)
committerChristian Brauner <brauner@kernel.org>
Mon, 12 Jan 2026 13:01:33 +0000 (14:01 +0100)
Allow the file system to explicitly implement lazytime syncing instead
of pigging back on generic inode dirtying.  This allows to simplify
the XFS implementation and prepares for non-blocking lazytime timestamp
updates.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: https://patch.msgid.link/20260108141934.2052404-8-hch@lst.de
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Documentation/filesystems/locking.rst
Documentation/filesystems/vfs.rst
fs/fs-writeback.c
include/linux/fs.h

index 37a4a7fa8094c5b3f0348c564f8bc2ce5bba0705..0312fba6d73bc8a2a9ab0bf47d0c71daf44f33d4 100644 (file)
@@ -82,6 +82,7 @@ prototypes::
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
        void (*update_time)(struct inode *inode, enum fs_update_time type,
                            int flags);
+       void (*sync_lazytime)(struct inode *inode);
        int (*atomic_open)(struct inode *, struct dentry *,
                                struct file *, unsigned open_flag,
                                umode_t create_mode);
@@ -118,6 +119,7 @@ getattr:    no
 listxattr:     no
 fiemap:                no
 update_time:   no
+sync_lazytime: no
 atomic_open:   shared (exclusive if O_CREAT is set in open flags)
 tmpfile:       no
 fileattr_get:  no or exclusive
index 51aa9db64784f36fc9576fcf823b573045f7d8ef..d8cb181f69f83fcddde5c324b0b323d4be6fb6c7 100644 (file)
@@ -487,6 +487,7 @@ As of kernel 2.6.22, the following members are defined:
                ssize_t (*listxattr) (struct dentry *, char *, size_t);
                void (*update_time)(struct inode *inode, enum fs_update_time type,
                                    int flags);
+               void (*sync_lazytime)(struct inode *inode);
                int (*atomic_open)(struct inode *, struct dentry *, struct file *,
                                   unsigned open_flag, umode_t create_mode);
                int (*tmpfile) (struct mnt_idmap *, struct inode *, struct file *, umode_t);
@@ -643,6 +644,11 @@ otherwise noted.
        an inode.  If this is not defined the VFS will update the inode
        itself and call mark_inode_dirty_sync.
 
+``sync_lazytime``:
+       called by the writeback code to update the lazy time stamps to
+       regular time stamp updates that get syncing into the on-disk
+       inode.
+
 ``atomic_open``
        called on the last component of an open.  Using this optional
        method the filesystem can look up, possibly create and open the
index 3d68b757136c82020397b89a0378e363591b6782..62658be2578bad5d98f97f9740fac1d132ea44cf 100644 (file)
@@ -1717,7 +1717,10 @@ bool sync_lazytime(struct inode *inode)
                return false;
 
        trace_writeback_lazytime(inode);
-       mark_inode_dirty_sync(inode);
+       if (inode->i_op->sync_lazytime)
+               inode->i_op->sync_lazytime(inode);
+       else
+               mark_inode_dirty_sync(inode);
        return true;
 }
 
@@ -2569,6 +2572,8 @@ void __mark_inode_dirty(struct inode *inode, int flags)
        trace_writeback_mark_inode_dirty(inode, flags);
 
        if (flags & I_DIRTY_INODE) {
+               bool was_dirty_time = false;
+
                /*
                 * Inode timestamp update will piggback on this dirtying.
                 * We tell ->dirty_inode callback that timestamps need to
@@ -2579,6 +2584,7 @@ void __mark_inode_dirty(struct inode *inode, int flags)
                        if (inode_state_read(inode) & I_DIRTY_TIME) {
                                inode_state_clear(inode, I_DIRTY_TIME);
                                flags |= I_DIRTY_TIME;
+                               was_dirty_time = true;
                        }
                        spin_unlock(&inode->i_lock);
                }
@@ -2591,9 +2597,12 @@ void __mark_inode_dirty(struct inode *inode, int flags)
                 * for just I_DIRTY_PAGES or I_DIRTY_TIME.
                 */
                trace_writeback_dirty_inode_start(inode, flags);
-               if (sb->s_op->dirty_inode)
+               if (sb->s_op->dirty_inode) {
                        sb->s_op->dirty_inode(inode,
                                flags & (I_DIRTY_INODE | I_DIRTY_TIME));
+               } else if (was_dirty_time && inode->i_op->sync_lazytime) {
+                       inode->i_op->sync_lazytime(inode);
+               }
                trace_writeback_dirty_inode(inode, flags);
 
                /* I_DIRTY_INODE supersedes I_DIRTY_TIME. */
index 77985b4ed6ffc265f3717cb38f17027388971d76..9cce8b9a29ace7594adfb19cdf6b6b2d4092e404 100644 (file)
@@ -2024,6 +2024,7 @@ struct inode_operations {
                      u64 len);
        int (*update_time)(struct inode *inode, enum fs_update_time type,
                           unsigned int flags);
+       void (*sync_lazytime)(struct inode *inode);
        int (*atomic_open)(struct inode *, struct dentry *,
                           struct file *, unsigned open_flag,
                           umode_t create_mode);