Sure, I agree with you on that, but it doesn't let us off the hook.
This isn't necessarily the first reuse of that page: after paging it
out and freeing it, it may have got allocated to some other purpose
and freed again, and then reassigned to the original use. And while
it held the data from that intermediate use, we may have done the
copy_cow_page from old_page to new_page, and now we come along and
substitute this corrupt new_page for the good old_page.
Hugh
--- linux-2.4.8-pre2/mm/memory.c Sun Jul 29 08:10:42 2001
+++ linux/mm/memory.c Sun Jul 29 13:12:20 2001
@@ -862,8 +862,8 @@
/*
* We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
*/
-static inline void break_cow(struct vm_area_struct * vma, struct page * old_page, struct page * new_page, unsigned long address,
- pte_t *page_table)
+static inline void break_cow(struct vm_area_struct * vma, struct page * new_page,
+ unsigned long address, pte_t *page_table)
{
flush_page_to_ram(new_page);
flush_cache_page(vma, address);
@@ -935,12 +935,15 @@
/*
* Ok, we need to copy. Oh, well..
*/
+ if (!PageReserved(old_page))
+ page_cache_get(old_page);
spin_unlock(&mm->page_table_lock);
new_page = alloc_page(GFP_HIGHUSER);
if (!new_page)
goto no_mem;
copy_cow_page(old_page,new_page,address);
+ page_cache_release(old_page);
/*
* Re-check the pte - we dropped the lock
@@ -949,7 +952,7 @@
if (pte_same(*page_table, pte)) {
if (PageReserved(old_page))
++mm->rss;
- break_cow(vma, old_page, new_page, address, page_table);
+ break_cow(vma, new_page, address, page_table);
/* Free the old page.. */
new_page = old_page;
-
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/