@@ -135,6 +135,27 @@ module_param(log_stats, int, 0644);
/* Number of free pages to remove on each call to gnttab_free_pages */
#define NUM_BATCH_FREE_PAGES 10
+/*
+ * Once a memory pressure is detected, keep aggressive shrinking of the free
+ * page pools for this time (msec)
+ */
+#define AGGRESSIVE_SHRINKING_DURATION 1
+
+static unsigned long xen_blk_mem_pressure_end;
+
+static unsigned long blkif_shrink_count(struct shrinker *shrinker,
+ struct shrink_control *sc)
+{
+ xen_blk_mem_pressure_end = jiffies +
+ msecs_to_jiffies(AGGRESSIVE_SHRINKING_DURATION);
+ return 0;
+}
+
+static struct shrinker blkif_shrinker = {
+ .count_objects = blkif_shrink_count,
+ .seeks = DEFAULT_SEEKS,
+};
+
static inline bool persistent_gnt_timeout(struct persistent_gnt *persistent_gnt)
{
return xen_blkif_pgrant_timeout &&
@@ -656,8 +677,11 @@ int xen_blkif_schedule(void *arg)
ring->next_lru = jiffies + msecs_to_jiffies(LRU_INTERVAL);
}
- /* Shrink if we have more than xen_blkif_max_buffer_pages */
- shrink_free_pagepool(ring, xen_blkif_max_buffer_pages);
+ /* Shrink the free pages pool if it is too large. */
+ if (time_before(jiffies, xen_blk_mem_pressure_end))
+ shrink_free_pagepool(ring, 0);
+ else
+ shrink_free_pagepool(ring, xen_blkif_max_buffer_pages);
if (log_stats && time_after(jiffies, ring->st_print))
print_stats(ring);
@@ -1500,6 +1524,9 @@ static int __init xen_blkif_init(void)
if (rc)
goto failed_init;
+ if (register_shrinker(&blkif_shrinker))
+ pr_warn("shrinker registration failed\n");
+
failed_init:
return rc;
}