net: ipv6 bind to device issue
[linux-2.6-block.git] / mm / msync.c
CommitLineData
1da177e4
LT
1/*
2 * linux/mm/msync.c
3 *
4 * Copyright (C) 1994-1999 Linus Torvalds
5 */
6
7/*
8 * The msync() system call.
9 */
8f2e9f15 10#include <linux/fs.h>
1da177e4
LT
11#include <linux/mm.h>
12#include <linux/mman.h>
9c50823e 13#include <linux/file.h>
1da177e4 14#include <linux/syscalls.h>
e8edc6e0 15#include <linux/sched.h>
1da177e4 16
1da177e4
LT
17/*
18 * MS_SYNC syncs the entire file - including mappings.
19 *
204ec841
PZ
20 * MS_ASYNC does not start I/O (it used to, up to 2.5.67).
21 * Nor does it marks the relevant pages dirty (it used to up to 2.6.17).
22 * Now it doesn't do anything, since dirty pages are properly tracked.
23 *
24 * The application may now run fsync() to
1da177e4
LT
25 * write out the dirty pages and wait on the writeout and check the result.
26 * Or the application may run fadvise(FADV_DONTNEED) against the fd to start
27 * async writeout immediately.
16538c40 28 * So by _not_ starting I/O in MS_ASYNC we provide complete flexibility to
1da177e4
LT
29 * applications.
30 */
6a6160a7 31SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags)
1da177e4
LT
32{
33 unsigned long end;
204ec841 34 struct mm_struct *mm = current->mm;
1da177e4 35 struct vm_area_struct *vma;
676758bd
AM
36 int unmapped_error = 0;
37 int error = -EINVAL;
1da177e4 38
1da177e4
LT
39 if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
40 goto out;
41 if (start & ~PAGE_MASK)
42 goto out;
43 if ((flags & MS_ASYNC) && (flags & MS_SYNC))
44 goto out;
45 error = -ENOMEM;
46 len = (len + ~PAGE_MASK) & PAGE_MASK;
47 end = start + len;
48 if (end < start)
49 goto out;
50 error = 0;
51 if (end == start)
52 goto out;
53 /*
54 * If the interval [start,end) covers some unmapped address ranges,
55 * just ignore them, but return -ENOMEM at the end.
56 */
204ec841
PZ
57 down_read(&mm->mmap_sem);
58 vma = find_vma(mm, start);
59 for (;;) {
9c50823e
AM
60 struct file *file;
61
204ec841
PZ
62 /* Still start < end. */
63 error = -ENOMEM;
64 if (!vma)
65 goto out_unlock;
1da177e4
LT
66 /* Here start < vma->vm_end. */
67 if (start < vma->vm_start) {
1da177e4 68 start = vma->vm_start;
204ec841
PZ
69 if (start >= end)
70 goto out_unlock;
71 unmapped_error = -ENOMEM;
1da177e4
LT
72 }
73 /* Here vma->vm_start <= start < vma->vm_end. */
204ec841
PZ
74 if ((flags & MS_INVALIDATE) &&
75 (vma->vm_flags & VM_LOCKED)) {
76 error = -EBUSY;
77 goto out_unlock;
1da177e4 78 }
9c50823e 79 file = vma->vm_file;
1da177e4 80 start = vma->vm_end;
204ec841 81 if ((flags & MS_SYNC) && file &&
707c21c8 82 (vma->vm_flags & VM_SHARED)) {
707c21c8 83 get_file(file);
204ec841 84 up_read(&mm->mmap_sem);
4c728ef5 85 error = vfs_fsync(file, file->f_path.dentry, 0);
707c21c8 86 fput(file);
204ec841
PZ
87 if (error || start >= end)
88 goto out;
89 down_read(&mm->mmap_sem);
90 vma = find_vma(mm, start);
9c50823e 91 } else {
204ec841
PZ
92 if (start >= end) {
93 error = 0;
94 goto out_unlock;
95 }
9c50823e
AM
96 vma = vma->vm_next;
97 }
204ec841 98 }
9c50823e 99out_unlock:
204ec841 100 up_read(&mm->mmap_sem);
9c50823e 101out:
204ec841 102 return error ? : unmapped_error;
1da177e4 103}