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_GPL(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 filemap_fdatawait(bdev->bd_inode->i_mapping);
90}
91
92
93
94
95
96
97
98
99
100
101
102SYSCALL_DEFINE0(sync)
103{
104 int nowait = 0, wait = 1;
105
106 wakeup_flusher_threads(0, WB_REASON_SYNC);
107 iterate_supers(sync_inodes_one_sb, NULL);
108 iterate_supers(sync_fs_one_sb, &nowait);
109 iterate_supers(sync_fs_one_sb, &wait);
110 iterate_bdevs(fdatawrite_one_bdev, NULL);
111 iterate_bdevs(fdatawait_one_bdev, NULL);
112 if (unlikely(laptop_mode))
113 laptop_sync_completion();
114 return 0;
115}
116
117static void do_sync_work(struct work_struct *work)
118{
119 int nowait = 0;
120
121
122
123
124
125 iterate_supers(sync_inodes_one_sb, &nowait);
126 iterate_supers(sync_fs_one_sb, &nowait);
127 iterate_bdevs(fdatawrite_one_bdev, NULL);
128 iterate_supers(sync_inodes_one_sb, &nowait);
129 iterate_supers(sync_fs_one_sb, &nowait);
130 iterate_bdevs(fdatawrite_one_bdev, NULL);
131 printk("Emergency Sync complete\n");
132 kfree(work);
133}
134
135void emergency_sync(void)
136{
137 struct work_struct *work;
138
139 work = kmalloc(sizeof(*work), GFP_ATOMIC);
140 if (work) {
141 INIT_WORK(work, do_sync_work);
142 schedule_work(work);
143 }
144}
145
146
147
148
149SYSCALL_DEFINE1(syncfs, int, fd)
150{
151 struct file *file;
152 struct super_block *sb;
153 int ret;
154 int fput_needed;
155
156 file = fget_light(fd, &fput_needed);
157 if (!file)
158 return -EBADF;
159 sb = file->f_dentry->d_sb;
160
161 down_read(&sb->s_umount);
162 ret = sync_filesystem(sb);
163 up_read(&sb->s_umount);
164
165 fput_light(file, fput_needed);
166 return ret;
167}
168
169
170
171
172
173
174
175
176
177
178
179
180int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
181{
182 if (!file->f_op || !file->f_op->fsync)
183 return -EINVAL;
184 return file->f_op->fsync(file, start, end, datasync);
185}
186EXPORT_SYMBOL(vfs_fsync_range);
187
188
189
190
191
192
193
194
195
196int vfs_fsync(struct file *file, int datasync)
197{
198 return vfs_fsync_range(file, 0, LLONG_MAX, datasync);
199}
200EXPORT_SYMBOL(vfs_fsync);
201
202static int do_fsync(unsigned int fd, int datasync)
203{
204 struct file *file;
205 int ret = -EBADF;
206 int fput_needed;
207
208 file = fget_light(fd, &fput_needed);
209 if (file) {
210 ret = vfs_fsync(file, datasync);
211 fput_light(file, fput_needed);
212 }
213 return ret;
214}
215
216SYSCALL_DEFINE1(fsync, unsigned int, fd)
217{
218 return do_fsync(fd, 0);
219}
220
221SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
222{
223 return do_fsync(fd, 1);
224}
225
226
227
228
229
230
231
232
233
234int generic_write_sync(struct file *file, loff_t pos, loff_t count)
235{
236 if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
237 return 0;
238 return vfs_fsync_range(file, pos, pos + count - 1,
239 (file->f_flags & __O_SYNC) ? 0 : 1);
240}
241EXPORT_SYMBOL(generic_write_sync);
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
282
283
284
285
286
287
288
289
290SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
291 unsigned int flags)
292{
293 int ret;
294 struct file *file;
295 struct address_space *mapping;
296 loff_t endbyte;
297 int fput_needed;
298 umode_t i_mode;
299
300 ret = -EINVAL;
301 if (flags & ~VALID_FLAGS)
302 goto out;
303
304 endbyte = offset + nbytes;
305
306 if ((s64)offset < 0)
307 goto out;
308 if ((s64)endbyte < 0)
309 goto out;
310 if (endbyte < offset)
311 goto out;
312
313 if (sizeof(pgoff_t) == 4) {
314 if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
315
316
317
318
319 ret = 0;
320 goto out;
321 }
322 if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
323
324
325
326 nbytes = 0;
327 }
328 }
329
330 if (nbytes == 0)
331 endbyte = LLONG_MAX;
332 else
333 endbyte--;
334
335 ret = -EBADF;
336 file = fget_light(fd, &fput_needed);
337 if (!file)
338 goto out;
339
340 i_mode = file->f_path.dentry->d_inode->i_mode;
341 ret = -ESPIPE;
342 if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
343 !S_ISLNK(i_mode))
344 goto out_put;
345
346 mapping = file->f_mapping;
347 if (!mapping) {
348 ret = -EINVAL;
349 goto out_put;
350 }
351
352 ret = 0;
353 if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
354 ret = filemap_fdatawait_range(mapping, offset, endbyte);
355 if (ret < 0)
356 goto out_put;
357 }
358
359 if (flags & SYNC_FILE_RANGE_WRITE) {
360 ret = filemap_fdatawrite_range(mapping, offset, endbyte);
361 if (ret < 0)
362 goto out_put;
363 }
364
365 if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
366 ret = filemap_fdatawait_range(mapping, offset, endbyte);
367
368out_put:
369 fput_light(file, fput_needed);
370out:
371 return ret;
372}
373#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
374asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes,
375 long flags)
376{
377 return SYSC_sync_file_range((int) fd, offset, nbytes,
378 (unsigned int) flags);
379}
380SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range);
381#endif
382
383
384
385SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags,
386 loff_t offset, loff_t nbytes)
387{
388 return sys_sync_file_range(fd, offset, nbytes, flags);
389}
390#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
391asmlinkage long SyS_sync_file_range2(long fd, long flags,
392 loff_t offset, loff_t nbytes)
393{
394 return SYSC_sync_file_range2((int) fd, (unsigned int) flags,
395 offset, nbytes);
396}
397SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
398#endif
399