From: Kirill Tkhai <tkhai@xxxxx> This and the next patches in this series aim to make time effect of synchronize_srcu() invisible for user. The patch splits unregister_shrinker() in two functions: unregister_shrinker_delayed_initiate() unregister_shrinker_delayed_finalize() and shrinker users may make the second of them to be called asynchronous (e.g., from workqueue). Next patches make superblock shrinker to follow this way, so user-visible umount() time won't contain delays from synchronize_srcu(). Signed-off-by: Kirill Tkhai <tkhai@xxxxx> Signed-off-by: Qi Zheng <zhengqi.arch@xxxxxxxxxxxxx> --- include/linux/shrinker.h | 2 ++ mm/vmscan.c | 22 ++++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/linux/shrinker.h b/include/linux/shrinker.h index 224293b2dd06..e9d5a19d83fe 100644 --- a/include/linux/shrinker.h +++ b/include/linux/shrinker.h @@ -102,6 +102,8 @@ extern void register_shrinker_prepared(struct shrinker *shrinker); extern int __printf(2, 3) register_shrinker(struct shrinker *shrinker, const char *fmt, ...); extern void unregister_shrinker(struct shrinker *shrinker); +extern void unregister_shrinker_delayed_initiate(struct shrinker *shrinker); +extern void unregister_shrinker_delayed_finalize(struct shrinker *shrinker); extern void free_prealloced_shrinker(struct shrinker *shrinker); extern void synchronize_shrinkers(void); diff --git a/mm/vmscan.c b/mm/vmscan.c index a773e97e152e..baf8d2327d70 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -799,10 +799,7 @@ int register_shrinker(struct shrinker *shrinker, const char *fmt, ...) #endif EXPORT_SYMBOL(register_shrinker); -/* - * Remove one - */ -void unregister_shrinker(struct shrinker *shrinker) +void unregister_shrinker_delayed_initiate(struct shrinker *shrinker) { struct dentry *debugfs_entry; int debugfs_id; @@ -819,6 +816,13 @@ void unregister_shrinker(struct shrinker *shrinker) mutex_unlock(&shrinker_mutex); shrinker_debugfs_remove(debugfs_entry, debugfs_id); +} +EXPORT_SYMBOL(unregister_shrinker_delayed_initiate); + +void unregister_shrinker_delayed_finalize(struct shrinker *shrinker) +{ + if (!shrinker->nr_deferred) + return; atomic_inc(&shrinker_srcu_generation); synchronize_srcu(&shrinker_srcu); @@ -826,6 +830,16 @@ void unregister_shrinker(struct shrinker *shrinker) kfree(shrinker->nr_deferred); shrinker->nr_deferred = NULL; } +EXPORT_SYMBOL(unregister_shrinker_delayed_finalize); + +/* + * Remove one + */ +void unregister_shrinker(struct shrinker *shrinker) +{ + unregister_shrinker_delayed_initiate(shrinker); + unregister_shrinker_delayed_finalize(shrinker); +} EXPORT_SYMBOL(unregister_shrinker); /** -- 2.30.2