[parisc-linux-cvs] linux-2.6 jejb

James Bottomley James.Bottomley at steeleye.com
Wed May 12 12:34:10 MDT 2004


On Wed, 2004-05-12 at 13:31, James Bottomley wrote:
> CVSROOT:	/var/cvs
> Module name:	linux-2.6
> Changes by:	jejb	04/05/12 12:31:36
> 
> Modified files:
> 	.              : Makefile 
> 	arch/parisc/kernel: cache.c 
> 	include/asm-parisc: cacheflush.h 
> 
> Log message:
> Fix problem in __flush_dcache_page() spotted by Hugh Dickins
> 
> The vma's on the i_mmap list are present even if the page has been
> COW'd.  Therefore, check to see that the pte still refers to the page
> we need to flush before actually flushing it.

Index: arch/parisc/kernel/cache.c
===================================================================
RCS file: /var/cvs/linux-2.6/arch/parisc/kernel/cache.c,v
retrieving revision 1.12
diff -u -p -r1.12 cache.c
--- a/arch/parisc/kernel/cache.c	28 Apr 2004 19:12:10 -0000	1.12
+++ b/arch/parisc/kernel/cache.c	12 May 2004 18:28:34 -0000
@@ -231,6 +231,7 @@ void __flush_dcache_page(struct page *pa
 {
 	struct address_space *mapping = page_mapping(page);
 	struct list_head *l;
+	pte_t *pte;
 
 	flush_kernel_dcache_page(page_address(page));
 
@@ -278,7 +279,7 @@ void __flush_dcache_page(struct page *pa
 	 * to flush one address here too */
 	list_for_each(l, &mapping->i_mmap) {
 		struct vm_area_struct *mpnt;
-		unsigned long off, addr;
+		unsigned long off, addr, pfn = page_to_pfn(page);
 
 		mpnt = list_entry(l, struct vm_area_struct, shared);
 
@@ -294,8 +295,14 @@ void __flush_dcache_page(struct page *pa
 		/* This is just for speed.  If the page translation isn't
 		 * there there's no point exciting the nadtlb handler into
 		 * a nullification frenzy */
-		if(!translation_exists(mpnt, addr))
+  		if(!(pte = translation_exists(mpnt, addr)))
 			continue;
+
+		/* make sure we really have this page: the private
+		 * mappings may cover this area but have COW'd this
+		 * particular page */
+		if(pte_pfn(*pte) != pfn)
+  			continue;
 
 		__flush_cache_page(mpnt, addr);
 
Index: include/asm-parisc/cacheflush.h
===================================================================
RCS file: /var/cvs/linux-2.6/include/asm-parisc/cacheflush.h,v
retrieving revision 1.11
diff -u -p -r1.11 cacheflush.h
--- a/include/asm-parisc/cacheflush.h	28 Apr 2004 19:13:01 -0000	1.11
+++ b/include/asm-parisc/cacheflush.h	12 May 2004 18:28:52 -0000
@@ -110,28 +110,29 @@ static inline void flush_cache_range(str
 
 /* Simple function to work out if we have an existing address translation
  * for a user space vma. */
-static inline int translation_exists(struct vm_area_struct *vma,
-				     unsigned long addr)
+static inline pte_t *__translation_exists(struct mm_struct *mm,
+					  unsigned long addr)
 {
-	pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
+	pgd_t *pgd = pgd_offset(mm, addr);
 	pmd_t *pmd;
 	pte_t *pte;
 
 	if(pgd_none(*pgd))
-		return 0;
+		return NULL;
 
 	pmd = pmd_offset(pgd, addr);
 	if(pmd_none(*pmd) || pmd_bad(*pmd))
-		return 0;
+		return NULL;
 
 	pte = pte_offset_map(pmd, addr);
 
 	/* The PA flush mappings show up as pte_none, but they're
 	 * valid none the less */
 	if(pte_none(*pte) && ((pte_val(*pte) & _PAGE_FLUSH) == 0))
-		return 0;
-	return 1;
+		return NULL;
+	return pte;
 }
+#define	translation_exists(vma, addr)	__translation_exists((vma)->vm_mm, addr)
 

 /* Private function to flush a page from the cache of a non-current



More information about the parisc-linux-cvs mailing list