add patch make-fsync-to-sync-parent-dir-in-no-journal-for-real-this-time
[ext4-patch-queue.git] / make-fsync-to-sync-parent-dir-in-no-journal-for-real-this-time
blob6def50b70a4da968c22aba590d39b6fd84e2ff3f
1 ext4: make fsync to sync parent dir in no-journal for real this time
3 From: Lukas Czerner <lczerner@redhat.com>
5 Previously commit 14ece1028b3ed53ffec1b1213ffc6acaf79ad77c added a
6 support for for syncing parent directory of newly created inodes to
7 make sure that the inode is not lost after a power failure in
8 no-journal mode.
10 However this does not work in majority of cases, namely:
11  - if the directory has inline data
12  - if the directory is already indexed
13  - if the directory already has at least one block and:
14         - the new entry fits into it
15         - or we've successfully converted it to indexed
17 So in those cases we might lose the inode entirely even after fsync in
18 the no-journal mode. This also includes ext2 default mode obviously.
20 I've noticed this while running xfstest generic/321 and even though the
21 test should fail (we need to run fsck after a crash in no-journal mode)
22 I could not find a newly created entries even when if it was fsynced
23 before.
25 Fix this by adjusting the ext4_add_entry() successful exit paths to set
26 the inode EXT4_STATE_NEWENTRY so that fsync has the chance to fsync the
27 parent directory as well.
29 Signed-off-by: Lukas Czerner <lczerner@redhat.com>
30 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
31 Reviewed-by: Jan Kara <jack@suse.cz>
32 Cc: Frank Mayhar <fmayhar@google.com>
33 Cc: stable@vger.kernel.org
34 ---
35  fs/ext4/namei.c | 19 ++++++++++---------
36  1 file changed, 10 insertions(+), 9 deletions(-)
38 diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
39 index 2291923..25e1e03 100644
40 --- a/fs/ext4/namei.c
41 +++ b/fs/ext4/namei.c
42 @@ -1865,7 +1865,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
43                           struct inode *inode)
44  {
45         struct inode *dir = dentry->d_parent->d_inode;
46 -       struct buffer_head *bh;
47 +       struct buffer_head *bh = NULL;
48         struct ext4_dir_entry_2 *de;
49         struct ext4_dir_entry_tail *t;
50         struct super_block *sb;
51 @@ -1889,14 +1889,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
52                         return retval;
53                 if (retval == 1) {
54                         retval = 0;
55 -                       return retval;
56 +                       goto out;
57                 }
58         }
60         if (is_dx(dir)) {
61                 retval = ext4_dx_add_entry(handle, dentry, inode);
62                 if (!retval || (retval != ERR_BAD_DX_DIR))
63 -                       return retval;
64 +                       goto out;
65                 ext4_clear_inode_flag(dir, EXT4_INODE_INDEX);
66                 dx_fallback++;
67                 ext4_mark_inode_dirty(handle, dir);
68 @@ -1908,14 +1908,14 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
69                         return PTR_ERR(bh);
71                 retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh);
72 -               if (retval != -ENOSPC) {
73 -                       brelse(bh);
74 -                       return retval;
75 -               }
76 +               if (retval != -ENOSPC)
77 +                       goto out;
79                 if (blocks == 1 && !dx_fallback &&
80 -                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX))
81 -                       return make_indexed_dir(handle, dentry, inode, bh);
82 +                   EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_DIR_INDEX)) {
83 +                       retval = make_indexed_dir(handle, dentry, inode, bh);
84 +                       goto out;
85 +               }
86                 brelse(bh);
87         }
88         bh = ext4_append(handle, dir, &block);
89 @@ -1931,6 +1931,7 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
90         }
92         retval = add_dirent_to_buf(handle, dentry, inode, de, bh);
93 +out:
94         brelse(bh);
95         if (retval == 0)
96                 ext4_set_inode_state(inode, EXT4_STATE_NEWENTRY);
97 -- 
98 1.8.3.1
101 To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
102 the body of a message to majordomo@vger.kernel.org
103 More majordomo info at  http://vger.kernel.org/majordomo-info.html