diff options
author | David Chinner <dgc@sgi.com> | 2008-05-19 02:29:46 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@redback.melbourne.sgi.com> | 2008-05-23 01:25:25 -0400 |
commit | 978b7237123d007b9fa983af6e0e2fa8f97f9934 (patch) | |
tree | ed4c8af42502efeb7ae79b166bb5890347b3de93 /fs/xfs/linux-2.6 | |
parent | c1e554aeea12d2dab5183e011c27dee6142dc927 (diff) |
[XFS] Fix fsync() b0rkage.
xfs_fsync() fails to wait for data I/O completion before checking if the
inode is dirty or clean to decide whether to log the inode or not. This
misses inode size updates when the data flushed by the fsync() is
extending the file.
Hence, like fdatasync(), we need to wait for I/o completion first, then
check the inode for cleanliness. Doing so makes the behaviour of
xfs_fsync() identical for fsync and fdatasync and we *always* use
synchronous semantics if the inode is dirty. Therefore also kill the
differences and remove the unused flags from the xfs_fsync function and
callers.
SGI-PV: 981296
SGI-Modid: xfs-linux-melb:xfs-kern:31033a
Signed-off-by: David Chinner <dgc@sgi.com>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Diffstat (limited to 'fs/xfs/linux-2.6')
-rw-r--r-- | fs/xfs/linux-2.6/xfs_file.c | 17 | ||||
-rw-r--r-- | fs/xfs/linux-2.6/xfs_vnode.h | 8 |
2 files changed, 11 insertions, 14 deletions
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index 65e78c13d4ae..5f60363b9343 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -184,19 +184,24 @@ xfs_file_release( | |||
184 | return -xfs_release(XFS_I(inode)); | 184 | return -xfs_release(XFS_I(inode)); |
185 | } | 185 | } |
186 | 186 | ||
187 | /* | ||
188 | * We ignore the datasync flag here because a datasync is effectively | ||
189 | * identical to an fsync. That is, datasync implies that we need to write | ||
190 | * only the metadata needed to be able to access the data that is written | ||
191 | * if we crash after the call completes. Hence if we are writing beyond | ||
192 | * EOF we have to log the inode size change as well, which makes it a | ||
193 | * full fsync. If we don't write beyond EOF, the inode core will be | ||
194 | * clean in memory and so we don't need to log the inode, just like | ||
195 | * fsync. | ||
196 | */ | ||
187 | STATIC int | 197 | STATIC int |
188 | xfs_file_fsync( | 198 | xfs_file_fsync( |
189 | struct file *filp, | 199 | struct file *filp, |
190 | struct dentry *dentry, | 200 | struct dentry *dentry, |
191 | int datasync) | 201 | int datasync) |
192 | { | 202 | { |
193 | int flags = FSYNC_WAIT; | ||
194 | |||
195 | if (datasync) | ||
196 | flags |= FSYNC_DATA; | ||
197 | xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED); | 203 | xfs_iflags_clear(XFS_I(dentry->d_inode), XFS_ITRUNCATED); |
198 | return -xfs_fsync(XFS_I(dentry->d_inode), flags, | 204 | return -xfs_fsync(XFS_I(dentry->d_inode)); |
199 | (xfs_off_t)0, (xfs_off_t)-1); | ||
200 | } | 205 | } |
201 | 206 | ||
202 | /* | 207 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 9d73cb5c0fc7..25eb2a9e8d9b 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -230,14 +230,6 @@ static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) | |||
230 | #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ | 230 | #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ |
231 | 231 | ||
232 | /* | 232 | /* |
233 | * Flags to vop_fsync/reclaim. | ||
234 | */ | ||
235 | #define FSYNC_NOWAIT 0 /* asynchronous flush */ | ||
236 | #define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ | ||
237 | #define FSYNC_INVAL 0x2 /* flush and invalidate cached data */ | ||
238 | #define FSYNC_DATA 0x4 /* synchronous fsync of data only */ | ||
239 | |||
240 | /* | ||
241 | * Tracking vnode activity. | 233 | * Tracking vnode activity. |
242 | */ | 234 | */ |
243 | #if defined(XFS_INODE_TRACE) | 235 | #if defined(XFS_INODE_TRACE) |