Commit 404067a2 authored by Lu Jialin's avatar Lu Jialin Committed by yanhaitao
Browse files

cgroup_writeback: fix deadlock in cgroup1_writeback

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I8Y0RW



--------------------------------

When read/write memory.wb_blkio_ino of a memcg, and delete the
memcg at the same time, it could cause deadlock as below:
CPU0                               CPU1
rlock(kn->active#4);
				  lock(cgroup_mutex);
				  lock(kn->active#4);
lock(cgroup_mutex);

Therefore, delete locking cgroup_mutex in reading/writing
memory.wb_blkio_ino, just use refcnt and rcu to make sure that
the blkcg exists.

Fixes: 13b8199f0a47 ("cgroup: support cgroup writeback on cgroupv1")
Signed-off-by: default avatarLu Jialin <lujialin4@huawei.com>
Signed-off-by: default avatarChen Ridong <chenridong@huawei.com>
parent 7abc3c4e
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -1121,8 +1121,6 @@ void wb_attach_memcg_to_blkcg(struct cgroup_subsys_state *memcg_css,
	if (!cgroup1_writeback)
		return;

	lockdep_assert_held(&cgroup_mutex);

	css_get(blkcg_css);
	memcg->wb_blk_css = blkcg_css;
	if (pre_blkcss == NULL)
+15 −6
Original line number Diff line number Diff line
@@ -5860,15 +5860,22 @@ static int wb_blkio_show(struct seq_file *m, void *v)
	if (!path)
		return -ENOMEM;

	mutex_lock(&cgroup_mutex);
	rcu_read_lock();
	blkcg_css = memcg->wb_blk_css;
	if (!css_tryget_online(blkcg_css)) {
		kfree(path);
		rcu_read_unlock();

		return -EINVAL;
	}
	blkcg_cgroup = blkcg_css->cgroup;
	blkcg_id = cgroup_ino(blkcg_cgroup);
	cgroup_path(blkcg_cgroup, path, PATH_MAX);
	mutex_unlock(&cgroup_mutex);
	seq_printf(m, "wb_blkio_path:%s\n", path);
	seq_printf(m, "wb_blkio_ino:%lu\n", blkcg_id);
	kfree(path);
	css_put(blkcg_css);
	rcu_read_unlock();

	return 0;
}
@@ -5891,22 +5898,24 @@ static ssize_t wb_blkio_write(struct kernfs_open_file *of, char *buf,
	if (ret)
		return ret;

	mutex_lock(&cgroup_mutex);
	rcu_read_lock();
	root = blkcg_root_css->cgroup->root;
	blk_cgroup = cgroup1_get_from_id(root, cgrp_id);
	if (IS_ERR(blk_cgroup)) {
		mutex_unlock(&cgroup_mutex);
		rcu_read_unlock();
		return -EINVAL;
	}
	blkcg_css = cgroup_tryget_css(blk_cgroup, &io_cgrp_subsys);
	if (!blkcg_css)
	if (!blkcg_css) {
		ret = -EINVAL;
		goto out_unlock;
	}
	wb_attach_memcg_to_blkcg(memcg_css, blkcg_css);
	css_put(blkcg_css);

out_unlock:
	cgroup_put(blk_cgroup);
	mutex_unlock(&cgroup_mutex);
	rcu_read_unlock();

	return ret < 0 ? ret : nbytes;
}