diff options
Diffstat (limited to 'usr/src/test')
-rw-r--r-- | usr/src/test/os-tests/runfiles/default.run | 5 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/regression/Makefile | 3 | ||||
-rw-r--r-- | usr/src/test/os-tests/tests/regression/illumos-15036.c | 123 |
3 files changed, 129 insertions, 2 deletions
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run index 49156ea42b..612563ebcd 100644 --- a/usr/src/test/os-tests/runfiles/default.run +++ b/usr/src/test/os-tests/runfiles/default.run @@ -148,4 +148,7 @@ tests = ['coretests'] tests = ['file_assoc.32', 'file_assoc.64'] [/opt/os-tests/tests/regression] -tests = ['illumos-15031'] +tests = [ + 'illumos-15031', + 'illumos-15036' + ] diff --git a/usr/src/test/os-tests/tests/regression/Makefile b/usr/src/test/os-tests/tests/regression/Makefile index 1536e83ca6..93a365167b 100644 --- a/usr/src/test/os-tests/tests/regression/Makefile +++ b/usr/src/test/os-tests/tests/regression/Makefile @@ -14,7 +14,8 @@ # PROGS = \ - illumos-15031 + illumos-15031 \ + illumos-15036 ROOTOPTDIR = $(ROOT)/opt/os-tests/tests ROOTOPTREGRESSION = $(ROOTOPTDIR)/regression diff --git a/usr/src/test/os-tests/tests/regression/illumos-15036.c b/usr/src/test/os-tests/tests/regression/illumos-15036.c new file mode 100644 index 0000000000..7530738c2d --- /dev/null +++ b/usr/src/test/os-tests/tests/regression/illumos-15036.c @@ -0,0 +1,123 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2022 Oxide Computer Company + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#include <dirent.h> +#include <port.h> +#include <err.h> +#include <assert.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/param.h> +#include <sys/poll.h> + +/* + * Attempt to trigger the #15036 regression. This depends on a subsequent + * allocation in the same slab setting a bit at a specific offset, so reliable + * detection of the issue is a challenge. This test uses brute force in its + * attempt, but cannot guarantee to trigger the behavior on a system affected by + * the issue. + */ + +/* + * We need regular files on a regular filesystem for fs_poll to be called. + * Assume that we can find some in our own tests dir. + * + * As for repetitions, this is not especially consistent, so really hammer + * things out of brute force. + */ +#define FILE_SRC "/opt/os-tests/tests" +#define FILE_COUNT 10 +#define TEST_REPEAT 10000 + +static uint_t +find_test_files(const char *dir, uint_t count, int *result_fds) +{ + assert(count > 0); + + DIR *dirp; + + dirp = opendir(dir); + if (dirp == NULL) { + return (0); + } + + dirent_t *de; + uint_t nvalid = 0; + while ((de = readdir(dirp)) != NULL) { + char path[MAXPATHLEN]; + struct stat st; + + (void) snprintf(path, sizeof (path), "%s/%s", dir, de->d_name); + if (lstat(path, &st) != 0 || (st.st_mode & S_IFREG) == 0) { + continue; + } + result_fds[nvalid] = open(path, O_RDONLY, 0); + if (result_fds[nvalid] < 0) { + continue; + } + + nvalid++; + if (nvalid == count) { + break; + } + } + + (void) closedir(dirp); + return (nvalid); +} + +int +main(int argc, char *argv[]) +{ + int poll_fds[FILE_COUNT]; + + if (find_test_files(FILE_SRC, FILE_COUNT, poll_fds) != FILE_COUNT) { + errx(EXIT_FAILURE, "FAIL - count not open test files to poll"); + } + + for (uint_t i = 0; i < TEST_REPEAT; i++) { + int port_fds[FILE_COUNT]; + + for (uint_t j = 0; j < FILE_COUNT; j++) { + port_fds[j] = port_create(); + if (port_fds[j] < 0) { + err(EXIT_FAILURE, "FAIL - port_create()"); + } + + int res = port_associate(port_fds[j], PORT_SOURCE_FD, + (uintptr_t)poll_fds[j], POLLIN, NULL); + if (res != 0) { + err(EXIT_FAILURE, "FAIL - port_associate()"); + } + } + + for (uint_t j = 0; j < FILE_COUNT; j++) { + int res = port_dissociate(port_fds[j], PORT_SOURCE_FD, + (uintptr_t)poll_fds[j]); + if (res != 0) { + err(EXIT_FAILURE, "FAIL - port_dissociate()"); + } + (void) close(port_fds[j]); + } + } + + (void) printf("PASS\n"); + return (EXIT_SUCCESS); +} |