aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/extents.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-12-08 23:51:10 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-12-08 23:51:10 -0500
commitb436b9bef84de6893e86346d8fbf7104bc520645 (patch)
tree50fb9ae167bcd622e9adf47646bcf3b4c7dd111d /fs/ext4/extents.c
parent194074acacebc169ded90a4657193f5180015051 (diff)
ext4: Wait for proper transaction commit on fsync
We cannot rely on buffer dirty bits during fsync because pdflush can come before fsync is called and clear dirty bits without forcing a transaction commit. What we do is that we track which transaction has last changed the inode and which transaction last changed allocation and force it to disk on fsync. Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/extents.c')
-rw-r--r--fs/ext4/extents.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 5967f18fd7e7..700206e525da 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3058,6 +3058,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3058 if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) { 3058 if (flags == EXT4_GET_BLOCKS_DIO_CONVERT_EXT) {
3059 ret = ext4_convert_unwritten_extents_dio(handle, inode, 3059 ret = ext4_convert_unwritten_extents_dio(handle, inode,
3060 path); 3060 path);
3061 if (ret >= 0)
3062 ext4_update_inode_fsync_trans(handle, inode, 1);
3061 goto out2; 3063 goto out2;
3062 } 3064 }
3063 /* buffered IO case */ 3065 /* buffered IO case */
@@ -3085,6 +3087,8 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
3085 ret = ext4_ext_convert_to_initialized(handle, inode, 3087 ret = ext4_ext_convert_to_initialized(handle, inode,
3086 path, iblock, 3088 path, iblock,
3087 max_blocks); 3089 max_blocks);
3090 if (ret >= 0)
3091 ext4_update_inode_fsync_trans(handle, inode, 1);
3088out: 3092out:
3089 if (ret <= 0) { 3093 if (ret <= 0) {
3090 err = ret; 3094 err = ret;
@@ -3323,10 +3327,16 @@ int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
3323 allocated = ext4_ext_get_actual_len(&newex); 3327 allocated = ext4_ext_get_actual_len(&newex);
3324 set_buffer_new(bh_result); 3328 set_buffer_new(bh_result);
3325 3329
3326 /* Cache only when it is _not_ an uninitialized extent */ 3330 /*
3327 if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) 3331 * Cache the extent and update transaction to commit on fdatasync only
3332 * when it is _not_ an uninitialized extent.
3333 */
3334 if ((flags & EXT4_GET_BLOCKS_UNINIT_EXT) == 0) {
3328 ext4_ext_put_in_cache(inode, iblock, allocated, newblock, 3335 ext4_ext_put_in_cache(inode, iblock, allocated, newblock,
3329 EXT4_EXT_CACHE_EXTENT); 3336 EXT4_EXT_CACHE_EXTENT);
3337 ext4_update_inode_fsync_trans(handle, inode, 1);
3338 } else
3339 ext4_update_inode_fsync_trans(handle, inode, 0);
3330out: 3340out:
3331 if (allocated > max_blocks) 3341 if (allocated > max_blocks)
3332 allocated = max_blocks; 3342 allocated = max_blocks;