From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 536E4C19F32 for ; Fri, 7 Mar 2025 09:35:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 06C7D10E0F2; Fri, 7 Mar 2025 09:35:33 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=intel.com header.i=@intel.com header.b="SDA5j9q/"; dkim-atps=neutral Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.12]) by gabe.freedesktop.org (Postfix) with ESMTPS id B2DEF10E0F2 for ; Fri, 7 Mar 2025 09:35:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1741340132; x=1772876132; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AiADFwPQrZYLFeNsMXUlZryTMTi/HkfkoiauSuDDH5I=; b=SDA5j9q/U9Tg0l3kE1SEPg5VvlrGDWMBmTwvydeHESS9XhdDwd5zxBvZ pwK23Dfpw4qMLUT/VSZXzSNNKqFTmym7P4dKTWxf8XTflWQL9cPBHzRin InApZmGFl4hy+j4ISKPLjOe3Bl7oaNPJ+czuGYSRiXIr/eGjXR9nZgWrU VE8l3S5QS7mTeiUC4Xxr8lnZPA4MyHUzyl1FaJ8mt2eIqZ7COnOQ9SdtZ WAJQiSqzkrvjf5Cwo6os8+2wqJPn/JThNHmFBGvqp4U+jwfN2bxns8Omi DeE3Sc7qfdRLgjF6yAn4jiawNSq4YfHdiBgV2Z+72kB/hCVclnBd3OxR8 g==; X-CSE-ConnectionGUID: WwLgNTPXQeaQSy21ZbSLXw== X-CSE-MsgGUID: ml07ZpSNQXyq2xHl66A2jw== X-IronPort-AV: E=McAfee;i="6700,10204,11365"; a="53772612" X-IronPort-AV: E=Sophos;i="6.14,228,1736841600"; d="scan'208";a="53772612" Received: from orviesa005.jf.intel.com ([10.64.159.145]) by orvoesa104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Mar 2025 01:35:32 -0800 X-CSE-ConnectionGUID: V8PImHphQOCLXd8Ri/DbSg== X-CSE-MsgGUID: YeXOR6v3SfuVfuF+JE3s0g== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.12,224,1728975600"; d="scan'208";a="124496949" Received: from jledworo-mobl.ger.corp.intel.com (HELO friendship7-home.clients.intel.com) ([10.245.114.21]) by orviesa005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 07 Mar 2025 01:35:27 -0800 From: Peter Senna Tschudin To: igt-dev@lists.freedesktop.org Cc: Peter Senna Tschudin , vitaly.prosyak@amd.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 Subject: [PATCH v8 i-g-t 1/3] runner/kmemleak: library to interact with kmemleak Date: Fri, 7 Mar 2025 10:34:24 +0100 Message-Id: <20250307093426.90479-2-peter.senna@linux.intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250307093426.90479-1-peter.senna@linux.intel.com> References: <20250307093426.90479-1-peter.senna@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: igt-dev@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development mailing list for IGT GPU Tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: igt-dev-bounces@lists.freedesktop.org Sender: "igt-dev" 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: Zbigniew Kempczyński Reviewed-by: Jonathan Cavitt Reviewed-by: Vitaly Prosyak Signed-off-by: Peter Senna Tschudin --- v8: - Update commit messages - Fix new line and documentation issues - Use fd instead of fp - Use open() and close() instead of fopen() and fclose() - Update error checking from (!fd) to (fd < 0) - Add error check for lseek() - Rename to KMEMLEAK_RESFILENAME - Increase buf size to 16KB to speedup copy - Rename the ifndef guard to RUNNER_KMEMLEAK_H v6: - Update copyright year to 2025 - Fix indentation issues caused by renaming igt_kmemleak* to runner_kmemleak* v5: - move the code from lib/ to runner/ - rename igt_* to runner_* - replace calls to igt_info() with calls to fprintf(stderr, ...) - #includes on kmemleak.c: - remove #include "igt_core.h" - sort includes aplhabetically - fix one ident error v4: - Cleaned-up CC list - Fixed Reviewed-by tag - Reintroduced ',' after "results-path". It was removed by accident - Changed unit testing for calling igt_kmemleak() with and without sync. v3: - Removed '>' from the end of one of the email addresses in the cc list - Removed email addresses that no longer exist v2: - Pass igt_kmemleak_sync as a function variable to igt_kmemleak instead of keeping it stored as a global variable - igt_kmemleak_found_leaks(): Remove call to fseek() after close() - igt_kmemleak_write(): Increase retry counter when writing 0 bytes - igt_kmemleak_write(): change type to bool - Unit Testing: Move the call to igt_kmemleak_init() to a fixture. - igt_kmemleak_append_to(): Add brackets to the if statement for improved readability runner/kmemleak.c | 277 ++++++++++++++++++++++++++++++++++ runner/kmemleak.h | 16 ++ runner/meson.build | 9 ++ runner/runner_kmemleak_test.c | 267 ++++++++++++++++++++++++++++++++ 4 files changed, 569 insertions(+) create mode 100644 runner/kmemleak.c create mode 100644 runner/kmemleak.h create mode 100644 runner/runner_kmemleak_test.c diff --git a/runner/kmemleak.c b/runner/kmemleak.c new file mode 100644 index 000000000..c6d2d592b --- /dev/null +++ b/runner/kmemleak.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#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; +} diff --git a/runner/kmemleak.h b/runner/kmemleak.h new file mode 100644 index 000000000..65c6f596d --- /dev/null +++ b/runner/kmemleak.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: MIT + * Copyright © 2025 Intel Corporation + */ + +#ifndef RUNNER_KMEMLEAK_H +#define RUNNER_KMEMLEAK_H + +#include + +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 */ diff --git a/runner/meson.build b/runner/meson.build index c62303ce3..ca27e69c5 100644 --- a/runner/meson.build +++ b/runner/meson.build @@ -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' diff --git a/runner/runner_kmemleak_test.c b/runner/runner_kmemleak_test.c new file mode 100644 index 000000000..ae3ebe113 --- /dev/null +++ b/runner/runner_kmemleak_test.c @@ -0,0 +1,267 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2025 Intel Corporation + */ + +#include +#include +#include +#include + +#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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_get_next_namepath+0x1f5/0x390\n" +" [] acpi_ps_parse_loop+0x4a5/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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" +" [] kmemleak_alloc+0x4b/0x80\n" +" [] kmem_cache_alloc_noprof+0x2ab/0x370\n" +" [] acpi_ps_alloc_op+0xdc/0xf0\n" +" [] acpi_ps_create_op+0x1c0/0x400\n" +" [] acpi_ps_parse_loop+0x16c/0xa60\n" +" [] acpi_ps_parse_aml+0x22f/0x5f0\n" +" [] acpi_ps_execute_method+0x152/0x380\n" +" [] acpi_ns_evaluate+0x31d/0x5e0\n" +" [] acpi_evaluate_object+0x206/0x490\n" +" [] __acpi_power_off.isra.0+0x22/0x70\n" +" [] acpi_turn_off_unused_power_resources+0xbb/0xf0\n" +" [] acpi_scan_init+0x119/0x290\n" +" [] acpi_init+0x23a/0x590\n" +" [] do_one_initcall+0x61/0x3d0\n" +" [] kernel_init_freeable+0x3e2/0x680\n" +" [] 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); +} -- 2.34.1