All of lore.kernel.org
 help / color / mirror / Atom feed
From: Peter Senna Tschudin <peter.senna@linux.intel.com>
To: igt-dev@lists.freedesktop.org
Cc: Peter Senna Tschudin <peter.senna@linux.intel.com>,
	christian.koenig@amd.com, alexander.deucher@amd.com,
	jesse.zhang@amd.com, harry.wentland@amd.com,
	zbigniew.kempczynski@intel.com, kamil.konieczny@linux.intel.com,
	ryszard.knop@intel.com, lucas.demarchi@intel.com,
	katarzyna.piecielska@intel.com,
	Jonathan Cavitt <jonathan.cavitt@intel.com>
Subject: [PATCH v7 i-g-t 2/3] runner/executor: Integrate igt_kmemleak scans
Date: Thu, 27 Feb 2025 11:18:52 +0100	[thread overview]
Message-ID: <20250227101853.361504-3-peter.senna@linux.intel.com> (raw)
In-Reply-To: <20250227101853.361504-1-peter.senna@linux.intel.com>

This patch modifies igt_runner to support runner_kmemleak() calls. By
default, kmemleak scanning is disabled, so new command-line options are
introduced to enable it:
 * -k, -k<option>, --kmemleak, --kmemleak=<option>

The available options are:
 * once: Perform a single kmemleak scan after all tests in the test list
 * complete.  each: Perform a kmemleak scan after each test completes.

If any kmemleaks are detected, they will be saved in the igt_runner results
directory under kmemleak.txt.

Additionally, this patch updates serialize_settings() and
read_settings_from_file() to persist igt_runner settings across runs. This
allows settings to be saved when running igt_runner --dry-run and later
restored when executing igt_resume.

The unit tests for igt_runner have been extended to verify:
 * Kmemleak scans are disabled by default.  Kmemleak scans can be enabled
 * via command-line arguments.  The kmemleak setting is correctly saved to
 * and restored from disk.

To test the new -k command-line option, this patch appends "--overwrite" to
*argv[] in runner_test.c to expand the argument array. This approach avoids
a major refactor of how *argv[] is defined across the file while keeping
the changes isolated to unit testing. Since this only affects tests, there
is no downstream impact.

Cc: christian.koenig@amd.com
Cc: alexander.deucher@amd.com
Cc: jesse.zhang@amd.com
Cc: harry.wentland@amd.com
Cc: zbigniew.kempczynski@intel.com
Cc: kamil.konieczny@linux.intel.com
Cc: ryszard.knop@intel.com
Cc: lucas.demarchi@intel.com
Cc: katarzyna.piecielska@intel.com
Reviewed-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
Reviewed-by: Jonathan Cavitt <jonathan.cavitt@intel.com>
Signed-off-by: Peter Senna Tschudin <peter.senna@linux.intel.com>
---
 runner/executor.c     | 26 ++++++++++++++++++++++++--
 runner/runner_tests.c | 13 ++++++++++++-
 runner/settings.c     | 31 ++++++++++++++++++++++++++++++-
 runner/settings.h     |  2 ++
 4 files changed, 68 insertions(+), 4 deletions(-)

diff --git a/runner/executor.c b/runner/executor.c
index 999e7f719..4eb4f1c72 100644
--- a/runner/executor.c
+++ b/runner/executor.c
@@ -31,6 +31,7 @@
 #include "igt_aux.h"
 #include "igt_core.h"
 #include "igt_facts.h"
+#include "kmemleak.h"
 #include "igt_taints.h"
 #include "igt_vec.h"
 #include "executor.h"
@@ -2370,6 +2371,14 @@ bool execute(struct execute_state *state,
 	if (settings->facts)
 		igt_facts_lists_init();
 
+	if (settings->kmemleak)
+		if (!runner_kmemleak_init(NULL)) {
+			errf("Failed to initialize kmemleak. Is kernel support enabled?\n"
+			     "Disabling kmemleak on igt_runner and continuing...\n");
+			settings->kmemleak = false;
+			settings->kmemleak_each = false;
+		}
+
 	if (state->next >= job_list->size) {
 		outf("All tests already executed.\n");
 		return true;
@@ -2497,10 +2506,18 @@ bool execute(struct execute_state *state,
 		bool already_written = false;
 
 		/* Collect facts before running each test */
-		if (settings->facts) {
+		if (settings->facts)
 			igt_facts(last_test);
+
+		if (settings->kmemleak_each)
+			if (!runner_kmemleak(last_test, resdirfd,
+					     settings->kmemleak_each,
+					     settings->sync))
+				errf("Failed to collect kmemleak logs after %s\n",
+				     last_test);
+
+		if (settings->facts || settings->kmemleak_each)
 			last_test = entry_display_name(&job_list->entries[state->next]);
-		}
 
 		if (should_die_because_signal(sigfd)) {
 			status = false;
@@ -2595,6 +2612,11 @@ bool execute(struct execute_state *state,
 	if (settings->facts)
 		igt_facts(last_test);
 
+	if (settings->kmemleak)
+		if (!runner_kmemleak(last_test, resdirfd,
+				     settings->kmemleak_each, settings->sync))
+			errf("Failed to collect kmemleak logs after the last test\n");
+
 	if ((timefd = openat(resdirfd, "endtime.txt", O_CREAT | O_WRONLY | O_EXCL, 0666)) >= 0) {
 		dprintf(timefd, "%f\n", timeofday_double());
 		close(timefd);
diff --git a/runner/runner_tests.c b/runner/runner_tests.c
index 93b3ebc9f..e62e7b34d 100644
--- a/runner/runner_tests.c
+++ b/runner/runner_tests.c
@@ -191,6 +191,7 @@ static void assert_settings_equal(struct settings *one, struct settings *two)
 	igt_assert_eq(one->dry_run, two->dry_run);
 	igt_assert_eq(one->allow_non_root, two->allow_non_root);
 	igt_assert_eq(one->facts, two->facts);
+	igt_assert_eq(one->kmemleak, two->kmemleak);
 	igt_assert_eq(one->sync, two->sync);
 	igt_assert_eq(one->log_level, two->log_level);
 	igt_assert_eq(one->overwrite, two->overwrite);
@@ -305,6 +306,7 @@ igt_main
 		igt_assert(igt_list_empty(&settings->env_vars));
 		igt_assert(!igt_vec_length(&settings->hook_strs));
 		igt_assert(!settings->facts);
+		igt_assert(!settings->kmemleak);
 		igt_assert(!settings->sync);
 		igt_assert_eq(settings->log_level, LOG_LEVEL_NORMAL);
 		igt_assert(!settings->overwrite);
@@ -427,6 +429,7 @@ igt_main
 		igt_assert_eq(settings->include_regexes.size, 0);
 		igt_assert_eq(settings->exclude_regexes.size, 0);
 		igt_assert(!settings->facts);
+		igt_assert(!settings->kmemleak);
 		igt_assert(!settings->sync);
 		igt_assert_eq(settings->log_level, LOG_LEVEL_NORMAL);
 		igt_assert(!settings->overwrite);
@@ -465,6 +468,7 @@ igt_main
 				       "-b", blacklist_name,
 				       "--blacklist", blacklist2_name,
 				       "-f",
+				       "-k",
 				       "-s",
 				       "-l", "verbose",
 				       "--overwrite",
@@ -524,6 +528,7 @@ igt_main
 		igt_assert_eqstr(*((char **)igt_vec_elem(&settings->hook_strs, 1)), "echo world");
 
 		igt_assert(settings->facts);
+		igt_assert(settings->kmemleak);
 		igt_assert(settings->sync);
 		igt_assert_eq(settings->log_level, LOG_LEVEL_VERBOSE);
 		igt_assert(settings->overwrite);
@@ -719,6 +724,7 @@ igt_main
 	igt_subtest("parse-clears-old-data") {
 		const char *argv[] = { "runner",
 				       "-n", "foo",
+				       "--overwrite",
 				       "--dry-run",
 				       "--allow-non-root",
 				       "test-root-dir",
@@ -728,21 +734,26 @@ igt_main
 		igt_assert(parse_options(ARRAY_SIZE(argv), (char**)argv, settings));
 
 		igt_assert_eqstr(settings->name, "foo");
+		igt_assert(settings->overwrite);
 		igt_assert(settings->dry_run);
 		igt_assert(!settings->test_list);
 		igt_assert(!settings->facts);
+		igt_assert(!settings->kmemleak);
 		igt_assert(!settings->sync);
 
 		argv[1] = "--test-list";
 		argv[3] = "--facts";
-		argv[4] = "--sync";
+		argv[4] = "--kmemleak";
+		argv[5] = "--sync";
 
 		igt_assert(parse_options(ARRAY_SIZE(argv), (char**)argv, settings));
 
 		igt_assert_eqstr(settings->name, "results-path");
 		igt_assert(!settings->dry_run);
+		igt_assert(!settings->overwrite);
 		igt_assert(strstr(settings->test_list, "foo") != NULL);
 		igt_assert(settings->facts);
+		igt_assert(settings->kmemleak);
 		igt_assert(settings->sync);
 	}
 
diff --git a/runner/settings.c b/runner/settings.c
index a2fddcaf6..1d34c5bfe 100644
--- a/runner/settings.c
+++ b/runner/settings.c
@@ -42,6 +42,7 @@ enum {
 	OPT_EXCLUDE = 'x',
 	OPT_ENVIRONMENT = 'e',
 	OPT_FACTS = 'f',
+	OPT_KMEMLEAK = 'k',
 	OPT_SYNC = 's',
 	OPT_LOG_LEVEL = 'l',
 	OPT_OVERWRITE = 'o',
@@ -233,6 +234,16 @@ static const char *usage_str =
 	"                                   not respond to ping.\n"
 	"                         all     - abort for all of the above.\n"
 	"  -f, --facts           Enable facts tracking\n"
+	"  -k, -k<option>, --kmemleak, --kmemleak=<option>\n"
+	"                        Enable kmemleak tracking. Each kmemleak scan\n"
+	"                        can take from 5 to 60 seconds, slowing down\n"
+	"                        the run considerably. The default is to scan\n"
+	"                        only once after the last test. It is also\n"
+	"                        possible to scan after each test. Possible\n"
+	"                        options:\n"
+	"                         once - The default is to run one kmemleak\n"
+	"                                scan after the last test\n"
+	"                         each - Run one kmemleak scan after each test\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"
@@ -682,6 +693,7 @@ bool parse_options(int argc, char **argv,
 		{"abort-on-monitored-error", optional_argument, NULL, OPT_ABORT_ON_ERROR},
 		{"disk-usage-limit", required_argument, NULL, OPT_DISK_USAGE_LIMIT},
 		{"facts", no_argument, NULL, OPT_FACTS},
+		{"kmemleak", optional_argument, NULL, OPT_KMEMLEAK},
 		{"sync", no_argument, NULL, OPT_SYNC},
 		{"log-level", required_argument, NULL, OPT_LOG_LEVEL},
 		{"test-list", required_argument, NULL, OPT_TEST_LIST},
@@ -712,7 +724,7 @@ bool parse_options(int argc, char **argv,
 	settings->dmesg_warn_level = -1;
 	settings->prune_mode = -1;
 
-	while ((c = getopt_long(argc, argv, "hn:dt:x:e:fsl:omb:L",
+	while ((c = getopt_long(argc, argv, "hn:dt:x:e:fk::sl:omb:L",
 				long_options, NULL)) != -1) {
 		switch (c) {
 		case OPT_VERSION:
@@ -756,6 +768,19 @@ bool parse_options(int argc, char **argv,
 		case OPT_FACTS:
 			settings->facts = true;
 			break;
+		case OPT_KMEMLEAK:
+			/* The default is once */
+			settings->kmemleak = true;
+			settings->kmemleak_each = false;
+			if (optarg) {
+				if (strcmp(optarg, "each") == 0) {
+					settings->kmemleak_each = true;
+				/* "once" is the default. No action needed */
+				} else if (strcmp(optarg, "once") != 0) {
+					usage(stderr, "Invalid kmemleak option");
+					goto error;
+				}
+			}
 		case OPT_SYNC:
 			settings->sync = true;
 			break;
@@ -1210,6 +1235,8 @@ bool serialize_settings(struct settings *settings)
 	SERIALIZE_INT(f, settings, dry_run);
 	SERIALIZE_INT(f, settings, allow_non_root);
 	SERIALIZE_INT(f, settings, facts);
+	SERIALIZE_INT(f, settings, kmemleak);
+	SERIALIZE_INT(f, settings, kmemleak_each);
 	SERIALIZE_INT(f, settings, sync);
 	SERIALIZE_INT(f, settings, log_level);
 	SERIALIZE_INT(f, settings, overwrite);
@@ -1326,6 +1353,8 @@ bool read_settings_from_file(struct settings *settings, FILE *f)
 		PARSE_INT(settings, name, val, dry_run);
 		PARSE_INT(settings, name, val, allow_non_root);
 		PARSE_INT(settings, name, val, facts);
+		PARSE_INT(settings, name, val, kmemleak);
+		PARSE_INT(settings, name, val, kmemleak_each);
 		PARSE_INT(settings, name, val, sync);
 		PARSE_INT(settings, name, val, log_level);
 		PARSE_INT(settings, name, val, overwrite);
diff --git a/runner/settings.h b/runner/settings.h
index 2266118a7..1f0b85318 100644
--- a/runner/settings.h
+++ b/runner/settings.h
@@ -58,6 +58,8 @@ struct settings {
 	struct igt_list_head env_vars;
 	struct igt_vec hook_strs;
 	bool facts;
+	bool kmemleak;
+	bool kmemleak_each;
 	bool sync;
 	int log_level;
 	bool overwrite;
-- 
2.34.1


  parent reply	other threads:[~2025-02-27 10:19 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-27 10:18 [PATCH v7 i-g-t 0/3] Integrate kmemleak scans in igt_runner Peter Senna Tschudin
2025-02-27 10:18 ` [PATCH v7 i-g-t 1/3] runner/kmemleak: library to interact with kmemleak Peter Senna Tschudin
2025-02-28  7:04   ` Peter Senna Tschudin
2025-03-06 12:32     ` Kamil Konieczny
2025-03-07  3:59       ` vitaly prosyak
2025-03-06 12:02   ` Kamil Konieczny
2025-02-27 10:18 ` Peter Senna Tschudin [this message]
2025-02-28  7:05   ` [PATCH v7 i-g-t 2/3] runner/executor: Integrate igt_kmemleak scans Peter Senna Tschudin
2025-03-06 12:25   ` Kamil Konieczny
2025-02-27 10:18 ` [PATCH v7 i-g-t 3/3] scripts/run-tests.sh: Add support to kmemleak reports and igt_facts Peter Senna Tschudin
2025-02-28  7:07   ` Peter Senna Tschudin
2025-02-28  3:56 ` ✓ Xe.CI.BAT: success for Integrate kmemleak scans in igt_runner (rev5) Patchwork
2025-02-28  4:28 ` ✓ i915.CI.BAT: " Patchwork
2025-02-28  8:37 ` ✗ Xe.CI.Full: failure " Patchwork
2025-02-28  9:06   ` Peter Senna Tschudin
2025-02-28 11:53     ` Ravali, JupallyX
2025-03-05  7:28 ` ✗ i915.CI.Full: " Patchwork
2025-03-05  7:44   ` Peter Senna Tschudin
2025-03-05 16:12     ` Illipilli, TejasreeX

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250227101853.361504-3-peter.senna@linux.intel.com \
    --to=peter.senna@linux.intel.com \
    --cc=alexander.deucher@amd.com \
    --cc=christian.koenig@amd.com \
    --cc=harry.wentland@amd.com \
    --cc=igt-dev@lists.freedesktop.org \
    --cc=jesse.zhang@amd.com \
    --cc=jonathan.cavitt@intel.com \
    --cc=kamil.konieczny@linux.intel.com \
    --cc=katarzyna.piecielska@intel.com \
    --cc=lucas.demarchi@intel.com \
    --cc=ryszard.knop@intel.com \
    --cc=zbigniew.kempczynski@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.