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/module.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/buffer_head.h>
18#include <linux/backing-dev.h>
19#include "internal.h"
20
21#define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
22 SYNC_FILE_RANGE_WAIT_AFTER)
23
24
25
26
27
28
29
30
31static int __sync_filesystem(struct super_block *sb, int wait)
32{
33
34
35
36
37 if (sb->s_bdi == &noop_backing_dev_info)
38 return 0;
39
40 if (sb->s_qcop && sb->s_qcop->quota_sync)
41 sb->s_qcop->quota_sync(sb, -1, wait);
42
43 if (wait)
44 sync_inodes_sb(sb);
45 else
46 writeback_inodes_sb(sb);
47
48 if (sb->s_op->sync_fs)
49 sb->s_op->sync_fs(sb, wait);
50 return __sync_blockdev(sb->s_bdev, wait);
51}
52
53
54
55
56
57
58int sync_filesystem(struct super_block *sb)
59{
60 int ret;
61
62
63
64
65
66 WARN_ON(!rwsem_is_locked(&sb->s_umount));
67
68
69
70
71 if (sb->s_flags & MS_RDONLY)
72 return 0;
73
74 ret = __sync_filesystem(sb, 0);
75 if (ret < 0)
76 return ret;
77 return __sync_filesystem(sb, 1);
78}
79EXPORT_SYMBOL_GPL(sync_filesystem);
80
81static void sync_one_sb(struct super_block *sb, void *arg)
82{
83 if (!(sb->s_flags & MS_RDONLY))
84 __sync_filesystem(sb, *(int *)arg);
85}
86
87
88
89
90static void sync_filesystems(int wait)
91{
92 iterate_supers(sync_one_sb, &wait);
93}
94
95
96
97
98
99SYSCALL_DEFINE0(sync)
100{
101 wakeup_flusher_threads(0);
102 sync_filesystems(0);
103 sync_filesystems(1);
104 if (unlikely(laptop_mode))
105 laptop_sync_completion();
106 return 0;
107}
108
109static void do_sync_work(struct work_struct *work)
110{
111
112
113
114
115 sync_filesystems(0);
116 sync_filesystems(0);
117 printk("Emergency Sync complete\n");
118 kfree(work);
119}
120
121void emergency_sync(void)
122{
123 struct work_struct *work;
124
125 work = kmalloc(sizeof(*work), GFP_ATOMIC);
126 if (work) {
127 INIT_WORK(work, do_sync_work);
128 schedule_work(work);
129 }
130}
131
132
133
134
135SYSCALL_DEFINE1(syncfs, int, fd)
136{
137 struct file *file;
138 struct super_block *sb;
139 int ret;
140 int fput_needed;
141
142 file = fget_light(fd, &fput_needed);
143 if (!file)
144 return -EBADF;
145 sb = file->f_dentry->d_sb;
146
147 down_read(&sb->s_umount);
148 ret = sync_filesystem(sb);
149 up_read(&sb->s_umount);
150
151 fput_light(file, fput_needed);
152 return ret;
153}
154
155
156
157
158
159
160
161
162
163
164
165
166int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
167{
168 struct address_space *mapping = file->f_mapping;
169 int err, ret;
170
171 if (!file->f_op || !file->f_op->fsync) {
172 ret = -EINVAL;
173 goto out;
174 }
175
176 ret = filemap_write_and_wait_range(mapping, start, end);
177
178
179
180
181
182 mutex_lock(&mapping->host->i_mutex);
183 err = file->f_op->fsync(file, datasync);
184 if (!ret)
185 ret = err;
186 mutex_unlock(&mapping->host->i_mutex);
187
188out:
189 return ret;
190}
191EXPORT_SYMBOL(vfs_fsync_range);
192
193
194
195
196
197
198
199
200
201int vfs_fsync(struct file *file, int datasync)
202{
203 return vfs_fsync_range(file, 0, LLONG_MAX, datasync);
204}
205EXPORT_SYMBOL(vfs_fsync);
206
207static int do_fsync(unsigned int fd, int datasync)
208{
209 struct file *file;
210 int ret = -EBADF;
211
212 file = fget(fd);
213 if (file) {
214 ret = vfs_fsync(file, datasync);
215 fput(file);
216 }
217 return ret;
218}
219
220SYSCALL_DEFINE1(fsync, unsigned int, fd)
221{
222 return do_fsync(fd, 0);
223}
224
225SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
226{
227 return do_fsync(fd, 1);
228}
229
230
231
232
233
234
235
236
237
238int generic_write_sync(struct file *file, loff_t pos, loff_t count)
239{
240 if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host))
241 return 0;
242 return vfs_fsync_range(file, pos, pos + count - 1,
243 (file->f_flags & __O_SYNC) ? 0 : 1);
244}
245EXPORT_SYMBOL(generic_write_sync);
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
290
291
292
293
294SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes,
295 unsigned int flags)
296{
297 int ret;
298 struct file *file;
299 struct address_space *mapping;
300 loff_t endbyte;
301 int fput_needed;
302 umode_t i_mode;
303
304 ret = -EINVAL;
305 if (flags & ~VALID_FLAGS)
306 goto out;
307
308 endbyte = offset + nbytes;
309
310 if ((s64)offset < 0)
311 goto out;
312 if ((s64)endbyte < 0)
313 goto out;
314 if (endbyte < offset)
315 goto out;
316
317 if (sizeof(pgoff_t) == 4) {
318 if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
319
320
321
322
323 ret = 0;
324 goto out;
325 }
326 if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
327
328
329
330 nbytes = 0;
331 }
332 }
333
334 if (nbytes == 0)
335 endbyte = LLONG_MAX;
336 else
337 endbyte--;
338
339 ret = -EBADF;
340 file = fget_light(fd, &fput_needed);
341 if (!file)
342 goto out;
343
344 i_mode = file->f_path.dentry->d_inode->i_mode;
345 ret = -ESPIPE;
346 if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
347 !S_ISLNK(i_mode))
348 goto out_put;
349
350 mapping = file->f_mapping;
351 if (!mapping) {
352 ret = -EINVAL;
353 goto out_put;
354 }
355
356 ret = 0;
357 if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
358 ret = filemap_fdatawait_range(mapping, offset, endbyte);
359 if (ret < 0)
360 goto out_put;
361 }
362
363 if (flags & SYNC_FILE_RANGE_WRITE) {
364 ret = filemap_fdatawrite_range(mapping, offset, endbyte);
365 if (ret < 0)
366 goto out_put;
367 }
368
369 if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
370 ret = filemap_fdatawait_range(mapping, offset, endbyte);
371
372out_put:
373 fput_light(file, fput_needed);
374out:
375 return ret;
376}
377#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
378asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes,
379 long flags)
380{
381 return SYSC_sync_file_range((int) fd, offset, nbytes,
382 (unsigned int) flags);
383}
384SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range);
385#endif
386
387
388
389SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags,
390 loff_t offset, loff_t nbytes)
391{
392 return sys_sync_file_range(fd, offset, nbytes, flags);
393}
394#ifdef CONFIG_HAVE_SYSCALL_WRAPPERS
395asmlinkage long SyS_sync_file_range2(long fd, long flags,
396 loff_t offset, loff_t nbytes)
397{
398 return SYSC_sync_file_range2((int) fd, (unsigned int) flags,
399 offset, nbytes);
400}
401SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2);
402#endif
403