14fdc3d75SEnji Cooper /*- 24fdc3d75SEnji Cooper * Copyright (c) 2006 Robert N. M. Watson 34fdc3d75SEnji Cooper * All rights reserved. 44fdc3d75SEnji Cooper * 54fdc3d75SEnji Cooper * Redistribution and use in source and binary forms, with or without 64fdc3d75SEnji Cooper * modification, are permitted provided that the following conditions 74fdc3d75SEnji Cooper * are met: 84fdc3d75SEnji Cooper * 1. Redistributions of source code must retain the above copyright 94fdc3d75SEnji Cooper * notice, this list of conditions and the following disclaimer. 104fdc3d75SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 114fdc3d75SEnji Cooper * notice, this list of conditions and the following disclaimer in the 124fdc3d75SEnji Cooper * documentation and/or other materials provided with the distribution. 134fdc3d75SEnji Cooper * 144fdc3d75SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 154fdc3d75SEnji Cooper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 164fdc3d75SEnji Cooper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 174fdc3d75SEnji Cooper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 184fdc3d75SEnji Cooper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 194fdc3d75SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 204fdc3d75SEnji Cooper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 214fdc3d75SEnji Cooper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 224fdc3d75SEnji Cooper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 234fdc3d75SEnji Cooper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 244fdc3d75SEnji Cooper * SUCH DAMAGE. 254fdc3d75SEnji Cooper */ 264fdc3d75SEnji Cooper 274fdc3d75SEnji Cooper #include <sys/cdefs.h> 284fdc3d75SEnji Cooper __FBSDID("$FreeBSD$"); 294fdc3d75SEnji Cooper 304fdc3d75SEnji Cooper #include <sys/param.h> 31*77ceadeeSMark Johnston #include <sys/ioctl.h> 324fdc3d75SEnji Cooper #include <sys/mman.h> 334fdc3d75SEnji Cooper #include <sys/resource.h> 344fdc3d75SEnji Cooper #include <sys/stat.h> 354fdc3d75SEnji Cooper #include <sys/syscall.h> 36*77ceadeeSMark Johnston #include <sys/sysctl.h> 374fdc3d75SEnji Cooper #include <sys/wait.h> 384fdc3d75SEnji Cooper 399afb12baSDavid Bright #include <ctype.h> 404fdc3d75SEnji Cooper #include <errno.h> 414fdc3d75SEnji Cooper #include <fcntl.h> 424fdc3d75SEnji Cooper #include <signal.h> 434fdc3d75SEnji Cooper #include <stdio.h> 444fdc3d75SEnji Cooper #include <stdlib.h> 454fdc3d75SEnji Cooper #include <string.h> 464fdc3d75SEnji Cooper #include <unistd.h> 474fdc3d75SEnji Cooper 484fdc3d75SEnji Cooper #include <atf-c.h> 494fdc3d75SEnji Cooper 504fdc3d75SEnji Cooper #define TEST_PATH_LEN 256 514fdc3d75SEnji Cooper static char test_path[TEST_PATH_LEN]; 529afb12baSDavid Bright static char test_path2[TEST_PATH_LEN]; 539afb12baSDavid Bright static unsigned int test_path_idx = 0; 549afb12baSDavid Bright 559afb12baSDavid Bright static void 569afb12baSDavid Bright gen_a_test_path(char *path) 579afb12baSDavid Bright { 582d5603feSDavid Bright snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d", 599afb12baSDavid Bright getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"), 609afb12baSDavid Bright test_path_idx); 619afb12baSDavid Bright 629afb12baSDavid Bright test_path_idx++; 639afb12baSDavid Bright 649afb12baSDavid Bright ATF_REQUIRE_MSG(mkstemp(path) != -1, 659afb12baSDavid Bright "mkstemp failed; errno=%d", errno); 669afb12baSDavid Bright ATF_REQUIRE_MSG(unlink(path) == 0, 679afb12baSDavid Bright "unlink failed; errno=%d", errno); 689afb12baSDavid Bright } 694fdc3d75SEnji Cooper 704fdc3d75SEnji Cooper static void 714fdc3d75SEnji Cooper gen_test_path(void) 724fdc3d75SEnji Cooper { 739afb12baSDavid Bright gen_a_test_path(test_path); 749afb12baSDavid Bright } 754fdc3d75SEnji Cooper 769afb12baSDavid Bright static void 779afb12baSDavid Bright gen_test_path2(void) 789afb12baSDavid Bright { 799afb12baSDavid Bright gen_a_test_path(test_path2); 804fdc3d75SEnji Cooper } 814fdc3d75SEnji Cooper 824fdc3d75SEnji Cooper /* 834fdc3d75SEnji Cooper * Attempt a shm_open() that should fail with an expected error of 'error'. 844fdc3d75SEnji Cooper */ 854fdc3d75SEnji Cooper static void 864fdc3d75SEnji Cooper shm_open_should_fail(const char *path, int flags, mode_t mode, int error) 874fdc3d75SEnji Cooper { 884fdc3d75SEnji Cooper int fd; 894fdc3d75SEnji Cooper 904fdc3d75SEnji Cooper fd = shm_open(path, flags, mode); 914fdc3d75SEnji Cooper ATF_CHECK_MSG(fd == -1, "shm_open didn't fail"); 924fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 934fdc3d75SEnji Cooper "shm_open didn't fail with expected errno; errno=%d; expected " 944fdc3d75SEnji Cooper "errno=%d", errno, error); 954fdc3d75SEnji Cooper } 964fdc3d75SEnji Cooper 974fdc3d75SEnji Cooper /* 984fdc3d75SEnji Cooper * Attempt a shm_unlink() that should fail with an expected error of 'error'. 994fdc3d75SEnji Cooper */ 1004fdc3d75SEnji Cooper static void 1014fdc3d75SEnji Cooper shm_unlink_should_fail(const char *path, int error) 1024fdc3d75SEnji Cooper { 1034fdc3d75SEnji Cooper 1044fdc3d75SEnji Cooper ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail"); 1054fdc3d75SEnji Cooper ATF_CHECK_MSG(error == errno, 1064fdc3d75SEnji Cooper "shm_unlink didn't fail with expected errno; errno=%d; expected " 1074fdc3d75SEnji Cooper "errno=%d", errno, error); 1084fdc3d75SEnji Cooper } 1094fdc3d75SEnji Cooper 1104fdc3d75SEnji Cooper /* 1119afb12baSDavid Bright * Open the test object and write a value to the first byte. Returns valid fd 1124fdc3d75SEnji Cooper * on success and -1 on failure. 1134fdc3d75SEnji Cooper */ 1144fdc3d75SEnji Cooper static int 1159afb12baSDavid Bright scribble_object(const char *path, char value) 1164fdc3d75SEnji Cooper { 1174fdc3d75SEnji Cooper char *page; 11894ebd6f5SEnji Cooper int fd, pagesize; 1194fdc3d75SEnji Cooper 12094ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 12194ebd6f5SEnji Cooper 1229afb12baSDavid Bright fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777); 1234fdc3d75SEnji Cooper if (fd < 0 && errno == EEXIST) { 1244fdc3d75SEnji Cooper if (shm_unlink(test_path) < 0) 1254fdc3d75SEnji Cooper atf_tc_fail("shm_unlink"); 1264fdc3d75SEnji Cooper fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777); 1274fdc3d75SEnji Cooper } 1284fdc3d75SEnji Cooper if (fd < 0) 1294fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 13094ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 1314fdc3d75SEnji Cooper atf_tc_fail("ftruncate failed; errno=%d", errno); 1324fdc3d75SEnji Cooper 13394ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1344fdc3d75SEnji Cooper if (page == MAP_FAILED) 1354fdc3d75SEnji Cooper atf_tc_fail("mmap failed; errno=%d", errno); 1364fdc3d75SEnji Cooper 1379afb12baSDavid Bright page[0] = value; 13894ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 13994ebd6f5SEnji Cooper errno); 1404fdc3d75SEnji Cooper 1414fdc3d75SEnji Cooper return (fd); 1424fdc3d75SEnji Cooper } 1434fdc3d75SEnji Cooper 1449afb12baSDavid Bright /* 1459afb12baSDavid Bright * Fail the test case if the 'path' does not refer to an shm whose first byte 1469afb12baSDavid Bright * is equal to expected_value 1479afb12baSDavid Bright */ 1489afb12baSDavid Bright static void 1499afb12baSDavid Bright verify_object(const char *path, char expected_value) 1509afb12baSDavid Bright { 1519afb12baSDavid Bright int fd; 1529afb12baSDavid Bright int pagesize; 1539afb12baSDavid Bright char *page; 1549afb12baSDavid Bright 1559afb12baSDavid Bright ATF_REQUIRE(0 < (pagesize = getpagesize())); 1569afb12baSDavid Bright 1579afb12baSDavid Bright fd = shm_open(path, O_RDONLY, 0777); 1589afb12baSDavid Bright if (fd < 0) 1599afb12baSDavid Bright atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s", 1609afb12baSDavid Bright errno, path); 1619afb12baSDavid Bright 1629afb12baSDavid Bright page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 1639afb12baSDavid Bright if (page == MAP_FAILED) 1649afb12baSDavid Bright atf_tc_fail("mmap(1)"); 1659afb12baSDavid Bright if (page[0] != expected_value) 1669afb12baSDavid Bright atf_tc_fail("Renamed object has incorrect value; has" 1679afb12baSDavid Bright "%d (0x%x, '%c'), expected %d (0x%x, '%c')\n", 1689afb12baSDavid Bright page[0], page[0], isprint(page[0]) ? page[0] : ' ', 1699afb12baSDavid Bright expected_value, expected_value, 1709afb12baSDavid Bright isprint(expected_value) ? expected_value : ' '); 1719afb12baSDavid Bright ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 1729afb12baSDavid Bright errno); 1739afb12baSDavid Bright close(fd); 1749afb12baSDavid Bright } 1759afb12baSDavid Bright 1764fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(remap_object); 1774fdc3d75SEnji Cooper ATF_TC_BODY(remap_object, tc) 1784fdc3d75SEnji Cooper { 1794fdc3d75SEnji Cooper char *page; 18094ebd6f5SEnji Cooper int fd, pagesize; 18194ebd6f5SEnji Cooper 18294ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 1834fdc3d75SEnji Cooper 1849afb12baSDavid Bright gen_test_path(); 1859afb12baSDavid Bright fd = scribble_object(test_path, '1'); 1864fdc3d75SEnji Cooper 18794ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1884fdc3d75SEnji Cooper if (page == MAP_FAILED) 1894fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 1904fdc3d75SEnji Cooper 1914fdc3d75SEnji Cooper if (page[0] != '1') 1924fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 1934fdc3d75SEnji Cooper 1944fdc3d75SEnji Cooper close(fd); 19594ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 19694ebd6f5SEnji Cooper errno); 1974fdc3d75SEnji Cooper 1984fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 1994fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 2004fdc3d75SEnji Cooper } 2014fdc3d75SEnji Cooper 2029afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_anon); 2039afb12baSDavid Bright ATF_TC_BODY(rename_from_anon, tc) 2049afb12baSDavid Bright { 2059afb12baSDavid Bright int rc; 2069afb12baSDavid Bright 2079afb12baSDavid Bright gen_test_path(); 2089afb12baSDavid Bright rc = shm_rename(SHM_ANON, test_path, 0); 2099afb12baSDavid Bright if (rc != -1) 2109afb12baSDavid Bright atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly"); 2119afb12baSDavid Bright } 2129afb12baSDavid Bright 2139afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer); 2149afb12baSDavid Bright ATF_TC_BODY(rename_bad_path_pointer, tc) 2159afb12baSDavid Bright { 2169afb12baSDavid Bright const char *bad_path; 2179afb12baSDavid Bright int rc; 2189afb12baSDavid Bright 2199afb12baSDavid Bright bad_path = (const char *)0x1; 2209afb12baSDavid Bright 2219afb12baSDavid Bright gen_test_path(); 2229afb12baSDavid Bright rc = shm_rename(test_path, bad_path, 0); 2239afb12baSDavid Bright if (rc != -1) 2249afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2259afb12baSDavid Bright 2269afb12baSDavid Bright rc = shm_rename(bad_path, test_path, 0); 2279afb12baSDavid Bright if (rc != -1) 2289afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2299afb12baSDavid Bright } 2309afb12baSDavid Bright 2319afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_from_nonexisting); 2329afb12baSDavid Bright ATF_TC_BODY(rename_from_nonexisting, tc) 2339afb12baSDavid Bright { 2349afb12baSDavid Bright int rc; 2359afb12baSDavid Bright 2369afb12baSDavid Bright gen_test_path(); 2372d5603feSDavid Bright gen_test_path2(); 2389afb12baSDavid Bright rc = shm_rename(test_path, test_path2, 0); 2399afb12baSDavid Bright if (rc != -1) 2409afb12baSDavid Bright atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); 2419afb12baSDavid Bright 2429afb12baSDavid Bright if (errno != ENOENT) 2432d5603feSDavid Bright atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d", 2442d5603feSDavid Bright errno); 2459afb12baSDavid Bright } 2469afb12baSDavid Bright 2479afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_anon); 2489afb12baSDavid Bright ATF_TC_BODY(rename_to_anon, tc) 2499afb12baSDavid Bright { 2509afb12baSDavid Bright int rc; 2519afb12baSDavid Bright 2529afb12baSDavid Bright gen_test_path(); 2539afb12baSDavid Bright rc = shm_rename(test_path, SHM_ANON, 0); 2549afb12baSDavid Bright if (rc != -1) 2559afb12baSDavid Bright atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly"); 2569afb12baSDavid Bright } 2579afb12baSDavid Bright 2589afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_replace); 2599afb12baSDavid Bright ATF_TC_BODY(rename_to_replace, tc) 2609afb12baSDavid Bright { 2619afb12baSDavid Bright char expected_value; 2629afb12baSDavid Bright int fd; 2639afb12baSDavid Bright int fd2; 2649afb12baSDavid Bright 2659afb12baSDavid Bright // Some contents we can verify later 2669afb12baSDavid Bright expected_value = 'g'; 2679afb12baSDavid Bright 2689afb12baSDavid Bright gen_test_path(); 2699afb12baSDavid Bright fd = scribble_object(test_path, expected_value); 2709afb12baSDavid Bright close(fd); 2719afb12baSDavid Bright 2729afb12baSDavid Bright // Give the other some different value so we can detect success 2739afb12baSDavid Bright gen_test_path2(); 2749afb12baSDavid Bright fd2 = scribble_object(test_path2, 'h'); 2759afb12baSDavid Bright close(fd2); 2769afb12baSDavid Bright 2779afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0, 2789afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 2799afb12baSDavid Bright 2809afb12baSDavid Bright // Read back renamed; verify contents 2819afb12baSDavid Bright verify_object(test_path2, expected_value); 2829afb12baSDavid Bright } 2839afb12baSDavid Bright 2849afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_noreplace); 2859afb12baSDavid Bright ATF_TC_BODY(rename_to_noreplace, tc) 2869afb12baSDavid Bright { 2879afb12baSDavid Bright char expected_value_from; 2889afb12baSDavid Bright char expected_value_to; 2899afb12baSDavid Bright int fd_from; 2909afb12baSDavid Bright int fd_to; 2919afb12baSDavid Bright int rc; 2929afb12baSDavid Bright 2939afb12baSDavid Bright // Some contents we can verify later 2949afb12baSDavid Bright expected_value_from = 'g'; 2959afb12baSDavid Bright gen_test_path(); 2969afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 2979afb12baSDavid Bright close(fd_from); 2989afb12baSDavid Bright 2999afb12baSDavid Bright // Give the other some different value so we can detect success 3009afb12baSDavid Bright expected_value_to = 'h'; 3019afb12baSDavid Bright gen_test_path2(); 3029afb12baSDavid Bright fd_to = scribble_object(test_path2, expected_value_to); 3039afb12baSDavid Bright close(fd_to); 3049afb12baSDavid Bright 3059afb12baSDavid Bright rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE); 3069afb12baSDavid Bright ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST), 3079afb12baSDavid Bright "shm_rename didn't fail as expected; errno: %d; return: %d", errno, 3089afb12baSDavid Bright rc); 3099afb12baSDavid Bright 3109afb12baSDavid Bright // Read back renamed; verify contents 3119afb12baSDavid Bright verify_object(test_path2, expected_value_to); 3129afb12baSDavid Bright } 3139afb12baSDavid Bright 3149afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange); 3159afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange, tc) 3169afb12baSDavid Bright { 3179afb12baSDavid Bright char expected_value_from; 3189afb12baSDavid Bright char expected_value_to; 3199afb12baSDavid Bright int fd_from; 3209afb12baSDavid Bright int fd_to; 3219afb12baSDavid Bright 3229afb12baSDavid Bright // Some contents we can verify later 3239afb12baSDavid Bright expected_value_from = 'g'; 3249afb12baSDavid Bright gen_test_path(); 3259afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 3269afb12baSDavid Bright close(fd_from); 3279afb12baSDavid Bright 3289afb12baSDavid Bright // Give the other some different value so we can detect success 3299afb12baSDavid Bright expected_value_to = 'h'; 3309afb12baSDavid Bright gen_test_path2(); 3319afb12baSDavid Bright fd_to = scribble_object(test_path2, expected_value_to); 3329afb12baSDavid Bright close(fd_to); 3339afb12baSDavid Bright 3349afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 3359afb12baSDavid Bright SHM_RENAME_EXCHANGE) == 0, 3369afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3379afb12baSDavid Bright 3389afb12baSDavid Bright // Read back renamed; verify contents 3399afb12baSDavid Bright verify_object(test_path, expected_value_to); 3409afb12baSDavid Bright verify_object(test_path2, expected_value_from); 3419afb12baSDavid Bright } 3429afb12baSDavid Bright 3439afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting); 3449afb12baSDavid Bright ATF_TC_BODY(rename_to_exchange_nonexisting, tc) 3459afb12baSDavid Bright { 3469afb12baSDavid Bright char expected_value_from; 3479afb12baSDavid Bright int fd_from; 3489afb12baSDavid Bright 3499afb12baSDavid Bright // Some contents we can verify later 3509afb12baSDavid Bright expected_value_from = 'g'; 3519afb12baSDavid Bright gen_test_path(); 3529afb12baSDavid Bright fd_from = scribble_object(test_path, expected_value_from); 3539afb12baSDavid Bright close(fd_from); 3549afb12baSDavid Bright 3559afb12baSDavid Bright gen_test_path2(); 3569afb12baSDavid Bright 3579afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 3589afb12baSDavid Bright SHM_RENAME_EXCHANGE) == 0, 3599afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3609afb12baSDavid Bright 3619afb12baSDavid Bright // Read back renamed; verify contents 3629afb12baSDavid Bright verify_object(test_path2, expected_value_from); 3639afb12baSDavid Bright } 3649afb12baSDavid Bright 3659afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_to_self); 3669afb12baSDavid Bright ATF_TC_BODY(rename_to_self, tc) 3679afb12baSDavid Bright { 3689afb12baSDavid Bright int fd; 3699afb12baSDavid Bright char expected_value; 3709afb12baSDavid Bright 3719afb12baSDavid Bright expected_value = 't'; 3729afb12baSDavid Bright 3739afb12baSDavid Bright gen_test_path(); 3749afb12baSDavid Bright fd = scribble_object(test_path, expected_value); 3759afb12baSDavid Bright close(fd); 3769afb12baSDavid Bright 3779afb12baSDavid Bright ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0, 3789afb12baSDavid Bright "shm_rename failed; errno=%d", errno); 3799afb12baSDavid Bright 3809afb12baSDavid Bright verify_object(test_path, expected_value); 3819afb12baSDavid Bright } 3829afb12baSDavid Bright 3839afb12baSDavid Bright ATF_TC_WITHOUT_HEAD(rename_bad_flag); 3849afb12baSDavid Bright ATF_TC_BODY(rename_bad_flag, tc) 3859afb12baSDavid Bright { 3869afb12baSDavid Bright int fd; 3879afb12baSDavid Bright int rc; 3889afb12baSDavid Bright 3899afb12baSDavid Bright /* Make sure we don't fail out due to ENOENT */ 3909afb12baSDavid Bright gen_test_path(); 3919afb12baSDavid Bright gen_test_path2(); 3929afb12baSDavid Bright fd = scribble_object(test_path, 'd'); 3939afb12baSDavid Bright close(fd); 3949afb12baSDavid Bright fd = scribble_object(test_path2, 'd'); 3959afb12baSDavid Bright close(fd); 3969afb12baSDavid Bright 3979afb12baSDavid Bright /* 3989afb12baSDavid Bright * Note: if we end up with enough flags that we use all the bits, 3999afb12baSDavid Bright * then remove this test completely. 4009afb12baSDavid Bright */ 4019afb12baSDavid Bright rc = shm_rename(test_path, test_path2, INT_MIN); 4029afb12baSDavid Bright ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL), 4039afb12baSDavid Bright "shm_rename should have failed with EINVAL; got: return=%d, " 4049afb12baSDavid Bright "errno=%d", rc, errno); 4059afb12baSDavid Bright } 4069afb12baSDavid Bright 4074fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(reopen_object); 4084fdc3d75SEnji Cooper ATF_TC_BODY(reopen_object, tc) 4094fdc3d75SEnji Cooper { 4104fdc3d75SEnji Cooper char *page; 41194ebd6f5SEnji Cooper int fd, pagesize; 41294ebd6f5SEnji Cooper 41394ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 4144fdc3d75SEnji Cooper 4159afb12baSDavid Bright gen_test_path(); 4169afb12baSDavid Bright fd = scribble_object(test_path, '1'); 4174fdc3d75SEnji Cooper close(fd); 4184fdc3d75SEnji Cooper 4194fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY, 0777); 4204fdc3d75SEnji Cooper if (fd < 0) 4214fdc3d75SEnji Cooper atf_tc_fail("shm_open(2) failed; errno=%d", errno); 4224fdc3d75SEnji Cooper 42394ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0); 4244fdc3d75SEnji Cooper if (page == MAP_FAILED) 4254fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 4264fdc3d75SEnji Cooper 4274fdc3d75SEnji Cooper if (page[0] != '1') 4284fdc3d75SEnji Cooper atf_tc_fail("missing data ('%c' != '1')", page[0]); 4294fdc3d75SEnji Cooper 43094ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 43194ebd6f5SEnji Cooper errno); 4324fdc3d75SEnji Cooper close(fd); 4334fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 4344fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 4354fdc3d75SEnji Cooper } 4364fdc3d75SEnji Cooper 4374fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(readonly_mmap_write); 4384fdc3d75SEnji Cooper ATF_TC_BODY(readonly_mmap_write, tc) 4394fdc3d75SEnji Cooper { 4404fdc3d75SEnji Cooper char *page; 44194ebd6f5SEnji Cooper int fd, pagesize; 44294ebd6f5SEnji Cooper 44394ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 4444fdc3d75SEnji Cooper 4454fdc3d75SEnji Cooper gen_test_path(); 4464fdc3d75SEnji Cooper 4474fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 4484fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 4494fdc3d75SEnji Cooper 4504fdc3d75SEnji Cooper /* PROT_WRITE should fail with EACCES. */ 45194ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 4524fdc3d75SEnji Cooper if (page != MAP_FAILED) 4534fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly"); 4544fdc3d75SEnji Cooper 4554fdc3d75SEnji Cooper if (errno != EACCES) 4564fdc3d75SEnji Cooper atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; " 4574fdc3d75SEnji Cooper "errno=%d", errno); 4584fdc3d75SEnji Cooper 4594fdc3d75SEnji Cooper close(fd); 4604fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 4614fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 4624fdc3d75SEnji Cooper } 4634fdc3d75SEnji Cooper 4644fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_after_link); 4654fdc3d75SEnji Cooper ATF_TC_BODY(open_after_link, tc) 4664fdc3d75SEnji Cooper { 4674fdc3d75SEnji Cooper int fd; 4684fdc3d75SEnji Cooper 4694fdc3d75SEnji Cooper gen_test_path(); 4704fdc3d75SEnji Cooper 4714fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777); 4724fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 4734fdc3d75SEnji Cooper close(fd); 4744fdc3d75SEnji Cooper 4754fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d", 4764fdc3d75SEnji Cooper errno); 4774fdc3d75SEnji Cooper 4784fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT); 4794fdc3d75SEnji Cooper } 4804fdc3d75SEnji Cooper 4814fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_invalid_path); 4824fdc3d75SEnji Cooper ATF_TC_BODY(open_invalid_path, tc) 4834fdc3d75SEnji Cooper { 4844fdc3d75SEnji Cooper 4854fdc3d75SEnji Cooper shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL); 4864fdc3d75SEnji Cooper } 4874fdc3d75SEnji Cooper 4884fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_write_only); 4894fdc3d75SEnji Cooper ATF_TC_BODY(open_write_only, tc) 4904fdc3d75SEnji Cooper { 4914fdc3d75SEnji Cooper 4924fdc3d75SEnji Cooper gen_test_path(); 4934fdc3d75SEnji Cooper 4944fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL); 4954fdc3d75SEnji Cooper } 4964fdc3d75SEnji Cooper 4974fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_extra_flags); 4984fdc3d75SEnji Cooper ATF_TC_BODY(open_extra_flags, tc) 4994fdc3d75SEnji Cooper { 5004fdc3d75SEnji Cooper 5014fdc3d75SEnji Cooper gen_test_path(); 5024fdc3d75SEnji Cooper 5034fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL); 5044fdc3d75SEnji Cooper } 5054fdc3d75SEnji Cooper 5064fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon); 5074fdc3d75SEnji Cooper ATF_TC_BODY(open_anon, tc) 5084fdc3d75SEnji Cooper { 5094fdc3d75SEnji Cooper int fd; 5104fdc3d75SEnji Cooper 5114fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_RDWR, 0777); 5124fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 5134fdc3d75SEnji Cooper close(fd); 5144fdc3d75SEnji Cooper } 5154fdc3d75SEnji Cooper 5164fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_anon_readonly); 5174fdc3d75SEnji Cooper ATF_TC_BODY(open_anon_readonly, tc) 5184fdc3d75SEnji Cooper { 5194fdc3d75SEnji Cooper 5204fdc3d75SEnji Cooper shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL); 5214fdc3d75SEnji Cooper } 5224fdc3d75SEnji Cooper 5234fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_bad_path_pointer); 5244fdc3d75SEnji Cooper ATF_TC_BODY(open_bad_path_pointer, tc) 5254fdc3d75SEnji Cooper { 5264fdc3d75SEnji Cooper 5274fdc3d75SEnji Cooper shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT); 5284fdc3d75SEnji Cooper } 5294fdc3d75SEnji Cooper 5304fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_path_too_long); 5314fdc3d75SEnji Cooper ATF_TC_BODY(open_path_too_long, tc) 5324fdc3d75SEnji Cooper { 5334fdc3d75SEnji Cooper char *page; 5344fdc3d75SEnji Cooper 5354fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 5364fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 5374fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 5384fdc3d75SEnji Cooper shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG); 5394fdc3d75SEnji Cooper free(page); 5404fdc3d75SEnji Cooper } 5414fdc3d75SEnji Cooper 5424fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_nonexisting_object); 5434fdc3d75SEnji Cooper ATF_TC_BODY(open_nonexisting_object, tc) 5444fdc3d75SEnji Cooper { 5454fdc3d75SEnji Cooper 5464fdc3d75SEnji Cooper shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT); 5474fdc3d75SEnji Cooper } 5484fdc3d75SEnji Cooper 5494fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(open_create_existing_object); 5504fdc3d75SEnji Cooper ATF_TC_BODY(open_create_existing_object, tc) 5514fdc3d75SEnji Cooper { 5524fdc3d75SEnji Cooper int fd; 5534fdc3d75SEnji Cooper 5544fdc3d75SEnji Cooper gen_test_path(); 5554fdc3d75SEnji Cooper 5564fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777); 5574fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 5584fdc3d75SEnji Cooper close(fd); 5594fdc3d75SEnji Cooper 5604fdc3d75SEnji Cooper shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL, 5614fdc3d75SEnji Cooper 0777, EEXIST); 5624fdc3d75SEnji Cooper 5634fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 5644fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 5654fdc3d75SEnji Cooper } 5664fdc3d75SEnji Cooper 5674fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(trunc_resets_object); 5684fdc3d75SEnji Cooper ATF_TC_BODY(trunc_resets_object, tc) 5694fdc3d75SEnji Cooper { 5704fdc3d75SEnji Cooper struct stat sb; 5714fdc3d75SEnji Cooper int fd; 5724fdc3d75SEnji Cooper 5734fdc3d75SEnji Cooper gen_test_path(); 5744fdc3d75SEnji Cooper 5754fdc3d75SEnji Cooper /* Create object and set size to 1024. */ 5764fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_CREAT, 0777); 5774fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno); 5784fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1, 5794fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 5804fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 5814fdc3d75SEnji Cooper "fstat(1) failed; errno=%d", errno); 5824fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size); 5834fdc3d75SEnji Cooper close(fd); 5844fdc3d75SEnji Cooper 5854fdc3d75SEnji Cooper /* Open with O_TRUNC which should reset size to 0. */ 5864fdc3d75SEnji Cooper fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777); 5874fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno); 5884fdc3d75SEnji Cooper ATF_REQUIRE_MSG(fstat(fd, &sb) != -1, 5894fdc3d75SEnji Cooper "fstat(2) failed; errno=%d", errno); 5904fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sb.st_size == 0, 5914fdc3d75SEnji Cooper "size was not 0 after truncation: %d", (int)sb.st_size); 5924fdc3d75SEnji Cooper close(fd); 5934fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, 5944fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 5954fdc3d75SEnji Cooper } 5964fdc3d75SEnji Cooper 5974fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer); 5984fdc3d75SEnji Cooper ATF_TC_BODY(unlink_bad_path_pointer, tc) 5994fdc3d75SEnji Cooper { 6004fdc3d75SEnji Cooper 6014fdc3d75SEnji Cooper shm_unlink_should_fail((char *)1024, EFAULT); 6024fdc3d75SEnji Cooper } 6034fdc3d75SEnji Cooper 6044fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(unlink_path_too_long); 6054fdc3d75SEnji Cooper ATF_TC_BODY(unlink_path_too_long, tc) 6064fdc3d75SEnji Cooper { 6074fdc3d75SEnji Cooper char *page; 6084fdc3d75SEnji Cooper 6094fdc3d75SEnji Cooper page = malloc(MAXPATHLEN + 1); 6104fdc3d75SEnji Cooper memset(page, 'a', MAXPATHLEN); 6114fdc3d75SEnji Cooper page[MAXPATHLEN] = '\0'; 6124fdc3d75SEnji Cooper shm_unlink_should_fail(page, ENAMETOOLONG); 6134fdc3d75SEnji Cooper free(page); 6144fdc3d75SEnji Cooper } 6154fdc3d75SEnji Cooper 6164fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(object_resize); 6174fdc3d75SEnji Cooper ATF_TC_BODY(object_resize, tc) 6184fdc3d75SEnji Cooper { 6194fdc3d75SEnji Cooper pid_t pid; 6204fdc3d75SEnji Cooper struct stat sb; 62194ebd6f5SEnji Cooper char *page; 62294ebd6f5SEnji Cooper int fd, pagesize, status; 62394ebd6f5SEnji Cooper 62494ebd6f5SEnji Cooper ATF_REQUIRE(0 < (pagesize = getpagesize())); 6254fdc3d75SEnji Cooper 6264fdc3d75SEnji Cooper /* Start off with a size of a single page. */ 6274fdc3d75SEnji Cooper fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777); 6284fdc3d75SEnji Cooper if (fd < 0) 6294fdc3d75SEnji Cooper atf_tc_fail("shm_open failed; errno=%d", errno); 6304fdc3d75SEnji Cooper 63194ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 6324fdc3d75SEnji Cooper atf_tc_fail("ftruncate(1) failed; errno=%d", errno); 6334fdc3d75SEnji Cooper 6344fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6354fdc3d75SEnji Cooper atf_tc_fail("fstat(1) failed; errno=%d", errno); 6364fdc3d75SEnji Cooper 63794ebd6f5SEnji Cooper if (sb.st_size != pagesize) 6384fdc3d75SEnji Cooper atf_tc_fail("first resize failed (%d != %d)", 63994ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 6404fdc3d75SEnji Cooper 6414fdc3d75SEnji Cooper /* Write a '1' to the first byte. */ 64294ebd6f5SEnji Cooper page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 6434fdc3d75SEnji Cooper if (page == MAP_FAILED) 6444fdc3d75SEnji Cooper atf_tc_fail("mmap(1)"); 6454fdc3d75SEnji Cooper 6464fdc3d75SEnji Cooper page[0] = '1'; 6474fdc3d75SEnji Cooper 64894ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d", 64994ebd6f5SEnji Cooper errno); 6504fdc3d75SEnji Cooper 6514fdc3d75SEnji Cooper /* Grow the object to 2 pages. */ 65294ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 6534fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 6544fdc3d75SEnji Cooper 6554fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6564fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 6574fdc3d75SEnji Cooper 65894ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 6594fdc3d75SEnji Cooper atf_tc_fail("second resize failed (%d != %d)", 66094ebd6f5SEnji Cooper (int)sb.st_size, pagesize * 2); 6614fdc3d75SEnji Cooper 6624fdc3d75SEnji Cooper /* Check for '1' at the first byte. */ 66394ebd6f5SEnji Cooper page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); 6644fdc3d75SEnji Cooper if (page == MAP_FAILED) 6654fdc3d75SEnji Cooper atf_tc_fail("mmap(2) failed; errno=%d", errno); 6664fdc3d75SEnji Cooper 6674fdc3d75SEnji Cooper if (page[0] != '1') 6684fdc3d75SEnji Cooper atf_tc_fail("'%c' != '1'", page[0]); 6694fdc3d75SEnji Cooper 6704fdc3d75SEnji Cooper /* Write a '2' at the start of the second page. */ 67194ebd6f5SEnji Cooper page[pagesize] = '2'; 6724fdc3d75SEnji Cooper 6734fdc3d75SEnji Cooper /* Shrink the object back to 1 page. */ 67494ebd6f5SEnji Cooper if (ftruncate(fd, pagesize) < 0) 6754fdc3d75SEnji Cooper atf_tc_fail("ftruncate(3) failed; errno=%d", errno); 6764fdc3d75SEnji Cooper 6774fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 6784fdc3d75SEnji Cooper atf_tc_fail("fstat(3) failed; errno=%d", errno); 6794fdc3d75SEnji Cooper 68094ebd6f5SEnji Cooper if (sb.st_size != pagesize) 6814fdc3d75SEnji Cooper atf_tc_fail("third resize failed (%d != %d)", 68294ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 6834fdc3d75SEnji Cooper 6844fdc3d75SEnji Cooper /* 6854fdc3d75SEnji Cooper * Fork a child process to make sure the second page is no 6864fdc3d75SEnji Cooper * longer valid. 6874fdc3d75SEnji Cooper */ 6884fdc3d75SEnji Cooper pid = fork(); 6894fdc3d75SEnji Cooper if (pid == -1) 6904fdc3d75SEnji Cooper atf_tc_fail("fork failed; errno=%d", errno); 6914fdc3d75SEnji Cooper 6924fdc3d75SEnji Cooper if (pid == 0) { 6934fdc3d75SEnji Cooper struct rlimit lim; 6944fdc3d75SEnji Cooper char c; 6954fdc3d75SEnji Cooper 6964fdc3d75SEnji Cooper /* Don't generate a core dump. */ 69794ebd6f5SEnji Cooper ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0); 6984fdc3d75SEnji Cooper lim.rlim_cur = 0; 69994ebd6f5SEnji Cooper ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0); 7004fdc3d75SEnji Cooper 7014fdc3d75SEnji Cooper /* 7024fdc3d75SEnji Cooper * The previous ftruncate(2) shrunk the backing object 7034fdc3d75SEnji Cooper * so that this address is no longer valid, so reading 7044f775512SJilles Tjoelker * from it should trigger a SIGBUS. 7054fdc3d75SEnji Cooper */ 70694ebd6f5SEnji Cooper c = page[pagesize]; 7074fdc3d75SEnji Cooper fprintf(stderr, "child: page 1: '%c'\n", c); 7084fdc3d75SEnji Cooper exit(0); 7094fdc3d75SEnji Cooper } 7104fdc3d75SEnji Cooper 7114fdc3d75SEnji Cooper if (wait(&status) < 0) 7124fdc3d75SEnji Cooper atf_tc_fail("wait failed; errno=%d", errno); 7134fdc3d75SEnji Cooper 7144f775512SJilles Tjoelker if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS) 7154fdc3d75SEnji Cooper atf_tc_fail("child terminated with status %x", status); 7164fdc3d75SEnji Cooper 7174fdc3d75SEnji Cooper /* Grow the object back to 2 pages. */ 71894ebd6f5SEnji Cooper if (ftruncate(fd, pagesize * 2) < 0) 7194fdc3d75SEnji Cooper atf_tc_fail("ftruncate(2) failed; errno=%d", errno); 7204fdc3d75SEnji Cooper 7214fdc3d75SEnji Cooper if (fstat(fd, &sb) < 0) 7224fdc3d75SEnji Cooper atf_tc_fail("fstat(2) failed; errno=%d", errno); 7234fdc3d75SEnji Cooper 72494ebd6f5SEnji Cooper if (sb.st_size != pagesize * 2) 7254fdc3d75SEnji Cooper atf_tc_fail("fourth resize failed (%d != %d)", 72694ebd6f5SEnji Cooper (int)sb.st_size, pagesize); 7274fdc3d75SEnji Cooper 7284fdc3d75SEnji Cooper /* 7294fdc3d75SEnji Cooper * Note that the mapping at 'page' for the second page is 7304fdc3d75SEnji Cooper * still valid, and now that the shm object has been grown 7314fdc3d75SEnji Cooper * back up to 2 pages, there is now memory backing this page 7324fdc3d75SEnji Cooper * so the read will work. However, the data should be zero 7334fdc3d75SEnji Cooper * rather than '2' as the old data was thrown away when the 7344fdc3d75SEnji Cooper * object was shrunk and the new pages when an object are 7354fdc3d75SEnji Cooper * grown are zero-filled. 7364fdc3d75SEnji Cooper */ 73794ebd6f5SEnji Cooper if (page[pagesize] != 0) 7384fdc3d75SEnji Cooper atf_tc_fail("invalid data at %d: %x != 0", 73994ebd6f5SEnji Cooper pagesize, (int)page[pagesize]); 7404fdc3d75SEnji Cooper 7414fdc3d75SEnji Cooper close(fd); 7424fdc3d75SEnji Cooper } 7434fdc3d75SEnji Cooper 7444fdc3d75SEnji Cooper /* Signal handler which does nothing. */ 7454fdc3d75SEnji Cooper static void 7464fdc3d75SEnji Cooper ignoreit(int sig __unused) 7474fdc3d75SEnji Cooper { 7484fdc3d75SEnji Cooper ; 7494fdc3d75SEnji Cooper } 7504fdc3d75SEnji Cooper 7514fdc3d75SEnji Cooper ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork); 7524fdc3d75SEnji Cooper ATF_TC_BODY(shm_functionality_across_fork, tc) 7534fdc3d75SEnji Cooper { 7544fdc3d75SEnji Cooper char *cp, c; 7554fdc3d75SEnji Cooper int error, desc, rv; 7564fdc3d75SEnji Cooper long scval; 7574fdc3d75SEnji Cooper sigset_t ss; 7584fdc3d75SEnji Cooper struct sigaction sa; 7594fdc3d75SEnji Cooper void *region; 7604fdc3d75SEnji Cooper size_t i, psize; 7614fdc3d75SEnji Cooper 7624fdc3d75SEnji Cooper #ifndef _POSIX_SHARED_MEMORY_OBJECTS 7634fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); 7644fdc3d75SEnji Cooper #else 7654fdc3d75SEnji Cooper printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n", 7664fdc3d75SEnji Cooper (long)_POSIX_SHARED_MEMORY_OBJECTS - 0); 7674fdc3d75SEnji Cooper if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1) 7684fdc3d75SEnji Cooper printf("***Indicates this feature may be unsupported!\n"); 7694fdc3d75SEnji Cooper #endif 7704fdc3d75SEnji Cooper errno = 0; 7714fdc3d75SEnji Cooper scval = sysconf(_SC_SHARED_MEMORY_OBJECTS); 7724fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 7734fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; " 7744fdc3d75SEnji Cooper "errno=%d", errno); 7754fdc3d75SEnji Cooper } else { 7764fdc3d75SEnji Cooper printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n", 7774fdc3d75SEnji Cooper scval); 7784fdc3d75SEnji Cooper if (scval == -1) 7794fdc3d75SEnji Cooper printf("***Indicates this feature is unsupported!\n"); 7804fdc3d75SEnji Cooper } 7814fdc3d75SEnji Cooper 7824fdc3d75SEnji Cooper errno = 0; 7834fdc3d75SEnji Cooper scval = sysconf(_SC_PAGESIZE); 7844fdc3d75SEnji Cooper if (scval == -1 && errno != 0) { 7854fdc3d75SEnji Cooper atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno); 78694ebd6f5SEnji Cooper } else if (scval <= 0) { 7874fdc3d75SEnji Cooper fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld", 7884fdc3d75SEnji Cooper scval); 7894fdc3d75SEnji Cooper psize = 4096; 7904fdc3d75SEnji Cooper } else { 7914fdc3d75SEnji Cooper printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval); 7924fdc3d75SEnji Cooper psize = scval; 7934fdc3d75SEnji Cooper } 7944fdc3d75SEnji Cooper 7954fdc3d75SEnji Cooper gen_test_path(); 7964fdc3d75SEnji Cooper desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600); 7974fdc3d75SEnji Cooper 7984fdc3d75SEnji Cooper ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno); 7994fdc3d75SEnji Cooper ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 8004fdc3d75SEnji Cooper "shm_unlink failed; errno=%d", errno); 8014fdc3d75SEnji Cooper ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1, 8024fdc3d75SEnji Cooper "ftruncate failed; errno=%d", errno); 8034fdc3d75SEnji Cooper 80494ebd6f5SEnji Cooper region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0); 8054fdc3d75SEnji Cooper ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno); 8064fdc3d75SEnji Cooper memset(region, '\377', psize); 8074fdc3d75SEnji Cooper 8084fdc3d75SEnji Cooper sa.sa_flags = 0; 8094fdc3d75SEnji Cooper sa.sa_handler = ignoreit; 8104fdc3d75SEnji Cooper sigemptyset(&sa.sa_mask); 8114fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0, 8124fdc3d75SEnji Cooper "sigaction failed; errno=%d", errno); 8134fdc3d75SEnji Cooper 8144fdc3d75SEnji Cooper sigemptyset(&ss); 8154fdc3d75SEnji Cooper sigaddset(&ss, SIGUSR1); 8164fdc3d75SEnji Cooper ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0, 8174fdc3d75SEnji Cooper "sigprocmask failed; errno=%d", errno); 8184fdc3d75SEnji Cooper 8194fdc3d75SEnji Cooper rv = fork(); 8204fdc3d75SEnji Cooper ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno); 8214fdc3d75SEnji Cooper if (rv == 0) { 8224fdc3d75SEnji Cooper sigemptyset(&ss); 8234fdc3d75SEnji Cooper sigsuspend(&ss); 8244fdc3d75SEnji Cooper 8254fdc3d75SEnji Cooper for (cp = region; cp < (char *)region + psize; cp++) { 8264fdc3d75SEnji Cooper if (*cp != '\151') 8274fdc3d75SEnji Cooper _exit(1); 8284fdc3d75SEnji Cooper } 8294fdc3d75SEnji Cooper if (lseek(desc, 0, SEEK_SET) == -1) 8304fdc3d75SEnji Cooper _exit(1); 8314fdc3d75SEnji Cooper for (i = 0; i < psize; i++) { 8324fdc3d75SEnji Cooper error = read(desc, &c, 1); 8334fdc3d75SEnji Cooper if (c != '\151') 8344fdc3d75SEnji Cooper _exit(1); 8354fdc3d75SEnji Cooper } 8364fdc3d75SEnji Cooper _exit(0); 8374fdc3d75SEnji Cooper } else { 8384fdc3d75SEnji Cooper int status; 8394fdc3d75SEnji Cooper 8404fdc3d75SEnji Cooper memset(region, '\151', psize - 2); 8414fdc3d75SEnji Cooper error = pwrite(desc, region, 2, psize - 2); 8424fdc3d75SEnji Cooper if (error != 2) { 8434fdc3d75SEnji Cooper if (error >= 0) 8444fdc3d75SEnji Cooper atf_tc_fail("short write; %d bytes written", 8454fdc3d75SEnji Cooper error); 8464fdc3d75SEnji Cooper else 8474fdc3d75SEnji Cooper atf_tc_fail("shmfd write"); 8484fdc3d75SEnji Cooper } 8494fdc3d75SEnji Cooper kill(rv, SIGUSR1); 8504fdc3d75SEnji Cooper waitpid(rv, &status, 0); 8514fdc3d75SEnji Cooper 8524fdc3d75SEnji Cooper if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 8534fdc3d75SEnji Cooper printf("Functionality test successful\n"); 8544fdc3d75SEnji Cooper } else if (WIFEXITED(status)) { 8554fdc3d75SEnji Cooper atf_tc_fail("Child process exited with status %d", 8564fdc3d75SEnji Cooper WEXITSTATUS(status)); 8574fdc3d75SEnji Cooper } else { 8584fdc3d75SEnji Cooper atf_tc_fail("Child process terminated with %s", 8594fdc3d75SEnji Cooper strsignal(WTERMSIG(status))); 8604fdc3d75SEnji Cooper } 8614fdc3d75SEnji Cooper } 86294ebd6f5SEnji Cooper 86394ebd6f5SEnji Cooper ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d", 86494ebd6f5SEnji Cooper errno); 86594ebd6f5SEnji Cooper shm_unlink(test_path); 8664fdc3d75SEnji Cooper } 8674fdc3d75SEnji Cooper 86895aa96f3SKyle Evans ATF_TC_WITHOUT_HEAD(cloexec); 86995aa96f3SKyle Evans ATF_TC_BODY(cloexec, tc) 87095aa96f3SKyle Evans { 87195aa96f3SKyle Evans int fd; 87295aa96f3SKyle Evans 87395aa96f3SKyle Evans gen_test_path(); 87495aa96f3SKyle Evans 87595aa96f3SKyle Evans /* shm_open(2) is required to set FD_CLOEXEC */ 87695aa96f3SKyle Evans fd = shm_open(SHM_ANON, O_RDWR, 0777); 87795aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 87895aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 87995aa96f3SKyle Evans close(fd); 88095aa96f3SKyle Evans 88195aa96f3SKyle Evans /* Also make sure that named shm is correct */ 88295aa96f3SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0600); 88395aa96f3SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 88495aa96f3SKyle Evans ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0); 88595aa96f3SKyle Evans close(fd); 88695aa96f3SKyle Evans } 88795aa96f3SKyle Evans 8885a391b57SKyle Evans ATF_TC_WITHOUT_HEAD(mode); 8895a391b57SKyle Evans ATF_TC_BODY(mode, tc) 8905a391b57SKyle Evans { 8915a391b57SKyle Evans struct stat st; 8925a391b57SKyle Evans int fd; 8935a391b57SKyle Evans mode_t restore_mask; 8945a391b57SKyle Evans 8955a391b57SKyle Evans gen_test_path(); 8965a391b57SKyle Evans 8975a391b57SKyle Evans /* Remove inhibitions from umask */ 8985a391b57SKyle Evans restore_mask = umask(0); 8995a391b57SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0600); 9005a391b57SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 9015a391b57SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 9025a391b57SKyle Evans ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0600); 9035a391b57SKyle Evans close(fd); 9045a391b57SKyle Evans ATF_REQUIRE(shm_unlink(test_path) == 0); 9055a391b57SKyle Evans 9065a391b57SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0660); 9075a391b57SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 9085a391b57SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 9095a391b57SKyle Evans ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0660); 9105a391b57SKyle Evans close(fd); 9115a391b57SKyle Evans ATF_REQUIRE(shm_unlink(test_path) == 0); 9125a391b57SKyle Evans 9135a391b57SKyle Evans fd = shm_open(test_path, O_CREAT | O_RDWR, 0666); 9145a391b57SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 9155a391b57SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 9165a391b57SKyle Evans ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0666); 9175a391b57SKyle Evans close(fd); 9185a391b57SKyle Evans ATF_REQUIRE(shm_unlink(test_path) == 0); 9195a391b57SKyle Evans 9205a391b57SKyle Evans umask(restore_mask); 9215a391b57SKyle Evans } 92295aa96f3SKyle Evans 923f1040532SKyle Evans ATF_TC_WITHOUT_HEAD(fallocate); 924f1040532SKyle Evans ATF_TC_BODY(fallocate, tc) 925f1040532SKyle Evans { 926f1040532SKyle Evans struct stat st; 927f1040532SKyle Evans int error, fd, sz; 928f1040532SKyle Evans 929f1040532SKyle Evans /* 930f1040532SKyle Evans * Primitive test case for posix_fallocate with shmd. Effectively 931f1040532SKyle Evans * expected to work like a smarter ftruncate that will grow the region 932f1040532SKyle Evans * as needed in a race-free way. 933f1040532SKyle Evans */ 934f1040532SKyle Evans fd = shm_open(SHM_ANON, O_RDWR, 0666); 935f1040532SKyle Evans ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno); 936f1040532SKyle Evans /* Set the initial size. */ 937f1040532SKyle Evans sz = 32; 938f1040532SKyle Evans ATF_REQUIRE(ftruncate(fd, sz) == 0); 939f1040532SKyle Evans 940f1040532SKyle Evans /* Now grow it. */ 941f1040532SKyle Evans error = 0; 942f1040532SKyle Evans sz *= 2; 943f1040532SKyle Evans ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0, 944f1040532SKyle Evans "posix_fallocate failed; error=%d", error); 945f1040532SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 946f1040532SKyle Evans ATF_REQUIRE(st.st_size == sz); 947f1040532SKyle Evans /* Attempt to shrink it; should succeed, but not change the size. */ 948f1040532SKyle Evans ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0, 949f1040532SKyle Evans "posix_fallocate failed; error=%d", error); 950f1040532SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 951f1040532SKyle Evans ATF_REQUIRE(st.st_size == sz); 952f1040532SKyle Evans /* Grow it using an offset of sz and len of sz. */ 953f1040532SKyle Evans ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0, 954f1040532SKyle Evans "posix_fallocate failed; error=%d", error); 955f1040532SKyle Evans ATF_REQUIRE(fstat(fd, &st) == 0); 956f1040532SKyle Evans ATF_REQUIRE(st.st_size == (sz * 2)); 957f1040532SKyle Evans 958f1040532SKyle Evans close(fd); 959f1040532SKyle Evans } 960f1040532SKyle Evans 961*77ceadeeSMark Johnston static int 962*77ceadeeSMark Johnston shm_open_large(int psind, int policy, size_t sz) 963*77ceadeeSMark Johnston { 964*77ceadeeSMark Johnston int error, fd; 965*77ceadeeSMark Johnston 966*77ceadeeSMark Johnston fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, psind, policy, 0); 967*77ceadeeSMark Johnston if (fd < 0 && errno == ENOTTY) 968*77ceadeeSMark Johnston atf_tc_skip("no large page support"); 969*77ceadeeSMark Johnston ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno); 970*77ceadeeSMark Johnston 971*77ceadeeSMark Johnston error = ftruncate(fd, sz); 972*77ceadeeSMark Johnston if (error != 0 && errno == ENOMEM) 973*77ceadeeSMark Johnston /* 974*77ceadeeSMark Johnston * The test system might not have enough memory to accommodate 975*77ceadeeSMark Johnston * the request. 976*77ceadeeSMark Johnston */ 977*77ceadeeSMark Johnston atf_tc_skip("failed to allocate %zu-byte superpage", sz); 978*77ceadeeSMark Johnston ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno); 979*77ceadeeSMark Johnston 980*77ceadeeSMark Johnston return (fd); 981*77ceadeeSMark Johnston } 982*77ceadeeSMark Johnston 983*77ceadeeSMark Johnston static int 984*77ceadeeSMark Johnston pagesizes(size_t ps[MAXPAGESIZES]) 985*77ceadeeSMark Johnston { 986*77ceadeeSMark Johnston int pscnt; 987*77ceadeeSMark Johnston 988*77ceadeeSMark Johnston pscnt = getpagesizes(ps, MAXPAGESIZES); 989*77ceadeeSMark Johnston ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno); 990*77ceadeeSMark Johnston ATF_REQUIRE_MSG(ps[0] == PAGE_SIZE, "psind 0 is %zu", ps[0]); 991*77ceadeeSMark Johnston ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt); 992*77ceadeeSMark Johnston if (pscnt == 1) 993*77ceadeeSMark Johnston atf_tc_skip("no large page support"); 994*77ceadeeSMark Johnston return (pscnt); 995*77ceadeeSMark Johnston } 996*77ceadeeSMark Johnston 997*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_basic); 998*77ceadeeSMark Johnston ATF_TC_BODY(largepage_basic, tc) 999*77ceadeeSMark Johnston { 1000*77ceadeeSMark Johnston char zeroes[PAGE_SIZE]; 1001*77ceadeeSMark Johnston char *addr, *vec; 1002*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1003*77ceadeeSMark Johnston int error, fd, pscnt; 1004*77ceadeeSMark Johnston 1005*77ceadeeSMark Johnston memset(zeroes, 0, PAGE_SIZE); 1006*77ceadeeSMark Johnston 1007*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1008*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1009*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1010*77ceadeeSMark Johnston 1011*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1012*77ceadeeSMark Johnston 0); 1013*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1014*77ceadeeSMark Johnston "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1015*77ceadeeSMark Johnston ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0, 1016*77ceadeeSMark Johnston "mmap(%zu bytes) returned unaligned mapping; addr=%p", 1017*77ceadeeSMark Johnston ps[i], addr); 1018*77ceadeeSMark Johnston 1019*77ceadeeSMark Johnston /* Force a page fault. */ 1020*77ceadeeSMark Johnston *(volatile char *)addr = 0; 1021*77ceadeeSMark Johnston 1022*77ceadeeSMark Johnston vec = malloc(ps[i] / PAGE_SIZE); 1023*77ceadeeSMark Johnston ATF_REQUIRE(vec != NULL); 1024*77ceadeeSMark Johnston error = mincore(addr, ps[i], vec); 1025*77ceadeeSMark Johnston ATF_REQUIRE_MSG(error == 0, "mincore failed; errno=%d", errno); 1026*77ceadeeSMark Johnston 1027*77ceadeeSMark Johnston /* Verify that all pages in the run are mapped. */ 1028*77ceadeeSMark Johnston for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) { 1029*77ceadeeSMark Johnston ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0, 1030*77ceadeeSMark Johnston "page %zu is not mapped", p); 1031*77ceadeeSMark Johnston ATF_REQUIRE_MSG((vec[p] & MINCORE_PSIND(i)) != 0, 1032*77ceadeeSMark Johnston "page %zu is not in a %zu-byte superpage", 1033*77ceadeeSMark Johnston p, ps[i]); 1034*77ceadeeSMark Johnston } 1035*77ceadeeSMark Johnston 1036*77ceadeeSMark Johnston /* Validate zeroing. */ 1037*77ceadeeSMark Johnston for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) { 1038*77ceadeeSMark Johnston ATF_REQUIRE_MSG(memcmp(addr + p * PAGE_SIZE, zeroes, 1039*77ceadeeSMark Johnston PAGE_SIZE) == 0, "page %zu miscompare", p); 1040*77ceadeeSMark Johnston } 1041*77ceadeeSMark Johnston 1042*77ceadeeSMark Johnston free(vec); 1043*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1044*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1045*77ceadeeSMark Johnston } 1046*77ceadeeSMark Johnston } 1047*77ceadeeSMark Johnston 1048*77ceadeeSMark Johnston extern int __sys_shm_open2(const char *, int, mode_t, int, const char *); 1049*77ceadeeSMark Johnston 1050*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_config); 1051*77ceadeeSMark Johnston ATF_TC_BODY(largepage_config, tc) 1052*77ceadeeSMark Johnston { 1053*77ceadeeSMark Johnston struct shm_largepage_conf lpc; 1054*77ceadeeSMark Johnston char *addr, *buf; 1055*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES + 1]; /* silence warnings if MAXPAGESIZES == 1 */ 1056*77ceadeeSMark Johnston int error, fd, pscnt; 1057*77ceadeeSMark Johnston 1058*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1059*77ceadeeSMark Johnston 1060*77ceadeeSMark Johnston fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0); 1061*77ceadeeSMark Johnston ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1062*77ceadeeSMark Johnston 1063*77ceadeeSMark Johnston /* 1064*77ceadeeSMark Johnston * Configure a large page policy for an object created without 1065*77ceadeeSMark Johnston * SHM_LARGEPAGE. 1066*77ceadeeSMark Johnston */ 1067*77ceadeeSMark Johnston lpc.psind = 1; 1068*77ceadeeSMark Johnston lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT; 1069*77ceadeeSMark Johnston error = ioctl(fd, FIOSSHMLPGCNF, &lpc); 1070*77ceadeeSMark Johnston ATF_REQUIRE(error != 0); 1071*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d", 1072*77ceadeeSMark Johnston errno); 1073*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1074*77ceadeeSMark Johnston 1075*77ceadeeSMark Johnston /* 1076*77ceadeeSMark Johnston * Create a largepage object and try to use it without actually 1077*77ceadeeSMark Johnston * configuring anything. 1078*77ceadeeSMark Johnston */ 1079*77ceadeeSMark Johnston fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE, 1080*77ceadeeSMark Johnston NULL); 1081*77ceadeeSMark Johnston if (fd < 0 && errno == ENOTTY) 1082*77ceadeeSMark Johnston atf_tc_skip("no large page support"); 1083*77ceadeeSMark Johnston ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno); 1084*77ceadeeSMark Johnston 1085*77ceadeeSMark Johnston error = ftruncate(fd, ps[1]); 1086*77ceadeeSMark Johnston ATF_REQUIRE(error != 0); 1087*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno); 1088*77ceadeeSMark Johnston 1089*77ceadeeSMark Johnston addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1090*77ceadeeSMark Johnston ATF_REQUIRE(addr == MAP_FAILED); 1091*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1092*77ceadeeSMark Johnston addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1093*77ceadeeSMark Johnston ATF_REQUIRE(addr == MAP_FAILED); 1094*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1095*77ceadeeSMark Johnston 1096*77ceadeeSMark Johnston buf = calloc(1, PAGE_SIZE); 1097*77ceadeeSMark Johnston ATF_REQUIRE(buf != NULL); 1098*77ceadeeSMark Johnston ATF_REQUIRE(write(fd, buf, PAGE_SIZE) == -1); 1099*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1100*77ceadeeSMark Johnston free(buf); 1101*77ceadeeSMark Johnston buf = calloc(1, ps[1]); 1102*77ceadeeSMark Johnston ATF_REQUIRE(buf != NULL); 1103*77ceadeeSMark Johnston ATF_REQUIRE(write(fd, buf, ps[1]) == -1); 1104*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno); 1105*77ceadeeSMark Johnston free(buf); 1106*77ceadeeSMark Johnston 1107*77ceadeeSMark Johnston error = posix_fallocate(fd, 0, PAGE_SIZE); 1108*77ceadeeSMark Johnston ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error); 1109*77ceadeeSMark Johnston 1110*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1111*77ceadeeSMark Johnston } 1112*77ceadeeSMark Johnston 1113*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_mmap); 1114*77ceadeeSMark Johnston ATF_TC_BODY(largepage_mmap, tc) 1115*77ceadeeSMark Johnston { 1116*77ceadeeSMark Johnston char *addr, *addr1, *vec; 1117*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1118*77ceadeeSMark Johnston int fd, pscnt; 1119*77ceadeeSMark Johnston 1120*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1121*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1122*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1123*77ceadeeSMark Johnston 1124*77ceadeeSMark Johnston /* For mincore(). */ 1125*77ceadeeSMark Johnston vec = malloc(ps[i]); 1126*77ceadeeSMark Johnston ATF_REQUIRE(vec != NULL); 1127*77ceadeeSMark Johnston 1128*77ceadeeSMark Johnston /* 1129*77ceadeeSMark Johnston * Wrong mapping size. 1130*77ceadeeSMark Johnston */ 1131*77ceadeeSMark Johnston addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED, 1132*77ceadeeSMark Johnston fd, 0); 1133*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr == MAP_FAILED, 1134*77ceadeeSMark Johnston "mmap(%zu bytes) succeeded", ps[i - 1]); 1135*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1136*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i - 1], errno); 1137*77ceadeeSMark Johnston 1138*77ceadeeSMark Johnston /* 1139*77ceadeeSMark Johnston * Fixed mappings. 1140*77ceadeeSMark Johnston */ 1141*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1142*77ceadeeSMark Johnston 0); 1143*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1144*77ceadeeSMark Johnston "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1145*77ceadeeSMark Johnston ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0, 1146*77ceadeeSMark Johnston "mmap(%zu bytes) returned unaligned mapping; addr=%p", 1147*77ceadeeSMark Johnston ps[i], addr); 1148*77ceadeeSMark Johnston 1149*77ceadeeSMark Johnston /* Try mapping a small page with anonymous memory. */ 1150*77ceadeeSMark Johnston addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE, 1151*77ceadeeSMark Johnston MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0); 1152*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1153*77ceadeeSMark Johnston "anon mmap(%zu bytes) succeeded", ps[i - 1]); 1154*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno); 1155*77ceadeeSMark Johnston 1156*77ceadeeSMark Johnston /* Check MAP_EXCL when creating a second largepage mapping. */ 1157*77ceadeeSMark Johnston addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1158*77ceadeeSMark Johnston MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1159*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr1 == MAP_FAILED, 1160*77ceadeeSMark Johnston "mmap(%zu bytes) succeeded", ps[i]); 1161*77ceadeeSMark Johnston /* XXX wrong errno */ 1162*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno); 1163*77ceadeeSMark Johnston 1164*77ceadeeSMark Johnston /* Overwrite a largepage mapping with a lagepage mapping. */ 1165*77ceadeeSMark Johnston addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE, 1166*77ceadeeSMark Johnston MAP_SHARED | MAP_FIXED, fd, 0); 1167*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1168*77ceadeeSMark Johnston "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1169*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr == addr1, 1170*77ceadeeSMark Johnston "mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1); 1171*77ceadeeSMark Johnston 1172*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i] == 0)); 1173*77ceadeeSMark Johnston 1174*77ceadeeSMark Johnston /* Clobber an anonymous mapping with a superpage. */ 1175*77ceadeeSMark Johnston addr1 = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, 1176*77ceadeeSMark Johnston MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 1177*77ceadeeSMark Johnston 0); 1178*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1179*77ceadeeSMark Johnston "mmap failed; error=%d", errno); 1180*77ceadeeSMark Johnston *(volatile char *)addr1 = '\0'; 1181*77ceadeeSMark Johnston addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE, 1182*77ceadeeSMark Johnston MAP_SHARED | MAP_FIXED, fd, 0); 1183*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1184*77ceadeeSMark Johnston "mmap failed; error=%d", errno); 1185*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr == addr1, 1186*77ceadeeSMark Johnston "mmap disobeyed MAP_FIXED, %p %p", addr, addr1); 1187*77ceadeeSMark Johnston *(volatile char *)addr = 0; /* fault */ 1188*77ceadeeSMark Johnston ATF_REQUIRE(mincore(addr, ps[i], vec) == 0); 1189*77ceadeeSMark Johnston for (size_t p = 0; p < ps[i] / PAGE_SIZE; p++) { 1190*77ceadeeSMark Johnston ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0, 1191*77ceadeeSMark Johnston "page %zu is not resident", p); 1192*77ceadeeSMark Johnston ATF_REQUIRE_MSG((vec[p] & MINCORE_PSIND(i)) != 0, 1193*77ceadeeSMark Johnston "page %zu is not resident", p); 1194*77ceadeeSMark Johnston } 1195*77ceadeeSMark Johnston 1196*77ceadeeSMark Johnston /* 1197*77ceadeeSMark Johnston * Copy-on-write mappings are not permitted. 1198*77ceadeeSMark Johnston */ 1199*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE, 1200*77ceadeeSMark Johnston fd, 0); 1201*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr == MAP_FAILED, 1202*77ceadeeSMark Johnston "mmap(%zu bytes) succeeded", ps[i]); 1203*77ceadeeSMark Johnston 1204*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1205*77ceadeeSMark Johnston } 1206*77ceadeeSMark Johnston } 1207*77ceadeeSMark Johnston 1208*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_munmap); 1209*77ceadeeSMark Johnston ATF_TC_BODY(largepage_munmap, tc) 1210*77ceadeeSMark Johnston { 1211*77ceadeeSMark Johnston char *addr; 1212*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES], ps1; 1213*77ceadeeSMark Johnston int fd, pscnt; 1214*77ceadeeSMark Johnston 1215*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1216*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1217*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1218*77ceadeeSMark Johnston ps1 = ps[i - 1]; 1219*77ceadeeSMark Johnston 1220*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1221*77ceadeeSMark Johnston 0); 1222*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1223*77ceadeeSMark Johnston "mmap(%zu bytes) failed; errno=%d", ps[i], errno); 1224*77ceadeeSMark Johnston 1225*77ceadeeSMark Johnston /* Try several unaligned munmap() requests. */ 1226*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps1) != 0); 1227*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1228*77ceadeeSMark Johnston "unexpected error %d from munmap", errno); 1229*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i] - ps1)); 1230*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1231*77ceadeeSMark Johnston "unexpected error %d from munmap", errno); 1232*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr + ps1, ps1) != 0); 1233*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1234*77ceadeeSMark Johnston "unexpected error %d from munmap", errno); 1235*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, 0)); 1236*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1237*77ceadeeSMark Johnston "unexpected error %d from munmap", errno); 1238*77ceadeeSMark Johnston 1239*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1240*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1241*77ceadeeSMark Johnston } 1242*77ceadeeSMark Johnston } 1243*77ceadeeSMark Johnston 1244*77ceadeeSMark Johnston static void 1245*77ceadeeSMark Johnston largepage_madvise(char *addr, size_t sz, int advice, int error) 1246*77ceadeeSMark Johnston { 1247*77ceadeeSMark Johnston if (error == 0) { 1248*77ceadeeSMark Johnston ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0, 1249*77ceadeeSMark Johnston "madvise(%zu, %d) failed; error=%d", sz, advice, errno); 1250*77ceadeeSMark Johnston } else { 1251*77ceadeeSMark Johnston ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0, 1252*77ceadeeSMark Johnston "madvise(%zu, %d) succeeded", sz, advice); 1253*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == error, 1254*77ceadeeSMark Johnston "unexpected error %d from madvise(%zu, %d)", 1255*77ceadeeSMark Johnston errno, sz, advice); 1256*77ceadeeSMark Johnston } 1257*77ceadeeSMark Johnston } 1258*77ceadeeSMark Johnston 1259*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_madvise); 1260*77ceadeeSMark Johnston ATF_TC_BODY(largepage_madvise, tc) 1261*77ceadeeSMark Johnston { 1262*77ceadeeSMark Johnston char *addr; 1263*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1264*77ceadeeSMark Johnston int fd, pscnt; 1265*77ceadeeSMark Johnston 1266*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1267*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1268*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1269*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1270*77ceadeeSMark Johnston 0); 1271*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1272*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1273*77ceadeeSMark Johnston 1274*77ceadeeSMark Johnston /* Advice that requires clipping. */ 1275*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_NORMAL, EINVAL); 1276*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_NORMAL, 0); 1277*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_RANDOM, EINVAL); 1278*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_RANDOM, 0); 1279*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_SEQUENTIAL, EINVAL); 1280*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0); 1281*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_NOSYNC, EINVAL); 1282*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_NOSYNC, 0); 1283*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_AUTOSYNC, EINVAL); 1284*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0); 1285*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_CORE, EINVAL); 1286*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_CORE, 0); 1287*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_NOCORE, EINVAL); 1288*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_NOCORE, 0); 1289*77ceadeeSMark Johnston 1290*77ceadeeSMark Johnston /* Advice that does not result in clipping. */ 1291*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_DONTNEED, 0); 1292*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_DONTNEED, 0); 1293*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_WILLNEED, 0); 1294*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_WILLNEED, 0); 1295*77ceadeeSMark Johnston largepage_madvise(addr, PAGE_SIZE, MADV_FREE, 0); 1296*77ceadeeSMark Johnston largepage_madvise(addr, ps[i], MADV_FREE, 0); 1297*77ceadeeSMark Johnston 1298*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1299*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1300*77ceadeeSMark Johnston } 1301*77ceadeeSMark Johnston } 1302*77ceadeeSMark Johnston 1303*77ceadeeSMark Johnston ATF_TC(largepage_mlock); 1304*77ceadeeSMark Johnston ATF_TC_HEAD(largepage_mlock, tc) 1305*77ceadeeSMark Johnston { 1306*77ceadeeSMark Johnston /* Needed to set rlimit. */ 1307*77ceadeeSMark Johnston atf_tc_set_md_var(tc, "require.user", "root"); 1308*77ceadeeSMark Johnston } 1309*77ceadeeSMark Johnston ATF_TC_BODY(largepage_mlock, tc) 1310*77ceadeeSMark Johnston { 1311*77ceadeeSMark Johnston struct rlimit rl; 1312*77ceadeeSMark Johnston char *addr; 1313*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES], sz; 1314*77ceadeeSMark Johnston u_long max_wired, wired; 1315*77ceadeeSMark Johnston int fd, error, pscnt; 1316*77ceadeeSMark Johnston 1317*77ceadeeSMark Johnston rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; 1318*77ceadeeSMark Johnston ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0, 1319*77ceadeeSMark Johnston "setrlimit failed; error=%d", errno); 1320*77ceadeeSMark Johnston 1321*77ceadeeSMark Johnston sz = sizeof(max_wired); 1322*77ceadeeSMark Johnston error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0); 1323*77ceadeeSMark Johnston ATF_REQUIRE_MSG(error == 0, 1324*77ceadeeSMark Johnston "sysctlbyname(vm.max_user_wired) failed; error=%d", errno); 1325*77ceadeeSMark Johnston ATF_REQUIRE(max_wired >= 0); 1326*77ceadeeSMark Johnston 1327*77ceadeeSMark Johnston sz = sizeof(wired); 1328*77ceadeeSMark Johnston error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL, 1329*77ceadeeSMark Johnston 0); 1330*77ceadeeSMark Johnston ATF_REQUIRE_MSG(error == 0, 1331*77ceadeeSMark Johnston "sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d", 1332*77ceadeeSMark Johnston errno); 1333*77ceadeeSMark Johnston ATF_REQUIRE(wired >= 0); 1334*77ceadeeSMark Johnston 1335*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1336*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1337*77ceadeeSMark Johnston if (ps[i] / PAGE_SIZE > max_wired - wired) { 1338*77ceadeeSMark Johnston /* Cannot wire past the limit. */ 1339*77ceadeeSMark Johnston atf_tc_skip("test would exceed wiring limit"); 1340*77ceadeeSMark Johnston } 1341*77ceadeeSMark Johnston 1342*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1343*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1344*77ceadeeSMark Johnston 0); 1345*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1346*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1347*77ceadeeSMark Johnston 1348*77ceadeeSMark Johnston ATF_REQUIRE(mlock(addr, PAGE_SIZE) != 0); 1349*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1350*77ceadeeSMark Johnston "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1351*77ceadeeSMark Johnston ATF_REQUIRE(mlock(addr, ps[i] - PAGE_SIZE) != 0); 1352*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EINVAL, 1353*77ceadeeSMark Johnston "unexpected error %d from mlock(%zu bytes)", errno, ps[i]); 1354*77ceadeeSMark Johnston 1355*77ceadeeSMark Johnston ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0, 1356*77ceadeeSMark Johnston "mlock failed; error=%d", errno); 1357*77ceadeeSMark Johnston 1358*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1359*77ceadeeSMark Johnston 1360*77ceadeeSMark Johnston ATF_REQUIRE(mlockall(MCL_FUTURE) == 0); 1361*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1362*77ceadeeSMark Johnston 0); 1363*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1364*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1365*77ceadeeSMark Johnston 1366*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1367*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1368*77ceadeeSMark Johnston } 1369*77ceadeeSMark Johnston } 1370*77ceadeeSMark Johnston 1371*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_msync); 1372*77ceadeeSMark Johnston ATF_TC_BODY(largepage_msync, tc) 1373*77ceadeeSMark Johnston { 1374*77ceadeeSMark Johnston char *addr; 1375*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1376*77ceadeeSMark Johnston int fd, pscnt; 1377*77ceadeeSMark Johnston 1378*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1379*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1380*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1381*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1382*77ceadeeSMark Johnston 0); 1383*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1384*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1385*77ceadeeSMark Johnston 1386*77ceadeeSMark Johnston memset(addr, 0, ps[i]); 1387*77ceadeeSMark Johnston 1388*77ceadeeSMark Johnston /* 1389*77ceadeeSMark Johnston * "Sync" requests are no-ops for SHM objects, so small 1390*77ceadeeSMark Johnston * PAGE_SIZE-sized requests succeed. 1391*77ceadeeSMark Johnston */ 1392*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_ASYNC) == 0, 1393*77ceadeeSMark Johnston "msync(MS_ASYNC) failed; error=%d", errno); 1394*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0, 1395*77ceadeeSMark Johnston "msync(MS_ASYNC) failed; error=%d", errno); 1396*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_SYNC) == 0, 1397*77ceadeeSMark Johnston "msync(MS_SYNC) failed; error=%d", errno); 1398*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0, 1399*77ceadeeSMark Johnston "msync(MS_SYNC) failed; error=%d", errno); 1400*77ceadeeSMark Johnston 1401*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, PAGE_SIZE, MS_INVALIDATE) != 0, 1402*77ceadeeSMark Johnston "msync(MS_INVALIDATE) succeeded"); 1403*77ceadeeSMark Johnston /* XXX wrong errno */ 1404*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == EBUSY, 1405*77ceadeeSMark Johnston "unexpected error %d from msync(MS_INVALIDATE)", errno); 1406*77ceadeeSMark Johnston ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0, 1407*77ceadeeSMark Johnston "msync(MS_INVALIDATE) failed; error=%d", errno); 1408*77ceadeeSMark Johnston memset(addr, 0, ps[i]); 1409*77ceadeeSMark Johnston 1410*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1411*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1412*77ceadeeSMark Johnston } 1413*77ceadeeSMark Johnston } 1414*77ceadeeSMark Johnston 1415*77ceadeeSMark Johnston static void 1416*77ceadeeSMark Johnston largepage_protect(char *addr, size_t sz, int prot, int error) 1417*77ceadeeSMark Johnston { 1418*77ceadeeSMark Johnston if (error == 0) { 1419*77ceadeeSMark Johnston ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0, 1420*77ceadeeSMark Johnston "mprotect(%zu, %x) failed; error=%d", sz, prot, errno); 1421*77ceadeeSMark Johnston } else { 1422*77ceadeeSMark Johnston ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0, 1423*77ceadeeSMark Johnston "mprotect(%zu, %x) succeeded", sz, prot); 1424*77ceadeeSMark Johnston ATF_REQUIRE_MSG(errno == error, 1425*77ceadeeSMark Johnston "unexpected error %d from mprotect(%zu, %x)", 1426*77ceadeeSMark Johnston errno, sz, prot); 1427*77ceadeeSMark Johnston } 1428*77ceadeeSMark Johnston } 1429*77ceadeeSMark Johnston 1430*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_mprotect); 1431*77ceadeeSMark Johnston ATF_TC_BODY(largepage_mprotect, tc) 1432*77ceadeeSMark Johnston { 1433*77ceadeeSMark Johnston char *addr, *addr1; 1434*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1435*77ceadeeSMark Johnston int fd, pscnt; 1436*77ceadeeSMark Johnston 1437*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1438*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1439*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1440*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1441*77ceadeeSMark Johnston 0); 1442*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1443*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1444*77ceadeeSMark Johnston 1445*77ceadeeSMark Johnston /* 1446*77ceadeeSMark Johnston * These should be no-ops from the pmap perspective since the 1447*77ceadeeSMark Johnston * page is not yet entered into the pmap. 1448*77ceadeeSMark Johnston */ 1449*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL); 1450*77ceadeeSMark Johnston largepage_protect(addr, ps[i], PROT_READ, 0); 1451*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL); 1452*77ceadeeSMark Johnston largepage_protect(addr, ps[i], PROT_NONE, 0); 1453*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, 1454*77ceadeeSMark Johnston PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1455*77ceadeeSMark Johnston largepage_protect(addr, ps[i], 1456*77ceadeeSMark Johnston PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1457*77ceadeeSMark Johnston 1458*77ceadeeSMark Johnston /* Trigger creation of a mapping and try again. */ 1459*77ceadeeSMark Johnston *(volatile char *)addr = 0; 1460*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, PROT_READ, EINVAL); 1461*77ceadeeSMark Johnston largepage_protect(addr, ps[i], PROT_READ, 0); 1462*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, PROT_NONE, EINVAL); 1463*77ceadeeSMark Johnston largepage_protect(addr, ps[i], PROT_NONE, 0); 1464*77ceadeeSMark Johnston largepage_protect(addr, PAGE_SIZE, 1465*77ceadeeSMark Johnston PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL); 1466*77ceadeeSMark Johnston largepage_protect(addr, ps[i], 1467*77ceadeeSMark Johnston PROT_READ | PROT_WRITE | PROT_EXEC, 0); 1468*77ceadeeSMark Johnston 1469*77ceadeeSMark Johnston memset(addr, 0, ps[i]); 1470*77ceadeeSMark Johnston 1471*77ceadeeSMark Johnston /* Map two contiguous large pages and merge map entries. */ 1472*77ceadeeSMark Johnston addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE, 1473*77ceadeeSMark Johnston MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0); 1474*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr1 != MAP_FAILED, 1475*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1476*77ceadeeSMark Johnston 1477*77ceadeeSMark Johnston largepage_protect(addr1 - PAGE_SIZE, PAGE_SIZE * 2, 1478*77ceadeeSMark Johnston PROT_READ | PROT_WRITE, EINVAL); 1479*77ceadeeSMark Johnston largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0); 1480*77ceadeeSMark Johnston 1481*77ceadeeSMark Johnston memset(addr, 0, ps[i] * 2); 1482*77ceadeeSMark Johnston 1483*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1484*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr1, ps[i]) == 0); 1485*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1486*77ceadeeSMark Johnston } 1487*77ceadeeSMark Johnston } 1488*77ceadeeSMark Johnston 1489*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_minherit); 1490*77ceadeeSMark Johnston ATF_TC_BODY(largepage_minherit, tc) 1491*77ceadeeSMark Johnston { 1492*77ceadeeSMark Johnston char *addr; 1493*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1494*77ceadeeSMark Johnston pid_t child; 1495*77ceadeeSMark Johnston int fd, pscnt, status; 1496*77ceadeeSMark Johnston 1497*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1498*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1499*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1500*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1501*77ceadeeSMark Johnston 0); 1502*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1503*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1504*77ceadeeSMark Johnston 1505*77ceadeeSMark Johnston ATF_REQUIRE(minherit(addr, PAGE_SIZE, INHERIT_SHARE) != 0); 1506*77ceadeeSMark Johnston 1507*77ceadeeSMark Johnston ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0, 1508*77ceadeeSMark Johnston "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1509*77ceadeeSMark Johnston child = fork(); 1510*77ceadeeSMark Johnston ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1511*77ceadeeSMark Johnston if (child == 0) { 1512*77ceadeeSMark Johnston char v; 1513*77ceadeeSMark Johnston 1514*77ceadeeSMark Johnston *(volatile char *)addr = 0; 1515*77ceadeeSMark Johnston if (mincore(addr, PAGE_SIZE, &v) != 0) 1516*77ceadeeSMark Johnston _exit(1); 1517*77ceadeeSMark Johnston if ((v & MINCORE_PSIND(i)) == 0) 1518*77ceadeeSMark Johnston _exit(2); 1519*77ceadeeSMark Johnston _exit(0); 1520*77ceadeeSMark Johnston } 1521*77ceadeeSMark Johnston ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1522*77ceadeeSMark Johnston "waitpid failed; error=%d", errno); 1523*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WIFEXITED(status), 1524*77ceadeeSMark Johnston "child was killed by signal %d", WTERMSIG(status)); 1525*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1526*77ceadeeSMark Johnston "child exited with status %d", WEXITSTATUS(status)); 1527*77ceadeeSMark Johnston 1528*77ceadeeSMark Johnston ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0, 1529*77ceadeeSMark Johnston "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1530*77ceadeeSMark Johnston child = fork(); 1531*77ceadeeSMark Johnston ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1532*77ceadeeSMark Johnston if (child == 0) { 1533*77ceadeeSMark Johnston char v; 1534*77ceadeeSMark Johnston 1535*77ceadeeSMark Johnston if (mincore(addr, PAGE_SIZE, &v) == 0) 1536*77ceadeeSMark Johnston _exit(1); 1537*77ceadeeSMark Johnston _exit(0); 1538*77ceadeeSMark Johnston } 1539*77ceadeeSMark Johnston ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1540*77ceadeeSMark Johnston "waitpid failed; error=%d", errno); 1541*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WIFEXITED(status), 1542*77ceadeeSMark Johnston "child was killed by signal %d", WTERMSIG(status)); 1543*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1544*77ceadeeSMark Johnston "child exited with status %d", WEXITSTATUS(status)); 1545*77ceadeeSMark Johnston 1546*77ceadeeSMark Johnston /* Copy-on-write is not supported for static large pages. */ 1547*77ceadeeSMark Johnston ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0, 1548*77ceadeeSMark Johnston "minherit(%zu bytes) succeeded", ps[i]); 1549*77ceadeeSMark Johnston 1550*77ceadeeSMark Johnston ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0, 1551*77ceadeeSMark Johnston "minherit(%zu bytes) failed; error=%d", ps[i], errno); 1552*77ceadeeSMark Johnston child = fork(); 1553*77ceadeeSMark Johnston ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno); 1554*77ceadeeSMark Johnston if (child == 0) { 1555*77ceadeeSMark Johnston char v; 1556*77ceadeeSMark Johnston 1557*77ceadeeSMark Johnston *(volatile char *)addr = 0; 1558*77ceadeeSMark Johnston if (mincore(addr, PAGE_SIZE, &v) != 0) 1559*77ceadeeSMark Johnston _exit(1); 1560*77ceadeeSMark Johnston if ((v & MINCORE_SUPER) != 0) 1561*77ceadeeSMark Johnston _exit(2); 1562*77ceadeeSMark Johnston _exit(0); 1563*77ceadeeSMark Johnston } 1564*77ceadeeSMark Johnston ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1565*77ceadeeSMark Johnston "waitpid failed; error=%d", errno); 1566*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WIFEXITED(status), 1567*77ceadeeSMark Johnston "child was killed by signal %d", WTERMSIG(status)); 1568*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1569*77ceadeeSMark Johnston "child exited with status %d", WEXITSTATUS(status)); 1570*77ceadeeSMark Johnston 1571*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1572*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1573*77ceadeeSMark Johnston } 1574*77ceadeeSMark Johnston } 1575*77ceadeeSMark Johnston 1576*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_pipe); 1577*77ceadeeSMark Johnston ATF_TC_BODY(largepage_pipe, tc) 1578*77ceadeeSMark Johnston { 1579*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1580*77ceadeeSMark Johnston char *addr; 1581*77ceadeeSMark Johnston ssize_t len; 1582*77ceadeeSMark Johnston int fd, pfd[2], pscnt, status; 1583*77ceadeeSMark Johnston pid_t child; 1584*77ceadeeSMark Johnston 1585*77ceadeeSMark Johnston pscnt = pagesizes(ps); 1586*77ceadeeSMark Johnston 1587*77ceadeeSMark Johnston for (int i = 1; i < pscnt; i++) { 1588*77ceadeeSMark Johnston fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]); 1589*77ceadeeSMark Johnston addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 1590*77ceadeeSMark Johnston 0); 1591*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, 1592*77ceadeeSMark Johnston "mmap(%zu bytes) failed; error=%d", ps[i], errno); 1593*77ceadeeSMark Johnston 1594*77ceadeeSMark Johnston /* Trigger creation of a mapping. */ 1595*77ceadeeSMark Johnston *(volatile char *)addr = '\0'; 1596*77ceadeeSMark Johnston 1597*77ceadeeSMark Johnston ATF_REQUIRE(pipe(pfd) == 0); 1598*77ceadeeSMark Johnston child = fork(); 1599*77ceadeeSMark Johnston ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno); 1600*77ceadeeSMark Johnston if (child == 0) { 1601*77ceadeeSMark Johnston char buf[BUFSIZ]; 1602*77ceadeeSMark Johnston ssize_t resid; 1603*77ceadeeSMark Johnston 1604*77ceadeeSMark Johnston (void)close(pfd[0]); 1605*77ceadeeSMark Johnston for (resid = (size_t)ps[i]; resid > 0; resid -= len) { 1606*77ceadeeSMark Johnston len = read(pfd[1], buf, sizeof(buf)); 1607*77ceadeeSMark Johnston if (len < 0) 1608*77ceadeeSMark Johnston _exit(1); 1609*77ceadeeSMark Johnston } 1610*77ceadeeSMark Johnston _exit(0); 1611*77ceadeeSMark Johnston } 1612*77ceadeeSMark Johnston ATF_REQUIRE(close(pfd[1]) == 0); 1613*77ceadeeSMark Johnston len = write(pfd[0], addr, ps[i]); 1614*77ceadeeSMark Johnston ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno); 1615*77ceadeeSMark Johnston ATF_REQUIRE_MSG(len == (ssize_t)ps[i], 1616*77ceadeeSMark Johnston "short write; len=%zd", len); 1617*77ceadeeSMark Johnston ATF_REQUIRE(close(pfd[0]) == 0); 1618*77ceadeeSMark Johnston 1619*77ceadeeSMark Johnston ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child, 1620*77ceadeeSMark Johnston "waitpid() failed; error=%d", errno); 1621*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WIFEXITED(status), 1622*77ceadeeSMark Johnston "child was killed by signal %d", WTERMSIG(status)); 1623*77ceadeeSMark Johnston ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0, 1624*77ceadeeSMark Johnston "child exited with status %d", WEXITSTATUS(status)); 1625*77ceadeeSMark Johnston 1626*77ceadeeSMark Johnston ATF_REQUIRE(munmap(addr, ps[i]) == 0); 1627*77ceadeeSMark Johnston ATF_REQUIRE(close(fd) == 0); 1628*77ceadeeSMark Johnston } 1629*77ceadeeSMark Johnston } 1630*77ceadeeSMark Johnston 1631*77ceadeeSMark Johnston ATF_TC_WITHOUT_HEAD(largepage_reopen); 1632*77ceadeeSMark Johnston ATF_TC_BODY(largepage_reopen, tc) 1633*77ceadeeSMark Johnston { 1634*77ceadeeSMark Johnston char *addr, *vec; 1635*77ceadeeSMark Johnston size_t ps[MAXPAGESIZES]; 1636*77ceadeeSMark Johnston int fd, psind; 1637*77ceadeeSMark Johnston 1638*77ceadeeSMark Johnston (void)pagesizes(ps); 1639*77ceadeeSMark Johnston psind = 1; 1640*77ceadeeSMark Johnston 1641*77ceadeeSMark Johnston gen_test_path(); 1642*77ceadeeSMark Johnston fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind, 1643*77ceadeeSMark Johnston SHM_LARGEPAGE_ALLOC_DEFAULT, 0600); 1644*77ceadeeSMark Johnston if (fd < 0 && errno == ENOTTY) 1645*77ceadeeSMark Johnston atf_tc_skip("no large page support"); 1646*77ceadeeSMark Johnston ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno); 1647*77ceadeeSMark Johnston 1648*77ceadeeSMark Johnston ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0, 1649*77ceadeeSMark Johnston "ftruncate failed; error=%d", errno); 1650*77ceadeeSMark Johnston 1651*77ceadeeSMark Johnston ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno); 1652*77ceadeeSMark Johnston 1653*77ceadeeSMark Johnston fd = shm_open(test_path, O_RDWR, 0); 1654*77ceadeeSMark Johnston ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno); 1655*77ceadeeSMark Johnston 1656*77ceadeeSMark Johnston addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 1657*77ceadeeSMark Johnston ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno); 1658*77ceadeeSMark Johnston 1659*77ceadeeSMark Johnston /* Trigger a fault and mapping creation. */ 1660*77ceadeeSMark Johnston *(volatile char *)addr = 0; 1661*77ceadeeSMark Johnston 1662*77ceadeeSMark Johnston vec = malloc(ps[psind] / PAGE_SIZE); 1663*77ceadeeSMark Johnston ATF_REQUIRE(vec != NULL); 1664*77ceadeeSMark Johnston ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0, 1665*77ceadeeSMark Johnston "mincore failed; error=%d", errno); 1666*77ceadeeSMark Johnston ATF_REQUIRE_MSG((vec[0] & MINCORE_PSIND(psind)) != 0, 1667*77ceadeeSMark Johnston "page not mapped into a %zu-byte superpage", ps[psind]); 1668*77ceadeeSMark Johnston 1669*77ceadeeSMark Johnston ATF_REQUIRE_MSG(shm_unlink(test_path) == 0, 1670*77ceadeeSMark Johnston "shm_unlink failed; errno=%d", errno); 1671*77ceadeeSMark Johnston ATF_REQUIRE_MSG(close(fd) == 0, 1672*77ceadeeSMark Johnston "close failed; errno=%d", errno); 1673*77ceadeeSMark Johnston } 1674*77ceadeeSMark Johnston 16754fdc3d75SEnji Cooper ATF_TP_ADD_TCS(tp) 16764fdc3d75SEnji Cooper { 16774fdc3d75SEnji Cooper 16784fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, remap_object); 16799afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_from_anon); 16809afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_bad_path_pointer); 16819afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_from_nonexisting); 16829afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_anon); 16839afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_replace); 16849afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_noreplace); 16859afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_exchange); 16869afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting); 16879afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_to_self); 16889afb12baSDavid Bright ATF_TP_ADD_TC(tp, rename_bad_flag); 16894fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, reopen_object); 16904fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, readonly_mmap_write); 16914fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_after_link); 16924fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_invalid_path); 16934fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_write_only); 16944fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_extra_flags); 16954fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon); 16964fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_anon_readonly); 16974fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_bad_path_pointer); 16984fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_path_too_long); 16994fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_nonexisting_object); 17004fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, open_create_existing_object); 17014fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, shm_functionality_across_fork); 17024fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, trunc_resets_object); 17034fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_bad_path_pointer); 17044fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, unlink_path_too_long); 17054fdc3d75SEnji Cooper ATF_TP_ADD_TC(tp, object_resize); 170695aa96f3SKyle Evans ATF_TP_ADD_TC(tp, cloexec); 17075a391b57SKyle Evans ATF_TP_ADD_TC(tp, mode); 1708f1040532SKyle Evans ATF_TP_ADD_TC(tp, fallocate); 1709*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_basic); 1710*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_config); 1711*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_mmap); 1712*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_munmap); 1713*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_madvise); 1714*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_mlock); 1715*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_msync); 1716*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_mprotect); 1717*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_minherit); 1718*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_pipe); 1719*77ceadeeSMark Johnston ATF_TP_ADD_TC(tp, largepage_reopen); 17204fdc3d75SEnji Cooper 17214fdc3d75SEnji Cooper return (atf_no_error()); 17224fdc3d75SEnji Cooper } 1723