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 */ 31 struct spl_shrinker_wrap { 32 struct shrinker shrinker; 33 spl_shrinker_cb countfunc; 34 spl_shrinker_cb scanfunc; 35 }; 36 37 static int 38 spl_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 48 struct shrinker * 49 spl_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 } 98 EXPORT_SYMBOL(spl_register_shrinker); 99 100 void 101 spl_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 } 115 EXPORT_SYMBOL(spl_unregister_shrinker); 116