To: linux-mm@xxxxxxxxx, and linux-mips@xxxxxxxxxxxxxx 于 2012年01月20日 13:18, Zumeng Chen 写道: > This patch fixes two issues as follows: > > For some filesystem with fsync == noop_fsync, there is not so much thing > to do, so sys_msync just passes by for all arches but some CPUs. > > For some CPUs with cache aliases(dmesg|grep alias), it maybe has an issue, > which reported by msync test suites in ltp-full when the memory of memset > used by msync01 runs into cache alias randomly. > > Consider the following scenario used by msync01 in ltp-full: > fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666)) < 0); > .../* initialization fildes by write(fildes); */ > addr = mmap(0, page_sz, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, > fildes, 0); > /* set buf with memset */ > memset(addr + OFFSET_1, 1, BUF_SIZE); > > /* msync the addr before using, or MS_SYNC*/ > msync(addr, page_sz, MS_ASYNC) > > /* Tries to read fildes */ > lseek(fildes, (off_t) OFFSET_1, SEEK_SET) != (off_t) OFFSET_1) { > nread = read(fildes, read_buf, sizeof(read_buf)); > > /* Then test the result */ > if (read_buf[count] != 1) { > > The test result is random too for CPUs with cache alias. So in this > situation, we have to flush the related vma to make sure the read is > correct. > > Signed-off-by: Zumeng Chen <zumeng.chen@xxxxxxxxxxxxx> > --- > mm/msync.c | 30 ++++++++++++++++++++++++++++++ > 1 files changed, 30 insertions(+), 0 deletions(-) > > diff --git a/mm/msync.c b/mm/msync.c > index 632df45..0021a7e 100644 > --- a/mm/msync.c > +++ b/mm/msync.c > @@ -13,6 +13,14 @@ > #include <linux/file.h> > #include <linux/syscalls.h> > #include <linux/sched.h> > +#include <asm/cacheflush.h> > + > +/* Cache aliases should be taken into accounts when msync. */ > +#ifdef cpu_has_dc_aliases > +#define CPU_HAS_CACHE_ALIAS cpu_has_dc_aliases > +#else > +#define CPU_HAS_CACHE_ALIAS 0 > +#endif > > /* > * MS_SYNC syncs the entire file - including mappings. > @@ -78,6 +86,28 @@ SYSCALL_DEFINE3(msync, unsigned long, start, size_t, len, int, flags) > } > file = vma->vm_file; > start = vma->vm_end; > + > + /* > + * For some filesystems with fsync == noop_fsync, msync just > + * passes by but some CPUs. > + * For CPUs with cache alias, msync has to flush the related > + * vma explicitly to make sure data coherency between memory > + * and cache, which includes MS_SYNC or MS_ASYNC. That is to > + * say, cache aliases should not be an async factor, so does > + * msync on other arches without cache aliases. > + */ > + if (file && file->f_op && file->f_op->fsync == noop_fsync) { > + if (CPU_HAS_CACHE_ALIAS) > + flush_cache_range(vma, vma->vm_start, > + vma->vm_end); > + if (start >= end) { > + error = 0; > + goto out_unlock; > + } > + vma = find_vma(mm, start); > + continue; > + } > + > if ((flags & MS_SYNC) && file && > (vma->vm_flags & VM_SHARED)) { > get_file(file);