1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include <linux/time.h>
26#include <linux/fs.h>
27#include <linux/sched.h>
28#include <linux/writeback.h>
29#include <linux/jbd2.h>
30#include <linux/blkdev.h>
31
32#include "ext4.h"
33#include "ext4_jbd2.h"
34
35#include <trace/events/ext4.h>
36
37static void dump_completed_IO(struct inode * inode)
38{
39#ifdef EXT4FS_DEBUG
40 struct list_head *cur, *before, *after;
41 ext4_io_end_t *io, *io0, *io1;
42 unsigned long flags;
43
44 if (list_empty(&EXT4_I(inode)->i_completed_io_list)){
45 ext4_debug("inode %lu completed_io list is empty\n", inode->i_ino);
46 return;
47 }
48
49 ext4_debug("Dump inode %lu completed_io list \n", inode->i_ino);
50 spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
51 list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list){
52 cur = &io->list;
53 before = cur->prev;
54 io0 = container_of(before, ext4_io_end_t, list);
55 after = cur->next;
56 io1 = container_of(after, ext4_io_end_t, list);
57
58 ext4_debug("io 0x%p from inode %lu,prev 0x%p,next 0x%p\n",
59 io, inode->i_ino, io0, io1);
60 }
61 spin_unlock_irqrestore(&EXT4_I(inode)->i_completed_io_lock, flags);
62#endif
63}
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78int ext4_flush_completed_IO(struct inode *inode)
79{
80 ext4_io_end_t *io;
81 struct ext4_inode_info *ei = EXT4_I(inode);
82 unsigned long flags;
83 int ret = 0;
84 int ret2 = 0;
85
86 dump_completed_IO(inode);
87 spin_lock_irqsave(&ei->i_completed_io_lock, flags);
88 while (!list_empty(&ei->i_completed_io_list)){
89 io = list_entry(ei->i_completed_io_list.next,
90 ext4_io_end_t, list);
91 list_del_init(&io->list);
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
107 ret = ext4_end_io_nolock(io);
108 if (ret < 0)
109 ret2 = ret;
110 spin_lock_irqsave(&ei->i_completed_io_lock, flags);
111 }
112 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
113 return (ret2 < 0) ? ret2 : 0;
114}
115
116
117
118
119
120
121
122
123
124static int ext4_sync_parent(struct inode *inode)
125{
126 struct writeback_control wbc;
127 struct dentry *dentry = NULL;
128 struct inode *next;
129 int ret = 0;
130
131 if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
132 return 0;
133 inode = igrab(inode);
134 while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
135 ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
136 dentry = NULL;
137 spin_lock(&inode->i_lock);
138 if (!list_empty(&inode->i_dentry)) {
139 dentry = list_first_entry(&inode->i_dentry,
140 struct dentry, d_alias);
141 dget(dentry);
142 }
143 spin_unlock(&inode->i_lock);
144 if (!dentry)
145 break;
146 next = igrab(dentry->d_parent->d_inode);
147 dput(dentry);
148 if (!next)
149 break;
150 iput(inode);
151 inode = next;
152 ret = sync_mapping_buffers(inode->i_mapping);
153 if (ret)
154 break;
155 memset(&wbc, 0, sizeof(wbc));
156 wbc.sync_mode = WB_SYNC_ALL;
157 wbc.nr_to_write = 0;
158 ret = sync_inode(inode, &wbc);
159 if (ret)
160 break;
161 }
162 iput(inode);
163 return ret;
164}
165
166
167
168
169
170
171
172
173
174
175static int __sync_inode(struct inode *inode, int datasync)
176{
177 int err;
178 int ret;
179
180 ret = sync_mapping_buffers(inode->i_mapping);
181 if (!(inode->i_state & I_DIRTY))
182 return ret;
183 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
184 return ret;
185
186 err = sync_inode_metadata(inode, 1);
187 if (ret == 0)
188 ret = err;
189 return ret;
190}
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
207{
208 struct inode *inode = file->f_mapping->host;
209 struct ext4_inode_info *ei = EXT4_I(inode);
210 journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
211 int ret;
212 tid_t commit_tid;
213 bool needs_barrier = false;
214
215 J_ASSERT(ext4_journal_current_handle() == NULL);
216
217 trace_ext4_sync_file_enter(file, datasync);
218
219 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
220 if (ret)
221 return ret;
222 mutex_lock(&inode->i_mutex);
223
224 if (inode->i_sb->s_flags & MS_RDONLY)
225 goto out;
226
227 ret = ext4_flush_completed_IO(inode);
228 if (ret < 0)
229 goto out;
230
231 if (!journal) {
232 ret = __sync_inode(inode, datasync);
233 if (!ret && !list_empty(&inode->i_dentry))
234 ret = ext4_sync_parent(inode);
235 goto out;
236 }
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252 if (ext4_should_journal_data(inode)) {
253 ret = ext4_force_commit(inode->i_sb);
254 goto out;
255 }
256
257 commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
258 if (journal->j_flags & JBD2_BARRIER &&
259 !jbd2_trans_will_send_data_barrier(journal, commit_tid))
260 needs_barrier = true;
261 jbd2_log_start_commit(journal, commit_tid);
262 ret = jbd2_log_wait_commit(journal, commit_tid);
263 if (needs_barrier)
264 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
265 out:
266 mutex_unlock(&inode->i_mutex);
267 trace_ext4_sync_file_exit(inode, ret);
268 return ret;
269}
270