1/* 2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. 3 * Copyright (C) 2007 The Regents of the University of California. 4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). 5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>. 6 * UCRL-CODE-235197 7 * 8 * This file is part of the SPL, Solaris Porting Layer. 9 * 10 * The SPL is free software; you can redistribute it and/or modify it 11 * under the terms of the GNU General Public License as published by the 12 * Free Software Foundation; either version 2 of the License, or (at your 13 * option) any later version. 14 * 15 * The SPL is distributed in the hope that it will be useful, but WITHOUT 16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 18 * for more details. 19 * 20 * You should have received a copy of the GNU General Public License along 21 * with the SPL. If not, see <http://www.gnu.org/licenses/>. 22 * 23 * Solaris Porting Layer (SPL) Shrinker Implementation. 24 */ 25 26#include <sys/kmem.h> 27#include <sys/shrinker.h> 28 29#ifdef HAVE_SINGLE_SHRINKER_CALLBACK 30/* 3.0-3.11: single shrink() callback, which we wrap to carry both functions */ 31struct spl_shrinker_wrap { 32 struct shrinker shrinker; 33 spl_shrinker_cb countfunc; 34 spl_shrinker_cb scanfunc; 35}; 36 37static int 38spl_shrinker_single_cb(struct shrinker *shrinker, struct shrink_control *sc) 39{ 40 struct spl_shrinker_wrap *sw = (struct spl_shrinker_wrap *)shrinker; 41 42 if (sc->nr_to_scan != 0) 43 (void) sw->scanfunc(&sw->shrinker, sc); 44 return (sw->countfunc(&sw->shrinker, sc)); 45} 46#endif 47 48struct shrinker * 49spl_register_shrinker(const char *name, spl_shrinker_cb countfunc, 50 spl_shrinker_cb scanfunc, int seek_cost) 51{ 52 struct shrinker *shrinker; 53 54 /* allocate shrinker */ 55#if defined(HAVE_SHRINKER_REGISTER) 56 /* 6.7: kernel will allocate the shrinker for us */ 57 shrinker = shrinker_alloc(0, name); 58#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK) 59 /* 3.12-6.6: we allocate the shrinker */ 60 shrinker = kmem_zalloc(sizeof (struct shrinker), KM_SLEEP); 61#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK) 62 /* 3.0-3.11: allocate a wrapper */ 63 struct spl_shrinker_wrap *sw = 64 kmem_zalloc(sizeof (struct spl_shrinker_wrap), KM_SLEEP); 65 shrinker = &sw->shrinker; 66#else 67 /* 2.x-2.6.22, or a newer shrinker API has been introduced. */ 68#error "Unknown shrinker API" 69#endif 70 71 if (shrinker == NULL) 72 return (NULL); 73 74 /* set callbacks */ 75#ifdef HAVE_SINGLE_SHRINKER_CALLBACK 76 sw->countfunc = countfunc; 77 sw->scanfunc = scanfunc; 78 shrinker->shrink = spl_shrinker_single_cb; 79#else 80 shrinker->count_objects = countfunc; 81 shrinker->scan_objects = scanfunc; 82#endif 83 84 /* set params */ 85 shrinker->seeks = seek_cost; 86 87 /* register with kernel */ 88#if defined(HAVE_SHRINKER_REGISTER) 89 shrinker_register(shrinker); 90#elif defined(HAVE_REGISTER_SHRINKER_VARARG) 91 register_shrinker(shrinker, name); 92#else 93 register_shrinker(shrinker); 94#endif 95 96 return (shrinker); 97} 98EXPORT_SYMBOL(spl_register_shrinker); 99 100void 101spl_unregister_shrinker(struct shrinker *shrinker) 102{ 103#if defined(HAVE_SHRINKER_REGISTER) 104 shrinker_free(shrinker); 105#elif defined(HAVE_SPLIT_SHRINKER_CALLBACK) 106 unregister_shrinker(shrinker); 107 kmem_free(shrinker, sizeof (struct shrinker)); 108#elif defined(HAVE_SINGLE_SHRINKER_CALLBACK) 109 unregister_shrinker(shrinker); 110 kmem_free(shrinker, sizeof (struct spl_shrinker_wrap)); 111#else 112#error "Unknown shrinker API" 113#endif 114} 115EXPORT_SYMBOL(spl_unregister_shrinker); 116