1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 Oxide Computer Company 14 */ 15 16 #include <stdio.h> 17 #include <unistd.h> 18 #include <stdlib.h> 19 #include <fcntl.h> 20 #include <dirent.h> 21 #include <port.h> 22 #include <err.h> 23 #include <assert.h> 24 25 #include <sys/types.h> 26 #include <sys/stat.h> 27 #include <sys/param.h> 28 #include <sys/poll.h> 29 30 /* 31 * Attempt to trigger the #15036 regression. This depends on a subsequent 32 * allocation in the same slab setting a bit at a specific offset, so reliable 33 * detection of the issue is a challenge. This test uses brute force in its 34 * attempt, but cannot guarantee to trigger the behavior on a system affected by 35 * the issue. 36 */ 37 38 /* 39 * We need regular files on a regular filesystem for fs_poll to be called. 40 * Assume that we can find some in our own tests dir. 41 * 42 * As for repetitions, this is not especially consistent, so really hammer 43 * things out of brute force. 44 */ 45 #define FILE_SRC "/opt/os-tests/tests" 46 #define FILE_COUNT 10 47 #define TEST_REPEAT 10000 48 49 static uint_t 50 find_test_files(const char *dir, uint_t count, int *result_fds) 51 { 52 assert(count > 0); 53 54 DIR *dirp; 55 56 dirp = opendir(dir); 57 if (dirp == NULL) { 58 return (0); 59 } 60 61 dirent_t *de; 62 uint_t nvalid = 0; 63 while ((de = readdir(dirp)) != NULL) { 64 char path[MAXPATHLEN]; 65 struct stat st; 66 67 (void) snprintf(path, sizeof (path), "%s/%s", dir, de->d_name); 68 if (lstat(path, &st) != 0 || (st.st_mode & S_IFREG) == 0) { 69 continue; 70 } 71 result_fds[nvalid] = open(path, O_RDONLY, 0); 72 if (result_fds[nvalid] < 0) { 73 continue; 74 } 75 76 nvalid++; 77 if (nvalid == count) { 78 break; 79 } 80 } 81 82 (void) closedir(dirp); 83 return (nvalid); 84 } 85 86 int 87 main(int argc, char *argv[]) 88 { 89 int poll_fds[FILE_COUNT]; 90 91 if (find_test_files(FILE_SRC, FILE_COUNT, poll_fds) != FILE_COUNT) { 92 errx(EXIT_FAILURE, "FAIL - count not open test files to poll"); 93 } 94 95 for (uint_t i = 0; i < TEST_REPEAT; i++) { 96 int port_fds[FILE_COUNT]; 97 98 for (uint_t j = 0; j < FILE_COUNT; j++) { 99 port_fds[j] = port_create(); 100 if (port_fds[j] < 0) { 101 err(EXIT_FAILURE, "FAIL - port_create()"); 102 } 103 104 int res = port_associate(port_fds[j], PORT_SOURCE_FD, 105 (uintptr_t)poll_fds[j], POLLIN, NULL); 106 if (res != 0) { 107 err(EXIT_FAILURE, "FAIL - port_associate()"); 108 } 109 } 110 111 for (uint_t j = 0; j < FILE_COUNT; j++) { 112 int res = port_dissociate(port_fds[j], PORT_SOURCE_FD, 113 (uintptr_t)poll_fds[j]); 114 if (res != 0) { 115 err(EXIT_FAILURE, "FAIL - port_dissociate()"); 116 } 117 (void) close(port_fds[j]); 118 } 119 } 120 121 (void) printf("PASS\n"); 122 return (EXIT_SUCCESS); 123 } 124