On Wed, May 31, 2023 at 09:57:36AM +0000, Qi Zheng wrote: > 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; This is new logic and isn't explained anywhere: why do we want to avoid RCU cleanup if (shrinker->nr_deferred == 0)? Regardless, whatever this is avoiding, it needs a comment to explain it. -Dave. -- Dave Chinner david@xxxxxxxxxxxxx