missing flush_dcache_page call in 2.4 kernel

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux