aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_vnodeops.c
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2010-09-27 22:27:25 -0400
committerAlex Elder <aelder@sgi.com>2010-10-18 16:07:45 -0400
commitdcd79a1423f64ee0184629874805c3ac40f3a2c5 (patch)
tree7015d6b6537d4fe3f5371a843a0a9cd45204fb47 /fs/xfs/xfs_vnodeops.c
parente176579e70118ed7cfdb60f963628fe0ca771f3d (diff)
xfs: don't use vfs writeback for pure metadata modifications
Under heavy multi-way parallel create workloads, the VFS struggles to write back all the inodes that have been changed in age order. The bdi flusher thread becomes CPU bound, spending 85% of it's time in the VFS code, mostly traversing the superblock dirty inode list to separate dirty inodes old enough to flush. We already keep an index of all metadata changes in age order - in the AIL - and continued log pressure will do age ordered writeback without any extra overhead at all. If there is no pressure on the log, the xfssyncd will periodically write back metadata in ascending disk address offset order so will be very efficient. Hence we can stop marking VFS inodes dirty during transaction commit or when changing timestamps during transactions. This will keep the inodes in the superblock dirty list to those containing data or unlogged metadata changes. However, the timstamp changes are slightly more complex than this - there are a couple of places that do unlogged updates of the timestamps, and the VFS need to be informed of these. Hence add a new function xfs_trans_ichgtime() for transactional changes, and leave xfs_ichgtime() for the non-transactional changes. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Alex Elder <aelder@sgi.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_vnodeops.c')
-rw-r--r--fs/xfs/xfs_vnodeops.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c
index dc6e4fb8bbc9..a230cd4d0774 100644
--- a/fs/xfs/xfs_vnodeops.c
+++ b/fs/xfs/xfs_vnodeops.c
@@ -184,8 +184,11 @@ xfs_setattr(
184 ip->i_size == 0 && ip->i_d.di_nextents == 0) { 184 ip->i_size == 0 && ip->i_d.di_nextents == 0) {
185 xfs_iunlock(ip, XFS_ILOCK_EXCL); 185 xfs_iunlock(ip, XFS_ILOCK_EXCL);
186 lock_flags &= ~XFS_ILOCK_EXCL; 186 lock_flags &= ~XFS_ILOCK_EXCL;
187 if (mask & ATTR_CTIME) 187 if (mask & ATTR_CTIME) {
188 xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 188 inode->i_mtime = inode->i_ctime =
189 current_fs_time(inode->i_sb);
190 xfs_mark_inode_dirty_sync(ip);
191 }
189 code = 0; 192 code = 0;
190 goto error_return; 193 goto error_return;
191 } 194 }
@@ -1391,7 +1394,7 @@ xfs_create(
1391 ASSERT(error != ENOSPC); 1394 ASSERT(error != ENOSPC);
1392 goto out_trans_abort; 1395 goto out_trans_abort;
1393 } 1396 }
1394 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 1397 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1395 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 1398 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
1396 1399
1397 if (is_dir) { 1400 if (is_dir) {
@@ -1742,7 +1745,7 @@ xfs_remove(
1742 ASSERT(error != ENOENT); 1745 ASSERT(error != ENOENT);
1743 goto out_bmap_cancel; 1746 goto out_bmap_cancel;
1744 } 1747 }
1745 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 1748 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1746 1749
1747 if (is_dir) { 1750 if (is_dir) {
1748 /* 1751 /*
@@ -1895,7 +1898,7 @@ xfs_link(
1895 &first_block, &free_list, resblks); 1898 &first_block, &free_list, resblks);
1896 if (error) 1899 if (error)
1897 goto abort_return; 1900 goto abort_return;
1898 xfs_ichgtime(tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 1901 xfs_trans_ichgtime(tp, tdp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
1899 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE); 1902 xfs_trans_log_inode(tp, tdp, XFS_ILOG_CORE);
1900 1903
1901 error = xfs_bumplink(tp, sip); 1904 error = xfs_bumplink(tp, sip);
@@ -2129,7 +2132,7 @@ xfs_symlink(
2129 &first_block, &free_list, resblks); 2132 &first_block, &free_list, resblks);
2130 if (error) 2133 if (error)
2131 goto error1; 2134 goto error1;
2132 xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 2135 xfs_trans_ichgtime(tp, dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2133 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); 2136 xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE);
2134 2137
2135 /* 2138 /*
@@ -2833,7 +2836,7 @@ xfs_change_file_space(
2833 if (ip->i_d.di_mode & S_IXGRP) 2836 if (ip->i_d.di_mode & S_IXGRP)
2834 ip->i_d.di_mode &= ~S_ISGID; 2837 ip->i_d.di_mode &= ~S_ISGID;
2835 2838
2836 xfs_ichgtime(ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); 2839 xfs_trans_ichgtime(tp, ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2837 } 2840 }
2838 if (setprealloc) 2841 if (setprealloc)
2839 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC; 2842 ip->i_d.di_flags |= XFS_DIFLAG_PREALLOC;