aboutsummaryrefslogtreecommitdiffstats
path: root/mm/rmap.c
diff options
context:
space:
mode:
authorRik van Riel <riel@redhat.com>2005-11-28 16:44:07 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-28 17:42:25 -0500
commitf7b7fd8f3ebbb2810d6893295aa984acd0fd30db (patch)
tree01afc1edafc50a3c65ec8576c05c60da53d8d242 /mm/rmap.c
parenta93a117eaa0bec426d4671a49bfa96a6fdcd2ac9 (diff)
[PATCH] temporarily disable swap token on memory pressure
Some users (hi Zwane) have seen a problem when running a workload that eats nearly all of physical memory - th system does an OOM kill, even when there is still a lot of swap free. The problem appears to be a very big task that is holding the swap token, and the VM has a very hard time finding any other page in the system that is swappable. Instead of ignoring the swap token when sc->priority reaches 0, we could simply take the swap token away from the memory hog and make sure we don't give it back to the memory hog for a few seconds. This patch resolves the problem Zwane ran into. Signed-off-by: Rik van Riel <riel@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm/rmap.c')
-rw-r--r--mm/rmap.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/mm/rmap.c b/mm/rmap.c
index 6389cda02a20..491ac350048f 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -290,7 +290,7 @@ pte_t *page_check_address(struct page *page, struct mm_struct *mm,
290 * repeatedly from either page_referenced_anon or page_referenced_file. 290 * repeatedly from either page_referenced_anon or page_referenced_file.
291 */ 291 */
292static int page_referenced_one(struct page *page, 292static int page_referenced_one(struct page *page,
293 struct vm_area_struct *vma, unsigned int *mapcount, int ignore_token) 293 struct vm_area_struct *vma, unsigned int *mapcount)
294{ 294{
295 struct mm_struct *mm = vma->vm_mm; 295 struct mm_struct *mm = vma->vm_mm;
296 unsigned long address; 296 unsigned long address;
@@ -311,7 +311,7 @@ static int page_referenced_one(struct page *page,
311 311
312 /* Pretend the page is referenced if the task has the 312 /* Pretend the page is referenced if the task has the
313 swap token and is in the middle of a page fault. */ 313 swap token and is in the middle of a page fault. */
314 if (mm != current->mm && !ignore_token && has_swap_token(mm) && 314 if (mm != current->mm && has_swap_token(mm) &&
315 rwsem_is_locked(&mm->mmap_sem)) 315 rwsem_is_locked(&mm->mmap_sem))
316 referenced++; 316 referenced++;
317 317
@@ -321,7 +321,7 @@ out:
321 return referenced; 321 return referenced;
322} 322}
323 323
324static int page_referenced_anon(struct page *page, int ignore_token) 324static int page_referenced_anon(struct page *page)
325{ 325{
326 unsigned int mapcount; 326 unsigned int mapcount;
327 struct anon_vma *anon_vma; 327 struct anon_vma *anon_vma;
@@ -334,8 +334,7 @@ static int page_referenced_anon(struct page *page, int ignore_token)
334 334
335 mapcount = page_mapcount(page); 335 mapcount = page_mapcount(page);
336 list_for_each_entry(vma, &anon_vma->head, anon_vma_node) { 336 list_for_each_entry(vma, &anon_vma->head, anon_vma_node) {
337 referenced += page_referenced_one(page, vma, &mapcount, 337 referenced += page_referenced_one(page, vma, &mapcount);
338 ignore_token);
339 if (!mapcount) 338 if (!mapcount)
340 break; 339 break;
341 } 340 }
@@ -354,7 +353,7 @@ static int page_referenced_anon(struct page *page, int ignore_token)
354 * 353 *
355 * This function is only called from page_referenced for object-based pages. 354 * This function is only called from page_referenced for object-based pages.
356 */ 355 */
357static int page_referenced_file(struct page *page, int ignore_token) 356static int page_referenced_file(struct page *page)
358{ 357{
359 unsigned int mapcount; 358 unsigned int mapcount;
360 struct address_space *mapping = page->mapping; 359 struct address_space *mapping = page->mapping;
@@ -392,8 +391,7 @@ static int page_referenced_file(struct page *page, int ignore_token)
392 referenced++; 391 referenced++;
393 break; 392 break;
394 } 393 }
395 referenced += page_referenced_one(page, vma, &mapcount, 394 referenced += page_referenced_one(page, vma, &mapcount);
396 ignore_token);
397 if (!mapcount) 395 if (!mapcount)
398 break; 396 break;
399 } 397 }
@@ -410,13 +408,10 @@ static int page_referenced_file(struct page *page, int ignore_token)
410 * Quick test_and_clear_referenced for all mappings to a page, 408 * Quick test_and_clear_referenced for all mappings to a page,
411 * returns the number of ptes which referenced the page. 409 * returns the number of ptes which referenced the page.
412 */ 410 */
413int page_referenced(struct page *page, int is_locked, int ignore_token) 411int page_referenced(struct page *page, int is_locked)
414{ 412{
415 int referenced = 0; 413 int referenced = 0;
416 414
417 if (!swap_token_default_timeout)
418 ignore_token = 1;
419
420 if (page_test_and_clear_young(page)) 415 if (page_test_and_clear_young(page))
421 referenced++; 416 referenced++;
422 417
@@ -425,15 +420,14 @@ int page_referenced(struct page *page, int is_locked, int ignore_token)
425 420
426 if (page_mapped(page) && page->mapping) { 421 if (page_mapped(page) && page->mapping) {
427 if (PageAnon(page)) 422 if (PageAnon(page))
428 referenced += page_referenced_anon(page, ignore_token); 423 referenced += page_referenced_anon(page);
429 else if (is_locked) 424 else if (is_locked)
430 referenced += page_referenced_file(page, ignore_token); 425 referenced += page_referenced_file(page);
431 else if (TestSetPageLocked(page)) 426 else if (TestSetPageLocked(page))
432 referenced++; 427 referenced++;
433 else { 428 else {
434 if (page->mapping) 429 if (page->mapping)
435 referenced += page_referenced_file(page, 430 referenced += page_referenced_file(page);
436 ignore_token);
437 unlock_page(page); 431 unlock_page(page);
438 } 432 }
439 } 433 }