diff --git a/mm/backing-dev.c b/mm/backing-dev.c index 1ae2b74cbad8d900a281222fa07d66c2e3475655..fa2e26826150306e2d13872efbf1064c8afa5554 100644 --- a/mm/backing-dev.c +++ b/mm/backing-dev.c @@ -438,8 +438,8 @@ static struct cgroup_subsys_state *cgwbv1_get_blkcss(struct mem_cgroup *memcg) struct cgroup_subsys_state *blkcg_css; rcu_read_lock(); - blkcg_css = memcg->wb_blk_css; - if (!css_tryget_online(blkcg_css)) { + blkcg_css = READ_ONCE(memcg->wb_blk_css); + if (!blkcg_css || !css_tryget_online(blkcg_css)) { blkcg_css = blkcg_root_css; css_get(blkcg_css); } @@ -1067,6 +1067,7 @@ EXPORT_SYMBOL(wait_iff_congested); #include "../kernel/cgroup/cgroup-internal.h" static bool cgroup1_writeback __read_mostly; +DEFINE_SPINLOCK(wb_blk_memlist_lock); bool cgroup1_writeback_enabled(void) { @@ -1080,6 +1081,7 @@ static void wb_kill_memcg(struct cgroup_subsys_state *memcg_css) list_del_init(&memcg->memcg_node); css_put(memcg->wb_blk_css); + memcg->wb_blk_css = NULL; } static void wb_kill_blkcg(struct cgroup_subsys_state *blkcg_css) @@ -1103,24 +1105,26 @@ void wb_kill_memcg_blkcg(struct cgroup_subsys_state *css) if (!cgroup1_writeback) return; - lockdep_assert_held(&cgroup_mutex); - + spin_lock(&wb_blk_memlist_lock); if (ss->id == io_cgrp_id) wb_kill_blkcg(css); else if (ss->id == memory_cgrp_id) wb_kill_memcg(css); + spin_unlock(&wb_blk_memlist_lock); } void wb_attach_memcg_to_blkcg(struct cgroup_subsys_state *memcg_css, struct cgroup_subsys_state *blkcg_css) { struct mem_cgroup *memcg = mem_cgroup_from_css(memcg_css); - struct cgroup_subsys_state *pre_blkcss = memcg->wb_blk_css; + struct cgroup_subsys_state *pre_blkcss = NULL; struct blkcg *blkcg = css_to_blkcg(blkcg_css); if (!cgroup1_writeback) return; + spin_lock(&wb_blk_memlist_lock); + pre_blkcss = memcg->wb_blk_css; css_get(blkcg_css); memcg->wb_blk_css = blkcg_css; if (pre_blkcss == NULL) @@ -1129,6 +1133,7 @@ void wb_attach_memcg_to_blkcg(struct cgroup_subsys_state *memcg_css, list_move(&memcg->memcg_node, &blkcg->memcg_list); css_put(pre_blkcss); } + spin_unlock(&wb_blk_memlist_lock); } static int __init enable_cgroup1_writeback(char *s) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 91159d30a7101cf486329edf2513d6e320797191..06dd6e99f66b45399b77b0efdaaade237594f9be 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5861,11 +5861,10 @@ static int wb_blkio_show(struct seq_file *m, void *v) return -ENOMEM; rcu_read_lock(); - blkcg_css = memcg->wb_blk_css; - if (!css_tryget_online(blkcg_css)) { + blkcg_css = READ_ONCE(memcg->wb_blk_css); + if (!blkcg_css || !css_tryget_online(blkcg_css)) { kfree(path); rcu_read_unlock(); - return -EINVAL; } blkcg_cgroup = blkcg_css->cgroup;