[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