Pull misc updates from Andrew Morton: "Updates to various subsystems which I help look after. lib, ocfs2, fatfs, autofs, squashfs, procfs, etc. A relatively small amount of material this time" * tag 'mm-nonmm-stable-2022-08-06-2' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (72 commits) scripts/gdb: ensure the absolute path is generated on initial source MAINTAINERS: kunit: add David Gow as a maintainer of KUnit mailmap: add linux.dev alias for Brendan Higgins mailmap: update Kirill's email profile: setup_profiling_timer() is moslty not implemented ocfs2: fix a typo in a comment ocfs2: use the bitmap API to simplify code ocfs2: remove some useless functions lib/mpi: fix typo 'the the' in comment proc: add some (hopefully) insightful comments bdi: remove enum wb_congested_state kernel/hung_task: fix address space of proc_dohung_task_timeout_secs lib/lzo/lzo1x_compress.c: replace ternary operator with min() and min_t() squashfs: support reading fragments in readahead call squashfs: implement readahead squashfs: always build "file direct" version of page actor Revert "squashfs: provide backing_dev_info in order to disable read-ahead" fs/ocfs2: Fix spelling typo in comment ia64: old_rr4 added under CONFIG_HUGETLB_PAGE proc: fix test for "vsyscall=xonly" boot option ...
Showing the changes to tools/testing (7 of 102 files). Show all
Unified · Split
| @@ -17,6 +17,7 @@ TARGETS += exec · 16 unmodified lines | |||
| 17 | TARGETS += filesystems | 17 | TARGETS += filesystems |
| 18 | TARGETS += filesystems/binderfs | 18 | TARGETS += filesystems/binderfs |
| 19 | TARGETS += filesystems/epoll | 19 | TARGETS += filesystems/epoll |
| 20 | TARGETS += filesystems/fat | ||
| 20 | TARGETS += firmware | 21 | TARGETS += firmware |
| 21 | TARGETS += fpu | 22 | TARGETS += fpu |
| 22 | TARGETS += ftrace | 23 | TARGETS += ftrace |
| @@ -0,0 +1,2 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0-only | ||
| 2 | rename_exchange | ||
| @@ -0,0 +1,7 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | TEST_PROGS := run_fat_tests.sh | ||
| 4 | TEST_GEN_PROGS_EXTENDED := rename_exchange | ||
| 5 | CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES) | ||
| 6 | |||
| 7 | include ../../lib.mk | ||
| @@ -0,0 +1,2 @@ | |||
| 1 | CONFIG_BLK_DEV_LOOP=y | ||
| 2 | CONFIG_VFAT_FS=y | ||
| @@ -0,0 +1,37 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 2 | /* | ||
| 3 | * Program that atomically exchanges two paths using | ||
| 4 | * the renameat2() system call RENAME_EXCHANGE flag. | ||
| 5 | * | ||
| 6 | * Copyright 2022 Red Hat Inc. | ||
| 7 | * Author: Javier Martinez Canillas <javierm@redhat.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #define _GNU_SOURCE | ||
| 11 | #include <fcntl.h> | ||
| 12 | #include <stdio.h> | ||
| 13 | #include <stdlib.h> | ||
| 14 | |||
| 15 | void print_usage(const char *program) | ||
| 16 | { | ||
| 17 | printf("Usage: %s [oldpath] [newpath]\n", program); | ||
| 18 | printf("Atomically exchange oldpath and newpath\n"); | ||
| 19 | } | ||
| 20 | |||
| 21 | int main(int argc, char *argv[]) | ||
| 22 | { | ||
| 23 | int ret; | ||
| 24 | |||
| 25 | if (argc != 3) { | ||
| 26 | print_usage(argv[0]); | ||
| 27 | exit(EXIT_FAILURE); | ||
| 28 | } | ||
| 29 | |||
| 30 | ret = renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE); | ||
| 31 | if (ret) { | ||
| 32 | perror("rename exchange failed"); | ||
| 33 | exit(EXIT_FAILURE); | ||
| 34 | } | ||
| 35 | |||
| 36 | exit(EXIT_SUCCESS); | ||
| 37 | } | ||
| @@ -0,0 +1,82 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | # SPDX-License-Identifier: GPL-2.0 | ||
| 3 | # | ||
| 4 | # Run filesystem operations tests on an 1 MiB disk image that is formatted with | ||
| 5 | # a vfat filesystem and mounted in a temporary directory using a loop device. | ||
| 6 | # | ||
| 7 | # Copyright 2022 Red Hat Inc. | ||
| 8 | # Author: Javier Martinez Canillas <javierm@redhat.com> | ||
| 9 | |||
| 10 | set -e | ||
| 11 | set -u | ||
| 12 | set -o pipefail | ||
| 13 | |||
| 14 | BASE_DIR="$(dirname $0)" | ||
| 15 | TMP_DIR="$(mktemp -d /tmp/fat_tests_tmp.XXXX)" | ||
| 16 | IMG_PATH="${TMP_DIR}/fat.img" | ||
| 17 | MNT_PATH="${TMP_DIR}/mnt" | ||
| 18 | |||
| 19 | cleanup() | ||
| 20 | { | ||
| 21 | mountpoint -q "${MNT_PATH}" && unmount_image | ||
| 22 | rm -rf "${TMP_DIR}" | ||
| 23 | } | ||
| 24 | trap cleanup SIGINT SIGTERM EXIT | ||
| 25 | |||
| 26 | create_loopback() | ||
| 27 | { | ||
| 28 | touch "${IMG_PATH}" | ||
| 29 | chattr +C "${IMG_PATH}" >/dev/null 2>&1 || true | ||
| 30 | |||
| 31 | truncate -s 1M "${IMG_PATH}" | ||
| 32 | mkfs.vfat "${IMG_PATH}" >/dev/null 2>&1 | ||
| 33 | } | ||
| 34 | |||
| 35 | mount_image() | ||
| 36 | { | ||
| 37 | mkdir -p "${MNT_PATH}" | ||
| 38 | sudo mount -o loop "${IMG_PATH}" "${MNT_PATH}" | ||
| 39 | } | ||
| 40 | |||
| 41 | rename_exchange_test() | ||
| 42 | { | ||
| 43 | local rename_exchange="${BASE_DIR}/rename_exchange" | ||
| 44 | local old_path="${MNT_PATH}/old_file" | ||
| 45 | local new_path="${MNT_PATH}/new_file" | ||
| 46 | |||
| 47 | echo old | sudo tee "${old_path}" >/dev/null 2>&1 | ||
| 48 | echo new | sudo tee "${new_path}" >/dev/null 2>&1 | ||
| 49 | sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 | ||
| 50 | sudo sync -f "${MNT_PATH}" | ||
| 51 | grep new "${old_path}" >/dev/null 2>&1 | ||
| 52 | grep old "${new_path}" >/dev/null 2>&1 | ||
| 53 | } | ||
| 54 | |||
| 55 | rename_exchange_subdir_test() | ||
| 56 | { | ||
| 57 | local rename_exchange="${BASE_DIR}/rename_exchange" | ||
| 58 | local dir_path="${MNT_PATH}/subdir" | ||
| 59 | local old_path="${MNT_PATH}/old_file" | ||
| 60 | local new_path="${dir_path}/new_file" | ||
| 61 | |||
| 62 | sudo mkdir -p "${dir_path}" | ||
| 63 | echo old | sudo tee "${old_path}" >/dev/null 2>&1 | ||
| 64 | echo new | sudo tee "${new_path}" >/dev/null 2>&1 | ||
| 65 | sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 | ||
| 66 | sudo sync -f "${MNT_PATH}" | ||
| 67 | grep new "${old_path}" >/dev/null 2>&1 | ||
| 68 | grep old "${new_path}" >/dev/null 2>&1 | ||
| 69 | } | ||
| 70 | |||
| 71 | unmount_image() | ||
| 72 | { | ||
| 73 | sudo umount "${MNT_PATH}" &> /dev/null | ||
| 74 | } | ||
| 75 | |||
| 76 | create_loopback | ||
| 77 | mount_image | ||
| 78 | rename_exchange_test | ||
| 79 | rename_exchange_subdir_test | ||
| 80 | unmount_image | ||
| 81 | |||
| 82 | exit 0 | ||
| @@ -211,10 +211,19 @@ static int make_exe(const uint8_t *payload, size_t len) · 210 unmodified lines | |||
| 211 | } | 211 | } |
| 212 | #endif | 212 | #endif |
| 213 | 213 | ||
| 214 | static bool g_vsyscall = false; | 214 | /* |
| 215 | * 0: vsyscall VMA doesn't exist vsyscall=none | ||
| 216 | * 1: vsyscall VMA is r-xp vsyscall=emulate | ||
| 217 | * 2: vsyscall VMA is --xp vsyscall=xonly | ||
| 218 | */ | ||
| 219 | static int g_vsyscall; | ||
| 220 | static const char *str_vsyscall; | ||
| 215 | 221 | ||
| 216 | static const char str_vsyscall[] = | 222 | static const char str_vsyscall_0[] = ""; |
| 223 | static const char str_vsyscall_1[] = | ||
| 217 | "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; | 224 | "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; |
| 225 | static const char str_vsyscall_2[] = | ||
| 226 | "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n"; | ||
| 218 | 227 | ||
| 219 | #ifdef __x86_64__ | 228 | #ifdef __x86_64__ |
| 220 | static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) | 229 | static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) |
| @@ -223,13 +232,47 @@ static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) · 2 unmodified lines | |||
| 223 | } | 232 | } |
| 224 | 233 | ||
| 225 | /* | 234 | /* |
| 226 | * vsyscall page can't be unmapped, probe it with memory load. | 235 | * vsyscall page can't be unmapped, probe it directly. |
| 227 | */ | 236 | */ |
| 228 | static void vsyscall(void) | 237 | static void vsyscall(void) |
| 229 | { | 238 | { |
| 230 | pid_t pid; | 239 | pid_t pid; |
| 231 | int wstatus; | 240 | int wstatus; |
| 232 | 241 | ||
| 242 | pid = fork(); | ||
| 243 | if (pid < 0) { | ||
| 244 | fprintf(stderr, "fork, errno %d\n", errno); | ||
| 245 | exit(1); | ||
| 246 | } | ||
| 247 | if (pid == 0) { | ||
| 248 | struct rlimit rlim = {0, 0}; | ||
| 249 | (void)setrlimit(RLIMIT_CORE, &rlim); | ||
| 250 | |||
| 251 | /* Hide "segfault at ffffffffff600000" messages. */ | ||
| 252 | struct sigaction act; | ||
| 253 | memset(&act, 0, sizeof(struct sigaction)); | ||
| 254 | act.sa_flags = SA_SIGINFO; | ||
| 255 | act.sa_sigaction = sigaction_SIGSEGV; | ||
| 256 | (void)sigaction(SIGSEGV, &act, NULL); | ||
| 257 | |||
| 258 | /* gettimeofday(NULL, NULL); */ | ||
| 259 | asm volatile ( | ||
| 260 | "call %P0" | ||
| 261 | : | ||
| 262 | : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL) | ||
| 263 | : "rax", "rcx", "r11" | ||
| 264 | ); | ||
| 265 | exit(0); | ||
| 266 | } | ||
| 267 | waitpid(pid, &wstatus, 0); | ||
| 268 | if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { | ||
| 269 | /* vsyscall page exists and is executable. */ | ||
| 270 | } else { | ||
| 271 | /* vsyscall page doesn't exist. */ | ||
| 272 | g_vsyscall = 0; | ||
| 273 | return; | ||
| 274 | } | ||
| 275 | |||
| 233 | pid = fork(); | 276 | pid = fork(); |
| 234 | if (pid < 0) { | 277 | if (pid < 0) { |
| 235 | fprintf(stderr, "fork, errno %d\n", errno); | 278 | fprintf(stderr, "fork, errno %d\n", errno); |
| @@ -251,8 +294,13 @@ static void vsyscall(void) · 15 unmodified lines | |||
| 251 | } | 294 | } |
| 252 | waitpid(pid, &wstatus, 0); | 295 | waitpid(pid, &wstatus, 0); |
| 253 | if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { | 296 | if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { |
| 254 | g_vsyscall = true; | 297 | /* vsyscall page is readable and executable. */ |
| 298 | g_vsyscall = 1; | ||
| 299 | return; | ||
| 255 | } | 300 | } |
| 301 | |||
| 302 | /* vsyscall page is executable but unreadable. */ | ||
| 303 | g_vsyscall = 2; | ||
| 256 | } | 304 | } |
| 257 | 305 | ||
| 258 | int main(void) | 306 | int main(void) |
| @@ -261,6 +309,19 @@ int main(void) · 2 unmodified lines | |||
| 261 | int exec_fd; | 309 | int exec_fd; |
| 262 | 310 | ||
| 263 | vsyscall(); | 311 | vsyscall(); |
| 312 | switch (g_vsyscall) { | ||
| 313 | case 0: | ||
| 314 | str_vsyscall = str_vsyscall_0; | ||
| 315 | break; | ||
| 316 | case 1: | ||
| 317 | str_vsyscall = str_vsyscall_1; | ||
| 318 | break; | ||
| 319 | case 2: | ||
| 320 | str_vsyscall = str_vsyscall_2; | ||
| 321 | break; | ||
| 322 | default: | ||
| 323 | abort(); | ||
| 324 | } | ||
| 264 | 325 | ||
| 265 | atexit(ate); | 326 | atexit(ate); |
| 266 | 327 | ||
| @@ -314,7 +375,7 @@ int main(void) · 47 unmodified lines | |||
| 314 | 375 | ||
| 315 | /* Test /proc/$PID/maps */ | 376 | /* Test /proc/$PID/maps */ |
| 316 | { | 377 | { |
| 317 | const size_t len = strlen(buf0) + (g_vsyscall ? strlen(str_vsyscall) : 0); | 378 | const size_t len = strlen(buf0) + strlen(str_vsyscall); |
| 318 | char buf[256]; | 379 | char buf[256]; |
| 319 | ssize_t rv; | 380 | ssize_t rv; |
| 320 | int fd; | 381 | int fd; |
| @@ -327,7 +388,7 @@ int main(void) · 6 unmodified lines | |||
| 327 | rv = read(fd, buf, sizeof(buf)); | 388 | rv = read(fd, buf, sizeof(buf)); |
| 328 | assert(rv == len); | 389 | assert(rv == len); |
| 329 | assert(memcmp(buf, buf0, strlen(buf0)) == 0); | 390 | assert(memcmp(buf, buf0, strlen(buf0)) == 0); |
| 330 | if (g_vsyscall) { | 391 | if (g_vsyscall > 0) { |
| 331 | assert(memcmp(buf + strlen(buf0), str_vsyscall, strlen(str_vsyscall)) == 0); | 392 | assert(memcmp(buf + strlen(buf0), str_vsyscall, strlen(str_vsyscall)) == 0); |
| 332 | } | 393 | } |
| 333 | } | 394 | } |
| @@ -374,7 +435,7 @@ int main(void) · 40 unmodified lines | |||
| 374 | assert(memmem(buf, rv, S[i], strlen(S[i]))); | 435 | assert(memmem(buf, rv, S[i], strlen(S[i]))); |
| 375 | } | 436 | } |
| 376 | 437 | ||
| 377 | if (g_vsyscall) { | 438 | if (g_vsyscall > 0) { |
| 378 | assert(memmem(buf, rv, str_vsyscall, strlen(str_vsyscall))); | 439 | assert(memmem(buf, rv, str_vsyscall, strlen(str_vsyscall))); |
| 379 | } | 440 | } |
| 380 | } | 441 | } |