diff options
Diffstat (limited to 'mm/msync.c')
-rw-r--r-- | mm/msync.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/mm/msync.c b/mm/msync.c index 632df4527c01..a5c673669ca6 100644 --- a/mm/msync.c +++ b/mm/msync.c | |||
@@ -58,6 +58,7 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) | |||
58 | vma = find_vma(mm, start); | 58 | vma = find_vma(mm, start); |
59 | for (;;) { | 59 | for (;;) { |
60 | struct file *file; | 60 | struct file *file; |
61 | loff_t fstart, fend; | ||
61 | 62 | ||
62 | /* Still start < end. */ | 63 | /* Still start < end. */ |
63 | error = -ENOMEM; | 64 | error = -ENOMEM; |
@@ -77,12 +78,17 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) | |||
77 | goto out_unlock; | 78 | goto out_unlock; |
78 | } | 79 | } |
79 | file = vma->vm_file; | 80 | file = vma->vm_file; |
81 | fstart = start + ((loff_t)vma->vm_pgoff << PAGE_SHIFT); | ||
82 | fend = fstart + (min(end, vma->vm_end) - start) - 1; | ||
80 | start = vma->vm_end; | 83 | start = vma->vm_end; |
81 | if ((flags & MS_SYNC) && file && | 84 | if ((flags & MS_SYNC) && file && |
82 | (vma->vm_flags & VM_SHARED)) { | 85 | (vma->vm_flags & VM_SHARED)) { |
83 | get_file(file); | 86 | get_file(file); |
84 | up_read(&mm->mmap_sem); | 87 | up_read(&mm->mmap_sem); |
85 | error = vfs_fsync(file, 0); | 88 | if (vma->vm_flags & VM_NONLINEAR) |
89 | error = vfs_fsync(file, 1); | ||
90 | else | ||
91 | error = vfs_fsync_range(file, fstart, fend, 1); | ||
86 | fput(file); | 92 | fput(file); |
87 | if (error || start >= end) | 93 | if (error || start >= end) |
88 | goto out; | 94 | goto out; |