0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/fs.h>
0012 #include <linux/mm.h>
0013 #include <linux/mman.h>
0014 #include <linux/file.h>
0015 #include <linux/syscalls.h>
0016 #include <linux/sched.h>
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags)
0033 {
0034 unsigned long end;
0035 struct mm_struct *mm = current->mm;
0036 struct vm_area_struct *vma;
0037 int unmapped_error = 0;
0038 int error = -EINVAL;
0039
0040 start = untagged_addr(start);
0041
0042 if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
0043 goto out;
0044 if (offset_in_page(start))
0045 goto out;
0046 if ((flags & MS_ASYNC) && (flags & MS_SYNC))
0047 goto out;
0048 error = -ENOMEM;
0049 len = (len + ~PAGE_MASK) & PAGE_MASK;
0050 end = start + len;
0051 if (end < start)
0052 goto out;
0053 error = 0;
0054 if (end == start)
0055 goto out;
0056
0057
0058
0059
0060
0061
0062 mmap_read_lock(mm);
0063 vma = find_vma(mm, start);
0064 for (;;) {
0065 struct file *file;
0066 loff_t fstart, fend;
0067
0068
0069 error = -ENOMEM;
0070 if (!vma)
0071 goto out_unlock;
0072
0073 if (start < vma->vm_start) {
0074 if (flags == MS_ASYNC)
0075 goto out_unlock;
0076 start = vma->vm_start;
0077 if (start >= end)
0078 goto out_unlock;
0079 unmapped_error = -ENOMEM;
0080 }
0081
0082 if ((flags & MS_INVALIDATE) &&
0083 (vma->vm_flags & VM_LOCKED)) {
0084 error = -EBUSY;
0085 goto out_unlock;
0086 }
0087 file = vma->vm_file;
0088 fstart = (start - vma->vm_start) +
0089 ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
0090 fend = fstart + (min(end, vma->vm_end) - start) - 1;
0091 start = vma->vm_end;
0092 if ((flags & MS_SYNC) && file &&
0093 (vma->vm_flags & VM_SHARED)) {
0094 get_file(file);
0095 mmap_read_unlock(mm);
0096 error = vfs_fsync_range(file, fstart, fend, 1);
0097 fput(file);
0098 if (error || start >= end)
0099 goto out;
0100 mmap_read_lock(mm);
0101 vma = find_vma(mm, start);
0102 } else {
0103 if (start >= end) {
0104 error = 0;
0105 goto out_unlock;
0106 }
0107 vma = vma->vm_next;
0108 }
0109 }
0110 out_unlock:
0111 mmap_read_unlock(mm);
0112 out:
0113 return error ? : unmapped_error;
0114 }