aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-02-15 04:44:49 -0500
committerAlex Elder <aelder@sgi.com>2010-03-01 17:34:45 -0500
commit66d834ea603d61bd90fedad90300ca91c5bba0a3 (patch)
treef73072b9d87bd71a0739f07e4d0e26f10c5d925a /fs/xfs
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')
-rw-r--r--fs/xfs/linux-2.6/xfs_aops.c4
-rw-r--r--fs/xfs/linux-2.6/xfs_file.c23
-rw-r--r--fs/xfs/linux-2.6/xfs_iops.c10
-rw-r--r--fs/xfs/xfs_inode.h1
4 files changed, 25 insertions, 13 deletions
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c
index 66abe36c1213..ce369a816ce3 100644
--- a/fs/xfs/linux-2.6/xfs_aops.c
+++ b/fs/xfs/linux-2.6/xfs_aops.c
@@ -187,7 +187,7 @@ xfs_setfilesize(
187 isize = xfs_ioend_new_eof(ioend); 187 isize = xfs_ioend_new_eof(ioend);
188 if (isize) { 188 if (isize) {
189 ip->i_d.di_size = isize; 189 ip->i_d.di_size = isize;
190 xfs_mark_inode_dirty_sync(ip); 190 xfs_mark_inode_dirty(ip);
191 } 191 }
192 192
193 xfs_iunlock(ip, XFS_ILOCK_EXCL); 193 xfs_iunlock(ip, XFS_ILOCK_EXCL);
@@ -341,7 +341,7 @@ xfs_submit_ioend_bio(
341 * but don't update the inode size until I/O completion. 341 * but don't update the inode size until I/O completion.
342 */ 342 */
343 if (xfs_ioend_new_eof(ioend)) 343 if (xfs_ioend_new_eof(ioend))
344 xfs_mark_inode_dirty_sync(XFS_I(ioend->io_inode)); 344 xfs_mark_inode_dirty(XFS_I(ioend->io_inode));
345 345
346 submit_bio(wbc->sync_mode == WB_SYNC_ALL ? 346 submit_bio(wbc->sync_mode == WB_SYNC_ALL ?
347 WRITE_SYNC_PLUG : WRITE, bio); 347 WRITE_SYNC_PLUG : WRITE, bio);
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(
97 return (-status); 97 return (-status);
98} 98}
99 99
100/*
101 * We ignore the datasync flag here because a datasync is effectively
102 * identical to an fsync. That is, datasync implies that we need to write
103 * only the metadata needed to be able to access the data that is written
104 * if we crash after the call completes. Hence if we are writing beyond
105 * EOF we have to log the inode size change as well, which makes it a
106 * full fsync. If we don't write beyond EOF, the inode core will be
107 * clean in memory and so we don't need to log the inode, just like
108 * fsync.
109 */
110STATIC int 100STATIC int
111xfs_file_fsync( 101xfs_file_fsync(
112 struct file *file, 102 struct file *file,
@@ -139,7 +129,18 @@ xfs_file_fsync(
139 */ 129 */
140 xfs_ilock(ip, XFS_ILOCK_SHARED); 130 xfs_ilock(ip, XFS_ILOCK_SHARED);
141 131
142 if (ip->i_update_core) { 132 /*
133 * First check if the VFS inode is marked dirty. All the dirtying
134 * of non-transactional updates no goes through mark_inode_dirty*,
135 * which allows us to distinguish beteeen pure timestamp updates
136 * and i_size updates which need to be caught for fdatasync.
137 * After that also theck for the dirty state in the XFS inode, which
138 * might gets cleared when the inode gets written out via the AIL
139 * or xfs_iflush_cluster.
140 */
141 if (((dentry->d_inode->i_state & I_DIRTY_DATASYNC) ||
142 ((dentry->d_inode->i_state & I_DIRTY_SYNC) && !datasync)) &&
143 ip->i_update_core) {
143 /* 144 /*
144 * Kick off a transaction to log the inode core to get the 145 * Kick off a transaction to log the inode core to get the
145 * updates. The sync transaction will also force the log. 146 * updates. The sync transaction will also force the log.
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index e8566bbf0f00..61a99608731e 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -91,6 +91,16 @@ xfs_mark_inode_dirty_sync(
91 mark_inode_dirty_sync(inode); 91 mark_inode_dirty_sync(inode);
92} 92}
93 93
94void
95xfs_mark_inode_dirty(
96 xfs_inode_t *ip)
97{
98 struct inode *inode = VFS_I(ip);
99
100 if (!(inode->i_state & (I_WILL_FREE|I_FREEING|I_CLEAR)))
101 mark_inode_dirty(inode);
102}
103
94/* 104/*
95 * Change the requested timestamp in the given inode. 105 * Change the requested timestamp in the given inode.
96 * We don't lock across timestamp updates, and we don't log them but 106 * We don't lock across timestamp updates, and we don't log them but
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 6c912b027596..41e8a4e2e3be 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -480,6 +480,7 @@ void xfs_lock_inodes(xfs_inode_t **, int, uint);
480void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); 480void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint);
481 481
482void xfs_synchronize_times(xfs_inode_t *); 482void xfs_synchronize_times(xfs_inode_t *);
483void xfs_mark_inode_dirty(xfs_inode_t *);
483void xfs_mark_inode_dirty_sync(xfs_inode_t *); 484void xfs_mark_inode_dirty_sync(xfs_inode_t *);
484 485
485#define IHOLD(ip) \ 486#define IHOLD(ip) \