All of lore.kernel.org
 help / color / mirror / Atom feed
* [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error
@ 2018-11-02 12:08 Petri Latvala
  2018-11-02 12:24 ` Martin Peres
                   ` (5 more replies)
  0 siblings, 6 replies; 8+ messages in thread
From: Petri Latvala @ 2018-11-02 12:08 UTC (permalink / raw)
  To: igt-dev; +Cc: Tomi Sarvela, Petri Latvala, Martin Peres

Deviating a bit from the piglit command line flag, igt_runner takes an
optional comma-separated list as an argument to
--abort-on-monitored-error for the list of conditions to abort
on. Without a list all possible conditions will be checked.

Two conditions implemented:
 - "taint" checks the kernel taint level for TAINT_PAGE, TAINT_DIE and
 TAINT_OOPS
 - "lockdep" checks the kernel lockdep status

Checking is done after every test binary execution, and if an abort
condition is met, the reason is printed to stderr (unless log level is
quiet) and the runner doesn't execute any further tests. Aborting
between subtests (when running in --multiple-mode) is not done.

A TODO item for the future is having aborting appear in the test
results.

Signed-off-by: Petri Latvala <petri.latvala@intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
Cc: Martin Peres <martin.peres@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
---

It should be noted that this is automatically active in CI, for it
gives --abort-on-monitored-error without a list to igt_runner already.


 runner/executor.c     | 92 ++++++++++++++++++++++++++++++++++++++++---
 runner/runner_tests.c | 49 ++++++++++++++++++++---
 runner/settings.c     | 75 ++++++++++++++++++++++++++++++++---
 runner/settings.h     |  8 +++-
 4 files changed, 206 insertions(+), 18 deletions(-)

diff --git a/runner/executor.c b/runner/executor.c
index fc79f772..98c31f36 100644
--- a/runner/executor.c
+++ b/runner/executor.c
@@ -108,6 +108,79 @@ static void ping_watchdogs(void)
 	}
 }
 
+static bool handle_lockdep(struct settings *settings)
+{
+	FILE *f = fopen("/proc/lockdep_stats", "r");
+	const char *debug_locks_line = " debug_locks:";
+	char buf[512];
+	int val;
+
+	if (!f)
+		return false;
+
+	while (fgets(buf, sizeof(buf), f) != NULL) {
+		if (!strncmp(buf, debug_locks_line, strlen(debug_locks_line))) {
+			char *p = buf + strlen(debug_locks_line);
+			if (sscanf(p, "%d", &val) == 1 &&
+			    val != 0) {
+				if (settings->log_level >= LOG_LEVEL_NORMAL) {
+					fprintf(stderr, "Lockdep triggered, aborting\n");
+				}
+				return true;
+			}
+
+			break;
+		}
+	}
+
+	return false;
+}
+
+static bool handle_taint(struct settings *settings)
+{
+	FILE *f = fopen("/proc/sys/kernel/tainted", "r");
+	int taint;
+	int bad_taints =
+		0x20  | /* TAINT_PAGE */
+		0x80  | /* TAINT_DIE */
+		0x200; /* TAINT_OOPS */
+
+	if (!f || fscanf(f, "%d", &taint) != 1)
+		return false;
+
+	if (taint & bad_taints) {
+		if (settings->log_level >= LOG_LEVEL_NORMAL) {
+			fprintf(stderr, "Kernel tainted (0x%x), aborting\n", taint);
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static struct {
+	int condition;
+	bool (*handler)(struct settings*);
+} abort_handlers[] = {
+	{ ABORT_LOCKDEP, handle_lockdep },
+	{ ABORT_TAINT, handle_taint },
+	{ 0, 0 },
+};
+
+static bool need_to_abort(struct settings* settings)
+{
+	typeof(*abort_handlers) *it;
+
+	for (it = abort_handlers; it->condition; it++) {
+		if (settings->abort_mask & it->condition &&
+		    it->handler(settings))
+			return true;
+	}
+
+	return false;
+}
+
 static void prune_subtest(struct job_list_entry *entry, char *subtest)
 {
 	char *excl;
@@ -1102,12 +1175,19 @@ bool execute(struct execute_state *state,
 
 	for (; state->next < job_list->size;
 	     state->next++) {
-		int result = execute_next_entry(state,
-						job_list->size,
-						&time_spent,
-						settings,
-						&job_list->entries[state->next],
-						testdirfd, resdirfd);
+		int result;
+
+		if (need_to_abort(settings)) {
+			status = false;
+			break;
+		}
+
+		result = execute_next_entry(state,
+					    job_list->size,
+					    &time_spent,
+					    settings,
+					    &job_list->entries[state->next],
+					    testdirfd, resdirfd);
 
 		if (result < 0) {
 			status = false;
diff --git a/runner/runner_tests.c b/runner/runner_tests.c
index 9c0f9eb0..829c60c3 100644
--- a/runner/runner_tests.c
+++ b/runner/runner_tests.c
@@ -142,7 +142,7 @@ static void assert_settings_equal(struct settings *one, struct settings *two)
 	 * Regex lists are not serialized, and thus won't be compared
 	 * here.
 	 */
-	igt_assert_eq(one->abort_on_error, two->abort_on_error);
+	igt_assert_eq(one->abort_mask, two->abort_mask);
 	igt_assert_eqstr(one->test_list, two->test_list);
 	igt_assert_eqstr(one->name, two->name);
 	igt_assert_eq(one->dry_run, two->dry_run);
@@ -208,7 +208,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -323,7 +323,7 @@ igt_main
 		setenv("IGT_TEST_ROOT", testdatadir, 1);
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -348,7 +348,7 @@ igt_main
 	igt_subtest("parse-all-settings") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
-				 "--abort-on-monitored-error",
+				 "--abort-on-monitored-error=taint,lockdep",
 				 "--test-list", "path-to-test-list",
 				 "--ignore-missing",
 				 "--dry-run",
@@ -370,7 +370,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
 		igt_assert(strstr(settings.test_list, "path-to-test-list") != NULL);
 		igt_assert_eqstr(settings.name, "foo");
 		igt_assert(settings.dry_run);
@@ -428,6 +428,45 @@ igt_main
 		igt_assert_eq(settings.log_level, LOG_LEVEL_VERBOSE);
 	}
 
+	igt_subtest("abort-conditions") {
+		char *argv[] = { "runner",
+				 "--abort-on-monitored-error=taint",
+				 "test-root-dir",
+				 "results-path",
+		};
+
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep,taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint,lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=all";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_ALL);
+
+		argv[1] = "--abort-on-monitored-error=";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, 0);
+
+		argv[1] = "--abort-on-monitored-error=doesnotexist";
+		igt_assert(!parse_options(ARRAY_SIZE(argv), argv, &settings));
+
+	}
+
 	igt_subtest("parse-clears-old-data") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
diff --git a/runner/settings.c b/runner/settings.c
index e2401455..e056493a 100644
--- a/runner/settings.c
+++ b/runner/settings.c
@@ -41,6 +41,16 @@ static struct {
 	{ 0, 0 },
 };
 
+static struct {
+	int value;
+	const char *name;
+} abort_conditions[] = {
+	{ ABORT_TAINT, "taint" },
+	{ ABORT_LOCKDEP, "lockdep" },
+	{ ABORT_ALL, "all" },
+	{ 0, 0 },
+};
+
 static bool set_log_level(struct settings* settings, const char *level)
 {
 	typeof(*log_levels) *it;
@@ -55,6 +65,52 @@ static bool set_log_level(struct settings* settings, const char *level)
 	return false;
 }
 
+static bool set_abort_condition(struct settings* settings, const char *cond)
+{
+	typeof(*abort_conditions) *it;
+
+	if (!cond) {
+		settings->abort_mask = ABORT_ALL;
+		return true;
+	}
+
+	if (strlen(cond) == 0) {
+		settings->abort_mask = 0;
+		return true;
+	}
+
+	for (it = abort_conditions; it->name; it++) {
+		if (!strcmp(cond, it->name)) {
+			settings->abort_mask |= it->value;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool parse_abort_conditions(struct settings *settings, const char *optarg)
+{
+	char *dup, *p;
+	if (!optarg)
+		return set_abort_condition(settings, NULL);
+
+	dup = strdup(optarg);
+	while (dup) {
+		if ((p = strchr(dup, ',')) != NULL) {
+			*p = '\0';
+			p++;
+		}
+
+		if (!set_abort_condition(settings, dup))
+			return false;
+
+		dup = p;
+	}
+
+	return true;
+}
+
 static const char *usage_str =
 	"usage: runner [options] [test_root] results-path\n\n"
 	"Options:\n"
@@ -67,9 +123,15 @@ static const char *usage_str =
 	"                        Run only matching tests (can be used more than once)\n"
 	"  -x <regex>, --exclude-tests <regex>\n"
 	"                        Exclude matching tests (can be used more than once)\n"
-	"  --abort-on-monitored-error\n"
+	"  --abort-on-monitored-error[=list]\n"
 	"                        Abort execution when a fatal condition is detected.\n"
-	"                        <TODO>\n"
+	"                        A comma-separated list of conditions to check can be\n"
+	"                        given. If not given, all conditions are checked. An\n"
+	"                        empty string as a condition disables aborting\n"
+	"                        Possible conditions:\n"
+	"                         lockdep - abort when kernel lockdep has been angered.\n"
+	"                         taint   - abort when kernel becomes fatally tainted.\n"
+	"                         all     - abort for all of the above.\n"
 	"  -s, --sync            Sync results to disk after every test\n"
 	"  -l {quiet,verbose,dummy}, --log-level {quiet,verbose,dummy}\n"
 	"                        Set the logger verbosity level\n"
@@ -193,7 +255,7 @@ bool parse_options(int argc, char **argv,
 		{"dry-run", no_argument, NULL, OPT_DRY_RUN},
 		{"include-tests", required_argument, NULL, OPT_INCLUDE},
 		{"exclude-tests", required_argument, NULL, OPT_EXCLUDE},
-		{"abort-on-monitored-error", no_argument, NULL, OPT_ABORT_ON_ERROR},
+		{"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR},
 		{"sync", no_argument, NULL, OPT_SYNC},
 		{"log-level", required_argument, NULL, OPT_LOG_LEVEL},
 		{"test-list", required_argument, NULL, OPT_TEST_LIST},
@@ -231,7 +293,8 @@ bool parse_options(int argc, char **argv,
 				goto error;
 			break;
 		case OPT_ABORT_ON_ERROR:
-			settings->abort_on_error = true;
+			if (!parse_abort_conditions(settings, optarg))
+				goto error;
 			break;
 		case OPT_SYNC:
 			settings->sync = true;
@@ -444,7 +507,7 @@ bool serialize_settings(struct settings *settings)
 		return false;
 	}
 
-	SERIALIZE_LINE(f, settings, abort_on_error, "%d");
+	SERIALIZE_LINE(f, settings, abort_mask, "%d");
 	if (settings->test_list)
 		SERIALIZE_LINE(f, settings, test_list, "%s");
 	if (settings->name)
@@ -501,7 +564,7 @@ bool read_settings(struct settings *settings, int dirfd)
 
 	while (fscanf(f, "%ms : %ms", &name, &val) == 2) {
 		int numval = atoi(val);
-		PARSE_LINE(settings, name, val, abort_on_error, numval);
+		PARSE_LINE(settings, name, val, abort_mask, numval);
 		PARSE_LINE(settings, name, val, test_list, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, name, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, dry_run, numval);
diff --git a/runner/settings.h b/runner/settings.h
index b489abc5..267d72cf 100644
--- a/runner/settings.h
+++ b/runner/settings.h
@@ -12,6 +12,12 @@ enum {
 	LOG_LEVEL_VERBOSE = 1,
 };
 
+#define ABORT_TAINT   (1 << 0)
+#define ABORT_LOCKDEP (1 << 1)
+#define ABORT_ALL     (ABORT_TAINT | ABORT_LOCKDEP)
+
+_Static_assert(ABORT_ALL == (ABORT_TAINT | ABORT_LOCKDEP), "ABORT_ALL must be all conditions bitwise or'd");
+
 struct regex_list {
 	char **regex_strings;
 	regex_t** regexes;
@@ -19,7 +25,7 @@ struct regex_list {
 };
 
 struct settings {
-	bool abort_on_error;
+	int abort_mask;
 	char *test_list;
 	char *name;
 	bool dry_run;
-- 
2.18.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
@ 2018-11-02 12:24 ` Martin Peres
  2018-11-02 12:24 ` Chris Wilson
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Martin Peres @ 2018-11-02 12:24 UTC (permalink / raw)
  To: Petri Latvala, igt-dev; +Cc: Tomi Sarvela

On 02/11/2018 14:08, Petri Latvala wrote:
> Deviating a bit from the piglit command line flag, igt_runner takes an
> optional comma-separated list as an argument to
> --abort-on-monitored-error for the list of conditions to abort
> on. Without a list all possible conditions will be checked.
> 
> Two conditions implemented:
>  - "taint" checks the kernel taint level for TAINT_PAGE, TAINT_DIE and
>  TAINT_OOPS
>  - "lockdep" checks the kernel lockdep status
> 
> Checking is done after every test binary execution, and if an abort
> condition is met, the reason is printed to stderr (unless log level is
> quiet) and the runner doesn't execute any further tests. Aborting
> between subtests (when running in --multiple-mode) is not done.
> 
> A TODO item for the future is having aborting appear in the test
> results.
> 
> Signed-off-by: Petri Latvala <petri.latvala@intel.com>
> Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
> Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
> Cc: Martin Peres <martin.peres@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>

        \o/
Oh yeah  |  !
        / \

Acked-by: Martin Peres <martin.peres@linux.intel.com>

> ---
> 
> It should be noted that this is automatically active in CI, for it
> gives --abort-on-monitored-error without a list to igt_runner already.
> 
> 
>  runner/executor.c     | 92 ++++++++++++++++++++++++++++++++++++++++---
>  runner/runner_tests.c | 49 ++++++++++++++++++++---
>  runner/settings.c     | 75 ++++++++++++++++++++++++++++++++---
>  runner/settings.h     |  8 +++-
>  4 files changed, 206 insertions(+), 18 deletions(-)
> 
> diff --git a/runner/executor.c b/runner/executor.c
> index fc79f772..98c31f36 100644
> --- a/runner/executor.c
> +++ b/runner/executor.c
> @@ -108,6 +108,79 @@ static void ping_watchdogs(void)
>  	}
>  }
>  
> +static bool handle_lockdep(struct settings *settings)
> +{
> +	FILE *f = fopen("/proc/lockdep_stats", "r");
> +	const char *debug_locks_line = " debug_locks:";
> +	char buf[512];
> +	int val;
> +
> +	if (!f)
> +		return false;
> +
> +	while (fgets(buf, sizeof(buf), f) != NULL) {
> +		if (!strncmp(buf, debug_locks_line, strlen(debug_locks_line))) {
> +			char *p = buf + strlen(debug_locks_line);
> +			if (sscanf(p, "%d", &val) == 1 &&
> +			    val != 0) {
> +				if (settings->log_level >= LOG_LEVEL_NORMAL) {
> +					fprintf(stderr, "Lockdep triggered, aborting\n");
> +				}
> +				return true;
> +			}
> +
> +			break;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static bool handle_taint(struct settings *settings)
> +{
> +	FILE *f = fopen("/proc/sys/kernel/tainted", "r");
> +	int taint;
> +	int bad_taints =
> +		0x20  | /* TAINT_PAGE */
> +		0x80  | /* TAINT_DIE */
> +		0x200; /* TAINT_OOPS */
> +
> +	if (!f || fscanf(f, "%d", &taint) != 1)
> +		return false;
> +
> +	if (taint & bad_taints) {
> +		if (settings->log_level >= LOG_LEVEL_NORMAL) {
> +			fprintf(stderr, "Kernel tainted (0x%x), aborting\n", taint);
> +		}
> +
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +static struct {
> +	int condition;
> +	bool (*handler)(struct settings*);
> +} abort_handlers[] = {
> +	{ ABORT_LOCKDEP, handle_lockdep },
> +	{ ABORT_TAINT, handle_taint },
> +	{ 0, 0 },
> +};
> +
> +static bool need_to_abort(struct settings* settings)
> +{
> +	typeof(*abort_handlers) *it;
> +
> +	for (it = abort_handlers; it->condition; it++) {
> +		if (settings->abort_mask & it->condition &&
> +		    it->handler(settings))
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
>  static void prune_subtest(struct job_list_entry *entry, char *subtest)
>  {
>  	char *excl;
> @@ -1102,12 +1175,19 @@ bool execute(struct execute_state *state,
>  
>  	for (; state->next < job_list->size;
>  	     state->next++) {
> -		int result = execute_next_entry(state,
> -						job_list->size,
> -						&time_spent,
> -						settings,
> -						&job_list->entries[state->next],
> -						testdirfd, resdirfd);
> +		int result;
> +
> +		if (need_to_abort(settings)) {
> +			status = false;
> +			break;
> +		}
> +
> +		result = execute_next_entry(state,
> +					    job_list->size,
> +					    &time_spent,
> +					    settings,
> +					    &job_list->entries[state->next],
> +					    testdirfd, resdirfd);
>  
>  		if (result < 0) {
>  			status = false;
> diff --git a/runner/runner_tests.c b/runner/runner_tests.c
> index 9c0f9eb0..829c60c3 100644
> --- a/runner/runner_tests.c
> +++ b/runner/runner_tests.c
> @@ -142,7 +142,7 @@ static void assert_settings_equal(struct settings *one, struct settings *two)
>  	 * Regex lists are not serialized, and thus won't be compared
>  	 * here.
>  	 */
> -	igt_assert_eq(one->abort_on_error, two->abort_on_error);
> +	igt_assert_eq(one->abort_mask, two->abort_mask);
>  	igt_assert_eqstr(one->test_list, two->test_list);
>  	igt_assert_eqstr(one->name, two->name);
>  	igt_assert_eq(one->dry_run, two->dry_run);
> @@ -208,7 +208,7 @@ igt_main
>  
>  		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
>  
> -		igt_assert(!settings.abort_on_error);
> +		igt_assert_eq(settings.abort_mask, 0);
>  		igt_assert(!settings.test_list);
>  		igt_assert_eqstr(settings.name, "path-to-results");
>  		igt_assert(!settings.dry_run);
> @@ -323,7 +323,7 @@ igt_main
>  		setenv("IGT_TEST_ROOT", testdatadir, 1);
>  		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
>  
> -		igt_assert(!settings.abort_on_error);
> +		igt_assert_eq(settings.abort_mask, 0);
>  		igt_assert(!settings.test_list);
>  		igt_assert_eqstr(settings.name, "path-to-results");
>  		igt_assert(!settings.dry_run);
> @@ -348,7 +348,7 @@ igt_main
>  	igt_subtest("parse-all-settings") {
>  		char *argv[] = { "runner",
>  				 "-n", "foo",
> -				 "--abort-on-monitored-error",
> +				 "--abort-on-monitored-error=taint,lockdep",
>  				 "--test-list", "path-to-test-list",
>  				 "--ignore-missing",
>  				 "--dry-run",
> @@ -370,7 +370,7 @@ igt_main
>  
>  		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
>  
> -		igt_assert(settings.abort_on_error);
> +		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
>  		igt_assert(strstr(settings.test_list, "path-to-test-list") != NULL);
>  		igt_assert_eqstr(settings.name, "foo");
>  		igt_assert(settings.dry_run);
> @@ -428,6 +428,45 @@ igt_main
>  		igt_assert_eq(settings.log_level, LOG_LEVEL_VERBOSE);
>  	}
>  
> +	igt_subtest("abort-conditions") {
> +		char *argv[] = { "runner",
> +				 "--abort-on-monitored-error=taint",
> +				 "test-root-dir",
> +				 "results-path",
> +		};
> +
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
> +
> +		argv[1] = "--abort-on-monitored-error=lockdep";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_LOCKDEP);
> +
> +		argv[1] = "--abort-on-monitored-error=taint";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
> +
> +		argv[1] = "--abort-on-monitored-error=lockdep,taint";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
> +
> +		argv[1] = "--abort-on-monitored-error=taint,lockdep";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
> +
> +		argv[1] = "--abort-on-monitored-error=all";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, ABORT_ALL);
> +
> +		argv[1] = "--abort-on-monitored-error=";
> +		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
> +		igt_assert_eq(settings.abort_mask, 0);
> +
> +		argv[1] = "--abort-on-monitored-error=doesnotexist";
> +		igt_assert(!parse_options(ARRAY_SIZE(argv), argv, &settings));
> +
> +	}
> +
>  	igt_subtest("parse-clears-old-data") {
>  		char *argv[] = { "runner",
>  				 "-n", "foo",
> diff --git a/runner/settings.c b/runner/settings.c
> index e2401455..e056493a 100644
> --- a/runner/settings.c
> +++ b/runner/settings.c
> @@ -41,6 +41,16 @@ static struct {
>  	{ 0, 0 },
>  };
>  
> +static struct {
> +	int value;
> +	const char *name;
> +} abort_conditions[] = {
> +	{ ABORT_TAINT, "taint" },
> +	{ ABORT_LOCKDEP, "lockdep" },
> +	{ ABORT_ALL, "all" },
> +	{ 0, 0 },
> +};
> +
>  static bool set_log_level(struct settings* settings, const char *level)
>  {
>  	typeof(*log_levels) *it;
> @@ -55,6 +65,52 @@ static bool set_log_level(struct settings* settings, const char *level)
>  	return false;
>  }
>  
> +static bool set_abort_condition(struct settings* settings, const char *cond)
> +{
> +	typeof(*abort_conditions) *it;
> +
> +	if (!cond) {
> +		settings->abort_mask = ABORT_ALL;
> +		return true;
> +	}
> +
> +	if (strlen(cond) == 0) {
> +		settings->abort_mask = 0;
> +		return true;
> +	}
> +
> +	for (it = abort_conditions; it->name; it++) {
> +		if (!strcmp(cond, it->name)) {
> +			settings->abort_mask |= it->value;
> +			return true;
> +		}
> +	}
> +
> +	return false;
> +}
> +
> +static bool parse_abort_conditions(struct settings *settings, const char *optarg)
> +{
> +	char *dup, *p;
> +	if (!optarg)
> +		return set_abort_condition(settings, NULL);
> +
> +	dup = strdup(optarg);
> +	while (dup) {
> +		if ((p = strchr(dup, ',')) != NULL) {
> +			*p = '\0';
> +			p++;
> +		}
> +
> +		if (!set_abort_condition(settings, dup))
> +			return false;
> +
> +		dup = p;
> +	}
> +
> +	return true;
> +}
> +
>  static const char *usage_str =
>  	"usage: runner [options] [test_root] results-path\n\n"
>  	"Options:\n"
> @@ -67,9 +123,15 @@ static const char *usage_str =
>  	"                        Run only matching tests (can be used more than once)\n"
>  	"  -x <regex>, --exclude-tests <regex>\n"
>  	"                        Exclude matching tests (can be used more than once)\n"
> -	"  --abort-on-monitored-error\n"
> +	"  --abort-on-monitored-error[=list]\n"
>  	"                        Abort execution when a fatal condition is detected.\n"
> -	"                        <TODO>\n"
> +	"                        A comma-separated list of conditions to check can be\n"
> +	"                        given. If not given, all conditions are checked. An\n"
> +	"                        empty string as a condition disables aborting\n"
> +	"                        Possible conditions:\n"
> +	"                         lockdep - abort when kernel lockdep has been angered.\n"
> +	"                         taint   - abort when kernel becomes fatally tainted.\n"
> +	"                         all     - abort for all of the above.\n"
>  	"  -s, --sync            Sync results to disk after every test\n"
>  	"  -l {quiet,verbose,dummy}, --log-level {quiet,verbose,dummy}\n"
>  	"                        Set the logger verbosity level\n"
> @@ -193,7 +255,7 @@ bool parse_options(int argc, char **argv,
>  		{"dry-run", no_argument, NULL, OPT_DRY_RUN},
>  		{"include-tests", required_argument, NULL, OPT_INCLUDE},
>  		{"exclude-tests", required_argument, NULL, OPT_EXCLUDE},
> -		{"abort-on-monitored-error", no_argument, NULL, OPT_ABORT_ON_ERROR},
> +		{"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR},
>  		{"sync", no_argument, NULL, OPT_SYNC},
>  		{"log-level", required_argument, NULL, OPT_LOG_LEVEL},
>  		{"test-list", required_argument, NULL, OPT_TEST_LIST},
> @@ -231,7 +293,8 @@ bool parse_options(int argc, char **argv,
>  				goto error;
>  			break;
>  		case OPT_ABORT_ON_ERROR:
> -			settings->abort_on_error = true;
> +			if (!parse_abort_conditions(settings, optarg))
> +				goto error;
>  			break;
>  		case OPT_SYNC:
>  			settings->sync = true;
> @@ -444,7 +507,7 @@ bool serialize_settings(struct settings *settings)
>  		return false;
>  	}
>  
> -	SERIALIZE_LINE(f, settings, abort_on_error, "%d");
> +	SERIALIZE_LINE(f, settings, abort_mask, "%d");
>  	if (settings->test_list)
>  		SERIALIZE_LINE(f, settings, test_list, "%s");
>  	if (settings->name)
> @@ -501,7 +564,7 @@ bool read_settings(struct settings *settings, int dirfd)
>  
>  	while (fscanf(f, "%ms : %ms", &name, &val) == 2) {
>  		int numval = atoi(val);
> -		PARSE_LINE(settings, name, val, abort_on_error, numval);
> +		PARSE_LINE(settings, name, val, abort_mask, numval);
>  		PARSE_LINE(settings, name, val, test_list, val ? strdup(val) : NULL);
>  		PARSE_LINE(settings, name, val, name, val ? strdup(val) : NULL);
>  		PARSE_LINE(settings, name, val, dry_run, numval);
> diff --git a/runner/settings.h b/runner/settings.h
> index b489abc5..267d72cf 100644
> --- a/runner/settings.h
> +++ b/runner/settings.h
> @@ -12,6 +12,12 @@ enum {
>  	LOG_LEVEL_VERBOSE = 1,
>  };
>  
> +#define ABORT_TAINT   (1 << 0)
> +#define ABORT_LOCKDEP (1 << 1)
> +#define ABORT_ALL     (ABORT_TAINT | ABORT_LOCKDEP)
> +
> +_Static_assert(ABORT_ALL == (ABORT_TAINT | ABORT_LOCKDEP), "ABORT_ALL must be all conditions bitwise or'd");
> +
>  struct regex_list {
>  	char **regex_strings;
>  	regex_t** regexes;
> @@ -19,7 +25,7 @@ struct regex_list {
>  };
>  
>  struct settings {
> -	bool abort_on_error;
> +	int abort_mask;
>  	char *test_list;
>  	char *name;
>  	bool dry_run;
> 
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
  2018-11-02 12:24 ` Martin Peres
@ 2018-11-02 12:24 ` Chris Wilson
  2018-11-02 12:53 ` [igt-dev] [PATCH i-g-t v2 " Petri Latvala
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 8+ messages in thread
From: Chris Wilson @ 2018-11-02 12:24 UTC (permalink / raw)
  To: Petri Latvala, igt-dev; +Cc: Tomi Sarvela, Petri Latvala, Martin Peres

Quoting Petri Latvala (2018-11-02 12:08:48)
> Deviating a bit from the piglit command line flag, igt_runner takes an
> optional comma-separated list as an argument to
> --abort-on-monitored-error for the list of conditions to abort
> on. Without a list all possible conditions will be checked.
> 
> Two conditions implemented:
>  - "taint" checks the kernel taint level for TAINT_PAGE, TAINT_DIE and
>  TAINT_OOPS
>  - "lockdep" checks the kernel lockdep status
> 
> Checking is done after every test binary execution, and if an abort
> condition is met, the reason is printed to stderr (unless log level is
> quiet) and the runner doesn't execute any further tests. Aborting
> between subtests (when running in --multiple-mode) is not done.
> 
> A TODO item for the future is having aborting appear in the test
> results.
> 
> Signed-off-by: Petri Latvala <petri.latvala@intel.com>
> Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
> Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
> Cc: Martin Peres <martin.peres@linux.intel.com>
> Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
> 
> It should be noted that this is automatically active in CI, for it
> gives --abort-on-monitored-error without a list to igt_runner already.
> 
> 
>  runner/executor.c     | 92 ++++++++++++++++++++++++++++++++++++++++---
>  runner/runner_tests.c | 49 ++++++++++++++++++++---
>  runner/settings.c     | 75 ++++++++++++++++++++++++++++++++---
>  runner/settings.h     |  8 +++-
>  4 files changed, 206 insertions(+), 18 deletions(-)
> 
> diff --git a/runner/executor.c b/runner/executor.c
> index fc79f772..98c31f36 100644
> --- a/runner/executor.c
> +++ b/runner/executor.c
> @@ -108,6 +108,79 @@ static void ping_watchdogs(void)
>         }
>  }
>  
> +static bool handle_lockdep(struct settings *settings)
> +{
> +       FILE *f = fopen("/proc/lockdep_stats", "r");
> +       const char *debug_locks_line = " debug_locks:";
> +       char buf[512];
> +       int val;
> +
> +       if (!f)
> +               return false;
> +
> +       while (fgets(buf, sizeof(buf), f) != NULL) {
> +               if (!strncmp(buf, debug_locks_line, strlen(debug_locks_line))) {

There's no guarantee here that you have the complete line within the
buf before parsing. Try getline() instead.

> +                       char *p = buf + strlen(debug_locks_line);
> +                       if (sscanf(p, "%d", &val) == 1 &&
> +                           val != 0) {
> +                               if (settings->log_level >= LOG_LEVEL_NORMAL) {
> +                                       fprintf(stderr, "Lockdep triggered, aborting\n");
> +                               }
> +                               return true;
> +                       }
> +
> +                       break;
> +               }
> +       }
> +
> +       return false;
> +}
> +
> +static bool handle_taint(struct settings *settings)
> +{
> +       FILE *f = fopen("/proc/sys/kernel/tainted", "r");
> +       int taint;

The value is (unsigned) long, important if we ever get more than 32b of
taints on 64b machines.
-Chris
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH i-g-t v2 1/1] runner: Implement --abort-on-monitored-error
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
  2018-11-02 12:24 ` Martin Peres
  2018-11-02 12:24 ` Chris Wilson
@ 2018-11-02 12:53 ` Petri Latvala
  2018-11-02 13:26   ` [igt-dev] [PATCH i-g-t v3 " Petri Latvala
  2018-11-02 13:06 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,1/1] " Patchwork
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 8+ messages in thread
From: Petri Latvala @ 2018-11-02 12:53 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala, Martin Peres, Tomi Sarvela

Deviating a bit from the piglit command line flag, igt_runner takes an
optional comma-separated list as an argument to
--abort-on-monitored-error for the list of conditions to abort
on. Without a list all possible conditions will be checked.

Two conditions implemented:
 - "taint" checks the kernel taint level for TAINT_PAGE, TAINT_DIE and
 TAINT_OOPS
 - "lockdep" checks the kernel lockdep status

Checking is done after every test binary execution, and if an abort
condition is met, the reason is printed to stderr (unless log level is
quiet) and the runner doesn't execute any further tests. Aborting
between subtests (when running in --multiple-mode) is not done.

A TODO item for the future is having aborting appear in the test
results.

v2:
 - Remember to fclose
 - Taints are unsigned long (Chris)
 - Use getline instead of fgets (Chris)

Signed-off-by: Petri Latvala <petri.latvala@intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
Cc: Martin Peres <martin.peres@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 runner/executor.c     | 103 +++++++++++++++++++++++++++++++++++++++---
 runner/runner_tests.c |  49 ++++++++++++++++++--
 runner/settings.c     |  75 +++++++++++++++++++++++++++---
 runner/settings.h     |   8 +++-
 4 files changed, 217 insertions(+), 18 deletions(-)

diff --git a/runner/executor.c b/runner/executor.c
index fc79f772..dff6ba9f 100644
--- a/runner/executor.c
+++ b/runner/executor.c
@@ -108,6 +108,90 @@ static void ping_watchdogs(void)
 	}
 }
 
+static bool handle_lockdep(struct settings *settings)
+{
+	FILE *f = fopen("/proc/lockdep_stats", "r");
+	const char *debug_locks_line = " debug_locks:";
+	char *buf = NULL;
+	size_t bufsize = 0;
+	int val;
+	bool ret = false;
+
+	if (!f)
+		return false;
+
+	while (getline(&buf, &bufsize, f) > 0) {
+		if (!strncmp(buf, debug_locks_line, strlen(debug_locks_line))) {
+			char *p = buf + strlen(debug_locks_line);
+			if (sscanf(p, "%d", &val) == 1 &&
+			    val != 0) {
+				if (settings->log_level >= LOG_LEVEL_NORMAL) {
+					fprintf(stderr, "Lockdep triggered, aborting\n");
+				}
+				ret = true;
+			}
+
+			break;
+		}
+	}
+
+	fclose(f);
+	free(buf);
+	return ret;
+}
+
+static bool handle_taint(struct settings *settings)
+{
+	FILE *f = fopen("/proc/sys/kernel/tainted", "r");
+	int s;
+	unsigned long taint;
+	unsigned long bad_taints =
+		0x20  | /* TAINT_PAGE */
+		0x80  | /* TAINT_DIE */
+		0x200; /* TAINT_OOPS */
+
+	if (!f)
+		return false;
+
+	s = fscanf(f, "%lu", &taint);
+	fclose(f);
+
+	if (s != 1)
+		return false;
+
+	if (taint & bad_taints) {
+		if (settings->log_level >= LOG_LEVEL_NORMAL) {
+			fprintf(stderr, "Kernel tainted (0x%lx), aborting\n", taint);
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static struct {
+	int condition;
+	bool (*handler)(struct settings*);
+} abort_handlers[] = {
+	{ ABORT_LOCKDEP, handle_lockdep },
+	{ ABORT_TAINT, handle_taint },
+	{ 0, 0 },
+};
+
+static bool need_to_abort(struct settings* settings)
+{
+	typeof(*abort_handlers) *it;
+
+	for (it = abort_handlers; it->condition; it++) {
+		if (settings->abort_mask & it->condition &&
+		    it->handler(settings))
+			return true;
+	}
+
+	return false;
+}
+
 static void prune_subtest(struct job_list_entry *entry, char *subtest)
 {
 	char *excl;
@@ -1102,12 +1186,19 @@ bool execute(struct execute_state *state,
 
 	for (; state->next < job_list->size;
 	     state->next++) {
-		int result = execute_next_entry(state,
-						job_list->size,
-						&time_spent,
-						settings,
-						&job_list->entries[state->next],
-						testdirfd, resdirfd);
+		int result;
+
+		if (need_to_abort(settings)) {
+			status = false;
+			break;
+		}
+
+		result = execute_next_entry(state,
+					    job_list->size,
+					    &time_spent,
+					    settings,
+					    &job_list->entries[state->next],
+					    testdirfd, resdirfd);
 
 		if (result < 0) {
 			status = false;
diff --git a/runner/runner_tests.c b/runner/runner_tests.c
index 9c0f9eb0..829c60c3 100644
--- a/runner/runner_tests.c
+++ b/runner/runner_tests.c
@@ -142,7 +142,7 @@ static void assert_settings_equal(struct settings *one, struct settings *two)
 	 * Regex lists are not serialized, and thus won't be compared
 	 * here.
 	 */
-	igt_assert_eq(one->abort_on_error, two->abort_on_error);
+	igt_assert_eq(one->abort_mask, two->abort_mask);
 	igt_assert_eqstr(one->test_list, two->test_list);
 	igt_assert_eqstr(one->name, two->name);
 	igt_assert_eq(one->dry_run, two->dry_run);
@@ -208,7 +208,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -323,7 +323,7 @@ igt_main
 		setenv("IGT_TEST_ROOT", testdatadir, 1);
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -348,7 +348,7 @@ igt_main
 	igt_subtest("parse-all-settings") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
-				 "--abort-on-monitored-error",
+				 "--abort-on-monitored-error=taint,lockdep",
 				 "--test-list", "path-to-test-list",
 				 "--ignore-missing",
 				 "--dry-run",
@@ -370,7 +370,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
 		igt_assert(strstr(settings.test_list, "path-to-test-list") != NULL);
 		igt_assert_eqstr(settings.name, "foo");
 		igt_assert(settings.dry_run);
@@ -428,6 +428,45 @@ igt_main
 		igt_assert_eq(settings.log_level, LOG_LEVEL_VERBOSE);
 	}
 
+	igt_subtest("abort-conditions") {
+		char *argv[] = { "runner",
+				 "--abort-on-monitored-error=taint",
+				 "test-root-dir",
+				 "results-path",
+		};
+
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep,taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint,lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=all";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_ALL);
+
+		argv[1] = "--abort-on-monitored-error=";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, 0);
+
+		argv[1] = "--abort-on-monitored-error=doesnotexist";
+		igt_assert(!parse_options(ARRAY_SIZE(argv), argv, &settings));
+
+	}
+
 	igt_subtest("parse-clears-old-data") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
diff --git a/runner/settings.c b/runner/settings.c
index e2401455..e056493a 100644
--- a/runner/settings.c
+++ b/runner/settings.c
@@ -41,6 +41,16 @@ static struct {
 	{ 0, 0 },
 };
 
+static struct {
+	int value;
+	const char *name;
+} abort_conditions[] = {
+	{ ABORT_TAINT, "taint" },
+	{ ABORT_LOCKDEP, "lockdep" },
+	{ ABORT_ALL, "all" },
+	{ 0, 0 },
+};
+
 static bool set_log_level(struct settings* settings, const char *level)
 {
 	typeof(*log_levels) *it;
@@ -55,6 +65,52 @@ static bool set_log_level(struct settings* settings, const char *level)
 	return false;
 }
 
+static bool set_abort_condition(struct settings* settings, const char *cond)
+{
+	typeof(*abort_conditions) *it;
+
+	if (!cond) {
+		settings->abort_mask = ABORT_ALL;
+		return true;
+	}
+
+	if (strlen(cond) == 0) {
+		settings->abort_mask = 0;
+		return true;
+	}
+
+	for (it = abort_conditions; it->name; it++) {
+		if (!strcmp(cond, it->name)) {
+			settings->abort_mask |= it->value;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool parse_abort_conditions(struct settings *settings, const char *optarg)
+{
+	char *dup, *p;
+	if (!optarg)
+		return set_abort_condition(settings, NULL);
+
+	dup = strdup(optarg);
+	while (dup) {
+		if ((p = strchr(dup, ',')) != NULL) {
+			*p = '\0';
+			p++;
+		}
+
+		if (!set_abort_condition(settings, dup))
+			return false;
+
+		dup = p;
+	}
+
+	return true;
+}
+
 static const char *usage_str =
 	"usage: runner [options] [test_root] results-path\n\n"
 	"Options:\n"
@@ -67,9 +123,15 @@ static const char *usage_str =
 	"                        Run only matching tests (can be used more than once)\n"
 	"  -x <regex>, --exclude-tests <regex>\n"
 	"                        Exclude matching tests (can be used more than once)\n"
-	"  --abort-on-monitored-error\n"
+	"  --abort-on-monitored-error[=list]\n"
 	"                        Abort execution when a fatal condition is detected.\n"
-	"                        <TODO>\n"
+	"                        A comma-separated list of conditions to check can be\n"
+	"                        given. If not given, all conditions are checked. An\n"
+	"                        empty string as a condition disables aborting\n"
+	"                        Possible conditions:\n"
+	"                         lockdep - abort when kernel lockdep has been angered.\n"
+	"                         taint   - abort when kernel becomes fatally tainted.\n"
+	"                         all     - abort for all of the above.\n"
 	"  -s, --sync            Sync results to disk after every test\n"
 	"  -l {quiet,verbose,dummy}, --log-level {quiet,verbose,dummy}\n"
 	"                        Set the logger verbosity level\n"
@@ -193,7 +255,7 @@ bool parse_options(int argc, char **argv,
 		{"dry-run", no_argument, NULL, OPT_DRY_RUN},
 		{"include-tests", required_argument, NULL, OPT_INCLUDE},
 		{"exclude-tests", required_argument, NULL, OPT_EXCLUDE},
-		{"abort-on-monitored-error", no_argument, NULL, OPT_ABORT_ON_ERROR},
+		{"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR},
 		{"sync", no_argument, NULL, OPT_SYNC},
 		{"log-level", required_argument, NULL, OPT_LOG_LEVEL},
 		{"test-list", required_argument, NULL, OPT_TEST_LIST},
@@ -231,7 +293,8 @@ bool parse_options(int argc, char **argv,
 				goto error;
 			break;
 		case OPT_ABORT_ON_ERROR:
-			settings->abort_on_error = true;
+			if (!parse_abort_conditions(settings, optarg))
+				goto error;
 			break;
 		case OPT_SYNC:
 			settings->sync = true;
@@ -444,7 +507,7 @@ bool serialize_settings(struct settings *settings)
 		return false;
 	}
 
-	SERIALIZE_LINE(f, settings, abort_on_error, "%d");
+	SERIALIZE_LINE(f, settings, abort_mask, "%d");
 	if (settings->test_list)
 		SERIALIZE_LINE(f, settings, test_list, "%s");
 	if (settings->name)
@@ -501,7 +564,7 @@ bool read_settings(struct settings *settings, int dirfd)
 
 	while (fscanf(f, "%ms : %ms", &name, &val) == 2) {
 		int numval = atoi(val);
-		PARSE_LINE(settings, name, val, abort_on_error, numval);
+		PARSE_LINE(settings, name, val, abort_mask, numval);
 		PARSE_LINE(settings, name, val, test_list, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, name, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, dry_run, numval);
diff --git a/runner/settings.h b/runner/settings.h
index b489abc5..267d72cf 100644
--- a/runner/settings.h
+++ b/runner/settings.h
@@ -12,6 +12,12 @@ enum {
 	LOG_LEVEL_VERBOSE = 1,
 };
 
+#define ABORT_TAINT   (1 << 0)
+#define ABORT_LOCKDEP (1 << 1)
+#define ABORT_ALL     (ABORT_TAINT | ABORT_LOCKDEP)
+
+_Static_assert(ABORT_ALL == (ABORT_TAINT | ABORT_LOCKDEP), "ABORT_ALL must be all conditions bitwise or'd");
+
 struct regex_list {
 	char **regex_strings;
 	regex_t** regexes;
@@ -19,7 +25,7 @@ struct regex_list {
 };
 
 struct settings {
-	bool abort_on_error;
+	int abort_mask;
 	char *test_list;
 	char *name;
 	bool dry_run;
-- 
2.18.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,1/1] runner: Implement --abort-on-monitored-error
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
                   ` (2 preceding siblings ...)
  2018-11-02 12:53 ` [igt-dev] [PATCH i-g-t v2 " Petri Latvala
@ 2018-11-02 13:06 ` Patchwork
  2018-11-02 14:55 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3) Patchwork
  2018-11-02 16:39 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2018-11-02 13:06 UTC (permalink / raw)
  To: Petri Latvala; +Cc: igt-dev

== Series Details ==

Series: series starting with [i-g-t,1/1] runner: Implement --abort-on-monitored-error
URL   : https://patchwork.freedesktop.org/series/51936/
State : success

== Summary ==

= CI Bug Log - changes from CI_DRM_5064 -> IGTPW_2028 =

== Summary - SUCCESS ==

  No regressions found.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/51936/revisions/1/mbox/


== Changes ==

  No changes found


== Participating hosts (47 -> 0) ==

  Missing    (47): fi-kbl-soraka fi-cnl-u fi-skl-6770hq fi-bdw-gvtdvm fi-icl-u2 fi-skl-6260u fi-apl-guc fi-bxt-j4205 fi-pnv-d510 fi-blb-e6850 fi-skl-6700hq fi-skl-6600u fi-snb-2600 fi-hsw-4770r fi-bxt-dsi fi-bdw-5557u fi-bsw-n3050 fi-byt-j1900 fi-glk-dsi fi-bwr-2160 fi-kbl-7500u fi-ctg-p8600 fi-hsw-4770 fi-gdg-551 fi-ivb-3770 fi-ivb-3520m fi-kbl-7560u fi-skl-6700k2 fi-kbl-r fi-kbl-7567u fi-ilk-m540 fi-skl-gvtdvm fi-skl-guc fi-cfl-8700k fi-cfl-s3 fi-glk-j4005 fi-hsw-peppy fi-byt-squawks fi-bsw-cyan fi-cfl-guc fi-kbl-guc fi-whl-u fi-kbl-x1275 fi-skl-iommu fi-bsw-kefka fi-icl-u fi-byt-clapper 


== Build changes ==

    * IGT: IGT_4703 -> IGTPW_2028

  CI_DRM_5064: 9458f0c67b519ddf1c2b4eec9110e826c4e7d2f3 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2028: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2028/
  IGT_4703: f882a542a3eb24e78e51aa6410a3a67c0efb4e97 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2028/issues.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [igt-dev] [PATCH i-g-t v3 1/1] runner: Implement --abort-on-monitored-error
  2018-11-02 12:53 ` [igt-dev] [PATCH i-g-t v2 " Petri Latvala
@ 2018-11-02 13:26   ` Petri Latvala
  0 siblings, 0 replies; 8+ messages in thread
From: Petri Latvala @ 2018-11-02 13:26 UTC (permalink / raw)
  To: igt-dev; +Cc: Petri Latvala, Martin Peres, Tomi Sarvela

Deviating a bit from the piglit command line flag, igt_runner takes an
optional comma-separated list as an argument to
--abort-on-monitored-error for the list of conditions to abort
on. Without a list all possible conditions will be checked.

Two conditions implemented:
 - "taint" checks the kernel taint level for TAINT_PAGE, TAINT_DIE and
 TAINT_OOPS
 - "lockdep" checks the kernel lockdep status

Checking is done after every test binary execution, and if an abort
condition is met, the reason is printed to stderr (unless log level is
quiet) and the runner doesn't execute any further tests. Aborting
between subtests (when running in --multiple-mode) is not done.

A TODO item for the future is having aborting appear in the test
results.

v2:
 - Remember to fclose
 - Taints are unsigned long (Chris)
 - Use getline instead of fgets (Chris)
v3:
 - Fix brainfart with lockdep

Signed-off-by: Petri Latvala <petri.latvala@intel.com>
Cc: Arkadiusz Hiler <arkadiusz.hiler@intel.com>
Cc: Tomi Sarvela <tomi.p.sarvela@intel.com>
Cc: Martin Peres <martin.peres@linux.intel.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
---
 runner/executor.c     | 103 +++++++++++++++++++++++++++++++++++++++---
 runner/runner_tests.c |  49 ++++++++++++++++++--
 runner/settings.c     |  75 +++++++++++++++++++++++++++---
 runner/settings.h     |   8 +++-
 4 files changed, 217 insertions(+), 18 deletions(-)

diff --git a/runner/executor.c b/runner/executor.c
index fc79f772..57e94b26 100644
--- a/runner/executor.c
+++ b/runner/executor.c
@@ -108,6 +108,90 @@ static void ping_watchdogs(void)
 	}
 }
 
+static bool handle_lockdep(struct settings *settings)
+{
+	FILE *f = fopen("/proc/lockdep_stats", "r");
+	const char *debug_locks_line = " debug_locks:";
+	char *buf = NULL;
+	size_t bufsize = 0;
+	int val;
+	bool ret = false;
+
+	if (!f)
+		return false;
+
+	while (getline(&buf, &bufsize, f) > 0) {
+		if (!strncmp(buf, debug_locks_line, strlen(debug_locks_line))) {
+			char *p = buf + strlen(debug_locks_line);
+			if (sscanf(p, "%d", &val) == 1 &&
+			    val != 1) {
+				if (settings->log_level >= LOG_LEVEL_NORMAL) {
+					fprintf(stderr, "Lockdep triggered, aborting\n");
+				}
+				ret = true;
+			}
+
+			break;
+		}
+	}
+
+	fclose(f);
+	free(buf);
+	return ret;
+}
+
+static bool handle_taint(struct settings *settings)
+{
+	FILE *f = fopen("/proc/sys/kernel/tainted", "r");
+	int s;
+	unsigned long taint;
+	unsigned long bad_taints =
+		0x20  | /* TAINT_PAGE */
+		0x80  | /* TAINT_DIE */
+		0x200; /* TAINT_OOPS */
+
+	if (!f)
+		return false;
+
+	s = fscanf(f, "%lu", &taint);
+	fclose(f);
+
+	if (s != 1)
+		return false;
+
+	if (taint & bad_taints) {
+		if (settings->log_level >= LOG_LEVEL_NORMAL) {
+			fprintf(stderr, "Kernel tainted (0x%lx), aborting\n", taint);
+		}
+
+		return true;
+	}
+
+	return false;
+}
+
+static struct {
+	int condition;
+	bool (*handler)(struct settings*);
+} abort_handlers[] = {
+	{ ABORT_LOCKDEP, handle_lockdep },
+	{ ABORT_TAINT, handle_taint },
+	{ 0, 0 },
+};
+
+static bool need_to_abort(struct settings* settings)
+{
+	typeof(*abort_handlers) *it;
+
+	for (it = abort_handlers; it->condition; it++) {
+		if (settings->abort_mask & it->condition &&
+		    it->handler(settings))
+			return true;
+	}
+
+	return false;
+}
+
 static void prune_subtest(struct job_list_entry *entry, char *subtest)
 {
 	char *excl;
@@ -1102,12 +1186,19 @@ bool execute(struct execute_state *state,
 
 	for (; state->next < job_list->size;
 	     state->next++) {
-		int result = execute_next_entry(state,
-						job_list->size,
-						&time_spent,
-						settings,
-						&job_list->entries[state->next],
-						testdirfd, resdirfd);
+		int result;
+
+		if (need_to_abort(settings)) {
+			status = false;
+			break;
+		}
+
+		result = execute_next_entry(state,
+					    job_list->size,
+					    &time_spent,
+					    settings,
+					    &job_list->entries[state->next],
+					    testdirfd, resdirfd);
 
 		if (result < 0) {
 			status = false;
diff --git a/runner/runner_tests.c b/runner/runner_tests.c
index 9c0f9eb0..829c60c3 100644
--- a/runner/runner_tests.c
+++ b/runner/runner_tests.c
@@ -142,7 +142,7 @@ static void assert_settings_equal(struct settings *one, struct settings *two)
 	 * Regex lists are not serialized, and thus won't be compared
 	 * here.
 	 */
-	igt_assert_eq(one->abort_on_error, two->abort_on_error);
+	igt_assert_eq(one->abort_mask, two->abort_mask);
 	igt_assert_eqstr(one->test_list, two->test_list);
 	igt_assert_eqstr(one->name, two->name);
 	igt_assert_eq(one->dry_run, two->dry_run);
@@ -208,7 +208,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -323,7 +323,7 @@ igt_main
 		setenv("IGT_TEST_ROOT", testdatadir, 1);
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(!settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, 0);
 		igt_assert(!settings.test_list);
 		igt_assert_eqstr(settings.name, "path-to-results");
 		igt_assert(!settings.dry_run);
@@ -348,7 +348,7 @@ igt_main
 	igt_subtest("parse-all-settings") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
-				 "--abort-on-monitored-error",
+				 "--abort-on-monitored-error=taint,lockdep",
 				 "--test-list", "path-to-test-list",
 				 "--ignore-missing",
 				 "--dry-run",
@@ -370,7 +370,7 @@ igt_main
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
 
-		igt_assert(settings.abort_on_error);
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
 		igt_assert(strstr(settings.test_list, "path-to-test-list") != NULL);
 		igt_assert_eqstr(settings.name, "foo");
 		igt_assert(settings.dry_run);
@@ -428,6 +428,45 @@ igt_main
 		igt_assert_eq(settings.log_level, LOG_LEVEL_VERBOSE);
 	}
 
+	igt_subtest("abort-conditions") {
+		char *argv[] = { "runner",
+				 "--abort-on-monitored-error=taint",
+				 "test-root-dir",
+				 "results-path",
+		};
+
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT);
+
+		argv[1] = "--abort-on-monitored-error=lockdep,taint";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=taint,lockdep";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_TAINT | ABORT_LOCKDEP);
+
+		argv[1] = "--abort-on-monitored-error=all";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, ABORT_ALL);
+
+		argv[1] = "--abort-on-monitored-error=";
+		igt_assert(parse_options(ARRAY_SIZE(argv), argv, &settings));
+		igt_assert_eq(settings.abort_mask, 0);
+
+		argv[1] = "--abort-on-monitored-error=doesnotexist";
+		igt_assert(!parse_options(ARRAY_SIZE(argv), argv, &settings));
+
+	}
+
 	igt_subtest("parse-clears-old-data") {
 		char *argv[] = { "runner",
 				 "-n", "foo",
diff --git a/runner/settings.c b/runner/settings.c
index e2401455..e056493a 100644
--- a/runner/settings.c
+++ b/runner/settings.c
@@ -41,6 +41,16 @@ static struct {
 	{ 0, 0 },
 };
 
+static struct {
+	int value;
+	const char *name;
+} abort_conditions[] = {
+	{ ABORT_TAINT, "taint" },
+	{ ABORT_LOCKDEP, "lockdep" },
+	{ ABORT_ALL, "all" },
+	{ 0, 0 },
+};
+
 static bool set_log_level(struct settings* settings, const char *level)
 {
 	typeof(*log_levels) *it;
@@ -55,6 +65,52 @@ static bool set_log_level(struct settings* settings, const char *level)
 	return false;
 }
 
+static bool set_abort_condition(struct settings* settings, const char *cond)
+{
+	typeof(*abort_conditions) *it;
+
+	if (!cond) {
+		settings->abort_mask = ABORT_ALL;
+		return true;
+	}
+
+	if (strlen(cond) == 0) {
+		settings->abort_mask = 0;
+		return true;
+	}
+
+	for (it = abort_conditions; it->name; it++) {
+		if (!strcmp(cond, it->name)) {
+			settings->abort_mask |= it->value;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static bool parse_abort_conditions(struct settings *settings, const char *optarg)
+{
+	char *dup, *p;
+	if (!optarg)
+		return set_abort_condition(settings, NULL);
+
+	dup = strdup(optarg);
+	while (dup) {
+		if ((p = strchr(dup, ',')) != NULL) {
+			*p = '\0';
+			p++;
+		}
+
+		if (!set_abort_condition(settings, dup))
+			return false;
+
+		dup = p;
+	}
+
+	return true;
+}
+
 static const char *usage_str =
 	"usage: runner [options] [test_root] results-path\n\n"
 	"Options:\n"
@@ -67,9 +123,15 @@ static const char *usage_str =
 	"                        Run only matching tests (can be used more than once)\n"
 	"  -x <regex>, --exclude-tests <regex>\n"
 	"                        Exclude matching tests (can be used more than once)\n"
-	"  --abort-on-monitored-error\n"
+	"  --abort-on-monitored-error[=list]\n"
 	"                        Abort execution when a fatal condition is detected.\n"
-	"                        <TODO>\n"
+	"                        A comma-separated list of conditions to check can be\n"
+	"                        given. If not given, all conditions are checked. An\n"
+	"                        empty string as a condition disables aborting\n"
+	"                        Possible conditions:\n"
+	"                         lockdep - abort when kernel lockdep has been angered.\n"
+	"                         taint   - abort when kernel becomes fatally tainted.\n"
+	"                         all     - abort for all of the above.\n"
 	"  -s, --sync            Sync results to disk after every test\n"
 	"  -l {quiet,verbose,dummy}, --log-level {quiet,verbose,dummy}\n"
 	"                        Set the logger verbosity level\n"
@@ -193,7 +255,7 @@ bool parse_options(int argc, char **argv,
 		{"dry-run", no_argument, NULL, OPT_DRY_RUN},
 		{"include-tests", required_argument, NULL, OPT_INCLUDE},
 		{"exclude-tests", required_argument, NULL, OPT_EXCLUDE},
-		{"abort-on-monitored-error", no_argument, NULL, OPT_ABORT_ON_ERROR},
+		{"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR},
 		{"sync", no_argument, NULL, OPT_SYNC},
 		{"log-level", required_argument, NULL, OPT_LOG_LEVEL},
 		{"test-list", required_argument, NULL, OPT_TEST_LIST},
@@ -231,7 +293,8 @@ bool parse_options(int argc, char **argv,
 				goto error;
 			break;
 		case OPT_ABORT_ON_ERROR:
-			settings->abort_on_error = true;
+			if (!parse_abort_conditions(settings, optarg))
+				goto error;
 			break;
 		case OPT_SYNC:
 			settings->sync = true;
@@ -444,7 +507,7 @@ bool serialize_settings(struct settings *settings)
 		return false;
 	}
 
-	SERIALIZE_LINE(f, settings, abort_on_error, "%d");
+	SERIALIZE_LINE(f, settings, abort_mask, "%d");
 	if (settings->test_list)
 		SERIALIZE_LINE(f, settings, test_list, "%s");
 	if (settings->name)
@@ -501,7 +564,7 @@ bool read_settings(struct settings *settings, int dirfd)
 
 	while (fscanf(f, "%ms : %ms", &name, &val) == 2) {
 		int numval = atoi(val);
-		PARSE_LINE(settings, name, val, abort_on_error, numval);
+		PARSE_LINE(settings, name, val, abort_mask, numval);
 		PARSE_LINE(settings, name, val, test_list, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, name, val ? strdup(val) : NULL);
 		PARSE_LINE(settings, name, val, dry_run, numval);
diff --git a/runner/settings.h b/runner/settings.h
index b489abc5..267d72cf 100644
--- a/runner/settings.h
+++ b/runner/settings.h
@@ -12,6 +12,12 @@ enum {
 	LOG_LEVEL_VERBOSE = 1,
 };
 
+#define ABORT_TAINT   (1 << 0)
+#define ABORT_LOCKDEP (1 << 1)
+#define ABORT_ALL     (ABORT_TAINT | ABORT_LOCKDEP)
+
+_Static_assert(ABORT_ALL == (ABORT_TAINT | ABORT_LOCKDEP), "ABORT_ALL must be all conditions bitwise or'd");
+
 struct regex_list {
 	char **regex_strings;
 	regex_t** regexes;
@@ -19,7 +25,7 @@ struct regex_list {
 };
 
 struct settings {
-	bool abort_on_error;
+	int abort_mask;
 	char *test_list;
 	char *name;
 	bool dry_run;
-- 
2.18.0

_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3)
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
                   ` (3 preceding siblings ...)
  2018-11-02 13:06 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,1/1] " Patchwork
@ 2018-11-02 14:55 ` Patchwork
  2018-11-02 16:39 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2018-11-02 14:55 UTC (permalink / raw)
  To: Petri Latvala; +Cc: igt-dev

== Series Details ==

Series: series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3)
URL   : https://patchwork.freedesktop.org/series/51936/
State : success

== Summary ==

= CI Bug Log - changes from CI_DRM_5064 -> IGTPW_2029 =

== Summary - WARNING ==

  Minor unknown changes coming with IGTPW_2029 need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_2029, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/51936/revisions/3/mbox/

== Possible new issues ==

  Here are the unknown changes that may have been introduced in IGTPW_2029:

  === IGT changes ===

    ==== Warnings ====

    igt@drv_selftest@live_guc:
      fi-skl-iommu:       SKIP -> PASS +1

    igt@kms_flip@basic-flip-vs-wf_vblank:
      fi-glk-j4005:       SKIP -> PASS

    
== Known issues ==

  Here are the changes found in IGTPW_2029 that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@kms_flip@basic-flip-vs-modeset:
      fi-skl-6700hq:      PASS -> DMESG-WARN (fdo#105998)

    igt@kms_frontbuffer_tracking@basic:
      fi-byt-clapper:     PASS -> FAIL (fdo#103167)

    igt@kms_pipe_crc_basic@read-crc-pipe-b-frame-sequence:
      fi-byt-clapper:     PASS -> FAIL (fdo#107362, fdo#103191) +1

    
    ==== Possible fixes ====

    igt@drv_selftest@live_hangcheck:
      fi-skl-iommu:       INCOMPLETE (fdo#108602) -> PASS

    igt@gem_exec_suspend@basic-s3:
      fi-blb-e6850:       INCOMPLETE (fdo#107718) -> PASS

    igt@kms_flip@basic-flip-vs-dpms:
      fi-skl-6700hq:      DMESG-WARN (fdo#105998) -> PASS

    igt@kms_flip@basic-flip-vs-modeset:
      fi-glk-j4005:       DMESG-WARN (fdo#106000) -> PASS

    igt@kms_pipe_crc_basic@nonblocking-crc-pipe-b-frame-sequence:
      fi-byt-clapper:     FAIL (fdo#107362, fdo#103191) -> PASS

    
  fdo#103167 https://bugs.freedesktop.org/show_bug.cgi?id=103167
  fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
  fdo#105998 https://bugs.freedesktop.org/show_bug.cgi?id=105998
  fdo#106000 https://bugs.freedesktop.org/show_bug.cgi?id=106000
  fdo#107362 https://bugs.freedesktop.org/show_bug.cgi?id=107362
  fdo#107718 https://bugs.freedesktop.org/show_bug.cgi?id=107718
  fdo#108602 https://bugs.freedesktop.org/show_bug.cgi?id=108602


== Participating hosts (47 -> 40) ==

  Missing    (7): fi-ilk-m540 fi-byt-squawks fi-icl-u2 fi-bsw-cyan fi-apl-guc fi-ctg-p8600 fi-icl-u 


== Build changes ==

    * IGT: IGT_4703 -> IGTPW_2029

  CI_DRM_5064: 9458f0c67b519ddf1c2b4eec9110e826c4e7d2f3 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2029: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2029/
  IGT_4703: f882a542a3eb24e78e51aa6410a3a67c0efb4e97 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2029/issues.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [igt-dev] ✓ Fi.CI.IGT: success for series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3)
  2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
                   ` (4 preceding siblings ...)
  2018-11-02 14:55 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3) Patchwork
@ 2018-11-02 16:39 ` Patchwork
  5 siblings, 0 replies; 8+ messages in thread
From: Patchwork @ 2018-11-02 16:39 UTC (permalink / raw)
  To: Petri Latvala; +Cc: igt-dev

== Series Details ==

Series: series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3)
URL   : https://patchwork.freedesktop.org/series/51936/
State : success

== Summary ==

= CI Bug Log - changes from IGT_4703_full -> IGTPW_2029_full =

== Summary - WARNING ==

  Minor unknown changes coming with IGTPW_2029_full need to be verified
  manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in IGTPW_2029_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  External URL: https://patchwork.freedesktop.org/api/1.0/series/51936/revisions/3/mbox/

== Possible new issues ==

  Here are the unknown changes that may have been introduced in IGTPW_2029_full:

  === IGT changes ===

    ==== Warnings ====

    igt@pm_rc6_residency@rc6-accuracy:
      shard-snb:          PASS -> SKIP

    
== Known issues ==

  Here are the changes found in IGTPW_2029_full that come from known issues:

  === IGT changes ===

    ==== Issues hit ====

    igt@gem_exec_schedule@pi-ringfull-vebox:
      shard-glk:          NOTRUN -> FAIL (fdo#103158)

    igt@gem_mmap_gtt@basic-short:
      shard-glk:          PASS -> DMESG-WARN (fdo#105763, fdo#106538) +3

    igt@kms_busy@extended-modeset-hang-newfb-render-a:
      shard-snb:          PASS -> DMESG-WARN (fdo#107956)

    igt@kms_busy@extended-modeset-hang-newfb-with-reset-render-b:
      shard-snb:          NOTRUN -> DMESG-WARN (fdo#107956) +1

    igt@kms_busy@extended-pageflip-modeset-hang-oldfb-render-b:
      shard-apl:          PASS -> DMESG-WARN (fdo#107956)

    igt@kms_cursor_crc@cursor-128x128-suspend:
      shard-apl:          PASS -> FAIL (fdo#103232, fdo#103191) +1

    igt@kms_cursor_crc@cursor-128x42-random:
      shard-glk:          PASS -> FAIL (fdo#103232) +3

    igt@kms_cursor_crc@cursor-256x85-random:
      shard-apl:          PASS -> FAIL (fdo#103232) +2
      shard-kbl:          PASS -> FAIL (fdo#103232)

    igt@kms_cursor_crc@cursor-64x64-suspend:
      shard-kbl:          PASS -> FAIL (fdo#103232, fdo#103191)

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-pwrite:
      shard-apl:          PASS -> FAIL (fdo#103167) +5

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-fullscreen:
      shard-kbl:          PASS -> FAIL (fdo#103167) +2

    igt@kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-onoff:
      shard-glk:          PASS -> FAIL (fdo#103167) +6

    igt@kms_plane_alpha_blend@pipe-c-alpha-7efc:
      shard-apl:          PASS -> FAIL (fdo#108145)

    igt@kms_plane_multiple@atomic-pipe-a-tiling-x:
      shard-glk:          PASS -> FAIL (fdo#103166)

    igt@kms_plane_multiple@atomic-pipe-c-tiling-y:
      shard-apl:          PASS -> FAIL (fdo#103166)

    igt@prime_vgem@basic-sync-default:
      shard-snb:          PASS -> INCOMPLETE (fdo#105411)

    
    ==== Possible fixes ====

    igt@drv_suspend@shrink:
      shard-snb:          INCOMPLETE (fdo#106886, fdo#105411) -> PASS

    igt@gem_exec_faulting_reloc@normal:
      shard-glk:          DMESG-WARN (fdo#105763, fdo#106538) -> PASS +1

    igt@kms_busy@extended-pageflip-hang-newfb-render-a:
      shard-glk:          DMESG-WARN (fdo#107956) -> PASS

    igt@kms_ccs@pipe-a-crc-sprite-planes-basic:
      shard-glk:          FAIL (fdo#108145) -> PASS

    igt@kms_cursor_crc@cursor-128x42-sliding:
      shard-apl:          FAIL (fdo#103232) -> PASS +2

    igt@kms_cursor_crc@cursor-256x256-dpms:
      shard-glk:          FAIL (fdo#103232) -> PASS +2

    igt@kms_cursor_crc@cursor-256x256-suspend:
      shard-apl:          FAIL (fdo#103232, fdo#103191) -> PASS

    igt@kms_cursor_crc@cursor-64x64-dpms:
      shard-kbl:          FAIL (fdo#103232) -> PASS +1

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-cur-indfb-draw-mmap-wc:
      shard-kbl:          FAIL (fdo#103167) -> PASS

    igt@kms_frontbuffer_tracking@fbc-1p-primscrn-spr-indfb-draw-mmap-cpu:
      shard-apl:          FAIL (fdo#103167) -> PASS +1

    igt@kms_frontbuffer_tracking@fbc-2p-primscrn-spr-indfb-draw-pwrite:
      shard-glk:          FAIL (fdo#103167) -> PASS +5

    igt@kms_plane_multiple@atomic-pipe-b-tiling-y:
      shard-glk:          FAIL (fdo#103166) -> PASS +4

    igt@kms_plane_multiple@atomic-pipe-c-tiling-yf:
      shard-apl:          FAIL (fdo#103166) -> PASS +2
      shard-kbl:          FAIL (fdo#103166) -> PASS +3

    igt@kms_setmode@basic:
      shard-apl:          FAIL (fdo#99912) -> PASS

    igt@kms_vblank@pipe-c-query-idle-hang:
      shard-glk:          INCOMPLETE (k.org#198133, fdo#103359) -> PASS

    
  fdo#103158 https://bugs.freedesktop.org/show_bug.cgi?id=103158
  fdo#103166 https://bugs.freedesktop.org/show_bug.cgi?id=103166
  fdo#103167 https://bugs.freedesktop.org/show_bug.cgi?id=103167
  fdo#103191 https://bugs.freedesktop.org/show_bug.cgi?id=103191
  fdo#103232 https://bugs.freedesktop.org/show_bug.cgi?id=103232
  fdo#103359 https://bugs.freedesktop.org/show_bug.cgi?id=103359
  fdo#105411 https://bugs.freedesktop.org/show_bug.cgi?id=105411
  fdo#105763 https://bugs.freedesktop.org/show_bug.cgi?id=105763
  fdo#106538 https://bugs.freedesktop.org/show_bug.cgi?id=106538
  fdo#106886 https://bugs.freedesktop.org/show_bug.cgi?id=106886
  fdo#107956 https://bugs.freedesktop.org/show_bug.cgi?id=107956
  fdo#108145 https://bugs.freedesktop.org/show_bug.cgi?id=108145
  fdo#99912 https://bugs.freedesktop.org/show_bug.cgi?id=99912
  k.org#198133 https://bugzilla.kernel.org/show_bug.cgi?id=198133


== Participating hosts (6 -> 5) ==

  Missing    (1): shard-skl 


== Build changes ==

    * IGT: IGT_4703 -> IGTPW_2029
    * Linux: CI_DRM_5060 -> CI_DRM_5064

  CI_DRM_5060: 68732cb54bff70449aa3bc5a500a20b8629f53fa @ git://anongit.freedesktop.org/gfx-ci/linux
  CI_DRM_5064: 9458f0c67b519ddf1c2b4eec9110e826c4e7d2f3 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGTPW_2029: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2029/
  IGT_4703: f882a542a3eb24e78e51aa6410a3a67c0efb4e97 @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/IGTPW_2029/shards.html
_______________________________________________
igt-dev mailing list
igt-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/igt-dev

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2018-11-02 16:39 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-02 12:08 [igt-dev] [PATCH i-g-t 1/1] runner: Implement --abort-on-monitored-error Petri Latvala
2018-11-02 12:24 ` Martin Peres
2018-11-02 12:24 ` Chris Wilson
2018-11-02 12:53 ` [igt-dev] [PATCH i-g-t v2 " Petri Latvala
2018-11-02 13:26   ` [igt-dev] [PATCH i-g-t v3 " Petri Latvala
2018-11-02 13:06 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,1/1] " Patchwork
2018-11-02 14:55 ` [igt-dev] ✓ Fi.CI.BAT: success for series starting with [i-g-t,v3,1/1] runner: Implement --abort-on-monitored-error (rev3) Patchwork
2018-11-02 16:39 ` [igt-dev] ✓ Fi.CI.IGT: " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.