|
@@ -303,7 +303,7 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru, int zone
|
|
|
/*
|
|
|
* Add a shrinker callback to be called from the vm.
|
|
|
*/
|
|
|
-int register_shrinker(struct shrinker *shrinker)
|
|
|
+int prealloc_shrinker(struct shrinker *shrinker)
|
|
|
{
|
|
|
size_t size = sizeof(*shrinker->nr_deferred);
|
|
|
|
|
@@ -313,10 +313,29 @@ int register_shrinker(struct shrinker *shrinker)
|
|
|
shrinker->nr_deferred = kzalloc(size, GFP_KERNEL);
|
|
|
if (!shrinker->nr_deferred)
|
|
|
return -ENOMEM;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+void free_prealloced_shrinker(struct shrinker *shrinker)
|
|
|
+{
|
|
|
+ kfree(shrinker->nr_deferred);
|
|
|
+ shrinker->nr_deferred = NULL;
|
|
|
+}
|
|
|
|
|
|
+void register_shrinker_prepared(struct shrinker *shrinker)
|
|
|
+{
|
|
|
down_write(&shrinker_rwsem);
|
|
|
list_add_tail(&shrinker->list, &shrinker_list);
|
|
|
up_write(&shrinker_rwsem);
|
|
|
+}
|
|
|
+
|
|
|
+int register_shrinker(struct shrinker *shrinker)
|
|
|
+{
|
|
|
+ int err = prealloc_shrinker(shrinker);
|
|
|
+
|
|
|
+ if (err)
|
|
|
+ return err;
|
|
|
+ register_shrinker_prepared(shrinker);
|
|
|
return 0;
|
|
|
}
|
|
|
EXPORT_SYMBOL(register_shrinker);
|