Introduce some helpers for dynamically allocating shrinker instance, and their uses are as follows: 1. shrinker_alloc_and_init() Used to allocate and initialize a shrinker instance, the priv_data parameter is used to pass the pointer of the previously embedded structure of the shrinker instance. 2. shrinker_free() Used to free the shrinker instance when the registration of shrinker fails. 3. unregister_and_free_shrinker() Used to unregister and free the shrinker instance, and the kfree() will be changed to kfree_rcu() later. Signed-off-by: Qi Zheng <zhengqi.arch@xxxxxxxxxxxxx> --- include/linux/shrinker.h | 12 ++++++++++++ mm/vmscan.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 43e6fcabbf51..8e9ba6fa3fcc 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -107,6 +107,18 @@ extern void unregister_shrinker(struct shrinker *shrinker); extern void free_prealloced_shrinker(struct shrinker *shrinker); extern void synchronize_shrinkers(void); +typedef unsigned long (*count_objects_cb)(struct shrinker *s, + struct shrink_control *sc); +typedef unsigned long (*scan_objects_cb)(struct shrinker *s, + struct shrink_control *sc); + +struct shrinker *shrinker_alloc_and_init(count_objects_cb count, + scan_objects_cb scan, long batch, + int seeks, unsigned flags, + void *priv_data); +void shrinker_free(struct shrinker *shrinker); +void unregister_and_free_shrinker(struct shrinker *shrinker); + #ifdef CONFIG_SHRINKER_DEBUG extern int shrinker_debugfs_add(struct shrinker *shrinker); extern struct dentry *shrinker_debugfs_detach(struct shrinker *shrinker, diff --git a/mm/vmscan.c b/mm/vmscan.c index 45d17c7cc555..64ff598fbad9 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -809,6 +809,41 @@ void unregister_shrinker(struct shrinker *shrinker) } EXPORT_SYMBOL(unregister_shrinker); +struct shrinker *shrinker_alloc_and_init(count_objects_cb count, + scan_objects_cb scan, long batch, + int seeks, unsigned flags, + void *priv_data) +{ + struct shrinker *shrinker; + + shrinker = kzalloc(sizeof(struct shrinker), GFP_KERNEL); + if (!shrinker) + return NULL; + + shrinker->count_objects = count; + shrinker->scan_objects = scan; + shrinker->batch = batch; + shrinker->seeks = seeks; + shrinker->flags = flags; + shrinker->private_data = priv_data; + + return shrinker; +} +EXPORT_SYMBOL(shrinker_alloc_and_init); + +void shrinker_free(struct shrinker *shrinker) +{ + kfree(shrinker); +} +EXPORT_SYMBOL(shrinker_free); + +void unregister_and_free_shrinker(struct shrinker *shrinker) +{ + unregister_shrinker(shrinker); + kfree(shrinker); +} +EXPORT_SYMBOL(unregister_and_free_shrinker); + /** * synchronize_shrinkers - Wait for all running shrinkers to complete. * -- 2.30.2