aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorTim Chase <[email protected]>2014-10-02 07:21:08 -0500
committerBrian Behlendorf <[email protected]>2014-10-28 09:34:51 -0700
commited6e9cc235b47b5c940178926715f871bd36dc5e (patch)
tree53ba7485463ca7c97aa3d2790afab1536919e410 /module
parent9635861742c6ac334877f944e17948aa11c2e57a (diff)
Linux 3.12 compat: shrinker semantics
The new shrinker API as of Linux 3.12 modifies "struct shrinker" by replacing the @shrink callback with the pair of @count_objects and @scan_objects. It also requires the return value of @count_objects to return the number of objects actually freed whereas the previous @shrink callback returned the number of remaining freeable objects. This patch adds support for the new @scan_objects return value semantics. Signed-off-by: Brian Behlendorf <[email protected]> Signed-off-by: Tim Chase <[email protected]> Closes #2837
Diffstat (limited to 'module')
-rw-r--r--module/zfs/arc.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/module/zfs/arc.c b/module/zfs/arc.c
index b42bb4050..96e17b61e 100644
--- a/module/zfs/arc.c
+++ b/module/zfs/arc.c
@@ -2604,27 +2604,39 @@ arc_evictable_memory(void) {
return (ghost_clean + MAX((int64_t)arc_size - (int64_t)arc_c_min, 0));
}
-static int
+/*
+ * If sc->nr_to_scan is zero, the caller is requesting a query of the
+ * number of objects which can potentially be freed. If it is nonzero,
+ * the request is to free that many objects.
+ *
+ * Linux kernels >= 3.12 have the count_objects and scan_objects callbacks
+ * in struct shrinker and also require the shrinker to return the number
+ * of objects freed.
+ *
+ * Older kernels require the shrinker to return the number of freeable
+ * objects following the freeing of nr_to_free.
+ */
+static spl_shrinker_t
__arc_shrinker_func(struct shrinker *shrink, struct shrink_control *sc)
{
- uint64_t pages;
+ int64_t pages;
/* The arc is considered warm once reclaim has occurred */
if (unlikely(arc_warm == B_FALSE))
arc_warm = B_TRUE;
/* Return the potential number of reclaimable pages */
- pages = btop(arc_evictable_memory());
+ pages = btop((int64_t)arc_evictable_memory());
if (sc->nr_to_scan == 0)
return (pages);
/* Not allowed to perform filesystem reclaim */
if (!(sc->gfp_mask & __GFP_FS))
- return (-1);
+ return (SHRINK_STOP);
/* Reclaim in progress */
if (mutex_tryenter(&arc_reclaim_thr_lock) == 0)
- return (-1);
+ return (SHRINK_STOP);
/*
* Evict the requested number of pages by shrinking arc_c the
@@ -2633,10 +2645,15 @@ __arc_shrinker_func(struct shrinker *shrink, struct shrink_control *sc)
*/
if (pages > 0) {
arc_kmem_reap_now(ARC_RECLAIM_AGGR, ptob(sc->nr_to_scan));
+
+#ifdef HAVE_SPLIT_SHRINKER_CALLBACK
+ pages = MAX(pages - btop(arc_evictable_memory()), 0);
+#else
pages = btop(arc_evictable_memory());
+#endif
} else {
arc_kmem_reap_now(ARC_RECLAIM_CONS, ptob(sc->nr_to_scan));
- pages = -1;
+ pages = SHRINK_STOP;
}
/*