linux-mips
[Top] [All Lists]

missing flush_dcache_page call in 2.4 kernel

To: linux-mips@linux-mips.org
Subject: missing flush_dcache_page call in 2.4 kernel
From: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Date: Thu, 25 Mar 2004 22:42:29 +0900 (JST)
Cc: ralf@linux-mips.org
Original-recipient: rfc822;linux-mips@linux-mips.org
Sender: linux-mips-bounce@linux-mips.org
I noticed that reading from file with mmap sometimes return wrong data
on 2.4 kernel.

This is a test program to reproduce the problem.

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

int main(int argc, char **argv)
{
        int fd;
        struct stat st;
        volatile unsigned char *buf;
        unsigned char dat, dat2;

        fd = open(argv[1], O_RDONLY);
        fstat(fd, &st);
        buf = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);

        dat = *buf;
        cacheflush(0, 0, 0);    // flush cache all
        dat2 = *buf;

        printf("dat %x dat2 %x\n", dat, dat2);

        munmap(buf, st.st_size);
        close(fd);
        return 0;
}

'dat' and 'dat2' should be same value, of course.  But sometimes they
differ.

This problem often happens when I read a file in IDE disk (using PIO)
just after mounted.  I saw same problem on a mtd JFFS2 partition a
while ago.  I suppose it is not a filesystem/driver problem.

After calling cacheflush(), it returns correct data.  And I checked
the virtual/physical address return by the mmap and found they had
different 'color' when the problem happens.  So it seems to be a
virtual aliasing problem.

Documentation/cachetlb.txt says:

  void flush_dcache_page(struct page *page)

        Any time the kernel writes to a page cache page, _OR_
        the kernel is about to read from a page cache page and
        user space shared/writable mappings of this page potentially
        exist, this routine is called.

But flush_dcache_page() did not called between the mmap() call and the
cacheflush() call.

Tracing the code path on the page fault, I noticed filemap_nopage()
uses old flush_page_to_ram() interface.  I suppose flush_dcache_page()
should be called in same place.  Is this a correct fix?


--- linux-2.4.25/mm/filemap.c   Wed Feb 18 22:36:32 2004
+++ linux/mm/filemap.c  Thu Mar 25 21:19:29 2004
@@ -2111,6 +2111,7 @@
         * and possibly copy it over to another page..
         */
        mark_page_accessed(page);
+       flush_dcache_page(page);
        flush_page_to_ram(page);
        return page;
 
---
Atsushi Nemoto

<Prev in Thread] Current Thread [Next in Thread>