lkml.org 
[lkml]   [2006]   [Dec]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
SubjectRe: 2.6.19 file content corruption on ext3
From
Date
On Mon, 2006-12-18 at 11:18 -0800, Linus Torvalds wrote:

> > diff --git a/mm/rmap.c b/mm/rmap.c
> > index d8a842a..3f9061e 100644
> > --- a/mm/rmap.c
> > +++ b/mm/rmap.c
> > @@ -448,7 +448,7 @@ static int page_mkclean_one(struct page
> > goto unlock;
> >
> > entry = ptep_get_and_clear(mm, address, pte);
> > - entry = pte_mkclean(entry);
> > + /*entry = pte_mkclean(entry);*/
> > entry = pte_wrprotect(entry);
> > ptep_establish(vma, address, pte, entry);
> > lazy_mmu_prot_update(entry);
>
> The above patch is bad. It's always going to hide the bug, but it hides it
> by just not doing anything at all.

Not quite, it does wrprotect still, so further updates will trigger the
do_wp_page() path and call set_page_dirty().

So we could make 'something' that would keep the tracking working and
not create corruption, say something like this:

However I'll try and figure out how we get so terribly confused on the
PG_dirty state that we have to clean it and fall back to pte_dirty. That
is the real issue we have.

---
include/linux/rmap.h | 6 ++++++
mm/page-writeback.c | 3 ++-
mm/rmap.c | 23 ++++++++++++++++++-----
3 files changed, 26 insertions(+), 6 deletions(-)

Index: linux-2.6-git/mm/rmap.c
===================================================================
--- linux-2.6-git.orig/mm/rmap.c 2006-12-18 11:06:29.000000000 +0100
+++ linux-2.6-git/mm/rmap.c 2006-12-19 08:33:57.000000000 +0100
@@ -428,7 +428,8 @@ int page_referenced(struct page *page, i
return referenced;
}

-static int page_mkclean_one(struct page *page, struct vm_area_struct *vma)
+static int page_mkcw_one(struct page *page,
+ struct vm_area_struct *vma, int make_clean)
{
struct mm_struct *mm = vma->vm_mm;
unsigned long address;
@@ -448,7 +449,8 @@ static int page_mkclean_one(struct page
goto unlock;

entry = ptep_get_and_clear(mm, address, pte);
- entry = pte_mkclean(entry);
+ if (make_clean)
+ entry = pte_mkclean(entry);
entry = pte_wrprotect(entry);
ptep_establish(vma, address, pte, entry);
lazy_mmu_prot_update(entry);
@@ -460,7 +462,8 @@ out:
return ret;
}

-static int page_mkclean_file(struct address_space *mapping, struct page *page)
+static int page_mkcw_file(struct address_space *mapping,
+ struct page *page, int make_clean)
{
pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT);
struct vm_area_struct *vma;
@@ -478,7 +481,7 @@ static int page_mkclean_file(struct addr
return ret;
}

-int page_mkclean(struct page *page)
+static int page_mkcw(struct page *page, int make_clean)
{
int ret = 0;

@@ -487,12 +490,22 @@ int page_mkclean(struct page *page)
if (page_mapped(page)) {
struct address_space *mapping = page_mapping(page);
if (mapping)
- ret = page_mkclean_file(mapping, page);
+ ret = page_mkcw_file(mapping, page, make_clean);
}

return ret;
}

+int page_mkclean(struct page *page)
+{
+ return page_mkcw(page, 1);
+}
+
+int page_wrprotect(struct page *page)
+{
+ return page_mkcw(page, 0);
+}
+
/**
* page_set_anon_rmap - setup new anonymous rmap
* @page: the page to add the mapping to
Index: linux-2.6-git/include/linux/rmap.h
===================================================================
--- linux-2.6-git.orig/include/linux/rmap.h 2006-12-19 08:31:59.000000000 +0100
+++ linux-2.6-git/include/linux/rmap.h 2006-12-19 08:32:28.000000000 +0100
@@ -110,6 +110,7 @@ unsigned long page_address_in_vma(struct
* returns the number of cleaned PTEs.
*/
int page_mkclean(struct page *);
+int page_wrprotect(struct page *);

#else /* !CONFIG_MMU */

@@ -125,6 +126,11 @@ static inline int page_mkclean(struct pa
return 0;
}

+static inline int page_wrprotect(struct page *page)
+{
+ return 0;
+}
+

#endif /* CONFIG_MMU */

Index: linux-2.6-git/mm/page-writeback.c
===================================================================
--- linux-2.6-git.orig/mm/page-writeback.c 2006-12-19 08:24:48.000000000 +0100
+++ linux-2.6-git/mm/page-writeback.c 2006-12-19 08:31:43.000000000 +0100
@@ -872,7 +872,8 @@ int test_clear_page_dirty(struct page *p
* page is locked, which pins the address_space
*/
if (mapping_cap_account_dirty(mapping)) {
- page_mkclean(page);
+ if (page_wrprotect(page))
+ set_page_dirty();
dec_zone_page_state(page, NR_FILE_DIRTY);
}
return 1;



-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2006-12-19 08:43    [W:0.361 / U:0.108 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site