diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-02-15 04:44:49 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-03-01 17:34:45 -0500 |
commit | 66d834ea603d61bd90fedad90300ca91c5bba0a3 (patch) | |
tree | f73072b9d87bd71a0739f07e4d0e26f10c5d925a /fs/xfs | |
parent | fd3200bef7d66ed3924f72c79a465fb7ff85478a (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.c | 4 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 23 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_iops.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_inode.h | 1 |
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 | */ | ||
110 | STATIC int | 100 | STATIC int |
111 | xfs_file_fsync( | 101 | xfs_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 | ||
94 | void | ||
95 | xfs_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); | |||
480 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); | 480 | void xfs_lock_two_inodes(xfs_inode_t *, xfs_inode_t *, uint); |
481 | 481 | ||
482 | void xfs_synchronize_times(xfs_inode_t *); | 482 | void xfs_synchronize_times(xfs_inode_t *); |
483 | void xfs_mark_inode_dirty(xfs_inode_t *); | ||
483 | void xfs_mark_inode_dirty_sync(xfs_inode_t *); | 484 | void xfs_mark_inode_dirty_sync(xfs_inode_t *); |
484 | 485 | ||
485 | #define IHOLD(ip) \ | 486 | #define IHOLD(ip) \ |