*/
#include <linux/slab.h>
#include <linux/pagemap.h>
+#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/mman.h>
#include <linux/hugetlb.h>
* write out the dirty pages and wait on the writeout and check the result.
* Or the application may run fadvise(FADV_DONTNEED) against the fd to start
* async writeout immediately.
- * So my _not_ starting I/O in MS_ASYNC we provide complete flexibility to
+ * So by _not_ starting I/O in MS_ASYNC we provide complete flexibility to
* applications.
*/
static int msync_interval(struct vm_area_struct *vma, unsigned long addr,
unsigned long end, int flags,
unsigned long *nr_pages_dirtied)
{
- int ret = 0;
struct file *file = vma->vm_file;
if ((flags & MS_INVALIDATE) && (vma->vm_flags & VM_LOCKED))
return -EBUSY;
- if (file && (vma->vm_flags & VM_SHARED)) {
+ if (file && (vma->vm_flags & VM_SHARED))
*nr_pages_dirtied = msync_page_range(vma, addr, end);
-
- if (flags & MS_SYNC) {
- struct address_space *mapping = file->f_mapping;
- int err;
-
- ret = filemap_fdatawrite(mapping);
- if (file->f_op && file->f_op->fsync) {
- /*
- * We don't take i_mutex here because mmap_sem
- * is already held.
- */
- err = file->f_op->fsync(file,file->f_dentry,1);
- if (err && !ret)
- ret = err;
- }
- err = filemap_fdatawait(mapping);
- if (!ret)
- ret = err;
- }
- }
- return ret;
+ return 0;
}
asmlinkage long sys_msync(unsigned long start, size_t len, int flags)
{
unsigned long end;
struct vm_area_struct *vma;
- int unmapped_error, error = -EINVAL;
+ int unmapped_error = 0;
+ int error = -EINVAL;
int done = 0;
if (flags & ~(MS_ASYNC | MS_INVALIDATE | MS_SYNC))
* just ignore them, but return -ENOMEM at the end.
*/
down_read(¤t->mm->mmap_sem);
- if (flags & MS_SYNC)
- current->flags |= PF_SYNCWRITE;
vma = find_vma(current->mm, start);
- unmapped_error = 0;
+ if (!vma) {
+ error = -ENOMEM;
+ goto out_unlock;
+ }
do {
unsigned long nr_pages_dirtied = 0;
struct file *file;
- /* Still start < end. */
- error = -ENOMEM;
- if (!vma)
- goto out_unlock;
/* Here start < vma->vm_end. */
if (start < vma->vm_start) {
unmapped_error = -ENOMEM;
fput(file);
down_read(¤t->mm->mmap_sem);
vma = find_vma(current->mm, start);
+ } else if ((flags & MS_SYNC) && file &&
+ (vma->vm_flags & VM_SHARED)) {
+ get_file(file);
+ up_read(¤t->mm->mmap_sem);
+ error = do_fsync(file, 0);
+ fput(file);
+ down_read(¤t->mm->mmap_sem);
+ if (error)
+ goto out_unlock;
+ vma = find_vma(current->mm, start);
} else {
vma = vma->vm_next;
}
- } while (!done);
+ } while (vma && !done);
out_unlock:
- current->flags &= ~PF_SYNCWRITE;
up_read(¤t->mm->mmap_sem);
out:
return error;