aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2013-08-16 22:06:53 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-08-16 22:06:53 -0400
commit0e20270454e45ff54c9f8546159924038e31bfa0 (patch)
tree6fa4fded382ea053ec6ef1d87ec83013a8037e11 /fs/ext4
parent5b61de757535095c99212c1ed857c3a0e0bbe386 (diff)
ext4: allocate delayed allocation blocks before rename
When ext4_rename() overwrites an already existing file, call ext4_alloc_da_blocks() before starting the journal handle which actually does the rename, instead of doing this afterwards. This improves the likelihood that the contents will survive a crash if an application replaces a file using the sequence: 1) write replacement contents to foo.new 2) <omit fsync of foo.new> 3) rename foo.new to foo It is still not a guarantee, since ext4_alloc_da_blocks() is *not* doing a file integrity sync; this means if foo.new is a very large file, it may not be completely flushed out to disk. However, for files smaller than a megabyte or so, any dirty pages should be flushed out before we do the rename operation, and so at the next journal commit, the CACHE FLUSH command will make sure al of these pages are safely on the disk platter. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/namei.c12
1 files changed, 7 insertions, 5 deletions
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index d9b721c172a6..1bec5a5c1e45 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3005,6 +3005,10 @@ static struct buffer_head *ext4_get_first_dir_block(handle_t *handle,
3005/* 3005/*
3006 * Anybody can rename anything with this: the permission checks are left to the 3006 * Anybody can rename anything with this: the permission checks are left to the
3007 * higher-level routines. 3007 * higher-level routines.
3008 *
3009 * n.b. old_{dentry,inode) refers to the source dentry/inode
3010 * while new_{dentry,inode) refers to the destination dentry/inode
3011 * This comes from rename(const char *oldpath, const char *newpath)
3008 */ 3012 */
3009static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, 3013static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3010 struct inode *new_dir, struct dentry *new_dentry) 3014 struct inode *new_dir, struct dentry *new_dentry)
@@ -3013,7 +3017,7 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3013 struct inode *old_inode, *new_inode; 3017 struct inode *old_inode, *new_inode;
3014 struct buffer_head *old_bh, *new_bh, *dir_bh; 3018 struct buffer_head *old_bh, *new_bh, *dir_bh;
3015 struct ext4_dir_entry_2 *old_de, *new_de; 3019 struct ext4_dir_entry_2 *old_de, *new_de;
3016 int retval, force_da_alloc = 0; 3020 int retval;
3017 int inlined = 0, new_inlined = 0; 3021 int inlined = 0, new_inlined = 0;
3018 struct ext4_dir_entry_2 *parent_de; 3022 struct ext4_dir_entry_2 *parent_de;
3019 3023
@@ -3048,6 +3052,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3048 new_bh = NULL; 3052 new_bh = NULL;
3049 } 3053 }
3050 } 3054 }
3055 if (new_inode && !test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
3056 ext4_alloc_da_blocks(old_inode);
3051 3057
3052 handle = ext4_journal_start(old_dir, EXT4_HT_DIR, 3058 handle = ext4_journal_start(old_dir, EXT4_HT_DIR,
3053 (2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) + 3059 (2 * EXT4_DATA_TRANS_BLOCKS(old_dir->i_sb) +
@@ -3188,8 +3194,6 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry,
3188 ext4_mark_inode_dirty(handle, new_inode); 3194 ext4_mark_inode_dirty(handle, new_inode);
3189 if (!new_inode->i_nlink) 3195 if (!new_inode->i_nlink)
3190 ext4_orphan_add(handle, new_inode); 3196 ext4_orphan_add(handle, new_inode);
3191 if (!test_opt(new_dir->i_sb, NO_AUTO_DA_ALLOC))
3192 force_da_alloc = 1;
3193 } 3197 }
3194 retval = 0; 3198 retval = 0;
3195 3199
@@ -3199,8 +3203,6 @@ end_rename:
3199 brelse(new_bh); 3203 brelse(new_bh);
3200 if (handle) 3204 if (handle)
3201 ext4_journal_stop(handle); 3205 ext4_journal_stop(handle);
3202 if (retval == 0 && force_da_alloc)
3203 ext4_alloc_da_blocks(old_inode);
3204 return retval; 3206 return retval;
3205} 3207}
3206 3208