Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 18: Page Reclaim and Swapping


struct shrinker *shrinker;
unsigned long ret = 0;
...
list_for_each_entry(shrinker, &shrinker_list, list) {
...

To achieve an even balance between page cache and shrinker cache shrinking, the number of cache
elements to be removed is calculated on the basis of thescannedvalue, which, in turn, is weighted with
theseekfactor of the cache and the maximum number of elements that can be freed by the current
shrinker:

mm/vmscan.c
unsigned long long delta;
unsigned long total_scan;
unsigned long max_pass = (*shrinker->shrinker)(0, gfp_mask);

delta = (4 * scanned) / shrinker->seeks;
delta *= max_pass;
do_div(delta, lru_pages + 1);
shrinker->nr += delta;

if (shrinker->nr > max_pass * 2)
shrinker->nr = max_pass * 2;

By convention, invoking the shrinker function with 0 as argument returns the number of objects in the
cache. The kernel also ensures that never more than half the entries in the cache are freed so that no
endless loop occurs.

The calculated number of objects to be freed is cumulated inshrinker->nr. Shrinking is triggered as
long as this value exceeds theSHRINK_BATCHthreshold value (typically defined as 128):

mm/vmscan.c
total_scan = shrinker->nr;
shrinker->nr = 0;
while (total_scan >= SHRINK_BATCH) {
long this_scan = SHRINK_BATCH;
int shrink_ret;
int nr_before;

nr_before = (*shrinker->shrink)(0, gfp_mask);
shrink_ret = (*shrinker->shrink)(this_scan, gfp_mask);
if (shrink_ret == -1)
break;
if (shrink_ret < nr_before)
ret += nr_before - shrink_ret;
mod_page_state(slabs_scanned, this_scan);
total_scan -= this_scan;

cond_resched();
}

shrinker->nr += total_scan;
}
...
}
Free download pdf