summaryrefslogtreecommitdiff
path: root/fs/xfs/linux-2.6/xfs_file.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-02-15 09:44:49 +0000
committerAlex Elder <aelder@sgi.com>2010-03-01 16:34:45 -0600
commit66d834ea603d61bd90fedad90300ca91c5bba0a3 (patch)
treef73072b9d87bd71a0739f07e4d0e26f10c5d925a /fs/xfs/linux-2.6/xfs_file.c
parentfd3200bef7d66ed3924f72c79a465fb7ff85478a (diff)
xfs: implement optimized fdatasync
Allow us to track the difference between timestamp and size updates by using mark_inode_dirty from the I/O completion code, and checking the VFS inode flags in xfs_file_fsync. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6/xfs_file.c')
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c
index 6c283b7be8ab..43f9554adaac 100644
--- a/fs/xfs/linux-2.6/xfs_file.c
+++ b/fs/xfs/linux-2.6/xfs_file.c
@@ -97,16 +97,6 @@ xfs_iozero(
return (-status);
}
-/*
- * We ignore the datasync flag here because a datasync is effectively
- * identical to an fsync. That is, datasync implies that we need to write
- * only the metadata needed to be able to access the data that is written
- * if we crash after the call completes. Hence if we are writing beyond
- * EOF we have to log the inode size change as well, which makes it a
- * full fsync. If we don't write beyond EOF, the inode core will be
- * clean in memory and so we don't need to log the inode, just like
- * fsync.
- */
STATIC int
xfs_file_fsync(
struct file *file,
@@ -139,7 +129,18 @@ xfs_file_fsync(
*/
xfs_ilock(ip, XFS_ILOCK_SHARED);
- if (ip->i_update_core) {
+ /*
+ * First check if the VFS inode is marked dirty. All the dirtying
+ * of non-transactional updates no goes through mark_inode_dirty*,
+ * which allows us to distinguish beteeen pure timestamp updates
+ * and i_size updates which need to be caught for fdatasync.
+ * After that also theck for the dirty state in the XFS inode, which
+ * might gets cleared when the inode gets written out via the AIL
+ * or xfs_iflush_cluster.
+ */
+ if (((dentry->d_inode->i_state & I_DIRTY_DATASYNC) ||
+ ((dentry->d_inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
+ ip->i_update_core) {
/*
* Kick off a transaction to log the inode core to get the
* updates. The sync transaction will also force the log.