diff options
author | Tim Chase <[email protected]> | 2014-10-02 07:21:08 -0500 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2014-10-28 09:34:51 -0700 |
commit | ed6e9cc235b47b5c940178926715f871bd36dc5e (patch) | |
tree | 53ba7485463ca7c97aa3d2790afab1536919e410 /module/zfs/arc.c | |
parent | 9635861742c6ac334877f944e17948aa11c2e57a (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/zfs/arc.c')
-rw-r--r-- | module/zfs/arc.c | 29 |
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; } /* |