[Crash-utility] [PATCH] foreach filter on state

Rabin Vincent rabin at rab.in
Thu Mar 8 15:21:19 UTC 2012


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




More information about the Crash-utility mailing list