Hello Dave,
The patch is used to add a new option, "-E regex", to perform the
command(s) on all commands whose names contains a match to "regex".
"regex" is interpreted as an POSIX extended regular expression.
The new option is helpful when using to search some commands whose names
are similar. And I think it is more reliable than "foreach <name>
<command> | grep xxx", for information comes from command may have a
match to "xxx".
P.S.
The patch uses some function defined in regex.h, which is offered by glibc.
--
--
Regards
Qiao Nuohan
diff --git a/defs.h b/defs.h
index a942dbb..deabe91 100755
--- a/defs.h
+++ b/defs.h
@@ -47,6 +47,7 @@
#include <sys/wait.h>
#include <sys/time.h>
#include <execinfo.h> /* backtrace() */
+#include <regex.h>
#ifndef ATTRIBUTE_UNUSED
#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
@@ -977,6 +978,7 @@ extern struct machdep_table *machdep;
#define FOREACH_F_FLAG (0x400000)
#define FOREACH_x_FLAG (0x800000)
#define FOREACH_d_FLAG (0x1000000)
+#define FOREACH_E_FLAG (0x2000000)
struct foreach_data {
ulong flags;
@@ -985,6 +987,7 @@ struct foreach_data {
char *comm_array[MAX_FOREACH_COMMS];
ulong pid_array[MAX_FOREACH_PIDS];
ulong arg_array[MAX_FOREACH_ARGS];
+ regex_t regex;
char *reference;
int keys;
int pids;
diff --git a/help.c b/help.c
index f752283..03f8b84 100755
--- a/help.c
+++ b/help.c
@@ -725,7 +725,7 @@ NULL,
char *help_foreach[] = {
"foreach",
"display command data for multiple tasks in the system",
-"[[pid | taskp | name | [kernel | user]] ...] command [flag] [argument]",
+"[[pid | taskp | name | [kernel | user]] ... | -E regex] command [flag]
[argument]",
" This command allows for a an examination of various kernel data associated",
" with any, or all, tasks in the system, without having to set the context",
" to each targeted task.\n",
@@ -737,7 +737,10 @@ 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.",
+" -E regex perform the command(s) on all commands whose names contains a
match",
+" to the given regex. regex is interpreted as an POSIX extended
regular",
+" expression.\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",
@@ -794,6 +797,17 @@ char *help_foreach[] = {
" Display the open files for all tasks:\n",
" %s> foreach files",
" ...\n",
+" Display the state of tasks whose name contains a match to 'event.*':\n",
+" %s> foreach -E 'event.*' task -R state",
+" PID: 99 TASK: ffff8804750d5500 CPU: 0 COMMAND: \"events/0\"",
+" state = 1,",
+" ",
+" PID: 100 TASK: ffff8804750d4ac0 CPU: 1 COMMAND: \"events/1\"",
+" state = 1,"
+" ",
+" PID: 101 TASK: ffff8804750d4080 CPU: 2 COMMAND: \"events/2\"",
+" state = 1,",
+" ...\n",
NULL
};
diff --git a/task.c b/task.c
index fde86eb..b8b709d 100755
--- a/task.c
+++ b/task.c
@@ -4896,9 +4896,14 @@ cmd_foreach(void)
BZERO(&foreach_data, sizeof(struct foreach_data));
fd = &foreach_data;
- while ((c = getopt(argcnt, args, "R:vomlgersStTpukcfFxhd")) != EOF) {
+ while ((c = getopt(argcnt, args, "E:R:vomlgersStTpukcfFxhd")) != EOF) {
switch(c)
{
+ case 'E':
+ if (regcomp(&fd->regex, optarg, REG_EXTENDED|REG_NOSUB))
+ error(FATAL, "invalid regular expression!\n");
+ fd->flags |= FOREACH_E_FLAG;
+ break;
case 'R':
fd->reference = optarg;
break;
@@ -5021,6 +5026,9 @@ cmd_foreach(void)
switch (str_to_context(args[optind], &value, &tc))
{
case STR_PID:
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'pid' "
+ "are mutually exclusive!\n");
if (p == MAX_FOREACH_PIDS)
error(INFO,
"too many pids specified!\n");
@@ -5033,6 +5041,9 @@ cmd_foreach(void)
break;
case STR_TASK:
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'taskp' "
+ "are mutually exclusive!\n");
if (t == MAX_FOREACH_TASKS)
error(INFO,
"too many tasks specified!\n");
@@ -5053,6 +5064,9 @@ cmd_foreach(void)
* Select all kernel threads.
*/
if (STREQ(args[optind], "kernel")) {
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'kernel' "
+ "are mutually exclusive!\n");
if (fd->flags & FOREACH_USER)
error(FATAL,
"user and kernel are mutually exclusive!\n");
@@ -5065,6 +5079,9 @@ cmd_foreach(void)
* Select only user threads.
*/
if (STREQ(args[optind], "user")) {
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'user' "
+ "are mutually exclusive!\n");
if (fd->flags & FOREACH_KERNEL)
error(FATAL,
"user and kernel are mutually
exclusive!\n");
@@ -5077,6 +5094,9 @@ cmd_foreach(void)
* Select only active tasks (dumpfile only)
*/
if (STREQ(args[optind], "active")) {
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'active' "
+ "are mutually exclusive!\n");
if (!DUMPFILE())
error(FATAL,
"active option not allowed on live systems\n");
@@ -5092,6 +5112,9 @@ cmd_foreach(void)
&args[optind][1] : args[optind];
if (comm_exists(p1)) {
+ if (fd->flags & FOREACH_E_FLAG)
+ error(FATAL, "'-E regex' and 'name' "
+ "are mutually exclusive!\n");
if (c == MAX_FOREACH_COMMS)
error(INFO, "too many commands specified!\n");
else {
@@ -5335,6 +5358,10 @@ foreach(struct foreach_data *fd)
if (STREQ(fd->comm_array[j], tc->comm))
doit = TRUE;
}
+ else if (fd->flags & FOREACH_E_FLAG) {
+ if (regexec(&fd->regex, tc->comm, 0, NULL, 0) == 0)
+ doit = TRUE;
+ }
else
doit = TRUE;
--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility