Messages in this thread | | | Date | Wed, 26 Jul 2023 17:20:49 +0800 | Subject | Re: [PATCH v2 03/47] mm: shrinker: add infrastructure for dynamically allocating shrinker | From | Qi Zheng <> |
| |
Hi Dave,
On 2023/7/26 15:26, Dave Chinner wrote: > On Mon, Jul 24, 2023 at 05:43:10PM +0800, Qi Zheng wrote: >> Currently, the shrinker instances can be divided into the following three >> types: >> >> a) global shrinker instance statically defined in the kernel, such as >> workingset_shadow_shrinker. >> >> b) global shrinker instance statically defined in the kernel modules, such >> as mmu_shrinker in x86. >> >> c) shrinker instance embedded in other structures. >> >> For case a, the memory of shrinker instance is never freed. For case b, >> the memory of shrinker instance will be freed after synchronize_rcu() when >> the module is unloaded. For case c, the memory of shrinker instance will >> be freed along with the structure it is embedded in. >> >> In preparation for implementing lockless slab shrink, we need to >> dynamically allocate those shrinker instances in case c, then the memory >> can be dynamically freed alone by calling kfree_rcu(). >> >> So this commit adds the following new APIs for dynamically allocating >> shrinker, and add a private_data field to struct shrinker to record and >> get the original embedded structure. >> >> 1. shrinker_alloc() >> >> Used to allocate shrinker instance itself and related memory, it will >> return a pointer to the shrinker instance on success and NULL on failure. >> >> 2. shrinker_free_non_registered() >> >> Used to destroy the non-registered shrinker instance. > > This is a bit nasty > >> >> 3. shrinker_register() >> >> Used to register the shrinker instance, which is same as the current >> register_shrinker_prepared(). >> >> 4. shrinker_unregister() > > rename this "shrinker_free()" and key the two different freeing > cases on the SHRINKER_REGISTERED bit rather than mostly duplicating > the two.
OK, will do in the next version.
> > void shrinker_free(struct shrinker *shrinker) > { > struct dentry *debugfs_entry = NULL; > int debugfs_id; > > if (!shrinker) > return; > > down_write(&shrinker_rwsem); > if (shrinker->flags & SHRINKER_REGISTERED) { > list_del(&shrinker->list); > debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id); > } else if (IS_ENABLED(CONFIG_SHRINKER_DEBUG)) { > kfree_const(shrinker->name); > } > > if (shrinker->flags & SHRINKER_MEMCG_AWARE) > unregister_memcg_shrinker(shrinker); > up_write(&shrinker_rwsem); > > if (debugfs_entry) > shrinker_debugfs_remove(debugfs_entry, debugfs_id); > > kfree(shrinker->nr_deferred); > kfree(shrinker); > } > EXPORT_SYMBOL_GPL(shrinker_free);
Ah, I will change all new APIs to use EXPORT_SYMBOL_GPL().
Thanks, Qi
>
| |