diff options
author | Hugh Dickins <hughd@google.com> | 2012-01-20 17:34:19 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-01-23 11:38:48 -0500 |
commit | 85046579bde15e532983438f86b36856e358f417 (patch) | |
tree | 9b80b31791e63520277617a5abe85692dc480cd0 /mm | |
parent | cb78edfdcef5259ac9e9088bd63810d21299928d (diff) |
SHM_UNLOCK: fix long unpreemptible section
scan_mapping_unevictable_pages() is used to make SysV SHM_LOCKed pages
evictable again once the shared memory is unlocked. It does this with
pagevec_lookup()s across the whole object (which might occupy most of
memory), and takes 300ms to unlock 7GB here. A cond_resched() every
PAGEVEC_SIZE pages would be good.
However, KOSAKI-san points out that this is called under shmem.c's
info->lock, and it's also under shm.c's shm_lock(), both spinlocks.
There is no strong reason for that: we need to take these pages off the
unevictable list soonish, but those locks are not required for it.
So move the call to scan_mapping_unevictable_pages() from shmem.c's
unlock handling up to shm.c's unlock handling. Remove the recently
added barrier, not needed now we have spin_unlock() before the scan.
Use get_file(), with subsequent fput(), to make sure we have a reference
to mapping throughout scan_mapping_unevictable_pages(): that's something
that was previously guaranteed by the shm_lock().
Remove shmctl's lru_add_drain_all(): we don't fault in pages at SHM_LOCK
time, and we lazily discover them to be Unevictable later, so it serves
no purpose for SHM_LOCK; and serves no purpose for SHM_UNLOCK, since
pages still on pagevec are not marked Unevictable.
The original code avoided redundant rescans by checking VM_LOCKED flag
at its level: now avoid them by checking shp's SHM_LOCKED.
The original code called scan_mapping_unevictable_pages() on a locked
area at shm_destroy() time: perhaps we once had accounting cross-checks
which required that, but not now, so skip the overhead and just let
inode eviction deal with them.
Put check_move_unevictable_page() and scan_mapping_unevictable_pages()
under CONFIG_SHMEM (with stub for the TINY case when ramfs is used),
more as comment than to save space; comment them used for SHM_UNLOCK.
Signed-off-by: Hugh Dickins <hughd@google.com>
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Minchan Kim <minchan.kim@gmail.com>
Cc: Rik van Riel <riel@redhat.com>
Cc: Shaohua Li <shaohua.li@intel.com>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michel Lespinasse <walken@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/shmem.c | 7 | ||||
-rw-r--r-- | mm/vmscan.c | 12 |
2 files changed, 11 insertions, 8 deletions
diff --git a/mm/shmem.c b/mm/shmem.c index feead1943d92..4aaa53abe302 100644 --- a/mm/shmem.c +++ b/mm/shmem.c | |||
@@ -1068,13 +1068,6 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user) | |||
1068 | user_shm_unlock(inode->i_size, user); | 1068 | user_shm_unlock(inode->i_size, user); |
1069 | info->flags &= ~VM_LOCKED; | 1069 | info->flags &= ~VM_LOCKED; |
1070 | mapping_clear_unevictable(file->f_mapping); | 1070 | mapping_clear_unevictable(file->f_mapping); |
1071 | /* | ||
1072 | * Ensure that a racing putback_lru_page() can see | ||
1073 | * the pages of this mapping are evictable when we | ||
1074 | * skip them due to !PageLRU during the scan. | ||
1075 | */ | ||
1076 | smp_mb__after_clear_bit(); | ||
1077 | scan_mapping_unevictable_pages(file->f_mapping); | ||
1078 | } | 1071 | } |
1079 | retval = 0; | 1072 | retval = 0; |
1080 | 1073 | ||
diff --git a/mm/vmscan.c b/mm/vmscan.c index 2880396f7953..e097c1026b58 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -3499,6 +3499,7 @@ int page_evictable(struct page *page, struct vm_area_struct *vma) | |||
3499 | return 1; | 3499 | return 1; |
3500 | } | 3500 | } |
3501 | 3501 | ||
3502 | #ifdef CONFIG_SHMEM | ||
3502 | /** | 3503 | /** |
3503 | * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list | 3504 | * check_move_unevictable_page - check page for evictability and move to appropriate zone lru list |
3504 | * @page: page to check evictability and move to appropriate lru list | 3505 | * @page: page to check evictability and move to appropriate lru list |
@@ -3509,6 +3510,8 @@ int page_evictable(struct page *page, struct vm_area_struct *vma) | |||
3509 | * | 3510 | * |
3510 | * Restrictions: zone->lru_lock must be held, page must be on LRU and must | 3511 | * Restrictions: zone->lru_lock must be held, page must be on LRU and must |
3511 | * have PageUnevictable set. | 3512 | * have PageUnevictable set. |
3513 | * | ||
3514 | * This function is only used for SysV IPC SHM_UNLOCK. | ||
3512 | */ | 3515 | */ |
3513 | static void check_move_unevictable_page(struct page *page, struct zone *zone) | 3516 | static void check_move_unevictable_page(struct page *page, struct zone *zone) |
3514 | { | 3517 | { |
@@ -3545,6 +3548,8 @@ retry: | |||
3545 | * | 3548 | * |
3546 | * Scan all pages in mapping. Check unevictable pages for | 3549 | * Scan all pages in mapping. Check unevictable pages for |
3547 | * evictability and move them to the appropriate zone lru list. | 3550 | * evictability and move them to the appropriate zone lru list. |
3551 | * | ||
3552 | * This function is only used for SysV IPC SHM_UNLOCK. | ||
3548 | */ | 3553 | */ |
3549 | void scan_mapping_unevictable_pages(struct address_space *mapping) | 3554 | void scan_mapping_unevictable_pages(struct address_space *mapping) |
3550 | { | 3555 | { |
@@ -3590,9 +3595,14 @@ void scan_mapping_unevictable_pages(struct address_space *mapping) | |||
3590 | pagevec_release(&pvec); | 3595 | pagevec_release(&pvec); |
3591 | 3596 | ||
3592 | count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned); | 3597 | count_vm_events(UNEVICTABLE_PGSCANNED, pg_scanned); |
3598 | cond_resched(); | ||
3593 | } | 3599 | } |
3594 | |||
3595 | } | 3600 | } |
3601 | #else | ||
3602 | void scan_mapping_unevictable_pages(struct address_space *mapping) | ||
3603 | { | ||
3604 | } | ||
3605 | #endif /* CONFIG_SHMEM */ | ||
3596 | 3606 | ||
3597 | static void warn_scan_unevictable_pages(void) | 3607 | static void warn_scan_unevictable_pages(void) |
3598 | { | 3608 | { |