Messages in this thread | | | Date | Fri, 6 Feb 2015 09:30:51 +0800 | From | Zefan Li <> | Subject | Re: [PATCH] sched, autogroup: Fix failure when writing to cpu.rt_runtime_us |
| |
On 2015/2/5 22:25, Peter Zijlstra wrote: > On Thu, Feb 05, 2015 at 04:33:24PM +0800, Zefan Li wrote: >> This is how to reproduce the bug: >> >> int main() { >> struct sched_param param = {.sched_priority=1}; >> >> if (fork() > 0) >> exit(0); >> >> setsid(); >> >> if (sched_setscheduler(0, SCHED_RR, ¶m) < 0){ >> perror("failed to sched_setscheduler()"); >> return -1; >> } >>
btw, if you move setscheduler() abvoe fork(), changing rt_runtime will succeed.
>> while(1) >> ; >> } >> >> # ./test >> # mount -t cgroup -o cpu xxx /cgroup >> # cat /cgroup/cpu.rt_runtime_us >> 950000 >> # echo 940000 > /cgroup/cpu.rt_runtime_us >> Device or Resource busy > > That's -EBUSY, but you're changing an -EPERM condition. Neither your > patch nor explanation of the matter make sense. >
I'm not changing the -EPERM condition. I'm adding an else condition which resets p->sched_task_group.
After running the test program, we have:
root | autogroup <-- the RT test program is now here
root.rt_runtime = 950000 autogroup.rt_runtime = 0
Now if you try to change the rt_runtime of the root cgroup, it returns -EBUSY.
That comes from:
static int tg_rt_schedulable(struct task_group *tg, void *data) ( ... if (rt_bandwidth_enabled() && !runtime && tg_has_rt_tasks(tg)) return -EBUSY; ... }
static inline int tg_has_rt_tasks(struct task_group *tg) { struct task_struct *g, *p;
for_each_process_thread(g, p) { if (rt_task(p) && task_group(p) == tg) return 1; }
return 0; }
here tg == autogroup, p == the test program, and task_group(p) returns autogroup, which is wrong.
See this commit:
commit f44937718ce3b8360f72f6c68c9481712517a867 Author: Mike Galbraith <efault@gmx.de> Date: Thu Jan 13 04:54:50 2011 +0100
sched, autogroup: Fix CONFIG_RT_GROUP_SCHED sched_setscheduler() failure ... + /* + * Autogroup RT tasks are redirected to the root task group ... + * the policy change to proceed. Thereafter, task_group() + * returns &root_task_group, ... + */
| |