/* * linux/mm/msync.c * * Copyright (C) 1994-1999 Linus Torvalds *//* * The msync() system call. */#include<linux/fs.h>#include<linux/mm.h>#include<linux/mman.h>#include<linux/file.h>#include<linux/syscalls.h>#include<linux/sched.h>/* * MS_SYNC syncs the entire file - including mappings. * * MS_ASYNC does not start I/O (it used to, up to 2.5.67). * Nor does it marks the relevant pages dirty (it used to up to 2.6.17). * Now it doesn't do anything, since dirty pages are properly tracked. * * The application may now run fsync() to * 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 by _not_ starting I/O in MS_ASYNC we provide complete flexibility to * applications. */SYSCALL_DEFINE3(msync,unsignedlong,start,size_t,len,int,flags){unsignedlongend;structmm_struct*mm=current->mm;structvm_area_struct*vma;intunmapped_error=0;interror=-EINVAL;if(flags&~(MS_ASYNC|MS_INVALIDATE|MS_SYNC))gotoout;if(start&~PAGE_MASK)gotoout;if((flags&MS_ASYNC)&&(flags&MS_SYNC))gotoout;error=-ENOMEM;len=(len+~PAGE_MASK)&PAGE_MASK;end=start+len;if(end<start)gotoout;error=0;if(end==start)gotoout;/* * If the interval [start,end) covers some unmapped address ranges, * just ignore them, but return -ENOMEM at the end. */down_read(&mm->mmap_sem);vma=find_vma(mm,start);for(;;){structfile*file;loff_tfstart,fend;/* Still start < end. */error=-ENOMEM;if(!vma)gotoout_unlock;/* Here start < vma->vm_end. */if(start<vma->vm_start){start=vma->vm_start;if(start>=end)gotoout_unlock;unmapped_error=-ENOMEM;}/* Here vma->vm_start <= start < vma->vm_end. */if((flags&MS_INVALIDATE)&&(vma->vm_flags&VM_LOCKED)){error=-EBUSY;gotoout_unlock;}file=vma->vm_file;fstart=(start-vma->vm_start)+((loff_t)vma->vm_pgoff<<PAGE_SHIFT);fend=fstart+(min(end,vma->vm_end)-start)-1;start=vma->vm_end;if((flags&MS_SYNC)&&file&&(vma->vm_flags&VM_SHARED)){get_file(file);up_read(&mm->mmap_sem);if(vma->vm_flags&VM_NONLINEAR)error=vfs_fsync(file,1);elseerror=vfs_fsync_range(file,fstart,fend,1);fput(file);if(error||start>=end)gotoout;down_read(&mm->mmap_sem);vma=find_vma(mm,start);}else{if(start>=end){error=0;gotoout_unlock;}vma=vma->vm_next;}}out_unlock:up_read(&mm->mmap_sem);out:returnerror?:unmapped_error;}