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 io->flag |= EXT4_IO_END_IN_FSYNC;
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
108 ret = ext4_end_io_nolock(io);
109 if (ret < 0)
110 ret2 = ret;
111 spin_lock_irqsave(&ei->i_completed_io_lock, flags);
112 io->flag &= ~EXT4_IO_END_IN_FSYNC;
113 }
114 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
115 return (ret2 < 0) ? ret2 : 0;
116}
117
118
119
120
121
122
123
124
125
126static int ext4_sync_parent(struct inode *inode)
127{
128 struct writeback_control wbc;
129 struct dentry *dentry = NULL;
130 struct inode *next;
131 int ret = 0;
132
133 if (!ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY))
134 return 0;
135 inode = igrab(inode);
136 while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
137 ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
138 dentry = NULL;
139 spin_lock(&inode->i_lock);
140 if (!list_empty(&inode->i_dentry)) {
141 dentry = list_first_entry(&inode->i_dentry,
142 struct dentry, d_alias);
143 dget(dentry);
144 }
145 spin_unlock(&inode->i_lock);
146 if (!dentry)
147 break;
148 next = igrab(dentry->d_parent->d_inode);
149 dput(dentry);
150 if (!next)
151 break;
152 iput(inode);
153 inode = next;
154 ret = sync_mapping_buffers(inode->i_mapping);
155 if (ret)
156 break;
157 memset(&wbc, 0, sizeof(wbc));
158 wbc.sync_mode = WB_SYNC_ALL;
159 wbc.nr_to_write = 0;
160 ret = sync_inode(inode, &wbc);
161 if (ret)
162 break;
163 }
164 iput(inode);
165 return ret;
166}
167
168
169
170
171
172
173
174
175
176
177static int __sync_inode(struct inode *inode, int datasync)
178{
179 int err;
180 int ret;
181
182 ret = sync_mapping_buffers(inode->i_mapping);
183 if (!(inode->i_state & I_DIRTY))
184 return ret;
185 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
186 return ret;
187
188 err = sync_inode_metadata(inode, 1);
189 if (ret == 0)
190 ret = err;
191 return ret;
192}
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
209{
210 struct inode *inode = file->f_mapping->host;
211 struct ext4_inode_info *ei = EXT4_I(inode);
212 journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
213 int ret;
214 tid_t commit_tid;
215 bool needs_barrier = false;
216
217 J_ASSERT(ext4_journal_current_handle() == NULL);
218
219 trace_ext4_sync_file_enter(file, datasync);
220
221 ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
222 if (ret)
223 return ret;
224 mutex_lock(&inode->i_mutex);
225
226 if (inode->i_sb->s_flags & MS_RDONLY)
227 goto out;
228
229 ret = ext4_flush_completed_IO(inode);
230 if (ret < 0)
231 goto out;
232
233 if (!journal) {
234 ret = __sync_inode(inode, datasync);
235 if (!ret && !list_empty(&inode->i_dentry))
236 ret = ext4_sync_parent(inode);
237 goto out;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254 if (ext4_should_journal_data(inode)) {
255 ret = ext4_force_commit(inode->i_sb);
256 goto out;
257 }
258
259 commit_tid = datasync ? ei->i_datasync_tid : ei->i_sync_tid;
260 if (journal->j_flags & JBD2_BARRIER &&
261 !jbd2_trans_will_send_data_barrier(journal, commit_tid))
262 needs_barrier = true;
263 jbd2_log_start_commit(journal, commit_tid);
264 ret = jbd2_log_wait_commit(journal, commit_tid);
265 if (needs_barrier)
266 blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL);
267 out:
268 mutex_unlock(&inode->i_mutex);
269 trace_ext4_sync_file_exit(inode, ret);
270 return ret;
271}
272