aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_file.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2011-10-02 10:25:16 -0400
committerAlex Elder <aelder@sgi.com>2011-10-11 22:15:09 -0400
commit1da2f2dbf2d2aaa1b0f6ca2f61fcf07e24eb659b (patch)
tree41340d0cb08191d0bba677391e238d3771443033 /fs/xfs/xfs_file.c
parent670ce93fef93bba8c8a422a79747385bec8e846a (diff)
xfs: optimize fsync on directories
Directories are only updated transactionally, which means fsync only needs to flush the log the inode is currently dirty, but not bother with checking for dirty data, non-transactional updates, and most importanly doesn't have to flush disk caches except as part of a transaction commit. While the first two optimizations can't easily be measured, the latter actually makes a difference when doing lots of fsync that do not actually have to commit the inode, e.g. because an earlier fsync already pushed the log far enough. The new xfs_dir_fsync is identical to xfs_nfs_commit_metadata except for the prototype, but I'm not sure creating a common helper for the two is worth it given how simple the functions are. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/xfs_file.c')
-rw-r--r--fs/xfs/xfs_file.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 0b600b51778c..753ed9b5c70b 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -124,6 +124,35 @@ xfs_iozero(
124 return (-status); 124 return (-status);
125} 125}
126 126
127/*
128 * Fsync operations on directories are much simpler than on regular files,
129 * as there is no file data to flush, and thus also no need for explicit
130 * cache flush operations, and there are no non-transaction metadata updates
131 * on directories either.
132 */
133STATIC int
134xfs_dir_fsync(
135 struct file *file,
136 loff_t start,
137 loff_t end,
138 int datasync)
139{
140 struct xfs_inode *ip = XFS_I(file->f_mapping->host);
141 struct xfs_mount *mp = ip->i_mount;
142 xfs_lsn_t lsn = 0;
143
144 trace_xfs_dir_fsync(ip);
145
146 xfs_ilock(ip, XFS_ILOCK_SHARED);
147 if (xfs_ipincount(ip))
148 lsn = ip->i_itemp->ili_last_lsn;
149 xfs_iunlock(ip, XFS_ILOCK_SHARED);
150
151 if (!lsn)
152 return 0;
153 return _xfs_log_force_lsn(mp, lsn, XFS_LOG_SYNC, NULL);
154}
155
127STATIC int 156STATIC int
128xfs_file_fsync( 157xfs_file_fsync(
129 struct file *file, 158 struct file *file,
@@ -1140,7 +1169,7 @@ const struct file_operations xfs_dir_file_operations = {
1140#ifdef CONFIG_COMPAT 1169#ifdef CONFIG_COMPAT
1141 .compat_ioctl = xfs_file_compat_ioctl, 1170 .compat_ioctl = xfs_file_compat_ioctl,
1142#endif 1171#endif
1143 .fsync = xfs_file_fsync, 1172 .fsync = xfs_dir_fsync,
1144}; 1173};
1145 1174
1146static const struct vm_operations_struct xfs_file_vm_ops = { 1175static const struct vm_operations_struct xfs_file_vm_ops = {