]>
Commit | Line | Data |
---|---|---|
2cb7cef9 BS |
1 | From: Thomas Gleixner <tglx@linutronix.de> |
2 | To: LKML <linux-kernel@vger.kernel.org> | |
3 | Cc: Andrew Morton <akpm@linux-foundation.org>, Rafael Wysocki <rjw@sisk.pl>, Ingo Molnar <mingo@elte.hu>, Peter Zijlstra <peterz@infradead.org>, Nathan Lynch <ntl@pobox.com>, Nigel Cunningham <nigel@tuxonice.net>, <stable@kernel.org>, containers@lists.linux-foundation.org, linux-pm@lists.linux-foundation.org, Matt Helsley <matthltc@us.ibm.com> | |
4 | Subject: [patch 2/2] sched: fix nr_uninterruptible accounting of frozen tasks really | |
5 | References: bnc#529660 | |
6 | ||
7 | commit e3c8ca8336 (sched: do not count frozen tasks toward load) broke | |
8 | the nr_uninterruptible accounting on freeze/thaw. On freeze the task | |
9 | is excluded from accounting with a check for (task->flags & | |
10 | PF_FROZEN), but that flag is cleared before the task is thawed. So | |
11 | while we prevent that the freezing task with state | |
12 | TASK_UNINTERRUPTIBLE is accounted to nr_uninterruptible we decrement | |
13 | nr_uninterruptible on thaw. | |
14 | ||
15 | Use a separate flag which is handled by the freezing task itself. Set | |
16 | it before calling the scheduler with TASK_UNINTERRUPTIBLE state and | |
17 | clear it after we return from frozen state. | |
18 | ||
19 | Signed-off-by: Thomas Gleixner <tglx@linutronix.de> | |
20 | Cc: Nathan Lynch <ntl@pobox.com> | |
21 | Cc: Andrew Morton <akpm@linux-foundation.org> | |
22 | Cc: Nigel Cunningham <nigel@tuxonice.net> | |
23 | Cc: <stable@kernel.org> | |
24 | Cc: containers@lists.linux-foundation.org | |
25 | Cc: linux-pm@lists.linux-foundation.org | |
26 | Cc: Matt Helsley <matthltc@us.ibm.com> | |
27 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
28 | --- | |
29 | include/linux/sched.h | 3 ++- | |
30 | kernel/freezer.c | 7 +++++++ | |
31 | 2 files changed, 9 insertions(+), 1 deletion(-) | |
32 | ||
33 | --- a/include/linux/sched.h | |
34 | +++ b/include/linux/sched.h | |
35 | @@ -203,7 +203,7 @@ extern unsigned long long time_sync_thre | |
36 | ((task->state & (__TASK_STOPPED | __TASK_TRACED)) != 0) | |
37 | #define task_contributes_to_load(task) \ | |
38 | ((task->state & TASK_UNINTERRUPTIBLE) != 0 && \ | |
39 | - (task->flags & PF_FROZEN) == 0) | |
40 | + (task->flags & PF_FREEZING) == 0) | |
41 | ||
42 | #define __set_task_state(tsk, state_value) \ | |
43 | do { (tsk)->state = (state_value); } while (0) | |
44 | @@ -1507,6 +1507,7 @@ extern cputime_t task_gtime(struct task_ | |
45 | #define PF_MEMALLOC 0x00000800 /* Allocating memory */ | |
46 | #define PF_FLUSHER 0x00001000 /* responsible for disk writeback */ | |
47 | #define PF_USED_MATH 0x00002000 /* if unset the fpu must be initialized before use */ | |
48 | +#define PF_FREEZING 0x00004000 /* freeze in progress. do not account to load */ | |
49 | #define PF_NOFREEZE 0x00008000 /* this thread should not be frozen */ | |
50 | #define PF_FROZEN 0x00010000 /* frozen for system suspend */ | |
51 | #define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */ | |
52 | --- a/kernel/freezer.c | |
53 | +++ b/kernel/freezer.c | |
54 | @@ -44,12 +44,19 @@ void refrigerator(void) | |
55 | recalc_sigpending(); /* We sent fake signal, clean it up */ | |
56 | spin_unlock_irq(¤t->sighand->siglock); | |
57 | ||
58 | + /* prevent accounting of that task to load */ | |
59 | + current->flags |= PF_FREEZING; | |
60 | + | |
61 | for (;;) { | |
62 | set_current_state(TASK_UNINTERRUPTIBLE); | |
63 | if (!frozen(current)) | |
64 | break; | |
65 | schedule(); | |
66 | } | |
67 | + | |
68 | + /* Remove the accounting blocker */ | |
69 | + current->flags &= ~PF_FREEZING; | |
70 | + | |
71 | pr_debug("%s left refrigerator\n", current->comm); | |
72 | __set_current_state(save); | |
73 | } |