diff options
author | Andrew Morton <akpm@osdl.org> | 2004-11-18 22:54:22 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-11-18 22:54:22 -0800 |
commit | c2234eee5c898eb2e2e8b11d4705ddb78eb2a751 (patch) | |
tree | 75eb56a82025fbebb32ad1017264098add2451ca /mm | |
parent | b356ea4b640230c86f3e36a1dfcc55f45ec078fb (diff) | |
download | history-c2234eee5c898eb2e2e8b11d4705ddb78eb2a751.tar.gz |
[PATCH] vmscan: ignore swap token when in trouble
The token-based thrashing control patches introduced a problem: when a task
which doesn't hold the token tries to run direct-reclaim, that task is told
that pages which belong to the token-holding mm are referenced, even though
they are not. This means that it is possible for a huge number of a
non-token-holding mm's pages to be scanned to no effect. Eventually, we give
up and go and oom-kill something.
So the patch arranges for the thrashing control logic to be defeated if the
caller has reached the highest level of scanning priority.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/rmap.c | 23 | ||||
-rw-r--r-- | mm/vmscan.c | 4 |
2 files changed, 15 insertions, 12 deletions
diff --git a/mm/rmap.c b/mm/rmap.c index b2f242f76cd734..83c86c2de4e5d0 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -254,7 +254,7 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) * repeatedly from either page_referenced_anon or page_referenced_file. */ static int page_referenced_one(struct page *page, - struct vm_area_struct *vma, unsigned int *mapcount) + struct vm_area_struct *vma, unsigned int *mapcount, int ignore_token) { struct mm_struct *mm = vma->vm_mm; unsigned long address; @@ -289,7 +289,7 @@ static int page_referenced_one(struct page *page, if (ptep_clear_flush_young(vma, address, pte)) referenced++; - if (mm != current->mm && has_swap_token(mm)) + if (mm != current->mm && !ignore_token && has_swap_token(mm)) referenced++; (*mapcount)--; @@ -302,7 +302,7 @@ out: return referenced; } -static int page_referenced_anon(struct page *page) +static int page_referenced_anon(struct page *page, int ignore_token) { unsigned int mapcount; struct anon_vma *anon_vma; @@ -315,7 +315,8 @@ static int page_referenced_anon(struct page *page) mapcount = page_mapcount(page); list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { - referenced += page_referenced_one(page, vma, &mapcount); + referenced += page_referenced_one(page, vma, &mapcount, + ignore_token); if (!mapcount) break; } @@ -334,7 +335,7 @@ static int page_referenced_anon(struct page *page) * * This function is only called from page_referenced for object-based pages. */ -static int page_referenced_file(struct page *page) +static int page_referenced_file(struct page *page, int ignore_token) { unsigned int mapcount; struct address_space *mapping = page->mapping; @@ -372,7 +373,8 @@ static int page_referenced_file(struct page *page) referenced++; break; } - referenced += page_referenced_one(page, vma, &mapcount); + referenced += page_referenced_one(page, vma, &mapcount, + ignore_token); if (!mapcount) break; } @@ -389,7 +391,7 @@ static int page_referenced_file(struct page *page) * Quick test_and_clear_referenced for all mappings to a page, * returns the number of ptes which referenced the page. */ -int page_referenced(struct page *page, int is_locked) +int page_referenced(struct page *page, int is_locked, int ignore_token) { int referenced = 0; @@ -401,14 +403,15 @@ int page_referenced(struct page *page, int is_locked) if (page_mapped(page) && page->mapping) { if (PageAnon(page)) - referenced += page_referenced_anon(page); + referenced += page_referenced_anon(page, ignore_token); else if (is_locked) - referenced += page_referenced_file(page); + referenced += page_referenced_file(page, ignore_token); else if (TestSetPageLocked(page)) referenced++; else { if (page->mapping) - referenced += page_referenced_file(page); + referenced += page_referenced_file(page, + ignore_token); unlock_page(page); } } diff --git a/mm/vmscan.c b/mm/vmscan.c index 44dadf2d3778bb..585c0cff921b9f 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -377,7 +377,7 @@ static int shrink_list(struct list_head *page_list, struct scan_control *sc) if (page_mapped(page) || PageSwapCache(page)) sc->nr_scanned++; - referenced = page_referenced(page, 1); + referenced = page_referenced(page, 1, sc->priority <= 0); /* In active use or really unfreeable? Activate it. */ if (referenced && page_mapping_inuse(page)) goto activate_locked; @@ -715,7 +715,7 @@ refill_inactive_zone(struct zone *zone, struct scan_control *sc) if (page_mapped(page)) { if (!reclaim_mapped || (total_swap_pages == 0 && PageAnon(page)) || - page_referenced(page, 0)) { + page_referenced(page, 0, sc->priority <= 0)) { list_add(&page->lru, &l_active); continue; } |