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 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 fd f = fdget(fd);
152 struct super_block *sb;
153 int ret;
154
155 if (!f.file)
156 return -EBADF;
157 sb = f.file->f_dentry->d_sb;
158
159 down_read(&sb->s_umount);
160 ret = sync_filesystem(sb);
161 up_read(&sb->s_umount);
162
163 fdput(f);
164 return ret;
165}
166
167
168
169
170
171
172
173
174
175
176
177
178int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
179{
180 if (!file->f_op->fsync)
181 return -EINVAL;
182 return file->f_op->fsync(file, start, end, datasync);
183}
184EXPORT_SYMBOL(vfs_fsync_range);
185
186
187
188
189
190
191
192
193
194int vfs_fsync(struct file *file, int datasync)
195{
196 return vfs_fsync_range(file, 0, LLONG_MAX, datasync);
197}
198EXPORT_SYMBOL(vfs_fsync);
199
200static int do_fsync(unsigned int fd, int datasync)
201{
202 struct fd f = fdget(fd);
203 int ret = -EBADF;
204
205 if (f.file) {
206 ret = vfs_fsync(f.file, datasync);
207 fdput(f);
208 }
209 return ret;
210}
211
212SYSCALL_DEFINE1(fsync, unsigned int, fd)
213{
214 return do_fsync(fd, 0);
215}
216
217SYSCALL_DEFINE1(fdatasync, unsigned int, fd)
218{
219 return do_fsync(fd, 1);
220}
221
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
269SYSCALL_DEFINE4(sync_file_range, int, fd, loff_t, offset, loff_t, nbytes,
270 unsigned int, flags)
271{
272 int ret;
273 struct fd f;
274 struct address_space *mapping;
275 loff_t endbyte;
276 umode_t i_mode;
277
278 ret = -EINVAL;
279 if (flags & ~VALID_FLAGS)
280 goto out;
281
282 endbyte = offset + nbytes;
283
284 if ((s64)offset < 0)
285 goto out;
286 if ((s64)endbyte < 0)
287 goto out;
288 if (endbyte < offset)
289 goto out;
290
291 if (sizeof(pgoff_t) == 4) {
292 if (offset >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
293
294
295
296
297 ret = 0;
298 goto out;
299 }
300 if (endbyte >= (0x100000000ULL << PAGE_CACHE_SHIFT)) {
301
302
303
304 nbytes = 0;
305 }
306 }
307
308 if (nbytes == 0)
309 endbyte = LLONG_MAX;
310 else
311 endbyte--;
312
313 ret = -EBADF;
314 f = fdget(fd);
315 if (!f.file)
316 goto out;
317
318 i_mode = file_inode(f.file)->i_mode;
319 ret = -ESPIPE;
320 if (!S_ISREG(i_mode) && !S_ISBLK(i_mode) && !S_ISDIR(i_mode) &&
321 !S_ISLNK(i_mode))
322 goto out_put;
323
324 mapping = f.file->f_mapping;
325 if (!mapping) {
326 ret = -EINVAL;
327 goto out_put;
328 }
329
330 ret = 0;
331 if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) {
332 ret = filemap_fdatawait_range(mapping, offset, endbyte);
333 if (ret < 0)
334 goto out_put;
335 }
336
337 if (flags & SYNC_FILE_RANGE_WRITE) {
338 ret = filemap_fdatawrite_range(mapping, offset, endbyte);
339 if (ret < 0)
340 goto out_put;
341 }
342
343 if (flags & SYNC_FILE_RANGE_WAIT_AFTER)
344 ret = filemap_fdatawait_range(mapping, offset, endbyte);
345
346out_put:
347 fdput(f);
348out:
349 return ret;
350}
351
352
353
354SYSCALL_DEFINE4(sync_file_range2, int, fd, unsigned int, flags,
355 loff_t, offset, loff_t, nbytes)
356{
357 return sys_sync_file_range(fd, offset, nbytes, flags);
358}
359