1
2
3
4
5#include <linux/kernel.h>
6#include <linux/file.h>
7#include <linux/fs.h>
8#include <linux/slab.h>
9#include <linux/export.h>
10#include <linux/namei.h>
11#include <linux/sched.h>
12#include <linux/writeback.h>
13#include <linux/syscalls.h>
14#include <linux/linkage.h>
15#include <linux/pagemap.h>
16#include <linux/quotaops.h>
17#include <linux/backing-dev.h>
18#include "internal.h"
19
20#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
21 SYNC_FILE_RANGE_WAIT_AFTER)
22
23
24
25
26
27
28
29
30static int __sync_filesystem(struct super_block *sb, int wait)
31{
32 if (wait)
33 sync_inodes_sb(sb);
34 else
35 writeback_inodes_sb(sb, WB_REASON_SYNC);
36
37 if (sb->s_op->sync_fs)
38 sb->s_op->sync_fs(sb, wait);
39 return __sync_blockdev(sb->s_bdev, wait);
40}
41
42
43
44
45
46
47int sync_filesystem(struct super_block *sb)
48{
49 int ret;
50
51
52
53
54
55 WARN_ON(!rwsem_is_locked(&sb->s_umount));
56
57
58
59
60 if (sb->s_flags & MS_RDONLY)
61 return 0;
62
63 ret = __sync_filesystem(sb, 0);
64 if (ret < 0)
65 return ret;
66 return __sync_filesystem(sb, 1);
67}
68EXPORT_SYMBOL(sync_filesystem);
69
70static void sync_inodes_one_sb(struct super_block *sb, void *arg)
71{
72 if (!(sb->s_flags & MS_RDONLY))
73 sync_inodes_sb(sb);
74}
75
76static void sync_fs_one_sb(struct super_block *sb, void *arg)
77{
78 if (!(sb->s_flags & MS_RDONLY) && sb->s_op->sync_fs)
79 sb->s_op->sync_fs(sb, *(int *)arg);
80}
81
82static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
83{
84 filemap_fdatawrite(bdev->bd_inode->i_mapping);
85}
86
87static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
88{
89
90
91
92
93
94 filemap_fdatawait_keep_errors(bdev->bd_inode->i_mapping);
95}
96
97
98
99
100
101
102
103
104
105
106
107SYSCALL_DEFINE0(sync)
108{
109 int nowait = 0, wait = 1;
110
111 wakeup_flusher_threads(0, WB_REASON_SYNC);
112 iterate_supers(sync_inodes_one_sb, NULL);
113 iterate_supers(sync_fs_one_sb, &nowait);
114 iterate_supers(sync_fs_one_sb, &wait);
115 iterate_bdevs(fdatawrite_one_bdev, NULL);
116 iterate_bdevs(fdatawait_one_bdev, NULL);
117 if (unlikely(laptop_mode))
118 laptop_sync_completion();
119 return 0;
120}
121
122static void do_sync_work(struct work_struct *work)
123{
124 int nowait = 0;
125
126
127
128
129
130 iterate_supers(sync_inodes_one_sb, &nowait);
131 iterate_supers(sync_fs_one_sb, &nowait);
132 iterate_bdevs(fdatawrite_one_bdev, NULL);
133 iterate_supers(sync_inodes_one_sb, &nowait);
134 iterate_supers(sync_fs_one_sb, &nowait);
135 iterate_bdevs(fdatawrite_one_bdev, NULL);
136 printk("Emergency Sync complete\n");
137 kfree(work);
138}
139
140void emergency_sync(void)
141{
142 struct work_struct *work;
143
144 work = kmalloc(sizeof(*work), GFP_ATOMIC);
145 if (work) {
146 INIT_WORK(work, do_sync_work);
147 schedule_work(work);
148 }
149}
150
151
152
153
154SYSCALL_DEFINE1(syncfs, int, fd)
155{
156 struct fd f = fdget(fd);
157 struct super_block *sb;
158 int ret;
159
160 if (!f.file)
161 return -EBADF;
162 sb = f.file->f_path.dentry->d_sb;
163
164 down_read(&sb->s_umount);
165 ret = sync_filesystem(sb);
166 up_read(&sb->s_umount);
167
168 fdput(f);
169 return ret;
170}
171
172
173
174
175
176
177
178
179
180
181
182
183int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
184{
185 struct inode *inode = file->f_mapping->host;
186
187 if (!file->f_op->fsync)
188 return -EINVAL;
189 if (!datasync && (inode->i_state & I_DIRTY_TIME)) {
190 spin_lock(&inode->i_lock);
191 inode->i_state &= ~I_DIRTY_TIME;
192 spin_unlock(&inode->i_lock);
193 mark_inode_dirty_sync(inode);
194 }
195 return file->f_op->fsync(file, start, end, datasync);
196}
197EXPORT_SYMBOL(vfs_fsync_range);
198
199
200
201
202
203
204
205
206
207int vfs_fsync(struct file *file, int datasync)
208{
209 return vfs_fsync_range(file, 0, LLONG_MAX, datasync);
210}
211EXPORT_SYMBOL(vfs_fsync);
212
213static int do_fsync(unsigned int fd, int datasync)
214{
215 struct fd f = fdget(fd);
216 int ret = -EBADF;
217
218 if (f.file) {
219 ret = vfs_fsync(f.file, datasync);
220 fdput(f);
221 }
222 return ret;
223}
224
225SYSCALL_DEFINE1(fsync, unsigned int, fd)
226{
227 return do_fsync(fd, 0);
228}
229
230SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
231{
232 return do_fsync(fd, 1);
233}
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
283 unsigned int, flags)
284{
285 int ret;
286 struct fd f;
287 struct address_space *mapping;
288 loff_t endbyte;
289 umode_t i_mode;
290
291 ret = -EINVAL;
292 if (flags & ~VALID_FLAGS)
293 goto out;
294
295 endbyte = offset + nbytes;
296
297 if ((s64)offset < 0)
298 goto out;
299 if ((s64)endbyte < 0)
300 goto out;
301 if (endbyte < offset)
302 goto out;
303
304 if (sizeof(pgoff_t) == 4) {
305 if (offset >= (0x100000000ULL << PAGE_SHIFT)) {
306
307
308
309
310 ret = 0;
311 goto out;
312 }
313 if (endbyte >= (0x100000000ULL << PAGE_SHIFT)) {
314
315
316
317 nbytes = 0;
318 }
319 }
320
321 if (nbytes == 0)
322 endbyte = LLONG_MAX;
323 else
324 endbyte--;
325
326 ret = -EBADF;
327 f = fdget(fd);
328 if (!f.file)
329 goto out;
330
331 i_mode = file_inode(f.file)->i_mode;
332 ret = -ESPIPE;
333 if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
334 !S_ISLNK(i_mode))
335 goto out_put;
336
337 mapping = f.file->f_mapping;
338 if (!mapping) {
339 ret = -EINVAL;
340 goto out_put;
341 }
342
343 ret = 0;
344 if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
345 ret = filemap_fdatawait_range(mapping, offset, endbyte);
346 if (ret < 0)
347 goto out_put;
348 }
349
350 if (flags & SYNC_FILE_RANGE_WRITE) {
351 ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
352 WB_SYNC_NONE);
353 if (ret < 0)
354 goto out_put;
355 }
356
357 if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
358 ret = filemap_fdatawait_range(mapping, offset, endbyte);
359
360out_put:
361 fdput(f);
362out:
363 return ret;
364}
365
366
367
368SYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags,
369 loff_t, offset, loff_t, nbytes)
370{
371 return sys_sync_file_range(fd, offset, nbytes, flags);
372}
373