Pull Kselftest fixes from Shuah Khan: - rseq build failures fixes related to glibc 2.30 compatibility from Mathieu Desnoyers - Kunit fixes and cleanups from SeongJae Park - Fixes to filesystems/epoll, firmware, and livepatch build failures and skip handling. * tag 'linux-kselftest-5.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: rseq/selftests: Clarify rseq_prepare_unload() helper requirements rseq/selftests: Fix: Namespace gettid() for compatibility with glibc 2.30 rseq/selftests: Turn off timeout setting kunit/kunit_tool_test: Test '--build_dir' option run kunit: Rename 'kunitconfig' to '.kunitconfig' kunit: Place 'test.log' under the 'build_dir' kunit: Create default config in '--build_dir' kunit: Remove duplicated defconfig creation docs/kunit/start: Use in-tree 'kunit_defconfig' selftests: livepatch: Fix it to do root uid check and skip selftests: firmware: Fix it to do root uid check and skip selftests: filesystems/epoll: fix build error
Unified · Split
| @@ -24,19 +24,16 @@ The wrapper can be run with: · 23 unmodified lines | ||
| 24 | 24 | For more information on this wrapper (also called kunit_tool) checkout the |
| 25 | 25 | :doc:`kunit-tool` page. |
| 26 | 26 | |
| 27 | −Creating a kunitconfig | |
| 28 | −====================== | |
| 27 | +Creating a .kunitconfig | |
| 28 | +======================= | |
| 29 | 29 | The Python script is a thin wrapper around Kbuild. As such, it needs to be |
| 30 | −configured with a ``kunitconfig`` file. This file essentially contains the | |
| 30 | +configured with a ``.kunitconfig`` file. This file essentially contains the | |
| 31 | 31 | regular Kernel config, with the specific test targets as well. |
| 32 | 32 | |
| 33 | 33 | .. code-block:: bash |
| 34 | 34 | |
| 35 | − git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO | |
| 36 | 35 | cd $PATH_TO_LINUX_REPO |
| 37 | − ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig | |
| 38 | − | |
| 39 | −You may want to add kunitconfig to your local gitignore. | |
| 36 | + cp arch/um/configs/kunit_defconfig .kunitconfig | |
| 40 | 37 | |
| 41 | 38 | Verifying KUnit Works |
| 42 | 39 | --------------------- |
| @@ -151,7 +148,7 @@ and the following to ``drivers/misc/Makefile``: · 108 unmodified lines | ||
| 151 | 148 | |
| 152 | 149 | obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o |
| 153 | 150 | |
| 154 | −Now add it to your ``kunitconfig``: | |
| 151 | +Now add it to your ``.kunitconfig``: | |
| 155 | 152 | |
| 156 | 153 | .. code-block:: none |
| 157 | 154 | |
| @@ -31,15 +31,12 @@ class KunitStatus(Enum): · 30 unmodified lines | ||
| 31 | 31 | TEST_FAILURE = auto() |
| 32 | 32 | |
| 33 | 33 | def create_default_kunitconfig(): |
| 34 | − if not os.path.exists(kunit_kernel.KUNITCONFIG_PATH): | |
| 34 | + if not os.path.exists(kunit_kernel.kunitconfig_path): | |
| 35 | 35 | shutil.copyfile('arch/um/configs/kunit_defconfig', |
| 36 | − kunit_kernel.KUNITCONFIG_PATH) | |
| 36 | + kunit_kernel.kunitconfig_path) | |
| 37 | 37 | |
| 38 | 38 | def run_tests(linux: kunit_kernel.LinuxSourceTree, |
| 39 | 39 | request: KunitRequest) -> KunitResult: |
| 40 | − if request.defconfig: | |
| 41 | − create_default_kunitconfig() | |
| 42 | − | |
| 43 | 40 | config_start = time.time() |
| 44 | 41 | success = linux.build_reconfig(request.build_dir) |
| 45 | 42 | config_end = time.time() |
| @@ -108,15 +105,22 @@ def main(argv, linux=None): · 62 unmodified lines | ||
| 108 | 105 | run_parser.add_argument('--build_dir', |
| 109 | 106 | help='As in the make command, it specifies the build ' |
| 110 | 107 | 'directory.', |
| 111 | − type=str, default=None, metavar='build_dir') | |
| 108 | + type=str, default='', metavar='build_dir') | |
| 112 | 109 | |
| 113 | 110 | run_parser.add_argument('--defconfig', |
| 114 | − help='Uses a default kunitconfig.', | |
| 111 | + help='Uses a default .kunitconfig.', | |
| 115 | 112 | action='store_true') |
| 116 | 113 | |
| 117 | 114 | cli_args = parser.parse_args(argv) |
| 118 | 115 | |
| 119 | 116 | if cli_args.subcommand == 'run': |
| 117 | + if cli_args.build_dir: | |
| 118 | + if not os.path.exists(cli_args.build_dir): | |
| 119 | + os.mkdir(cli_args.build_dir) | |
| 120 | + kunit_kernel.kunitconfig_path = os.path.join( | |
| 121 | + cli_args.build_dir, | |
| 122 | + kunit_kernel.kunitconfig_path) | |
| 123 | + | |
| 120 | 124 | if cli_args.defconfig: |
| 121 | 125 | create_default_kunitconfig() |
| 122 | 126 | |
| @@ -14,7 +14,7 @@ import os · 13 unmodified lines | ||
| 14 | 14 | import kunit_config |
| 15 | 15 | |
| 16 | 16 | KCONFIG_PATH = '.config' |
| 17 | −KUNITCONFIG_PATH = 'kunitconfig' | |
| 17 | +kunitconfig_path = '.kunitconfig' | |
| 18 | 18 | |
| 19 | 19 | class ConfigError(Exception): |
| 20 | 20 | """Represents an error trying to configure the Linux kernel.""" |
| @@ -82,7 +82,7 @@ class LinuxSourceTree(object): · 61 unmodified lines | ||
| 82 | 82 | |
| 83 | 83 | def __init__(self): |
| 84 | 84 | self._kconfig = kunit_config.Kconfig() |
| 85 | − self._kconfig.read_from_file(KUNITCONFIG_PATH) | |
| 85 | + self._kconfig.read_from_file(kunitconfig_path) | |
| 86 | 86 | self._ops = LinuxSourceTreeOperations() |
| 87 | 87 | |
| 88 | 88 | def clean(self): |
| @@ -111,7 +111,7 @@ class LinuxSourceTree(object): · 22 unmodified lines | ||
| 111 | 111 | return True |
| 112 | 112 | |
| 113 | 113 | def build_reconfig(self, build_dir): |
| 114 | − """Creates a new .config if it is not a subset of the kunitconfig.""" | |
| 114 | + """Creates a new .config if it is not a subset of the .kunitconfig.""" | |
| 115 | 115 | kconfig_path = get_kconfig_path(build_dir) |
| 116 | 116 | if os.path.exists(kconfig_path): |
| 117 | 117 | existing_kconfig = kunit_config.Kconfig() |
| @@ -140,10 +140,10 @@ class LinuxSourceTree(object): · 22 unmodified lines | ||
| 140 | 140 | return False |
| 141 | 141 | return True |
| 142 | 142 | |
| 143 | − def run_kernel(self, args=[], timeout=None, build_dir=None): | |
| 143 | + def run_kernel(self, args=[], timeout=None, build_dir=''): | |
| 144 | 144 | args.extend(['mem=256M']) |
| 145 | 145 | process = self._ops.linux_bin(args, timeout, build_dir) |
| 146 | − with open('test.log', 'w') as f: | |
| 146 | + with open(os.path.join(build_dir, 'test.log'), 'w') as f: | |
| 147 | 147 | for line in process.stdout: |
| 148 | 148 | f.write(line.rstrip().decode('ascii') + '\n') |
| 149 | 149 | yield line.rstrip().decode('ascii') |
| @@ -174,6 +174,7 @@ class KUnitMainTest(unittest.TestCase): · 173 unmodified lines | ||
| 174 | 174 | kunit.main(['run'], self.linux_source_mock) |
| 175 | 175 | assert self.linux_source_mock.build_reconfig.call_count == 1 |
| 176 | 176 | assert self.linux_source_mock.run_kernel.call_count == 1 |
| 177 | + self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=300) | |
| 177 | 178 | self.print_mock.assert_any_call(StrContains('Testing complete.')) |
| 178 | 179 | |
| 179 | 180 | def test_run_passes_args_fail(self): |
| @@ -199,7 +200,14 @@ class KUnitMainTest(unittest.TestCase): · 19 unmodified lines | ||
| 199 | 200 | timeout = 3453 |
| 200 | 201 | kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock) |
| 201 | 202 | assert self.linux_source_mock.build_reconfig.call_count == 1 |
| 202 | − self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=None, timeout=timeout) | |
| 203 | + self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=timeout) | |
| 204 | + self.print_mock.assert_any_call(StrContains('Testing complete.')) | |
| 205 | + | |
| 206 | + def test_run_builddir(self): | |
| 207 | + build_dir = '.kunit' | |
| 208 | + kunit.main(['run', '--build_dir', build_dir], self.linux_source_mock) | |
| 209 | + assert self.linux_source_mock.build_reconfig.call_count == 1 | |
| 210 | + self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=build_dir, timeout=300) | |
| 203 | 211 | self.print_mock.assert_any_call(StrContains('Testing complete.')) |
| 204 | 212 | |
| 205 | 213 | if __name__ == '__main__': |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | 2 | |
| 3 | 3 | CFLAGS += -I../../../../../usr/include/ |
| 4 | −LDFLAGS += -lpthread | |
| 4 | +LDLIBS += -lpthread | |
| 5 | 5 | TEST_GEN_PROGS := epoll_wakeup_test |
| 6 | 6 | |
| 7 | 7 | include ../../lib.mk |
| @@ -34,6 +34,12 @@ test_modprobe() · 33 unmodified lines | ||
| 34 | 34 | |
| 35 | 35 | check_mods() |
| 36 | 36 | { |
| 37 | + local uid=$(id -u) | |
| 38 | + if [ $uid -ne 0 ]; then | |
| 39 | + echo "skip all tests: must be run as root" >&2 | |
| 40 | + exit $ksft_skip | |
| 41 | + fi | |
| 42 | + | |
| 37 | 43 | trap "test_modprobe" EXIT |
| 38 | 44 | if [ ! -d $DIR ]; then |
| 39 | 45 | modprobe test_firmware |
| @@ -7,6 +7,9 @@ · 6 unmodified lines | ||
| 7 | 7 | MAX_RETRIES=600 |
| 8 | 8 | RETRY_INTERVAL=".1" # seconds |
| 9 | 9 | |
| 10 | +# Kselftest framework requirement - SKIP code is 4 | |
| 11 | +ksft_skip=4 | |
| 12 | + | |
| 10 | 13 | # log(msg) - write message to kernel log |
| 11 | 14 | # msg - insightful words |
| 12 | 15 | function log() { |
| @@ -18,7 +21,16 @@ function log() { · 5 unmodified lines | ||
| 18 | 21 | function skip() { |
| 19 | 22 | log "SKIP: $1" |
| 20 | 23 | echo "SKIP: $1" >&2 |
| 21 | − exit 4 | |
| 24 | + exit $ksft_skip | |
| 25 | +} | |
| 26 | + | |
| 27 | +# root test | |
| 28 | +function is_root() { | |
| 29 | + uid=$(id -u) | |
| 30 | + if [ $uid -ne 0 ]; then | |
| 31 | + echo "skip all tests: must be run as root" >&2 | |
| 32 | + exit $ksft_skip | |
| 33 | + fi | |
| 22 | 34 | } |
| 23 | 35 | |
| 24 | 36 | # die(msg) - game over, man |
| @@ -62,6 +74,7 @@ function set_ftrace_enabled() { · 37 unmodified lines | ||
| 62 | 74 | # for verbose livepatching output and turn on |
| 63 | 75 | # the ftrace_enabled sysctl. |
| 64 | 76 | function setup_config() { |
| 77 | + is_root | |
| 65 | 78 | push_config |
| 66 | 79 | set_dynamic_debug |
| 67 | 80 | set_ftrace_enabled 1 |
| @@ -8,8 +8,7 @@ MOD_LIVEPATCH=test_klp_state · 7 unmodified lines | ||
| 8 | 8 | MOD_LIVEPATCH2=test_klp_state2 |
| 9 | 9 | MOD_LIVEPATCH3=test_klp_state3 |
| 10 | 10 | |
| 11 | −set_dynamic_debug | |
| 12 | − | |
| 11 | +setup_config | |
| 13 | 12 | |
| 14 | 13 | # TEST: Loading and removing a module that modifies the system state |
| 15 | 14 | |
| @@ -15,7 +15,7 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <errno.h> |
| 16 | 16 | #include <stddef.h> |
| 17 | 17 | |
| 18 | −static inline pid_t gettid(void) | |
| 18 | +static inline pid_t rseq_gettid(void) | |
| 19 | 19 | { |
| 20 | 20 | return syscall(__NR_gettid); |
| 21 | 21 | } |
| @@ -373,11 +373,12 @@ void *test_percpu_spinlock_thread(void *arg) · 351 unmodified lines | ||
| 373 | 373 | rseq_percpu_unlock(&data->lock, cpu); |
| 374 | 374 | #ifndef BENCHMARK |
| 375 | 375 | if (i != 0 && !(i % (reps / 10))) |
| 376 | − printf_verbose("tid %d: count %lld\n", (int) gettid(), i); | |
| 376 | + printf_verbose("tid %d: count %lld\n", | |
| 377 | + (int) rseq_gettid(), i); | |
| 377 | 378 | #endif |
| 378 | 379 | } |
| 379 | 380 | printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", |
| 380 | − (int) gettid(), nr_abort, signals_delivered); | |
| 381 | + (int) rseq_gettid(), nr_abort, signals_delivered); | |
| 381 | 382 | if (!opt_disable_rseq && thread_data->reg && |
| 382 | 383 | rseq_unregister_current_thread()) |
| 383 | 384 | abort(); |
| @@ -454,11 +455,12 @@ void *test_percpu_inc_thread(void *arg) · 70 unmodified lines | ||
| 454 | 455 | } while (rseq_unlikely(ret)); |
| 455 | 456 | #ifndef BENCHMARK |
| 456 | 457 | if (i != 0 && !(i % (reps / 10))) |
| 457 | − printf_verbose("tid %d: count %lld\n", (int) gettid(), i); | |
| 458 | + printf_verbose("tid %d: count %lld\n", | |
| 459 | + (int) rseq_gettid(), i); | |
| 458 | 460 | #endif |
| 459 | 461 | } |
| 460 | 462 | printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", |
| 461 | − (int) gettid(), nr_abort, signals_delivered); | |
| 463 | + (int) rseq_gettid(), nr_abort, signals_delivered); | |
| 462 | 464 | if (!opt_disable_rseq && thread_data->reg && |
| 463 | 465 | rseq_unregister_current_thread()) |
| 464 | 466 | abort(); |
| @@ -605,7 +607,7 @@ void *test_percpu_list_thread(void *arg) · 140 unmodified lines | ||
| 605 | 607 | } |
| 606 | 608 | |
| 607 | 609 | printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", |
| 608 | − (int) gettid(), nr_abort, signals_delivered); | |
| 610 | + (int) rseq_gettid(), nr_abort, signals_delivered); | |
| 609 | 611 | if (!opt_disable_rseq && rseq_unregister_current_thread()) |
| 610 | 612 | abort(); |
| 611 | 613 | |
| @@ -796,7 +798,7 @@ void *test_percpu_buffer_thread(void *arg) · 184 unmodified lines | ||
| 796 | 798 | } |
| 797 | 799 | |
| 798 | 800 | printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", |
| 799 | − (int) gettid(), nr_abort, signals_delivered); | |
| 801 | + (int) rseq_gettid(), nr_abort, signals_delivered); | |
| 800 | 802 | if (!opt_disable_rseq && rseq_unregister_current_thread()) |
| 801 | 803 | abort(); |
| 802 | 804 | |
| @@ -1011,7 +1013,7 @@ void *test_percpu_memcpy_buffer_thread(void *arg) · 208 unmodified lines | ||
| 1011 | 1013 | } |
| 1012 | 1014 | |
| 1013 | 1015 | printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", |
| 1014 | − (int) gettid(), nr_abort, signals_delivered); | |
| 1016 | + (int) rseq_gettid(), nr_abort, signals_delivered); | |
| 1015 | 1017 | if (!opt_disable_rseq && rseq_unregister_current_thread()) |
| 1016 | 1018 | abort(); |
| 1017 | 1019 | |
| @@ -149,11 +149,13 @@ static inline void rseq_clear_rseq_cs(void) · 148 unmodified lines | ||
| 149 | 149 | /* |
| 150 | 150 | * rseq_prepare_unload() should be invoked by each thread executing a rseq |
| 151 | 151 | * critical section at least once between their last critical section and |
| 152 | − * library unload of the library defining the rseq critical section | |
| 153 | − * (struct rseq_cs). This also applies to use of rseq in code generated by | |
| 154 | − * JIT: rseq_prepare_unload() should be invoked at least once by each | |
| 155 | − * thread executing a rseq critical section before reclaim of the memory | |
| 156 | − * holding the struct rseq_cs. | |
| 152 | + * library unload of the library defining the rseq critical section (struct | |
| 153 | + * rseq_cs) or the code referred to by the struct rseq_cs start_ip and | |
| 154 | + * post_commit_offset fields. This also applies to use of rseq in code | |
| 155 | + * generated by JIT: rseq_prepare_unload() should be invoked at least once by | |
| 156 | + * each thread executing a rseq critical section before reclaim of the memory | |
| 157 | + * holding the struct rseq_cs or reclaim of the code pointed to by struct | |
| 158 | + * rseq_cs start_ip and post_commit_offset fields. | |
| 157 | 159 | */ |
| 158 | 160 | static inline void rseq_prepare_unload(void) |
| 159 | 161 | { |
| @@ -0,0 +1 @@ | ||
| 1 | +timeout=0 | |