diff options
-rw-r--r-- | mm/vmscan.c | 84 |
1 files changed, 8 insertions, 76 deletions
diff --git a/mm/vmscan.c b/mm/vmscan.c index ac644fe85589..3886b0bd7869 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c | |||
@@ -3417,66 +3417,12 @@ void scan_mapping_unevictable_pages(struct address_space *mapping) | |||
3417 | 3417 | ||
3418 | } | 3418 | } |
3419 | 3419 | ||
3420 | /** | 3420 | static void warn_scan_unevictable_pages(void) |
3421 | * scan_zone_unevictable_pages - check unevictable list for evictable pages | ||
3422 | * @zone - zone of which to scan the unevictable list | ||
3423 | * | ||
3424 | * Scan @zone's unevictable LRU lists to check for pages that have become | ||
3425 | * evictable. Move those that have to @zone's inactive list where they | ||
3426 | * become candidates for reclaim, unless shrink_inactive_zone() decides | ||
3427 | * to reactivate them. Pages that are still unevictable are rotated | ||
3428 | * back onto @zone's unevictable list. | ||
3429 | */ | ||
3430 | #define SCAN_UNEVICTABLE_BATCH_SIZE 16UL /* arbitrary lock hold batch size */ | ||
3431 | static void scan_zone_unevictable_pages(struct zone *zone) | ||
3432 | { | 3421 | { |
3433 | struct list_head *l_unevictable = &zone->lru[LRU_UNEVICTABLE].list; | 3422 | printk_once(KERN_WARNING |
3434 | unsigned long scan; | 3423 | "The scan_unevictable_pages sysctl/node-interface has been " |
3435 | unsigned long nr_to_scan = zone_page_state(zone, NR_UNEVICTABLE); | 3424 | "disabled for lack of a legitimate use case. If you have " |
3436 | 3425 | "one, please send an email to linux-mm@kvack.org.\n"); | |
3437 | while (nr_to_scan > 0) { | ||
3438 | unsigned long batch_size = min(nr_to_scan, | ||
3439 | SCAN_UNEVICTABLE_BATCH_SIZE); | ||
3440 | |||
3441 | spin_lock_irq(&zone->lru_lock); | ||
3442 | for (scan = 0; scan < batch_size; scan++) { | ||
3443 | struct page *page = lru_to_page(l_unevictable); | ||
3444 | |||
3445 | if (!trylock_page(page)) | ||
3446 | continue; | ||
3447 | |||
3448 | prefetchw_prev_lru_page(page, l_unevictable, flags); | ||
3449 | |||
3450 | if (likely(PageLRU(page) && PageUnevictable(page))) | ||
3451 | check_move_unevictable_page(page, zone); | ||
3452 | |||
3453 | unlock_page(page); | ||
3454 | } | ||
3455 | spin_unlock_irq(&zone->lru_lock); | ||
3456 | |||
3457 | nr_to_scan -= batch_size; | ||
3458 | } | ||
3459 | } | ||
3460 | |||
3461 | |||
3462 | /** | ||
3463 | * scan_all_zones_unevictable_pages - scan all unevictable lists for evictable pages | ||
3464 | * | ||
3465 | * A really big hammer: scan all zones' unevictable LRU lists to check for | ||
3466 | * pages that have become evictable. Move those back to the zones' | ||
3467 | * inactive list where they become candidates for reclaim. | ||
3468 | * This occurs when, e.g., we have unswappable pages on the unevictable lists, | ||
3469 | * and we add swap to the system. As such, it runs in the context of a task | ||
3470 | * that has possibly/probably made some previously unevictable pages | ||
3471 | * evictable. | ||
3472 | */ | ||
3473 | static void scan_all_zones_unevictable_pages(void) | ||
3474 | { | ||
3475 | struct zone *zone; | ||
3476 | |||
3477 | for_each_zone(zone) { | ||
3478 | scan_zone_unevictable_pages(zone); | ||
3479 | } | ||
3480 | } | 3426 | } |
3481 | 3427 | ||
3482 | /* | 3428 | /* |
@@ -3489,11 +3435,8 @@ int scan_unevictable_handler(struct ctl_table *table, int write, | |||
3489 | void __user *buffer, | 3435 | void __user *buffer, |
3490 | size_t *length, loff_t *ppos) | 3436 | size_t *length, loff_t *ppos) |
3491 | { | 3437 | { |
3438 | warn_scan_unevictable_pages(); | ||
3492 | proc_doulongvec_minmax(table, write, buffer, length, ppos); | 3439 | proc_doulongvec_minmax(table, write, buffer, length, ppos); |
3493 | |||
3494 | if (write && *(unsigned long *)table->data) | ||
3495 | scan_all_zones_unevictable_pages(); | ||
3496 | |||
3497 | scan_unevictable_pages = 0; | 3440 | scan_unevictable_pages = 0; |
3498 | return 0; | 3441 | return 0; |
3499 | } | 3442 | } |
@@ -3508,6 +3451,7 @@ static ssize_t read_scan_unevictable_node(struct sys_device *dev, | |||
3508 | struct sysdev_attribute *attr, | 3451 | struct sysdev_attribute *attr, |
3509 | char *buf) | 3452 | char *buf) |
3510 | { | 3453 | { |
3454 | warn_scan_unevictable_pages(); | ||
3511 | return sprintf(buf, "0\n"); /* always zero; should fit... */ | 3455 | return sprintf(buf, "0\n"); /* always zero; should fit... */ |
3512 | } | 3456 | } |
3513 | 3457 | ||
@@ -3515,19 +3459,7 @@ static ssize_t write_scan_unevictable_node(struct sys_device *dev, | |||
3515 | struct sysdev_attribute *attr, | 3459 | struct sysdev_attribute *attr, |
3516 | const char *buf, size_t count) | 3460 | const char *buf, size_t count) |
3517 | { | 3461 | { |
3518 | struct zone *node_zones = NODE_DATA(dev->id)->node_zones; | 3462 | warn_scan_unevictable_pages(); |
3519 | struct zone *zone; | ||
3520 | unsigned long res; | ||
3521 | unsigned long req = strict_strtoul(buf, 10, &res); | ||
3522 | |||
3523 | if (req || !res) | ||
3524 | return 1; /* Invalid input or zero is no-op */ | ||
3525 | |||
3526 | for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { | ||
3527 | if (!populated_zone(zone)) | ||
3528 | continue; | ||
3529 | scan_zone_unevictable_pages(zone); | ||
3530 | } | ||
3531 | return 1; | 3463 | return 1; |
3532 | } | 3464 | } |
3533 | 3465 | ||