Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • ivyl/igt
  • rodrigovivi/igt-gpu-tools
  • sima/igt-gpu-tools
  • adrinael/igt-gpu-tools
  • mvlad/igt-gpu-tools
  • mupuf/igt-gpu-tools
  • alatiera/igt-gpu-tools
  • strassek/igt-gpu-tools
  • ayan.halder/igt-gpu-tools
  • tomba/igt-gpu-tools
  • tomeu/igt-gpu-tools
  • robh/igt-gpu-tools
  • tpm/igt-gpu-tools
  • demarchi/igt-gpu-tools
  • lyudess/igt-gpu-tools
  • xyliu/igt-gpu-tools
  • bosheng/igt-gpu-tools
  • emersion/igt-gpu-tools
  • gtucker/igt-gpu-tools
  • omrigan/igt-gpu-tools
  • mtolakan/igt-gpu-tools
  • Acidburn0zzz/igt-gpu-tools
  • renchenglei/igt-gpu-tools
  • trimagiccube/igt-gpu-tools
  • haihao/igt-gpu-tools
  • antonovitch/igt-gpu-tools
  • aknautiyal/igt-gpu-tools
  • jani/igt-gpu-tools
  • xexaxo/igt-gpu-tools
  • llandwerlin/igt-gpu-tools
  • daniels/igt-gpu-tools
  • alyssa/igt-gpu-tools
  • nchery/igt-gpu-tools
  • sagarghuge/igt-gpu-tools
  • knljoshi98/igt-gpu-tools
  • shadeslayer/igt-gpu-tools
  • agners/igt-gpu-tools
  • lfiedoro/igt-gpu-tools
  • jcline/igt-gpu-tools
  • stanelyintel/igt-gpu-tools
  • sameer.lattannavar/igt-gpu-tools
  • tzimmermann/igt-gpu-tools
  • zxye/igt-gpu-tools
  • alan_previn_intel/igt-gpu-tools
  • linkmauve/igt-gpu-tools
  • nroberts/igt-gpu-tools
  • agrodzov/igt-gpu-tools
  • rpurdie/igt-gpu-tools
  • kraj/igt-gpu-tools
  • gfxstrand/igt-gpu-tools
  • mcasas/igt-gpu-tools
  • bbrezillon/igt-gpu-tools
  • isinyaaa/igt-gpu-tools
  • hwentland/igt-gpu-tools
  • vitalyp/igt-gpu-tools
  • tales-aparecida/igt-gpu-tools
  • saigowth/igt-gpu-tools
  • bmodem/igt-gpu-tools
58 results
Show changes
Commits on Source (3)
  • Peter Senna Tschudin's avatar
    runner/kmemleak: library to interact with kmemleak · 8cbefa9f
    Peter Senna Tschudin authored and Kamil Konieczny's avatar Kamil Konieczny committed
    
    Adds a simple library for interacting with kmemleak and add
    unit testing for the library. There are two modes intended to
    integrate with igt_runner:
     - once: collect kmemleaks after all test completed
     - each: collect kmemleaks after eachb test completes
    
    Cc: vitaly.prosyak@amd.com
    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: default avatarZbigniew Kempczyński <zbigniew.kempczynski@intel.com>
    Reviewed-by: default avatarJonathan Cavitt <jonathan.cavitt@intel.com>
    Reviewed-by: default avatarVitaly Prosyak <vitaly.prosyak@amd.com>
    Signed-off-by: default avatarPeter Senna Tschudin <peter.senna@linux.intel.com>
    Reviewed-by: default avatarKamil Konieczny <kamil.konieczny@linux.intel.com>
    8cbefa9f
  • Peter Senna Tschudin's avatar
    runner/executor: Integrate igt_kmemleak scans · f42d48f1
    Peter Senna Tschudin authored and Kamil Konieczny's avatar Kamil Konieczny committed
    
    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: Do single kmemleak scan after last test in the test list
     * each: Perform a kmemleak scan after each test completes
    
    By default, kmemleak scanning is disabled. 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: vitaly.prosyak@amd.com
    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: default avatarZbigniew Kempczyński <zbigniew.kempczynski@intel.com>
    Reviewed-by: default avatarJonathan Cavitt <jonathan.cavitt@intel.com>
    Reviewed-by: default avatarVitaly Prosyak <vitaly.prosyak@amd.com>
    Signed-off-by: default avatarPeter Senna Tschudin <peter.senna@linux.intel.com>
    f42d48f1
  • Peter Senna Tschudin's avatar
    scripts/run-tests.sh: Add support to kmemleak and igt_facts · 3ad12993
    Peter Senna Tschudin authored and Kamil Konieczny's avatar Kamil Konieczny committed
    
    Updates scripts/run-tests.sh to include the following options:
    
     -f:        enable igt_facts on igt_runner
     -K <mode>: Linux Kernel kmemleak reports
                - once: run a kmemleak scan after all tests
                - each: run a kmemleak scan after each test
    
    These options are simply relayed to igt_runner.
    
    Cc: vitaly.prosyak@amd.com
    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: default avatarVitaly Prosyak <vitaly.prosyak@amd.com>
    Signed-off-by: default avatarPeter Senna Tschudin <peter.senna@linux.intel.com>
    3ad12993
......@@ -34,6 +34,7 @@
#include "igt_taints.h"
#include "igt_vec.h"
#include "executor.h"
#include "kmemleak.h"
#include "output_strings.h"
#include "runnercomms.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);
......
// SPDX-License-Identifier: MIT
/*
* Copyright © 2025 Intel Corporation
*/
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include "kmemleak.h"
/* We can change the path for unit testing, see runner_kmemleak_init() */
static char runner_kmemleak_file[256] = "/sys/kernel/debug/kmemleak";
#define MAX_WRITE_RETRIES 5
/**
* runner_kmemleak_write: Writes the buffer to the file descriptor retrying when
* possible.
* @fd: The file descriptor to write to.
* @buf: Pointer to the data to write.
* @count: Total number of bytes to write.
*
* Writes the buffer to the file descriptor retrying when possible.
*/
static bool runner_kmemleak_write(int fd, const void *buf, size_t count)
{
const char *ptr = buf;
size_t remaining = count;
ssize_t written;
int retries = 0;
while (remaining > 0) {
written = write(fd, ptr, remaining);
if (written > 0) {
ptr += written;
remaining -= written;
} else if (written == -1) {
if (errno == EINTR || errno == EAGAIN) {
/* Retry for recoverable errors */
if (++retries > MAX_WRITE_RETRIES) {
fprintf(stderr, "%s: Exceeded retry limit\n", __func__);
return false;
}
continue;
} else {
/* Log unrecoverable error */
fprintf(stderr, "%s: unrecoverable write error\n", __func__);
return false;
}
} else if (written == 0) {
if (++retries > MAX_WRITE_RETRIES) {
fprintf(stderr, "%s: Exceeded retry limit\n", __func__);
return false;
}
}
}
return true;
}
/**
* runner_kmemleak_cmd:
* @cmd: command to send to kmemleak
*
* Send a command to kmemleak.
*
* Returns: true if sending the command was successful, false otherwise.
*/
static bool runner_kmemleak_cmd(const char *cmd)
{
int fd;
bool res;
fd = open(runner_kmemleak_file, O_RDWR);
if (fd < 0)
return false;
res = runner_kmemleak_write(fd, cmd, strlen(cmd));
close(fd);
return res;
}
/**
* runner_kmemleak_clear:
*
* Trigger an immediate clear on kmemleak.
*
* Returns: true if sending the command to clear was successful, false
* otherwise.
*/
static bool runner_kmemleak_clear(void)
{
return runner_kmemleak_cmd("clear");
}
/**
* runner_kmemleak_found_leaks:
*
* Check if kmemleak found any leaks by trying to read one byte from the
* kmemleak file.
*
* Returns: true if kmemleak found any leaks, false otherwise.
*/
static bool runner_kmemleak_found_leaks(void)
{
int fd;
char buf[1];
size_t rlen;
fd = open(runner_kmemleak_file, O_RDONLY);
if (fd < 0)
return false;
rlen = read(fd, buf, 1);
if (rlen == 1)
lseek(fd, 0, SEEK_SET);
close(fd);
return rlen == 1;
}
/**
* runner_kmemleak_scan:
*
* Trigger an immediate scan on kmemleak.
*
* Returns: true if leaks are found. False on failure and when no leaks are
* found.
*/
static bool runner_kmemleak_scan(void)
{
if (!runner_kmemleak_cmd("scan"))
return false;
/* kmemleak documentation states that "the memory scanning is only
* performed when the /sys/kernel/debug/kmemleak file is read." Read
* a byte to trigger the scan now.
*/
return runner_kmemleak_found_leaks();
}
/**
* runner_kmemleak_append_to:
* @last_test: last test name to append to the file
* @resdirfd: file descriptor of the results directory
* @kmemleak_each: if true we scan after each test
* @sync: sync the kmemleak file often
*
* Append the kmemleak file to the result file adding a header indicating if
* the leaks are for all tests or for a single one.
*
* Returns: true if appending to the file was successful, false otherwise.
*/
static bool runner_kmemleak_append_to(const char *last_test, int resdirfd,
bool kmemleak_each, bool sync)
{
const char *before = "kmemleaks found before running any test\n\n";
const char *once = "kmemleaks found after running all tests\n";
int kmemleakfd, resfilefd;
char buf[16384];
size_t rlen;
kmemleakfd = open(runner_kmemleak_file, O_RDONLY);
if (kmemleakfd < 0)
return false;
/* Seek back to first byte */
if (lseek(kmemleakfd, 0, SEEK_SET) == (off_t)-1) {
close(kmemleakfd);
return false;
}
/* Open text file to append */
resfilefd = openat(resdirfd, KMEMLEAK_RESFILENAME,
O_RDWR | O_CREAT | O_APPEND, 0666);
if (resfilefd < 0) {
close(kmemleakfd);
return false;
}
/* This is the header added before the content of the kmemleak file */
if (kmemleak_each) {
if (!last_test) {
runner_kmemleak_write(resfilefd, before, strlen(before));
} else {
/* Write \n\n last_test \n to buf */
snprintf(buf, sizeof(buf),
"\n\nkmemleaks found after running %s:\n",
last_test);
runner_kmemleak_write(resfilefd, buf, strlen(buf));
memset(buf, 0, sizeof(buf));
}
} else {
runner_kmemleak_write(resfilefd, once, strlen(once));
}
if (sync)
fsync(resfilefd);
while ((rlen = read(kmemleakfd, buf, sizeof(buf))) > 0) {
if (!runner_kmemleak_write(resfilefd, buf, rlen)) {
close(resfilefd);
close(kmemleakfd);
return false;
}
if (sync)
fsync(resfilefd);
}
close(resfilefd);
close(kmemleakfd);
return true;
}
/**
* runner_kmemleak_init:
* @unit_test_kmemleak_file: path to kmemleak file for unit testing
*
* Check if kmemleak is enabled in the kernel, if debugfs is mounted and
* if kmemleak file is present and readable.
*
* Returns: true if kmemleak is enabled, false otherwise.
*/
bool runner_kmemleak_init(const char *unit_test_kmemleak_file)
{
int fd;
if (unit_test_kmemleak_file)
snprintf(runner_kmemleak_file,
sizeof(runner_kmemleak_file),
"%s",
unit_test_kmemleak_file);
fd = open(runner_kmemleak_file, O_RDONLY);
if (fd < 0)
return false;
close(fd);
return true;
}
/**
* runner_kmemleak:
* @last_test: last test name to append to the file
* @resdirfd: file descriptor of the results directory
* @kmemleak_each: Are we scanning once or scanning after each test?
* @sync: sync the kmemleak file often
*
* This is the main function that should be called when integrating runner_kmemleak
* into igt_runner or elsewhere. There are two flows:
* - run once: runs only once after all tests are completed
* - run for each test: runs after every test
*
* Returns: true on success, false otherwise.
*/
bool runner_kmemleak(const char *last_test, int resdirfd, bool kmemleak_each,
bool sync)
{
/* Scan to collect results */
if (runner_kmemleak_scan())
if (!runner_kmemleak_append_to(last_test, resdirfd,
kmemleak_each, sync))
return false;
if (kmemleak_each)
runner_kmemleak_clear();
return true;
}
/* SPDX-License-Identifier: MIT
* Copyright © 2025 Intel Corporation
*/
#ifndef RUNNER_KMEMLEAK_H
#define RUNNER_KMEMLEAK_H
#include <stdbool.h>
bool runner_kmemleak_init(const char *unit_test_kmemleak_file);
bool runner_kmemleak(const char *last_test, int resdirfd,
bool kmemleak_each, bool sync);
#define KMEMLEAK_RESFILENAME "kmemleak.txt"
#endif /* RUNNER_KMEMLEAK_H */
......@@ -3,6 +3,7 @@ build_runner = get_option('runner')
runnerlib_sources = [ 'settings.c',
'job_list.c',
'executor.c',
'kmemleak.c',
'resultgen.c',
lib_version,
]
......@@ -13,6 +14,7 @@ results_sources = [ 'results.c' ]
decoder_sources = [ 'decoder.c' ]
runner_test_sources = [ 'runner_tests.c' ]
runner_json_test_sources = [ 'runner_json_tests.c' ]
runner_kmemleak_test_sources = [ 'runner_kmemleak_test.c' ]
jsonc = dependency('json-c', required: build_runner)
runner_deps = [jsonc, glib]
......@@ -74,6 +76,13 @@ if jsonc.found() and build_tests
dependencies : [igt_deps, jsonc])
test('runner_json', runner_json_test, timeout : 300)
runner_kmemleak_test = executable('runner_kmemleak_test',
runner_kmemleak_test_sources,
link_with : runnerlib,
install : false,
dependencies : [igt_deps])
test('runner_kmemleak', runner_kmemleak_test, timeout : 300)
build_info += 'Build test runner: true'
if liboping.found()
build_info += 'Build test runner with oping: true'
......
// SPDX-License-Identifier: MIT
/*
* Copyright © 2025 Intel Corporation
*/
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <zlib.h>
#include "igt.h"
#include "kmemleak.h"
const char *kmemleak_file_example =
"unreferenced object 0xffff888102a2e638 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 00 00 00 00 00 00 00 00 0d 01 a2 00 00 00 00 00 ................\n"
" f0 7c 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .|..............\n"
" backtrace (crc 2df71a7e):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2ed18 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 38 e6 a2 02 81 88 ff ff 0d 11 2d 00 00 00 00 00 8.........-.....\n"
" f2 7c 03 00 00 c9 ff ff 58 ea a2 02 81 88 ff ff .|......X.......\n"
" backtrace (crc ec2a8bdc):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2ea58 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 38 e6 a2 02 81 88 ff ff 0d 01 a0 00 00 00 00 00 8...............\n"
" f6 7c 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .|..............\n"
" backtrace (crc f911c0d1):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e428 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 58 ea a2 02 81 88 ff ff 0d 01 35 00 00 00 00 00 X.........5.....\n"
" fc 7c 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .|..............\n"
" backtrace (crc cb8aaffd):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e008 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 28 e4 a2 02 81 88 ff ff 0d 01 2d 00 00 00 00 00 (.........-.....\n"
" fc 7c 03 00 00 c9 ff ff c8 e2 a2 02 81 88 ff ff .|..............\n"
" backtrace (crc 7f883e78):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2b9e5>] acpi_ps_get_next_namepath+0x1f5/0x390\n"
" [<ffffffff81c2cc15>] acpi_ps_parse_loop+0x4a5/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e2c8 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 28 e4 a2 02 81 88 ff ff 0d 01 73 00 00 00 00 00 (.........s.....\n"
" 00 7d 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .}..............\n"
" backtrace (crc 338c016):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e378 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" c8 e2 a2 02 81 88 ff ff 0d 01 0d 00 00 00 00 00 ................\n"
" 01 7d 03 00 00 c9 ff ff 98 e7 a2 02 81 88 ff ff .}..............\n"
" backtrace (crc 665fb8a7):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e798 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 7c8 e2 a2 02 81 88 ff ff 0d 01 98 00 00 00 00 00 ................\n"
" 1b 7d 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .}..............\n"
" backtrace (crc b7a23a1c):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170"
"unreferenced object 0xffff888102a2e0b8 (size 80):\n"
" comm \"swapper/0\", pid 1, jiffies 4294672730\n"
" hex dump (first 32 bytes):\n"
" 98 e7 a2 02 81 88 ff ff 0d 01 2d 00 00 00 00 00 ..........-.....\n"
" 1c 7d 03 00 00 c9 ff ff 00 00 00 00 00 00 00 00 .}..............\n"
" backtrace (crc 14d67a9c):\n"
" [<ffffffff824cd71b>] kmemleak_alloc+0x4b/0x80\n"
" [<ffffffff814e169b>] kmem_cache_alloc_noprof+0x2ab/0x370\n"
" [<ffffffff81c2f4dc>] acpi_ps_alloc_op+0xdc/0xf0\n"
" [<ffffffff81c2d650>] acpi_ps_create_op+0x1c0/0x400\n"
" [<ffffffff81c2c8dc>] acpi_ps_parse_loop+0x16c/0xa60\n"
" [<ffffffff81c2e94f>] acpi_ps_parse_aml+0x22f/0x5f0\n"
" [<ffffffff81c2fa82>] acpi_ps_execute_method+0x152/0x380\n"
" [<ffffffff81c233ed>] acpi_ns_evaluate+0x31d/0x5e0\n"
" [<ffffffff81c2a606>] acpi_evaluate_object+0x206/0x490\n"
" [<ffffffff81bf1202>] __acpi_power_off.isra.0+0x22/0x70\n"
" [<ffffffff81bf275b>] acpi_turn_off_unused_power_resources+0xbb/0xf0\n"
" [<ffffffff83867799>] acpi_scan_init+0x119/0x290\n"
" [<ffffffff8386711a>] acpi_init+0x23a/0x590\n"
" [<ffffffff81002c71>] do_one_initcall+0x61/0x3d0\n"
" [<ffffffff837dce32>] kernel_init_freeable+0x3e2/0x680\n"
" [<ffffffff824ca53b>] kernel_init+0x1b/0x170\n";
static const char *runner_kmemleak_unit_testing_resdir = "/tmp";
igt_main
{
char unit_testing_kmemleak_filepath[256] = "/tmp/runner_kmemleak_test_XXXXXX";
int written_bytes;
int resdirfd;
int fd;
igt_fixture {
/* resdirfd is used by runner_kmemleak() to store results */
igt_assert(resdirfd = open(runner_kmemleak_unit_testing_resdir,
O_DIRECTORY | O_RDONLY));
/* Try to delete results file in case of leftovers,
* ignoring errors as the file may not exist
*/
unlinkat(resdirfd, KMEMLEAK_RESFILENAME, 0);
/* Creating a fake kmemleak file for unit testing */
fd = mkstemp(unit_testing_kmemleak_filepath);
igt_assert(fd >= 0);
written_bytes = write(fd, kmemleak_file_example,
strlen(kmemleak_file_example));
igt_assert_eq(written_bytes, strlen(kmemleak_file_example));
close(fd);
/* Initializing runner_kmemleak with a fake kmemleak file
* for unit testing
*/
igt_assert(runner_kmemleak_init(unit_testing_kmemleak_filepath));
}
igt_subtest_group {
igt_subtest("test_runner_kmemleak_once")
igt_assert(runner_kmemleak(NULL, resdirfd, false, true));
igt_subtest("test_runner_kmemleak_each") {
igt_assert(runner_kmemleak("test_name_1", resdirfd,
true, false));
igt_assert(runner_kmemleak("test_name_2", resdirfd,
true, true));
igt_assert(runner_kmemleak("test_name_3", resdirfd,
true, false));
}
igt_fixture {
close(resdirfd);
}
}
igt_fixture
unlinkat(resdirfd, KMEMLEAK_RESFILENAME, 0);
}
......@@ -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);
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -132,9 +132,13 @@ print_help() {
echo " -P store code coverage results per each test. Should be"
echo " used together with -k option"
echo " -d download Piglit to $ROOT/piglit"
echo " -f enable igt_facts on igt_runner"
echo " -h display this help message"
echo " -k <kernel_dir> Linux Kernel source code directory used to generate code"
echo " coverage builds."
echo " -K <mode> Linux Kernel kmemleak reports"
echo " - once: run a kmemleak scan after all tests"
echo " - each: run a kmemleak scan after each test"
echo " -l list all available tests"
echo " -r <directory> store the results in directory"
echo " (default: $RESULTS)"
......@@ -160,12 +164,14 @@ print_help() {
echo "Useful patterns for test filtering are described in the API documentation."
}
while getopts ":c:dhk:lPr:st:T:vx:Rnpb:m:" opt; do
while getopts ":c:dfhk:K:lPr:st:T:vx:Rnpb:m:" opt; do
case $opt in
c) COV_ARGS="$COV_ARGS --collect-code-cov --collect-script $OPTARG " ;;
d) download_piglit; exit ;;
f) IGT_FACTS="-f" ;;
h) print_help; exit ;;
k) IGT_KERNEL_TREE="$OPTARG" ;;
K) KMEMLEAK="--kmemleak=$OPTARG" ;;
l) LIST_TESTS="true" ;;
P) COV_ARGS="$COV_ARGS --coverage-per-test"; COV_PER_TEST=1 ;;
r) RESULTS="$OPTARG" ;;
......@@ -256,7 +262,7 @@ if [ "x$RESUME_RUN" != "x" ]; then
execute_runner 1 $RESUME $RESUME_ARGS $COV_ARGS "$RESULTS"
else
mkdir -p "$RESULTS"
execute_runner 1 $RUNNER $RUN_ARGS -o -s "$RESULTS" $COV_ARGS $VERBOSE $FILTER --prune-mode $PRUNE_MODE
execute_runner 1 $RUNNER $RUN_ARGS -o $IGT_FACTS $KMEMLEAK -s "$RESULTS" $COV_ARGS $VERBOSE $FILTER --prune-mode $PRUNE_MODE
fi
if [ "$SUMMARY" = "html" ]; then
......