diff options
Diffstat (limited to 'fs/sync.c')
-rw-r--r-- | fs/sync.c | 86 |
1 files changed, 36 insertions, 50 deletions
@@ -5,6 +5,7 @@ | |||
5 | #include <linux/kernel.h> | 5 | #include <linux/kernel.h> |
6 | #include <linux/file.h> | 6 | #include <linux/file.h> |
7 | #include <linux/fs.h> | 7 | #include <linux/fs.h> |
8 | #include <linux/slab.h> | ||
8 | #include <linux/module.h> | 9 | #include <linux/module.h> |
9 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
10 | #include <linux/writeback.h> | 11 | #include <linux/writeback.h> |
@@ -13,6 +14,7 @@ | |||
13 | #include <linux/pagemap.h> | 14 | #include <linux/pagemap.h> |
14 | #include <linux/quotaops.h> | 15 | #include <linux/quotaops.h> |
15 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
17 | #include <linux/backing-dev.h> | ||
16 | #include "internal.h" | 18 | #include "internal.h" |
17 | 19 | ||
18 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ | 20 | #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ |
@@ -31,17 +33,17 @@ static int __sync_filesystem(struct super_block *sb, int wait) | |||
31 | * This should be safe, as we require bdi backing to actually | 33 | * This should be safe, as we require bdi backing to actually |
32 | * write out data in the first place | 34 | * write out data in the first place |
33 | */ | 35 | */ |
34 | if (!sb->s_bdi) | 36 | if (!sb->s_bdi || sb->s_bdi == &noop_backing_dev_info) |
35 | return 0; | 37 | return 0; |
36 | 38 | ||
37 | /* Avoid doing twice syncing and cache pruning for quota sync */ | 39 | if (sb->s_qcop && sb->s_qcop->quota_sync) |
38 | if (!wait) { | 40 | sb->s_qcop->quota_sync(sb, -1, wait); |
39 | writeout_quota_sb(sb, -1); | 41 | |
40 | writeback_inodes_sb(sb); | 42 | if (wait) |
41 | } else { | ||
42 | sync_quota_sb(sb, -1); | ||
43 | sync_inodes_sb(sb); | 43 | sync_inodes_sb(sb); |
44 | } | 44 | else |
45 | writeback_inodes_sb(sb); | ||
46 | |||
45 | if (sb->s_op->sync_fs) | 47 | if (sb->s_op->sync_fs) |
46 | sb->s_op->sync_fs(sb, wait); | 48 | sb->s_op->sync_fs(sb, wait); |
47 | return __sync_blockdev(sb->s_bdev, wait); | 49 | return __sync_blockdev(sb->s_bdev, wait); |
@@ -295,10 +297,11 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd) | |||
295 | */ | 297 | */ |
296 | int generic_write_sync(struct file *file, loff_t pos, loff_t count) | 298 | int generic_write_sync(struct file *file, loff_t pos, loff_t count) |
297 | { | 299 | { |
298 | if (!(file->f_flags & O_SYNC) && !IS_SYNC(file->f_mapping->host)) | 300 | if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host)) |
299 | return 0; | 301 | return 0; |
300 | return vfs_fsync_range(file, file->f_path.dentry, pos, | 302 | return vfs_fsync_range(file, file->f_path.dentry, pos, |
301 | pos + count - 1, 1); | 303 | pos + count - 1, |
304 | (file->f_flags & __O_SYNC) ? 0 : 1); | ||
302 | } | 305 | } |
303 | EXPORT_SYMBOL(generic_write_sync); | 306 | EXPORT_SYMBOL(generic_write_sync); |
304 | 307 | ||
@@ -354,6 +357,7 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, | |||
354 | { | 357 | { |
355 | int ret; | 358 | int ret; |
356 | struct file *file; | 359 | struct file *file; |
360 | struct address_space *mapping; | ||
357 | loff_t endbyte; /* inclusive */ | 361 | loff_t endbyte; /* inclusive */ |
358 | int fput_needed; | 362 | int fput_needed; |
359 | umode_t i_mode; | 363 | umode_t i_mode; |
@@ -404,7 +408,28 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, | |||
404 | !S_ISLNK(i_mode)) | 408 | !S_ISLNK(i_mode)) |
405 | goto out_put; | 409 | goto out_put; |
406 | 410 | ||
407 | ret = do_sync_mapping_range(file->f_mapping, offset, endbyte, flags); | 411 | mapping = file->f_mapping; |
412 | if (!mapping) { | ||
413 | ret = -EINVAL; | ||
414 | goto out_put; | ||
415 | } | ||
416 | |||
417 | ret = 0; | ||
418 | if (flags & SYNC_FILE_RANGE_WAIT_BEFORE) { | ||
419 | ret = filemap_fdatawait_range(mapping, offset, endbyte); | ||
420 | if (ret < 0) | ||
421 | goto out_put; | ||
422 | } | ||
423 | |||
424 | if (flags & SYNC_FILE_RANGE_WRITE) { | ||
425 | ret = filemap_fdatawrite_range(mapping, offset, endbyte); | ||
426 | if (ret < 0) | ||
427 | goto out_put; | ||
428 | } | ||
429 | |||
430 | if (flags & SYNC_FILE_RANGE_WAIT_AFTER) | ||
431 | ret = filemap_fdatawait_range(mapping, offset, endbyte); | ||
432 | |||
408 | out_put: | 433 | out_put: |
409 | fput_light(file, fput_needed); | 434 | fput_light(file, fput_needed); |
410 | out: | 435 | out: |
@@ -436,42 +461,3 @@ asmlinkage long SyS_sync_file_range2(long fd, long flags, | |||
436 | } | 461 | } |
437 | SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2); | 462 | SYSCALL_ALIAS(sys_sync_file_range2, SyS_sync_file_range2); |
438 | #endif | 463 | #endif |
439 | |||
440 | /* | ||
441 | * `endbyte' is inclusive | ||
442 | */ | ||
443 | int 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 | } | ||
474 | out: | ||
475 | return ret; | ||
476 | } | ||
477 | EXPORT_SYMBOL_GPL(do_sync_mapping_range); | ||