diff options
author | Rik van Riel <riel@redhat.com> | 2005-11-28 16:44:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-28 17:42:25 -0500 |
commit | f7b7fd8f3ebbb2810d6893295aa984acd0fd30db (patch) | |
tree | 01afc1edafc50a3c65ec8576c05c60da53d8d242 /mm/rmap.c | |
parent | a93a117eaa0bec426d4671a49bfa96a6fdcd2ac9 (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.c | 26 |
1 files changed, 10 insertions, 16 deletions
@@ -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 | */ |
292 | static int page_referenced_one(struct page *page, | 292 | static 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 | ||
324 | static int page_referenced_anon(struct page *page, int ignore_token) | 324 | static 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 | */ |
357 | static int page_referenced_file(struct page *page, int ignore_token) | 356 | static 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 | */ |
413 | int page_referenced(struct page *page, int is_locked, int ignore_token) | 411 | int 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 | } |