lkml.org 
[lkml]   [2004]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] rmaplock 5/6 unuse_process mmap_sem
Updating the mm lock ordering documentation drew attention to the fact
that we were wrong to blithely add down_read(&mm->mmap_sem) to swapoff's
unuse_process, while it holds swapcache page lock: not very likely, but
it could deadlock against, say, mlock faulting a page back in from swap.

But it looks like these days it's safe to drop and reacquire page lock
if down_read_trylock fails: the page lock is held to stop try_to_unmap
unmapping the page's ptes as fast as try_to_unuse is mapping them back
in; but the recent fix for get_user_pages works to prevent that too.

Signed-off-by: Hugh Dickins <hugh@veritas.com>

mm/rmap.c | 4 ++++
mm/swapfile.c | 10 +++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)

--- rmaplock4/mm/rmap.c 2004-07-12 18:20:48.025890256 +0100
+++ rmaplock5/mm/rmap.c 2004-07-12 18:21:02.456696440 +0100
@@ -526,6 +526,10 @@ static int try_to_unmap_one(struct page
* an exclusive swap page, do_wp_page will replace it by a copy
* page, and the user never get to see the data GUP was holding
* the original page for.
+ *
+ * This test is also useful for when swapoff (unuse_process) has
+ * to drop page lock: its reference to the page stops existing
+ * ptes from being unmapped, so swapoff can make progress.
*/
if (PageSwapCache(page) &&
page_count(page) != page_mapcount(page) + 2) {
--- rmaplock4/mm/swapfile.c 2004-07-09 10:53:46.000000000 +0100
+++ rmaplock5/mm/swapfile.c 2004-07-12 18:21:02.458696136 +0100
@@ -548,7 +548,15 @@ static int unuse_process(struct mm_struc
/*
* Go through process' page directory.
*/
- down_read(&mm->mmap_sem);
+ if (!down_read_trylock(&mm->mmap_sem)) {
+ /*
+ * Our reference to the page stops try_to_unmap_one from
+ * unmapping its ptes, so swapoff can make progress.
+ */
+ unlock_page(page);
+ down_read(&mm->mmap_sem);
+ lock_page(page);
+ }
spin_lock(&mm->page_table_lock);
for (vma = mm->mmap; vma; vma = vma->vm_next) {
if (!is_vm_hugetlb_page(vma)) {
-
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: 2005-03-22 14:04    [W:0.058 / U:0.060 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site