The patch below adds support to filter foreach on task states.  I've
found [foreach state=D bt] and [foreach state=R bt] useful; the former
allows to emulate the show-blocked-tasks Magic SysRq.

Rabin

diff --git a/defs.h b/defs.h
index 2e7f6bd..dc12844 100755
--- a/defs.h
+++ b/defs.h
@@ -974,6 +974,7 @@ extern struct machdep_table *machdep;
 #define FOREACH_F_FLAG  (0x400000)
 #define FOREACH_x_FLAG  (0x800000)
 #define FOREACH_d_FLAG (0x1000000)
+#define FOREACH_STATE  (0x2000000)
 
 struct foreach_data {
        ulong flags;
@@ -982,6 +983,7 @@ struct foreach_data {
         char *comm_array[MAX_FOREACH_COMMS];
         ulong pid_array[MAX_FOREACH_PIDS];
        ulong arg_array[MAX_FOREACH_ARGS];
+       ulong state;
        char *reference;
        int keys;
        int pids;
diff --git a/help.c b/help.c
index adaaea7..dedf479 100755
--- a/help.c
+++ b/help.c
@@ -736,7 +736,9 @@ char *help_foreach[] = {
 "           precede the name string with a \"\\\".",
 "     user  perform the command(s) on all user (non-kernel) threads.",
 "   kernel  perform the command(s) on all kernel threads.",
-"   active  perform the command(s) on the active thread on each CPU.\n",
+"   active  perform the command(s) on the active thread on each CPU.",
+"  state=?  perform the command(s) on all tasks in the specified state.",
+"           (? is one of R, S, D, T, Z, X, W)\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",
@@ -793,6 +795,9 @@ char *help_foreach[] = {
 "  Display the open files for all tasks:\n",
 "    %s> foreach files",
 "    ...\n",
+"  Display the stack traces for all blocked (TASK_UNINTERRUPTIBLE) tasks:\n",
+"    %s> foreach state=D bt",
+"    ...\n",
 NULL
 };
 
diff --git a/task.c b/task.c
index 433a043..de033c3 100755
--- a/task.c
+++ b/task.c
@@ -5061,6 +5061,35 @@ cmd_foreach(void)
                        continue;
                }
 
+                if (STRNEQ(args[optind], "state=")) {
+                       const char *p = args[optind] + strlen("state=");
+                       ulong state = 0;
+
+                       if (STREQ(p, "R"))
+                               state = _RUNNING_;
+                       else if (STREQ(p, "S"))
+                               state = _INTERRUPTIBLE_;
+                       else if (STREQ(p, "D"))
+                               state = _UNINTERRUPTIBLE_;
+                       else if (STREQ(p, "T"))
+                               state = _STOPPED_;
+                       else if (STREQ(p, "Z"))
+                               state = _ZOMBIE_;
+                       else if (STREQ(p, "X"))
+                               state = _DEAD_;
+                       else if (STREQ(p, "W"))
+                               state = _SWAPPING_;
+                       else if (*p)
+                               error(FATAL, "invalid state: %s\n", p);
+                       else
+                               error(FATAL, "no state specified\n");
+
+                       fd->flags |= FOREACH_STATE;
+                       fd->state = state;
+                       optind++;
+                       continue;
+               }
+
                /*
                 *  Select only user threads.
                 */
@@ -5322,6 +5351,9 @@ foreach(struct foreach_data *fd)
                if ((fd->flags & FOREACH_KERNEL) && !is_kernel_thread(tc->task))
                        continue;
 
+               if ((fd->flags & FOREACH_STATE) && task_state(tc->task) != 
fd->state)
+                       continue;
+
                if (specified) {
                        for (j = 0; j < fd->tasks; j++) 
                                if (fd->task_array[j] == tc->task)
-- 
1.7.9.1

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to