|
@@ -3417,66 +3417,12 @@ void scan_mapping_unevictable_pages(struct address_space *mapping)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-/**
|
|
|
|
- * scan_zone_unevictable_pages - check unevictable list for evictable pages
|
|
|
|
- * @zone - zone of which to scan the unevictable list
|
|
|
|
- *
|
|
|
|
- * Scan @zone's unevictable LRU lists to check for pages that have become
|
|
|
|
- * evictable. Move those that have to @zone's inactive list where they
|
|
|
|
- * become candidates for reclaim, unless shrink_inactive_zone() decides
|
|
|
|
- * to reactivate them. Pages that are still unevictable are rotated
|
|
|
|
- * back onto @zone's unevictable list.
|
|
|
|
- */
|
|
|
|
-#define SCAN_UNEVICTABLE_BATCH_SIZE 16UL /* arbitrary lock hold batch size */
|
|
|
|
-static void scan_zone_unevictable_pages(struct zone *zone)
|
|
|
|
|
|
+static void warn_scan_unevictable_pages(void)
|
|
{
|
|
{
|
|
- struct list_head *l_unevictable = &zone->lru[LRU_UNEVICTABLE].list;
|
|
|
|
- unsigned long scan;
|
|
|
|
- unsigned long nr_to_scan = zone_page_state(zone, NR_UNEVICTABLE);
|
|
|
|
-
|
|
|
|
- while (nr_to_scan > 0) {
|
|
|
|
- unsigned long batch_size = min(nr_to_scan,
|
|
|
|
- SCAN_UNEVICTABLE_BATCH_SIZE);
|
|
|
|
-
|
|
|
|
- spin_lock_irq(&zone->lru_lock);
|
|
|
|
- for (scan = 0; scan < batch_size; scan++) {
|
|
|
|
- struct page *page = lru_to_page(l_unevictable);
|
|
|
|
-
|
|
|
|
- if (!trylock_page(page))
|
|
|
|
- continue;
|
|
|
|
-
|
|
|
|
- prefetchw_prev_lru_page(page, l_unevictable, flags);
|
|
|
|
-
|
|
|
|
- if (likely(PageLRU(page) && PageUnevictable(page)))
|
|
|
|
- check_move_unevictable_page(page, zone);
|
|
|
|
-
|
|
|
|
- unlock_page(page);
|
|
|
|
- }
|
|
|
|
- spin_unlock_irq(&zone->lru_lock);
|
|
|
|
-
|
|
|
|
- nr_to_scan -= batch_size;
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * scan_all_zones_unevictable_pages - scan all unevictable lists for evictable pages
|
|
|
|
- *
|
|
|
|
- * A really big hammer: scan all zones' unevictable LRU lists to check for
|
|
|
|
- * pages that have become evictable. Move those back to the zones'
|
|
|
|
- * inactive list where they become candidates for reclaim.
|
|
|
|
- * This occurs when, e.g., we have unswappable pages on the unevictable lists,
|
|
|
|
- * and we add swap to the system. As such, it runs in the context of a task
|
|
|
|
- * that has possibly/probably made some previously unevictable pages
|
|
|
|
- * evictable.
|
|
|
|
- */
|
|
|
|
-static void scan_all_zones_unevictable_pages(void)
|
|
|
|
-{
|
|
|
|
- struct zone *zone;
|
|
|
|
-
|
|
|
|
- for_each_zone(zone) {
|
|
|
|
- scan_zone_unevictable_pages(zone);
|
|
|
|
- }
|
|
|
|
|
|
+ printk_once(KERN_WARNING
|
|
|
|
+ "The scan_unevictable_pages sysctl/node-interface has been "
|
|
|
|
+ "disabled for lack of a legitimate use case. If you have "
|
|
|
|
+ "one, please send an email to linux-mm@kvack.org.\n");
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -3489,11 +3435,8 @@ int scan_unevictable_handler(struct ctl_table *table, int write,
|
|
void __user *buffer,
|
|
void __user *buffer,
|
|
size_t *length, loff_t *ppos)
|
|
size_t *length, loff_t *ppos)
|
|
{
|
|
{
|
|
|
|
+ warn_scan_unevictable_pages();
|
|
proc_doulongvec_minmax(table, write, buffer, length, ppos);
|
|
proc_doulongvec_minmax(table, write, buffer, length, ppos);
|
|
-
|
|
|
|
- if (write && *(unsigned long *)table->data)
|
|
|
|
- scan_all_zones_unevictable_pages();
|
|
|
|
-
|
|
|
|
scan_unevictable_pages = 0;
|
|
scan_unevictable_pages = 0;
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -3508,6 +3451,7 @@ static ssize_t read_scan_unevictable_node(struct sys_device *dev,
|
|
struct sysdev_attribute *attr,
|
|
struct sysdev_attribute *attr,
|
|
char *buf)
|
|
char *buf)
|
|
{
|
|
{
|
|
|
|
+ warn_scan_unevictable_pages();
|
|
return sprintf(buf, "0\n"); /* always zero; should fit... */
|
|
return sprintf(buf, "0\n"); /* always zero; should fit... */
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3515,19 +3459,7 @@ static ssize_t write_scan_unevictable_node(struct sys_device *dev,
|
|
struct sysdev_attribute *attr,
|
|
struct sysdev_attribute *attr,
|
|
const char *buf, size_t count)
|
|
const char *buf, size_t count)
|
|
{
|
|
{
|
|
- struct zone *node_zones = NODE_DATA(dev->id)->node_zones;
|
|
|
|
- struct zone *zone;
|
|
|
|
- unsigned long res;
|
|
|
|
- unsigned long req = strict_strtoul(buf, 10, &res);
|
|
|
|
-
|
|
|
|
- if (req || !res)
|
|
|
|
- return 1; /* Invalid input or zero is no-op */
|
|
|
|
-
|
|
|
|
- for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
|
|
|
|
- if (!populated_zone(zone))
|
|
|
|
- continue;
|
|
|
|
- scan_zone_unevictable_pages(zone);
|
|
|
|
- }
|
|
|
|
|
|
+ warn_scan_unevictable_pages();
|
|
return 1;
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|