Discussion:
[Crash-utility] [PATCH 3/3] Add support for TASK_NEW task state
Kazuhito Hagio
2018-07-19 14:51:50 UTC
Permalink
kernel commit 7dc603c902 ("sched/fair: Fix PELT integrity for new
tasks") introduced TASK_NEW state. This patch adds support for it
as 'NE' state.

Signed-off-by: Kazuhito Hagio <k-***@ab.jp.nec.com>
---
help.c | 4 ++--
task.c | 21 +++++++++++++++++++++
2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/help.c b/help.c
index 14cae8e..83cda7c 100644
--- a/help.c
+++ b/help.c
@@ -837,7 +837,7 @@ char *help_foreach[] = {
" kernel perform the command(s) on all kernel threads.",
" active perform the command(s) on the active thread on each CPU.",
" state perform the command(s) on all tasks in the specified state, which",
-" may be one of: RU, IN, UN, ST, ZO, TR, SW, DE, WA, PA or ID.\n",
+" may be one of: RU, IN, UN, ST, ZO, TR, SW, DE, WA, PA, ID or NE.\n",
" If none of the task-identifying arguments above are entered, the command",
" will be performed on all tasks.\n",
" command select one or more of the following commands to be run on the tasks",
@@ -1292,7 +1292,7 @@ char *help_ps[] = {
" 3. the CPU number that the task ran on last.",
" 4. the task_struct address or the kernel stack pointer of the process.",
" (see -s option below)",
-" 5. the task state (RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA, ID).",
+" 5. the task state (RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA, ID, NE).",
" 6. the percentage of physical memory being used by this task.",
" 7. the virtual address size of this task in kilobytes.",
" 8. the resident set size of this task in kilobytes.",
diff --git a/task.c b/task.c
index 5412215..39fb0de 100644
--- a/task.c
+++ b/task.c
@@ -5172,6 +5172,7 @@ static long _WAKING_ = TASK_STATE_UNINITIALIZED;
static long _NONINTERACTIVE_ = TASK_STATE_UNINITIALIZED;
static long _PARKED_ = TASK_STATE_UNINITIALIZED;
static long _NOLOAD_ = TASK_STATE_UNINITIALIZED;
+static long _NEW_ = TASK_STATE_UNINITIALIZED;

#define valid_task_state(X) ((X) != TASK_STATE_UNINITIALIZED)

@@ -5249,6 +5250,10 @@ dump_task_states(void)
if (valid_task_state(_NOLOAD_))
fprintf(fp, " NOLOAD: %3ld (0x%lx)\n",
_NOLOAD_, _NOLOAD_);
+
+ if (valid_task_state(_NEW_))
+ fprintf(fp, " NEW: %3ld (0x%lx)\n",
+ _NEW_, _NEW_);
}


@@ -5332,6 +5337,9 @@ old_defaults:
case 'N':
_NOLOAD_ = (1 << (i-1));
break;
+ case 'n':
+ _NEW_ = (1 << (i-1));
+ break;
}
}

@@ -5401,6 +5409,7 @@ old_defaults:
_WAKEKILL_ = (bitpos << 2); /* TASK_WAKEKILL */
_WAKING_ = (bitpos << 3); /* TASK_WAKING */
_NOLOAD_ = (bitpos << 4); /* TASK_NOLOAD */
+ _NEW_ = (bitpos << 5); /* TASK_NEW */
}
} else if (THIS_KERNEL_VERSION >= LINUX(2,6,32)) {
/*
@@ -5490,6 +5499,10 @@ task_state_string_verbose(ulong task, char *buf)
sprintf(&buf[strlen(buf)], "%sTASK_NOLOAD",
count++ ? "|" : "");

+ if (valid_task_state(_NEW_) && (state & _NEW_))
+ sprintf(&buf[strlen(buf)], "%sTASK_NEW",
+ count++ ? "|" : "");
+
if (valid_task_state(_NONINTERACTIVE_) &&
(state & _NONINTERACTIVE_))
sprintf(&buf[strlen(buf)], "%sTASK_NONINTERACTIVE",
@@ -5589,6 +5602,11 @@ task_state_string(ulong task, char *buf, int verbose)
valid++;
}

+ if (state == _NEW_) {
+ sprintf(buf, "NE");
+ valid++;
+ }
+
if (valid && exclusive)
strcat(buf, "EX");

@@ -6287,6 +6305,7 @@ cmd_foreach(void)
STREQ(args[optind], "PA") ||
STREQ(args[optind], "WA") ||
STREQ(args[optind], "ID") ||
+ STREQ(args[optind], "NE") ||
STREQ(args[optind], "SW")) {

if (fd->flags & FOREACH_STATE)
@@ -6314,6 +6333,8 @@ cmd_foreach(void)
fd->state = _WAKING_;
else if (STREQ(args[optind], "ID"))
fd->state = _UNINTERRUPTIBLE_|_NOLOAD_;
+ else if (STREQ(args[optind], "NE"))
+ fd->state = _NEW_;

if (fd->state == TASK_STATE_UNINITIALIZED)
error(FATAL,
--
1.8.3.1
Kazuhito Hagio
2018-07-19 14:51:49 UTC
Permalink
kernel commit 06eb61844d ("sched/debug: Add explicit TASK_IDLE
printing") exposed the TASK_IDLE task state to user space as
'I (idle)' state.
On the other hand, crash still shows 'UN' for TASK_IDLE state.

It is confusing for support folks, and 'foreach UN bt', which shows
useful information for troubles like system stall, includes unexpected
idle tasks. So let's print TASK_IDLE as 'ID' state.

Signed-off-by: Kazuhito Hagio <k-***@ab.jp.nec.com>
---
help.c | 4 ++--
task.c | 22 +++++++++++++++++++++-
2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/help.c b/help.c
index 54bf9b4..14cae8e 100644
--- a/help.c
+++ b/help.c
@@ -837,7 +837,7 @@ char *help_foreach[] = {
" kernel perform the command(s) on all kernel threads.",
" active perform the command(s) on the active thread on each CPU.",
" state perform the command(s) on all tasks in the specified state, which",
-" may be one of: RU, IN, UN, ST, ZO, TR, SW, DE, WA or PA.\n",
+" may be one of: RU, IN, UN, ST, ZO, TR, SW, DE, WA, PA or ID.\n",
" If none of the task-identifying arguments above are entered, the command",
" will be performed on all tasks.\n",
" command select one or more of the following commands to be run on the tasks",
@@ -1292,7 +1292,7 @@ char *help_ps[] = {
" 3. the CPU number that the task ran on last.",
" 4. the task_struct address or the kernel stack pointer of the process.",
" (see -s option below)",
-" 5. the task state (RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA).",
+" 5. the task state (RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA, ID).",
" 6. the percentage of physical memory being used by this task.",
" 7. the virtual address size of this task in kilobytes.",
" 8. the resident set size of this task in kilobytes.",
diff --git a/task.c b/task.c
index 164e546..5412215 100644
--- a/task.c
+++ b/task.c
@@ -5539,7 +5539,11 @@ task_state_string(ulong task, char *buf, int verbose)
}

if (state & _UNINTERRUPTIBLE_) {
- sprintf(buf, "UN");
+ if (valid_task_state(_NOLOAD_) &&
+ (state & _NOLOAD_))
+ sprintf(buf, "ID");
+ else
+ sprintf(buf, "UN");
valid++;
set++;
}
@@ -6282,6 +6286,7 @@ cmd_foreach(void)
STREQ(args[optind], "DE") ||
STREQ(args[optind], "PA") ||
STREQ(args[optind], "WA") ||
+ STREQ(args[optind], "ID") ||
STREQ(args[optind], "SW")) {

if (fd->flags & FOREACH_STATE)
@@ -6307,6 +6312,8 @@ cmd_foreach(void)
fd->state = _PARKED_;
else if (STREQ(args[optind], "WA"))
fd->state = _WAKING_;
+ else if (STREQ(args[optind], "ID"))
+ fd->state = _UNINTERRUPTIBLE_|_NOLOAD_;

if (fd->state == TASK_STATE_UNINITIALIZED)
error(FATAL,
@@ -6687,6 +6694,19 @@ foreach(struct foreach_data *fd)
if (fd->state == _RUNNING_) {
if (task_state(tc->task) != _RUNNING_)
continue;
+ } else if (fd->state & _UNINTERRUPTIBLE_) {
+ if (!(task_state(tc->task) & _UNINTERRUPTIBLE_))
+ continue;
+
+ if (valid_task_state(_NOLOAD_)) {
+ if (fd->state & _NOLOAD_) {
+ if (!(task_state(tc->task) & _NOLOAD_))
+ continue;
+ } else {
+ if ((task_state(tc->task) & _NOLOAD_))
+ continue;
+ }
+ }
} else if (!(task_state(tc->task) & fd->state))
continue;
}
--
1.8.3.1
Kazuhito Hagio
2018-07-19 14:51:48 UTC
Permalink
Since Linux 4.14, kernel commit 20435d84e5 ("sched/debug: Intruduce
task_state_to_char() helper function") removed the 'stat_nam' symbol,
with which we've got the values of task state bitmasks. So now we
need to get them correctly by using 'task_state_array' again.

Signed-off-by: Kazuhito Hagio <k-***@ab.jp.nec.com>
---
task.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/task.c b/task.c
index 1b32629..164e546 100644
--- a/task.c
+++ b/task.c
@@ -5282,6 +5282,7 @@ old_defaults:
/*
* If the later version of stat_nam[] array exists that contains
* WAKING, WAKEKILL and PARKED, use it instead of task_state_array[].
+ * Available since kernel version 2.6.33 to 4.13.
*/
if (((len = get_array_length("stat_nam", NULL, 0)) > 0) &&
read_string(symbol_value("stat_nam"), buf, BUFSIZE-1) &&
@@ -5393,7 +5394,15 @@ old_defaults:
_NONINTERACTIVE_ = 64;
}

- if (THIS_KERNEL_VERSION >= LINUX(2,6,32)) {
+ if (THIS_KERNEL_VERSION >= LINUX(4,14,0)) {
+ if (valid_task_state(_PARKED_)) {
+ bitpos = _PARKED_;
+ _DEAD_ |= (bitpos << 1); /* TASK_DEAD */
+ _WAKEKILL_ = (bitpos << 2); /* TASK_WAKEKILL */
+ _WAKING_ = (bitpos << 3); /* TASK_WAKING */
+ _NOLOAD_ = (bitpos << 4); /* TASK_NOLOAD */
+ }
+ } else if (THIS_KERNEL_VERSION >= LINUX(2,6,32)) {
/*
* Account for states not listed in task_state_array[]
*/
--
1.8.3.1
Dave Anderson
2018-07-19 17:46:38 UTC
Permalink
Kazu,

The patch looks good and tests OK -- queued for crash-7.2.4:

https://github.com/crash-utility/crash/commit/a10917ba3203aa8b20e2aa1b84dc12c1e17445e1

Thanks,
Dave


----- Original Message -----
Post by Kazuhito Hagio
kernel commit 06eb61844d ("sched/debug: Add explicit TASK_IDLE
printing") exposed the TASK_IDLE task state to user space as
'I (idle)' state.
$ cat /proc/4/status
Name: kworker/0:0H
Umask: 0000
State: I (idle)
$ ps 4
PID TTY STAT TIME COMMAND
4 ? I< 0:00 [kworker/0:0H]
On the other hand, crash still shows 'UN' for TASK_IDLE state.
crash> ps 4
PID PPID CPU TASK ST %MEM VSZ RSS COMM
4 2 0 ffff8d1dbe884200 UN 0.0 0 0 [kworker/0:0H]
crash> ps -S
RU: 3
IN: 69
UN: 53
It is confusing for support folks, and 'foreach UN bt', which shows
useful information for troubles like system stall, includes unexpected
idle tasks. So let's print TASK_IDLE as 'ID' state. [Patch 2]
Intruduce task_state_to_char() helper function") removed the 'stat_nam'
symbol, with which we've got the values of task state bitmasks. So
now we need to get them correctly by using 'task_state_array' again.
[Patch 1]
Additionally, kernel commit 7dc603c902 ("sched/fair: Fix PELT integrity
for new tasks") introduced TASK_NEW state. [Patch 3] adds support for
it as 'NE' state.
Fix task state bitmasks for 4.14 and later
Add support for TASK_IDLE task state
Add support for TASK_NEW task state
help.c | 4 ++--
task.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 54 insertions(+), 4 deletions(-)
--
1.8.3.1
--
Crash-utility mailing list
https://www.redhat.com/mailman/listinfo/crash-utility
Continue reading on narkive:
Loading...