int register_shrinker(struct shrinker *);
void unregister_shrinker(struct shrinker *);
-void run_shrinkers(void);
+void run_shrinkers(gfp_t gfp_mask, bool);
#endif /* __TOOLS_LINUX_SHRINKER_H */
void *p;
do {
- run_shrinkers();
+ run_shrinkers(flags, i != 0);
if (size) {
size_t alignment = min(rounddown_pow_of_two(size), (size_t)PAGE_SIZE);
void *p;
do {
- run_shrinkers();
+ run_shrinkers(flags, i != 0);
p = aligned_alloc(PAGE_SIZE, size);
if (p && (flags & __GFP_ZERO))
size = round_up(size, PAGE_SIZE);
do {
- run_shrinkers();
+ run_shrinkers(gfp_mask, i != 0);
p = aligned_alloc(PAGE_SIZE, size);
if (p && gfp_mask & __GFP_ZERO)
return ret;
}
-void run_shrinkers(void)
+static void run_shrinkers_allocation_failed(gfp_t gfp_mask)
+{
+ struct shrinker *shrinker;
+
+ mutex_lock(&shrinker_lock);
+ list_for_each_entry(shrinker, &shrinker_list, list) {
+ struct shrink_control sc = { .gfp_mask = gfp_mask, };
+
+ unsigned long have = shrinker->count_objects(shrinker, &sc);
+
+ sc.nr_to_scan = have / 8;
+
+ shrinker->scan_objects(shrinker, &sc);
+ }
+ mutex_unlock(&shrinker_lock);
+}
+
+void run_shrinkers(gfp_t gfp_mask, bool allocation_failed)
{
struct shrinker *shrinker;
struct meminfo info;
if (list_empty(&shrinker_list))
return;
+ if (allocation_failed) {
+ run_shrinkers_allocation_failed(gfp_mask);
+ return;
+ }
+
info = read_meminfo();
if (info.total && info.available) {
mutex_lock(&shrinker_lock);
list_for_each_entry(shrinker, &shrinker_list, list) {
struct shrink_control sc = {
- .nr_to_scan = want_shrink >> PAGE_SHIFT
+ .gfp_mask = gfp_mask,
+ .nr_to_scan = want_shrink >> PAGE_SHIFT
};
shrinker->scan_objects(shrinker, &sc);