Commit c0a5b560 authored by Vladimir Davydov's avatar Vladimir Davydov Committed by Linus Torvalds

list_lru: organize all list_lrus to list

To make list_lru memcg aware, we need all list_lrus to be kept on a list
protected by a mutex, so that we could sleep while walking over the
list.

Therefore after this change list_lru_destroy may sleep.  Fortunately,
there is only one user that calls it from an atomic context - it's
put_super - and we can easily fix it by calling list_lru_destroy before
put_super in destroy_locked_super - anyway we don't longer need lrus by
that time.

Another point that should be noted is that list_lru_destroy is allowed
to be called on an uninitialized zeroed-out object, in which case it is
a no-op.  Before this patch this was guaranteed by kfree, but now we
need an explicit check there.
Signed-off-by: default avatarVladimir Davydov <vdavydov@parallels.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Greg Thelen <gthelen@google.com>
Cc: Glauber Costa <glommer@gmail.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Christoph Lameter <cl@linux.com>
Cc: Pekka Enberg <penberg@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Tejun Heo <tj@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ff0b67ef
...@@ -282,6 +282,14 @@ void deactivate_locked_super(struct super_block *s) ...@@ -282,6 +282,14 @@ void deactivate_locked_super(struct super_block *s)
unregister_shrinker(&s->s_shrink); unregister_shrinker(&s->s_shrink);
fs->kill_sb(s); fs->kill_sb(s);
/*
* Since list_lru_destroy() may sleep, we cannot call it from
* put_super(), where we hold the sb_lock. Therefore we destroy
* the lru lists right now.
*/
list_lru_destroy(&s->s_dentry_lru);
list_lru_destroy(&s->s_inode_lru);
put_filesystem(fs); put_filesystem(fs);
put_super(s); put_super(s);
} else { } else {
......
...@@ -31,6 +31,9 @@ struct list_lru_node { ...@@ -31,6 +31,9 @@ struct list_lru_node {
struct list_lru { struct list_lru {
struct list_lru_node *node; struct list_lru_node *node;
#ifdef CONFIG_MEMCG_KMEM
struct list_head list;
#endif
}; };
void list_lru_destroy(struct list_lru *lru); void list_lru_destroy(struct list_lru *lru);
......
...@@ -9,6 +9,34 @@ ...@@ -9,6 +9,34 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/list_lru.h> #include <linux/list_lru.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/mutex.h>
#ifdef CONFIG_MEMCG_KMEM
static LIST_HEAD(list_lrus);
static DEFINE_MUTEX(list_lrus_mutex);
static void list_lru_register(struct list_lru *lru)
{
mutex_lock(&list_lrus_mutex);
list_add(&lru->list, &list_lrus);
mutex_unlock(&list_lrus_mutex);
}
static void list_lru_unregister(struct list_lru *lru)
{
mutex_lock(&list_lrus_mutex);
list_del(&lru->list);
mutex_unlock(&list_lrus_mutex);
}
#else
static void list_lru_register(struct list_lru *lru)
{
}
static void list_lru_unregister(struct list_lru *lru)
{
}
#endif /* CONFIG_MEMCG_KMEM */
bool list_lru_add(struct list_lru *lru, struct list_head *item) bool list_lru_add(struct list_lru *lru, struct list_head *item)
{ {
...@@ -137,12 +165,18 @@ int list_lru_init_key(struct list_lru *lru, struct lock_class_key *key) ...@@ -137,12 +165,18 @@ int list_lru_init_key(struct list_lru *lru, struct lock_class_key *key)
INIT_LIST_HEAD(&lru->node[i].list); INIT_LIST_HEAD(&lru->node[i].list);
lru->node[i].nr_items = 0; lru->node[i].nr_items = 0;
} }
list_lru_register(lru);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(list_lru_init_key); EXPORT_SYMBOL_GPL(list_lru_init_key);
void list_lru_destroy(struct list_lru *lru) void list_lru_destroy(struct list_lru *lru)
{ {
/* Already destroyed or not yet initialized? */
if (!lru->node)
return;
list_lru_unregister(lru);
kfree(lru->node); kfree(lru->node);
lru->node = NULL;
} }
EXPORT_SYMBOL_GPL(list_lru_destroy); EXPORT_SYMBOL_GPL(list_lru_destroy);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment