Commit e9414845 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull cgroup fixes from Tejun Heo:

 - cgroup.procs listing related fixes.

   It didn't interlock properly with exiting tasks leaving a short
   window where a cgroup has empty cgroup.procs but still can't be
   removed and misbehaved on short reads.

 - psi_show() crash fix on 32bit ino archs

 - Empty release_agent handling fix

* 'for-5.6-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup:
  cgroup1: don't call release_agent when it is ""
  cgroup: fix psi_show() crash on 32bit ino archs
  cgroup: Iterate tasks that did not finish do_exit()
  cgroup: cgroup_procs_next should increase position index
  cgroup-v1: cgroup_pidlist_next should update position index
parents 2c1aca4b 2e5383d7
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -62,6 +62,7 @@ struct css_task_iter {
	struct list_head		*mg_tasks_head;
	struct list_head		*dying_tasks_head;

	struct list_head		*cur_tasks_head;
	struct css_set			*cur_cset;
	struct css_set			*cur_dcset;
	struct task_struct		*cur_task;
+2 −1
Original line number Diff line number Diff line
@@ -471,6 +471,7 @@ static void *cgroup_pidlist_next(struct seq_file *s, void *v, loff_t *pos)
	 */
	p++;
	if (p >= end) {
		(*pos)++;
		return NULL;
	} else {
		*pos = *p;
@@ -782,7 +783,7 @@ void cgroup1_release_agent(struct work_struct *work)

	pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
	agentbuf = kstrdup(cgrp->root->release_agent_path, GFP_KERNEL);
	if (!pathbuf || !agentbuf)
	if (!pathbuf || !agentbuf || !strlen(agentbuf))
		goto out;

	spin_lock_irq(&css_set_lock);
+26 −13
Original line number Diff line number Diff line
@@ -3542,21 +3542,21 @@ static int cpu_stat_show(struct seq_file *seq, void *v)
static int cgroup_io_pressure_show(struct seq_file *seq, void *v)
{
	struct cgroup *cgrp = seq_css(seq)->cgroup;
	struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
	struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;

	return psi_show(seq, psi, PSI_IO);
}
static int cgroup_memory_pressure_show(struct seq_file *seq, void *v)
{
	struct cgroup *cgrp = seq_css(seq)->cgroup;
	struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
	struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;

	return psi_show(seq, psi, PSI_MEM);
}
static int cgroup_cpu_pressure_show(struct seq_file *seq, void *v)
{
	struct cgroup *cgrp = seq_css(seq)->cgroup;
	struct psi_group *psi = cgroup_id(cgrp) == 1 ? &psi_system : &cgrp->psi;
	struct psi_group *psi = cgroup_ino(cgrp) == 1 ? &psi_system : &cgrp->psi;

	return psi_show(seq, psi, PSI_CPU);
}
@@ -4400,12 +4400,16 @@ static void css_task_iter_advance_css_set(struct css_task_iter *it)
		}
	} while (!css_set_populated(cset) && list_empty(&cset->dying_tasks));

	if (!list_empty(&cset->tasks))
	if (!list_empty(&cset->tasks)) {
		it->task_pos = cset->tasks.next;
	else if (!list_empty(&cset->mg_tasks))
		it->cur_tasks_head = &cset->tasks;
	} else if (!list_empty(&cset->mg_tasks)) {
		it->task_pos = cset->mg_tasks.next;
	else
		it->cur_tasks_head = &cset->mg_tasks;
	} else {
		it->task_pos = cset->dying_tasks.next;
		it->cur_tasks_head = &cset->dying_tasks;
	}

	it->tasks_head = &cset->tasks;
	it->mg_tasks_head = &cset->mg_tasks;
@@ -4463,10 +4467,14 @@ static void css_task_iter_advance(struct css_task_iter *it)
		else
			it->task_pos = it->task_pos->next;

		if (it->task_pos == it->tasks_head)
		if (it->task_pos == it->tasks_head) {
			it->task_pos = it->mg_tasks_head->next;
		if (it->task_pos == it->mg_tasks_head)
			it->cur_tasks_head = it->mg_tasks_head;
		}
		if (it->task_pos == it->mg_tasks_head) {
			it->task_pos = it->dying_tasks_head->next;
			it->cur_tasks_head = it->dying_tasks_head;
		}
		if (it->task_pos == it->dying_tasks_head)
			css_task_iter_advance_css_set(it);
	} else {
@@ -4485,11 +4493,12 @@ static void css_task_iter_advance(struct css_task_iter *it)
			goto repeat;

		/* and dying leaders w/o live member threads */
		if (!atomic_read(&task->signal->live))
		if (it->cur_tasks_head == it->dying_tasks_head &&
		    !atomic_read(&task->signal->live))
			goto repeat;
	} else {
		/* skip all dying ones */
		if (task->flags & PF_EXITING)
		if (it->cur_tasks_head == it->dying_tasks_head)
			goto repeat;
	}
}
@@ -4595,6 +4604,9 @@ static void *cgroup_procs_next(struct seq_file *s, void *v, loff_t *pos)
	struct kernfs_open_file *of = s->private;
	struct css_task_iter *it = of->priv;

	if (pos)
		(*pos)++;

	return css_task_iter_next(it);
}

@@ -4610,7 +4622,7 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
	 * from position 0, so we can simply keep iterating on !0 *pos.
	 */
	if (!it) {
		if (WARN_ON_ONCE((*pos)++))
		if (WARN_ON_ONCE((*pos)))
			return ERR_PTR(-EINVAL);

		it = kzalloc(sizeof(*it), GFP_KERNEL);
@@ -4618,10 +4630,11 @@ static void *__cgroup_procs_start(struct seq_file *s, loff_t *pos,
			return ERR_PTR(-ENOMEM);
		of->priv = it;
		css_task_iter_start(&cgrp->self, iter_flags, it);
	} else if (!(*pos)++) {
	} else if (!(*pos)) {
		css_task_iter_end(it);
		css_task_iter_start(&cgrp->self, iter_flags, it);
	}
	} else
		return it->cur_task;

	return cgroup_procs_next(s, NULL, NULL);
}