mm: shrinker: make global slab shrink lockless
[linux-2.6-block.git] / include / linux / shrinker.h
index ba5ac82b5dbd1cba1341def4501d24ec48e83864..e4f93120e0ab8a4c4342e165f3b0ad3290b8cb2f 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <linux/atomic.h>
 #include <linux/types.h>
+#include <linux/refcount.h>
+#include <linux/completion.h>
 
 #define SHRINKER_UNIT_BITS     BITS_PER_LONG
 
@@ -87,6 +89,17 @@ struct shrinker {
        int seeks;      /* seeks to recreate an obj */
        unsigned flags;
 
+       /*
+        * The reference count of this shrinker. Registered shrinker have an
+        * initial refcount of 1, then the lookup operations are now allowed
+        * to use it via shrinker_try_get(). Later in the unregistration step,
+        * the initial refcount will be discarded, and will free the shrinker
+        * asynchronously via RCU after its refcount reaches 0.
+        */
+       refcount_t refcount;
+       struct completion done; /* use to wait for refcount to reach 0 */
+       struct rcu_head rcu;
+
        void *private_data;
 
        /* These are for internal use */
@@ -122,6 +135,17 @@ struct shrinker *shrinker_alloc(unsigned int flags, const char *fmt, ...);
 void shrinker_register(struct shrinker *shrinker);
 void shrinker_free(struct shrinker *shrinker);
 
+static inline bool shrinker_try_get(struct shrinker *shrinker)
+{
+       return refcount_inc_not_zero(&shrinker->refcount);
+}
+
+static inline void shrinker_put(struct shrinker *shrinker)
+{
+       if (refcount_dec_and_test(&shrinker->refcount))
+               complete(&shrinker->done);
+}
+
 #ifdef CONFIG_SHRINKER_DEBUG
 extern int __printf(2, 3) shrinker_debugfs_rename(struct shrinker *shrinker,
                                                  const char *fmt, ...);