1
2
3
4
5#include <linux/kernel.h>
6#include <linux/file.h>
7#include <linux/fs.h>
8#include <linux/module.h>
9#include <linux/sched.h>
10#include <linux/writeback.h>
11#include <linux/syscalls.h>
12#include <linux/linkage.h>
13#include <linux/pagemap.h>
14#include <linux/quotaops.h>
15#include <linux/buffer_head.h>
16#include "internal.h"
17
18#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
19 SYNC_FILE_RANGE_WAIT_AFTER)
20
21
22
23
24
25
26
27
28static int __sync_filesystem(struct super_block *sb, int wait)
29{
30
31
32
33
34 if (!sb->s_bdi)
35 return 0;
36
37
38 if (!wait) {
39 writeout_quota_sb(sb, -1);
40 writeback_inodes_sb(sb);
41 } else {
42 sync_quota_sb(sb, -1);
43 sync_inodes_sb(sb);
44 }
45 if (sb->s_op->sync_fs)
46 sb->s_op->sync_fs(sb, wait);
47 return __sync_blockdev(sb->s_bdev, wait);
48}
49
50
51
52
53
54
55int sync_filesystem(struct super_block *sb)
56{
57 int ret;
58
59
60
61
62
63 WARN_ON(!rwsem_is_locked(&sb->s_umount));
64
65
66
67
68 if (sb->s_flags & MS_RDONLY)
69 return 0;
70
71 ret = __sync_filesystem(sb, 0);
72 if (ret < 0)
73 return ret;
74 return __sync_filesystem(sb, 1);
75}
76EXPORT_SYMBOL_GPL(sync_filesystem);
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92static void sync_filesystems(int wait)
93{
94 struct super_block *sb;
95 static DEFINE_MUTEX(mutex);
96
97 mutex_lock(&mutex);
98 spin_lock(&sb_lock);
99 list_for_each_entry(sb, &super_blocks, s_list)
100 sb->s_need_sync = 1;
101
102restart:
103 list_for_each_entry(sb, &super_blocks, s_list) {
104 if (!sb->s_need_sync)
105 continue;
106 sb->s_need_sync = 0;
107 sb->s_count++;
108 spin_unlock(&sb_lock);
109
110 down_read(&sb->s_umount);
111 if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
112 __sync_filesystem(sb, wait);
113 up_read(&sb->s_umount);
114
115
116 spin_lock(&sb_lock);
117 if (__put_super_and_need_restart(sb))
118 goto restart;
119 }
120 spin_unlock(&sb_lock);
121 mutex_unlock(&mutex);
122}
123
124
125
126
127
128SYSCALL_DEFINE0(sync)
129{
130 wakeup_flusher_threads(0);
131 sync_filesystems(0);
132 sync_filesystems(1);
133 if (unlikely(laptop_mode))
134 laptop_sync_completion();
135 return 0;
136}
137
138static void do_sync_work(struct work_struct *work)
139{
140
141
142
143
144 sync_filesystems(0);
145 sync_filesystems(0);
146 printk("Emergency Sync complete\n");
147 kfree(work);
148}
149
150void emergency_sync(void)
151{
152 struct work_struct *work;
153
154 work = kmalloc(sizeof(*work), GFP_ATOMIC);
155 if (work) {
156 INIT_WORK(work, do_sync_work);
157 schedule_work(work);
158 }
159}
160
161
162
163
164
165
166int file_fsync(struct file *filp, struct dentry *dentry, int datasync)
167{
168 struct inode * inode = dentry->d_inode;
169 struct super_block * sb;
170 int ret, err;
171
172
173 ret = write_inode_now(inode, 0);
174
175
176 sb = inode->i_sb;
177 if (sb->s_dirt && sb->s_op->write_super)
178 sb->s_op->write_super(sb);
179
180
181 err = sync_blockdev(sb->s_bdev);
182 if (!ret)
183 ret = err;
184 return ret;
185}
186EXPORT_SYMBOL(file_fsync);
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204int vfs_fsync_range(struct file *file, struct dentry *dentry, loff_t start,
205 loff_t end, int datasync)
206{
207 const struct file_operations *fop;
208 struct address_space *mapping;
209 int err, ret;
210
211
212
213
214
215
216 if (file) {
217 mapping = file->f_mapping;
218 fop = file->f_op;
219 } else {
220 mapping = dentry->d_inode->i_mapping;
221 fop = dentry->d_inode->i_fop;
222 }
223
224 if (!fop || !fop->fsync) {
225 ret = -EINVAL;
226 goto out;
227 }
228
229 ret = filemap_write_and_wait_range(mapping, start, end);
230
231
232
233
234
235 mutex_lock(&mapping->host->i_mutex);
236 err = fop->fsync(file, dentry, datasync);
237 if (!ret)
238 ret = err;
239 mutex_unlock(&mapping->host->i_mutex);
240
241out:
242 return ret;
243}
244EXPORT_SYMBOL(vfs_fsync_range);
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259int vfs_fsync(struct file *file, struct dentry *dentry, int datasync)
260{
261 return vfs_fsync_range(file, dentry, 0, LLONG_MAX, datasync);
262}
263EXPORT_SYMBOL(vfs_fsync);
264
265static int do_fsync(unsigned int fd, int datasync)
266{
267 struct file *file;
268 int ret = -EBADF;
269
270 file = fget(fd);
271 if (file) {
272 ret = vfs_fsync(file, file->f_path.dentry, datasync);
273 fput(file);
274 }
275 return ret;
276}
277
278SYSCALL_DEFINE1(fsync, unsigned int, fd)
279{
280 return do_fsync(fd, 0);
281}
282
283SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
284{
285 return do_fsync(fd, 1);
286}
287
288
289
290
291
292
293
294
295
296int generic_write_sync(struct file *file, loff_t pos, loff_t count)
297{
298 if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host))
299 return 0;
300 return vfs_fsync_range(file, file->f_path.dentry, pos,
301 pos + count - 1, 1);
302}
303EXPORT_SYMBOL(generic_write_sync);
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
353 unsigned int flags)
354{
355 int ret;
356 struct file *file;
357 loff_t endbyte;
358 int fput_needed;
359 umode_t i_mode;
360
361 ret = -EINVAL;
362 if (flags & ~VALID_FLAGS)
363 goto out;
364
365 endbyte = offset + nbytes;
366
367 if ((s64)offset < 0)
368 goto out;
369 if ((s64)endbyte < 0)
370 goto out;
371 if (endbyte < offset)
372 goto out;
373
374 if (sizeof(pgoff_t) == 4) {
375 if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
376
377
378
379
380 ret = 0;
381 goto out;
382 }
383 if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
384
385
386
387 nbytes = 0;
388 }
389 }
390
391 if (nbytes == 0)
392 endbyte = LLONG_MAX;
393 else
394 endbyte--;
395
396 ret = -EBADF;
397 file = fget_light(fd, &fput_needed);
398 if (!file)
399 goto out;
400
401 i_mode = file->f_path.dentry->d_inode->i_mode;
402 ret = -ESPIPE;
403 if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
404 !S_ISLNK(i_mode))
405 goto out_put;
406
407 ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags);
408out_put:
409 fput_light(file, fput_needed);
410out:
411 return ret;
412}
413#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
414asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes,
415 long flags)
416{
417 return SYSC_sync_file_range((int) fd, offset, nbytes,
418 (unsigned int) flags);
419}
420SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range);
421#endif
422
423
424
425SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags,
426 loff_t offset, loff_t nbytes)
427{
428 return sys_sync_file_range(fd, offset, nbytes, flags);
429}
430#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
431asmlinkage long SyS_sync_file_range2(long fd, long flags,
432 loff_t offset, loff_t nbytes)
433{
434 return SYSC_sync_file_range2((int) fd, (unsigned int) flags,
435 offset, nbytes);
436}
437SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
438#endif
439
440
441
442
443int do_sync_mapping_range(struct address_space *mapping, loff_t offset,
444 loff_t endbyte, unsigned int flags)
445{
446 int ret;
447
448 if (!mapping) {
449 ret = -EINVAL;
450 goto out;
451 }
452
453 ret = 0;
454 if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
455 ret = wait_on_page_writeback_range(mapping,
456 offset >> PAGE_CACHE_SHIFT,
457 endbyte >> PAGE_CACHE_SHIFT);
458 if (ret < 0)
459 goto out;
460 }
461
462 if (flags & SYNC_FILE_RANGE_WRITE) {
463 ret = __filemap_fdatawrite_range(mapping, offset, endbyte,
464 WB_SYNC_ALL);
465 if (ret < 0)
466 goto out;
467 }
468
469 if (flags & SYNC_FILE_RANGE_WAIT_AFTER) {
470 ret = wait_on_page_writeback_range(mapping,
471 offset >> PAGE_CACHE_SHIFT,
472 endbyte >> PAGE_CACHE_SHIFT);
473 }
474out:
475 return ret;
476}
477EXPORT_SYMBOL_GPL(do_sync_mapping_range);
478