flush_tlb_page in unuse_pte

Bill Hawes (whawes@star.net)
Tue, 26 Aug 1997 10:52:40 -0400


This is a multi-part message in MIME format.
--------------E1F08FF7DE906B3DCEA6337E
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

I'm working on a patch to fix a minor race in unuse_pte, and have a
question about the use of flush_tlb_page. Currently the call to
flush_tlb_page occurs after a blocking operation, and I'm trying to
ensure that no references are made to the vma after blocking.

First of all, I'm not sure why the call to flush_tlb_page is needed,
given that the page is currently swapped out. Under what conditions
would a tlb hold data for a swapped-out page?

Secondly, if the call is needed, is there any reason why it can't
precede the call to read_swap_page?

The patch-in-progress is attached.

Regards,
Bill
--------------E1F08FF7DE906B3DCEA6337E
Content-Type: text/plain; charset=us-ascii; name="unuse_51-patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="unuse_51-patch"

--- mm/swapfile.c.old Sat Jul 19 08:17:17 1997
+++ mm/swapfile.c Tue Aug 26 09:58:29 1997
@@ -172,18 +172,21 @@
pte_t *dir, unsigned int type, unsigned long page)
{
pte_t pte = *dir;
+ pgprot_t page_prot;

if (pte_none(pte))
return 0;
if (pte_present(pte)) {
struct page *pg;
unsigned long page_nr = MAP_NR(pte_page(pte));
+ unsigned long entry;
+
if (page_nr >= max_mapnr)
return 0;
pg = mem_map + page_nr;
- if (!in_swap_cache(pg))
+ if (!(entry = in_swap_cache(pg)))
return 0;
- if (SWP_TYPE(in_swap_cache(pg)) != type)
+ if (SWP_TYPE(entry) != type)
return 0;
delete_from_swap_cache(pg);
set_pte(dir, pte_mkdirty(pte));
@@ -191,14 +194,24 @@
}
if (SWP_TYPE(pte_val(pte)) != type)
return 0;
+ /*
+ * Calling read_swap_page will block, so we should complete all
+ * references to the vma prior to reading the page (see below).
+ */
+ ++vma->vm_mm->rss;
+ page_prot = vma->vm_page_prot;
read_swap_page(pte_val(pte), (char *) page);
if (pte_val(*dir) != pte_val(pte)) {
free_page(page);
return 1;
}
- set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot))));
+ set_pte(dir, pte_mkwrite(pte_mkdirty(mk_pte(page, page_prot))));
+ /*
+ * Do we need this? It isn't completely safe to use the vma here,
+ * but flush_tlb_page() varies greatly by architecture, so it's
+ * difficult to save the information we need ahead of time.
+ */
flush_tlb_page(vma, address);
- ++vma->vm_mm->rss;
swap_free(pte_val(pte));
return 1;
}

--------------E1F08FF7DE906B3DCEA6337E--