lazytime for XFS V2
Subsystems (2)
Hi all,
this series implements the lazytime feature for XFS. Unlike ext4 we don't bother supporting the file system parsed text option as MS_LAZYTIME has been supported by util-linux for a long time now. The first patch is needed to make sure XFS actually sees that a dirty inode was dirtied due to lazy time, which is important for XFS as we don't otherwise use the VFS inode dirty tracking for metadata.
Changes since V1:
- fix i_version logging in xfs_vn_update_time,
- document the racy I_DIRTY_TIME check
PATCH 1/2 fs: don't clear I_DIRTY_TIME before calling mark_inode_dirty_sync
__mark_inode_dirty already takes care of that, and for the XFS lazytime implementation we need to know that ->dirty_inode was called because I_DIRTY_TIME was set.
--- fs/inode.c | 1 - fs/sync.c | 6 +----- 2 files changed, 1 insertion(+), 6 deletions(-)
fs/inode.c +0 -1
@@ -1533,7 +1533,6 @@ void iput(struct inode *inode)if (atomic_dec_and_lock (&inode->i_count, &inode->i_lock)) {if (inode->i_nlink && (inode->i_state &I_DIRTY_TIME )) {atomic_inc (&inode->i_count); - inode->i_state &= ~I_DIRTY_TIME ;spin_unlock (&inode->i_lock);trace_writeback_lazytime_iput (inode);mark_inode_dirty_sync (inode);
fs/sync.c +1 -5
@@ -187,12 +187,8 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)if (!file->f_op->fsync)return -EINVAL ; -if (!datasync && (inode->i_state &I_DIRTY_TIME )) { -spin_lock (&inode->i_lock); - inode->i_state &= ~I_DIRTY_TIME ; -spin_unlock (&inode->i_lock); +if (!datasync && (inode->i_state &I_DIRTY_TIME ))mark_inode_dirty_sync (inode); - }return file->f_op->fsync (file, start, end, datasync); }EXPORT_SYMBOL (vfs_fsync_range);
Signature · 1 line
2.14.2
PATCH 2/2 xfs: implement the lazytime mount option
In reply to Christoph HellwigUse the VFS dirty inode tracking for lazytime inodes only, and just log them in ->dirty_inode.
--- fs/xfs/xfs_iops.c | 13 ++++++++++++- fs/xfs/xfs_super.c | 23 +++++++++++++++++++++++ fs/xfs/xfs_trans_inode.c | 14 ++++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-)
fs/xfs/xfs_iops.c +12 -1
@@ -46,6 +46,7 @@#include <linux/security.h> #include <linux/iomap.h> #include <linux/slab.h> +#include <linux/iversion.h> /* * Directories have different lock order w.r.t. mmap_sem compared to regular
@@ -1052,11 +1053,21 @@ xfs_vn_update_time( {struct xfs_inode *ip =XFS_I (inode);struct xfs_mount *mp = ip->i_mount; +int log_flags =XFS_ILOG_TIMESTAMP ;struct xfs_trans *tp;int error;trace_xfs_update_time (ip); +if (inode->i_sb->s_flags &SB_LAZYTIME ) { +if (!((flags &S_VERSION ) && +inode_maybe_inc_iversion (inode, false))) +return generic_update_time (inode, now, flags); + +/* Capture the iversion update that just occurred */ + log_flags |=XFS_ILOG_CORE ; + } + error =xfs_trans_alloc (mp, &M_RES (mp)->tr_fsyncts,0 ,0 ,0 , &tp);if (error)return error;
@@ -1070,7 +1081,7 @@ xfs_vn_update_time( inode->i_atime = *now;xfs_trans_ijoin (tp, ip,XFS_ILOCK_EXCL ); -xfs_trans_log_inode (tp, ip,XFS_ILOG_TIMESTAMP ); +xfs_trans_log_inode (tp, ip, log_flags);return xfs_trans_commit (tp); }
fs/xfs/xfs_super.c +23 -0
@@ -1007,6 +1007,28 @@ xfs_fs_destroy_inode(xfs_inode_set_reclaim_tag (ip); } +static void +xfs_fs_dirty_inode ( +struct inode *inode, +int flag) +{ +struct xfs_inode *ip =XFS_I (inode); +struct xfs_mount *mp = ip->i_mount; +struct xfs_trans *tp; + +if (!(inode->i_sb->s_flags &SB_LAZYTIME )) +return ; +if (flag !=I_DIRTY_SYNC || !(inode->i_state &I_DIRTY_TIME )) +return ; + +if (xfs_trans_alloc (mp, &M_RES (mp)->tr_fsyncts,0 ,0 ,0 , &tp)) +return ; +xfs_ilock (ip,XFS_ILOCK_EXCL ); +xfs_trans_ijoin (tp, ip,XFS_ILOCK_EXCL ); +xfs_trans_log_inode (tp, ip,XFS_ILOG_TIMESTAMP ); +xfs_trans_commit (tp); +} +/* * Slab object creation initialisation for the XFS inode. * This covers only the idempotent fields in the XFS inode;
@@ -1787,6 +1809,7 @@ xfs_fs_free_cached_objects(static const struct super_operations xfs_super_operations = { .alloc_inode = xfs_fs_alloc_inode, .destroy_inode = xfs_fs_destroy_inode, + .dirty_inode = xfs_fs_dirty_inode, .drop_inode = xfs_fs_drop_inode, .put_super = xfs_fs_put_super, .sync_fs = xfs_fs_sync_fs,
fs/xfs/xfs_trans_inode.c +14 -0
@@ -98,9 +98,23 @@ xfs_trans_log_inode( xfs_inode_t *ip, uint flags) { +struct inode *inode =VFS_I (ip); +ASSERT (ip->i_itemp !=NULL );ASSERT (xfs_isilocked (ip,XFS_ILOCK_EXCL )); +/* +* Don't bother with i_lock for the I_DIRTY_TIME check here, as races +* don't matter - we either will need an extra transaction in 24 hours +* to log the timestamps, or will clear already cleared fields in the +* worst case. +*/ +if (inode->i_state & (I_DIRTY_TIME |I_DIRTY_TIME_EXPIRED )) { +spin_lock (&inode->i_lock); + inode->i_state &= ~(I_DIRTY_TIME |I_DIRTY_TIME_EXPIRED ); +spin_unlock (&inode->i_lock); + } +/* * First time we log the inode in a transaction, bump the inode change * counter if it is configured for this to occur. While we have the
Signature · 1 line
2.14.2
Re: [PATCH 2/2] xfs: implement the lazytime mount option
Quoted 4 lines · Christoph Hellwig
Use the VFS dirty inode tracking for lazytime inodes only, and just log them in ->dirty_inode.
Signed-off-by Christoph Hellwig <[email protected]>
Works fine. I can't think of a cleaner way to implement this, so it looks good to me.
Signature · 2 lines
Dave Chinner [email protected]