Update propagate-errors-up-to-ext4_find_entry-s-callers to define
[ext4-patch-queue.git] / fix-transaction-issues-for-ext4_fallocate-and-ext_zero_range
blobae64883973796c72edcf20ce2a33d4a657875973
1 ext4: fix transaction issues for ext4_fallocate and ext_zero_range
3 From: Dmitry Monakhov <dmonakhov@openvz.org>
5 After commit f282ac19d86f we use different transactions for preallocation
6 and i_disksize update which result in complain from fsck after power-failure.
7 spotted by generic/019. IMHO this is regression because fs becomes inconsistent,
8 even more 'e2fsck -p' will no longer works (which drives admins go crazy)
9 Same transaction requirement applies ctime,mtime updates
11 testcase: xfstest generic/019
13 Cc: stable@vger.kernel.org # v3.15+
14 Fixes: f282ac19d86f0507e91759dcf3d15fcb3a964d2a
15 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
16 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
17 diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
18 index f0e6934..510f61b 100644
19 --- a/fs/ext4/extents.c
20 +++ b/fs/ext4/extents.c
21 @@ -4665,7 +4665,8 @@ retry:
22  }
24  static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
25 -                                 ext4_lblk_t len, int flags, int mode)
26 +                                 ext4_lblk_t len, loff_t new_size,
27 +                                 int flags, int mode)
28  {
29         struct inode *inode = file_inode(file);
30         handle_t *handle;
31 @@ -4674,8 +4675,10 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
32         int retries = 0;
33         struct ext4_map_blocks map;
34         unsigned int credits;
35 +       loff_t epos;
37         map.m_lblk = offset;
38 +       map.m_len = len;
39         /*
40          * Don't normalize the request if it can fit in one extent so
41          * that it doesn't get unnecessarily split into multiple
42 @@ -4690,9 +4693,7 @@ static int ext4_alloc_file_blocks(struct file *file, ext4_lblk_t offset,
43         credits = ext4_chunk_trans_blocks(inode, len);
45  retry:
46 -       while (ret >= 0 && ret < len) {
47 -               map.m_lblk = map.m_lblk + ret;
48 -               map.m_len = len = len - ret;
49 +       while (ret >= 0 && len) {
50                 handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
51                                             credits);
52                 if (IS_ERR(handle)) {
53 @@ -4709,6 +4710,21 @@ retry:
54                         ret2 = ext4_journal_stop(handle);
55                         break;
56                 }
57 +               map.m_lblk += ret;
58 +               map.m_len = len = len - ret;
59 +               epos = (loff_t)map.m_lblk << inode->i_blkbits;
60 +               inode->i_ctime = ext4_current_time(inode);
61 +               if (new_size) {
62 +                       if (epos > new_size)
63 +                               epos = new_size;
64 +                       if (ext4_update_inode_size(inode, epos) & 0x1)
65 +                               inode->i_mtime = inode->i_ctime;
66 +               } else {
67 +                       if (epos > inode->i_size)
68 +                               ext4_set_inode_flag(inode,
69 +                                                   EXT4_INODE_EOFBLOCKS);
70 +               }
71 +               ext4_mark_inode_dirty(handle, inode);
72                 ret2 = ext4_journal_stop(handle);
73                 if (ret2)
74                         break;
75 @@ -4731,7 +4747,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
76         loff_t new_size = 0;
77         int ret = 0;
78         int flags;
79 -       int partial;
80 +       int partial_begin, partial_end;
81         loff_t start, end;
82         ext4_lblk_t lblk;
83         struct address_space *mapping = inode->i_mapping;
84 @@ -4771,7 +4787,8 @@ static long ext4_zero_range(struct file *file, loff_t offset,
86         if (start < offset || end > offset + len)
87                 return -EINVAL;
88 -       partial = (offset + len) & ((1 << blkbits) - 1);
89 +       partial_begin = offset & ((1 << blkbits) - 1);
90 +       partial_end = (offset + len) & ((1 << blkbits) - 1);
92         lblk = start >> blkbits;
93         max_blocks = (end >> blkbits);
94 @@ -4805,7 +4822,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
95                  * If we have a partial block after EOF we have to allocate
96                  * the entire block.
97                  */
98 -               if (partial)
99 +               if (partial_end)
100                         max_blocks += 1;
101         }
103 @@ -4813,6 +4830,7 @@ static long ext4_zero_range(struct file *file, loff_t offset,
105                 /* Now release the pages and zero block aligned part of pages*/
106                 truncate_pagecache_range(inode, start, end - 1);
107 +               inode->i_mtime = inode->i_ctime = ext4_current_time(inode);
109                 /* Wait all existing dio workers, newcomers will block on i_mutex */
110                 ext4_inode_block_unlocked_dio(inode);
111 @@ -4825,11 +4843,13 @@ static long ext4_zero_range(struct file *file, loff_t offset,
112                 if (ret)
113                         goto out_dio;
115 -               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, flags,
116 -                                            mode);
117 +               ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
118 +                                            flags, mode);
119                 if (ret)
120                         goto out_dio;
121         }
122 +       if (!partial_begin && !partial_end)
123 +               goto out_dio;
125         handle = ext4_journal_start(inode, EXT4_HT_MISC, 4);
126         if (IS_ERR(handle)) {
127 @@ -4849,7 +4869,6 @@ static long ext4_zero_range(struct file *file, loff_t offset,
128                 if ((offset + len) > i_size_read(inode))
129                         ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
130         }
132         ext4_mark_inode_dirty(handle, inode);
134         /* Zero out partial block at the edges of the range */
135 @@ -4876,7 +4895,6 @@ out_mutex:
136  long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
138         struct inode *inode = file_inode(file);
139 -       handle_t *handle;
140         loff_t new_size = 0;
141         unsigned int max_blocks;
142         int ret = 0;
143 @@ -4932,32 +4950,15 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
144                         goto out;
145         }
147 -       ret = ext4_alloc_file_blocks(file, lblk, max_blocks, flags, mode);
148 +       ret = ext4_alloc_file_blocks(file, lblk, max_blocks, new_size,
149 +                                    flags, mode);
150         if (ret)
151                 goto out;
153 -       handle = ext4_journal_start(inode, EXT4_HT_INODE, 2);
154 -       if (IS_ERR(handle))
155 -               goto out;
157 -       inode->i_ctime = ext4_current_time(inode);
159 -       if (new_size) {
160 -               if (ext4_update_inode_size(inode, new_size) & 0x1)
161 -                       inode->i_mtime = inode->i_ctime;
162 -       } else {
163 -               /*
164 -               * Mark that we allocate beyond EOF so the subsequent truncate
165 -               * can proceed even if the new size is the same as i_size.
166 -               */
167 -               if ((offset + len) > i_size_read(inode))
168 -                       ext4_set_inode_flag(inode, EXT4_INODE_EOFBLOCKS);
169 +       if (file->f_flags & O_SYNC && EXT4_SB(inode->i_sb)->s_journal) {
170 +               ret = jbd2_complete_transaction(EXT4_SB(inode->i_sb)->s_journal,
171 +                                               EXT4_I(inode)->i_sync_tid);
172         }
173 -       ext4_mark_inode_dirty(handle, inode);
174 -       if (file->f_flags & O_SYNC)
175 -               ext4_handle_sync(handle);
177 -       ext4_journal_stop(handle);
178  out:
179         mutex_unlock(&inode->i_mutex);
180         trace_ext4_fallocate_exit(inode, offset, max_blocks, ret);