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