get_scan_count

来源:互联网 发布:30岁转行程序员 编辑:程序博客网 时间:2024/05/04 15:07


/*
 * Determine how aggressively the anon and file LRU lists should be
 * scanned.  The relative value of each set of LRU lists is determined
 * by looking at the fraction of the pages scanned we did rotate back
 * onto the active list instead of evict.
 *
 * nr[0] = anon inactive pages to scan; nr[1] = anon active pages to scan
 * nr[2] = file inactive pages to scan; nr[3] = file active pages to scan
 */
static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
  struct scan_control *sc, unsigned long *nr, unsigned long *lru_pages)
{
int swappiness = mem_cgroup_swappiness(memcg);
struct zone_reclaim_stat *reclaim_stat = &lruvec->reclaim_stat;
u64 fraction[2];
u64 denominator = 0;/* gcc */
struct zone *zone = lruvec_zone(lruvec);
unsigned long anon_prio, file_prio;
enum scan_balance scan_balance;
unsigned long anon, file;
bool force_scan = false;
unsigned long ap, fp;
enum lru_list lru;
bool some_scanned;
int pass;



if (current_is_kswapd()) {
if (!zone_reclaimable(zone))
force_scan = true;
if (!mem_cgroup_online(memcg))
force_scan = true;
}
if (!global_reclaim(sc))
force_scan = true;


/* If we have no swap space, do not bother scanning anon pages. */
if (!sc->may_swap || mem_cgroup_get_nr_swap_pages(memcg) <= 0) {
scan_balance = SCAN_FILE;
goto out;
}


if (!global_reclaim(sc) && !swappiness) {
scan_balance = SCAN_FILE;
goto out;
}

if (!sc->priority && swappiness) {
scan_balance = SCAN_EQUAL;
goto out;
}


if (global_reclaim(sc)) {
unsigned long zonefile;
unsigned long zonefree;


zonefree = zone_page_state(zone, NR_FREE_PAGES);

zonefile = zone_page_state(zone, NR_ACTIVE_FILE) +  zone_page_state(zone, NR_INACTIVE_FILE);


if (unlikely(zonefile + zonefree <= high_wmark_pages(zone))) {
scan_balance = SCAN_ANON;
goto out;
}
}

if (!inactive_list_is_low(lruvec, true) && lruvec_lru_size(lruvec, LRU_INACTIVE_FILE) >> sc->priority) {
scan_balance = SCAN_FILE;
goto out;
}


scan_balance = SCAN_FRACT;

anon_prio = swappiness;
file_prio = 200 - anon_prio;

anon  = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON) + lruvec_lru_size(lruvec, LRU_INACTIVE_ANON);
file  = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE) + lruvec_lru_size(lruvec, LRU_INACTIVE_FILE);


spin_lock_irq(&zone->lru_lock);
if (unlikely(reclaim_stat->recent_scanned[0] > anon / 4)) {
reclaim_stat->recent_scanned[0] /= 2;
reclaim_stat->recent_rotated[0] /= 2;
}


if (unlikely(reclaim_stat->recent_scanned[1] > file / 4)) {
reclaim_stat->recent_scanned[1] /= 2;
reclaim_stat->recent_rotated[1] /= 2;
}

ap = anon_prio * (reclaim_stat->recent_scanned[0] + 1);
ap /= reclaim_stat->recent_rotated[0] + 1;


fp = file_prio * (reclaim_stat->recent_scanned[1] + 1);
fp /= reclaim_stat->recent_rotated[1] + 1;
spin_unlock_irq(&zone->lru_lock);


fraction[0] = ap;
fraction[1] = fp;
denominator = ap + fp + 1;
out:
some_scanned = false;
/* Only use force_scan on second pass. */
for (pass = 0; !some_scanned && pass < 2; pass++) {
*lru_pages = 0;
for_each_evictable_lru(lru) {
int file = is_file_lru(lru);
unsigned long size;
unsigned long scan;


size = lruvec_lru_size(lruvec, lru);
scan = size >> sc->priority;


if (!scan && pass && force_scan)
scan = min(size, SWAP_CLUSTER_MAX);


switch (scan_balance) {
case SCAN_EQUAL:
/* Scan lists relative to size */
break;
case SCAN_FRACT:
scan = div64_u64(scan * fraction[file],denominator);
break;
case SCAN_FILE:
case SCAN_ANON:
/* Scan one type exclusively */
if ((scan_balance == SCAN_FILE) != file) {
size = 0;
scan = 0;
}
break;
default:
/* Look ma, no brain */
BUG();
}

*lru_pages += size;
nr[lru] = scan;

/*
* Skip the second pass and don't force_scan,if we found something to scan.
*/
some_scanned |= !!scan;
}
}
}
0 0
原创粉丝点击