Path: blob/main/tests/sys/posixshm/posixshm_test.c
39534 views
/*-1* Copyright (c) 2006 Robert N. M. Watson2* All rights reserved.3*4* Copyright (c) 2021 The FreeBSD Foundation5*6* Portions of this software were developed by Ka Ho Ng7* under sponsorship from the FreeBSD Foundation.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*/3031#include <sys/param.h>32#include <sys/ioctl.h>33#include <sys/mman.h>34#include <sys/resource.h>35#include <sys/stat.h>36#include <sys/syscall.h>37#include <sys/sysctl.h>38#include <sys/wait.h>3940#include <ctype.h>41#include <errno.h>42#include <fcntl.h>43#include <signal.h>44#include <stdio.h>45#include <stdlib.h>46#include <string.h>47#include <unistd.h>4849#include <atf-c.h>5051#define TEST_PATH_LEN 25652static char test_path[TEST_PATH_LEN];53static char test_path2[TEST_PATH_LEN];54static unsigned int test_path_idx = 0;5556static void57gen_a_test_path(char *path)58{59snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d",60getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"),61test_path_idx);6263test_path_idx++;6465ATF_REQUIRE_MSG(mkstemp(path) != -1,66"mkstemp failed; errno=%d", errno);67ATF_REQUIRE_MSG(unlink(path) == 0,68"unlink failed; errno=%d", errno);69}7071static void72gen_test_path(void)73{74gen_a_test_path(test_path);75}7677static void78gen_test_path2(void)79{80gen_a_test_path(test_path2);81}8283/*84* Attempt a shm_open() that should fail with an expected error of 'error'.85*/86static void87shm_open_should_fail(const char *path, int flags, mode_t mode, int error)88{89int fd;9091fd = shm_open(path, flags, mode);92ATF_CHECK_MSG(fd == -1, "shm_open didn't fail");93ATF_CHECK_MSG(error == errno,94"shm_open didn't fail with expected errno; errno=%d; expected "95"errno=%d", errno, error);96}9798/*99* Attempt a shm_unlink() that should fail with an expected error of 'error'.100*/101static void102shm_unlink_should_fail(const char *path, int error)103{104105ATF_CHECK_MSG(shm_unlink(path) == -1, "shm_unlink didn't fail");106ATF_CHECK_MSG(error == errno,107"shm_unlink didn't fail with expected errno; errno=%d; expected "108"errno=%d", errno, error);109}110111/*112* Open the test object and write a value to the first byte. Returns valid fd113* on success and -1 on failure.114*/115static int116scribble_object(const char *path, char value)117{118char *page;119int fd, pagesize;120121ATF_REQUIRE(0 < (pagesize = getpagesize()));122123fd = shm_open(path, O_CREAT|O_EXCL|O_RDWR, 0777);124if (fd < 0 && errno == EEXIST) {125if (shm_unlink(test_path) < 0)126atf_tc_fail("shm_unlink");127fd = shm_open(test_path, O_CREAT | O_EXCL | O_RDWR, 0777);128}129if (fd < 0)130atf_tc_fail("shm_open failed; errno=%d", errno);131if (ftruncate(fd, pagesize) < 0)132atf_tc_fail("ftruncate failed; errno=%d", errno);133134page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);135if (page == MAP_FAILED)136atf_tc_fail("mmap failed; errno=%d", errno);137138page[0] = value;139ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",140errno);141142return (fd);143}144145/*146* Fail the test case if the 'path' does not refer to an shm whose first byte147* is equal to expected_value148*/149static void150verify_object(const char *path, char expected_value)151{152int fd;153int pagesize;154char *page;155156ATF_REQUIRE(0 < (pagesize = getpagesize()));157158fd = shm_open(path, O_RDONLY, 0777);159if (fd < 0)160atf_tc_fail("shm_open failed in verify_object; errno=%d, path=%s",161errno, path);162163page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);164if (page == MAP_FAILED)165atf_tc_fail("mmap(1)");166if (page[0] != expected_value)167atf_tc_fail("Renamed object has incorrect value; has"168"%d (0x%x, '%c'), expected %d (0x%x, '%c')\n",169page[0], page[0], isprint(page[0]) ? page[0] : ' ',170expected_value, expected_value,171isprint(expected_value) ? expected_value : ' ');172ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",173errno);174close(fd);175}176177static off_t shm_max_pages = 32;178static const char byte_to_fill = 0x5f;179180static int181shm_fill(int fd, off_t offset, off_t len)182{183int error;184size_t blen, page_size;185char *buf;186187error = 0;188page_size = getpagesize();189buf = malloc(page_size);190if (buf == NULL)191return (1);192193while (len > 0) {194blen = len < (off_t)page_size ? (size_t)len : page_size;195memset(buf, byte_to_fill, blen);196if (pwrite(fd, buf, blen, offset) != (ssize_t)blen) {197error = 1;198break;199}200len -= blen;201offset += blen;202}203204free(buf);205return (error);206}207208static int209check_content_dealloc(int fd, off_t hole_start, off_t hole_len, off_t shm_sz)210{211int error;212size_t blen, page_size;213off_t offset, resid;214struct stat statbuf;215char *buf, *sblk;216217error = 0;218page_size = getpagesize();219buf = malloc(page_size * 2);220if (buf == NULL)221return (1);222sblk = buf + page_size;223224memset(sblk, 0, page_size);225226if ((uint64_t)hole_start + hole_len > (uint64_t)shm_sz)227hole_len = shm_sz - hole_start;228229/*230* Check hole is zeroed.231*/232offset = hole_start;233resid = hole_len;234while (resid > 0) {235blen = resid < (off_t)page_size ? (size_t)resid : page_size;236if (pread(fd, buf, blen, offset) != (ssize_t)blen) {237error = 1;238break;239}240if (memcmp(buf, sblk, blen) != 0) {241error = 1;242break;243}244resid -= blen;245offset += blen;246}247248memset(sblk, byte_to_fill, page_size);249250/*251* Check file region before hole is zeroed.252*/253offset = 0;254resid = hole_start;255while (resid > 0) {256blen = resid < (off_t)page_size ? (size_t)resid : page_size;257if (pread(fd, buf, blen, offset) != (ssize_t)blen) {258error = 1;259break;260}261if (memcmp(buf, sblk, blen) != 0) {262error = 1;263break;264}265resid -= blen;266offset += blen;267}268269/*270* Check file region after hole is zeroed.271*/272offset = hole_start + hole_len;273resid = shm_sz - offset;274while (resid > 0) {275blen = resid < (off_t)page_size ? (size_t)resid : page_size;276if (pread(fd, buf, blen, offset) != (ssize_t)blen) {277error = 1;278break;279}280if (memcmp(buf, sblk, blen) != 0) {281error = 1;282break;283}284resid -= blen;285offset += blen;286}287288/*289* Check file size matches with expected file size.290*/291if (fstat(fd, &statbuf) == -1)292error = -1;293if (statbuf.st_size != shm_sz)294error = -1;295296free(buf);297return (error);298}299300ATF_TC_WITHOUT_HEAD(remap_object);301ATF_TC_BODY(remap_object, tc)302{303char *page;304int fd, pagesize;305306ATF_REQUIRE(0 < (pagesize = getpagesize()));307308gen_test_path();309fd = scribble_object(test_path, '1');310311page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);312if (page == MAP_FAILED)313atf_tc_fail("mmap(2) failed; errno=%d", errno);314315if (page[0] != '1')316atf_tc_fail("missing data ('%c' != '1')", page[0]);317318close(fd);319ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",320errno);321322ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,323"shm_unlink failed; errno=%d", errno);324}325326ATF_TC_WITHOUT_HEAD(rename_from_anon);327ATF_TC_BODY(rename_from_anon, tc)328{329int rc;330331gen_test_path();332rc = shm_rename(SHM_ANON, test_path, 0);333if (rc != -1)334atf_tc_fail("shm_rename from SHM_ANON succeeded unexpectedly");335}336337ATF_TC_WITHOUT_HEAD(rename_bad_path_pointer);338ATF_TC_BODY(rename_bad_path_pointer, tc)339{340const char *bad_path;341int rc;342343bad_path = (const char *)0x1;344345gen_test_path();346rc = shm_rename(test_path, bad_path, 0);347if (rc != -1)348atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");349350rc = shm_rename(bad_path, test_path, 0);351if (rc != -1)352atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");353}354355ATF_TC_WITHOUT_HEAD(rename_from_nonexisting);356ATF_TC_BODY(rename_from_nonexisting, tc)357{358int rc;359360gen_test_path();361gen_test_path2();362rc = shm_rename(test_path, test_path2, 0);363if (rc != -1)364atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly");365366if (errno != ENOENT)367atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d",368errno);369}370371ATF_TC_WITHOUT_HEAD(rename_to_anon);372ATF_TC_BODY(rename_to_anon, tc)373{374int rc;375376gen_test_path();377rc = shm_rename(test_path, SHM_ANON, 0);378if (rc != -1)379atf_tc_fail("shm_rename to SHM_ANON succeeded unexpectedly");380}381382ATF_TC_WITHOUT_HEAD(rename_to_replace);383ATF_TC_BODY(rename_to_replace, tc)384{385char expected_value;386int fd;387int fd2;388389// Some contents we can verify later390expected_value = 'g';391392gen_test_path();393fd = scribble_object(test_path, expected_value);394close(fd);395396// Give the other some different value so we can detect success397gen_test_path2();398fd2 = scribble_object(test_path2, 'h');399close(fd2);400401ATF_REQUIRE_MSG(shm_rename(test_path, test_path2, 0) == 0,402"shm_rename failed; errno=%d", errno);403404// Read back renamed; verify contents405verify_object(test_path2, expected_value);406}407408ATF_TC_WITHOUT_HEAD(rename_to_noreplace);409ATF_TC_BODY(rename_to_noreplace, tc)410{411char expected_value_from;412char expected_value_to;413int fd_from;414int fd_to;415int rc;416417// Some contents we can verify later418expected_value_from = 'g';419gen_test_path();420fd_from = scribble_object(test_path, expected_value_from);421close(fd_from);422423// Give the other some different value so we can detect success424expected_value_to = 'h';425gen_test_path2();426fd_to = scribble_object(test_path2, expected_value_to);427close(fd_to);428429rc = shm_rename(test_path, test_path2, SHM_RENAME_NOREPLACE);430ATF_REQUIRE_MSG((rc == -1) && (errno == EEXIST),431"shm_rename didn't fail as expected; errno: %d; return: %d", errno,432rc);433434// Read back renamed; verify contents435verify_object(test_path2, expected_value_to);436}437438ATF_TC_WITHOUT_HEAD(rename_to_exchange);439ATF_TC_BODY(rename_to_exchange, tc)440{441char expected_value_from;442char expected_value_to;443int fd_from;444int fd_to;445446// Some contents we can verify later447expected_value_from = 'g';448gen_test_path();449fd_from = scribble_object(test_path, expected_value_from);450close(fd_from);451452// Give the other some different value so we can detect success453expected_value_to = 'h';454gen_test_path2();455fd_to = scribble_object(test_path2, expected_value_to);456close(fd_to);457458ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,459SHM_RENAME_EXCHANGE) == 0,460"shm_rename failed; errno=%d", errno);461462// Read back renamed; verify contents463verify_object(test_path, expected_value_to);464verify_object(test_path2, expected_value_from);465}466467ATF_TC_WITHOUT_HEAD(rename_to_exchange_nonexisting);468ATF_TC_BODY(rename_to_exchange_nonexisting, tc)469{470char expected_value_from;471int fd_from;472473// Some contents we can verify later474expected_value_from = 'g';475gen_test_path();476fd_from = scribble_object(test_path, expected_value_from);477close(fd_from);478479gen_test_path2();480481ATF_REQUIRE_MSG(shm_rename(test_path, test_path2,482SHM_RENAME_EXCHANGE) == 0,483"shm_rename failed; errno=%d", errno);484485// Read back renamed; verify contents486verify_object(test_path2, expected_value_from);487}488489ATF_TC_WITHOUT_HEAD(rename_to_self);490ATF_TC_BODY(rename_to_self, tc)491{492int fd;493char expected_value;494495expected_value = 't';496497gen_test_path();498fd = scribble_object(test_path, expected_value);499close(fd);500501ATF_REQUIRE_MSG(shm_rename(test_path, test_path, 0) == 0,502"shm_rename failed; errno=%d", errno);503504verify_object(test_path, expected_value);505}506507ATF_TC_WITHOUT_HEAD(rename_bad_flag);508ATF_TC_BODY(rename_bad_flag, tc)509{510int fd;511int rc;512513/* Make sure we don't fail out due to ENOENT */514gen_test_path();515gen_test_path2();516fd = scribble_object(test_path, 'd');517close(fd);518fd = scribble_object(test_path2, 'd');519close(fd);520521/*522* Note: if we end up with enough flags that we use all the bits,523* then remove this test completely.524*/525rc = shm_rename(test_path, test_path2, INT_MIN);526ATF_REQUIRE_MSG((rc == -1) && (errno == EINVAL),527"shm_rename should have failed with EINVAL; got: return=%d, "528"errno=%d", rc, errno);529}530531ATF_TC_WITHOUT_HEAD(reopen_object);532ATF_TC_BODY(reopen_object, tc)533{534char *page;535int fd, pagesize;536537ATF_REQUIRE(0 < (pagesize = getpagesize()));538539gen_test_path();540fd = scribble_object(test_path, '1');541close(fd);542543fd = shm_open(test_path, O_RDONLY, 0777);544if (fd < 0)545atf_tc_fail("shm_open(2) failed; errno=%d", errno);546547page = mmap(0, pagesize, PROT_READ, MAP_SHARED, fd, 0);548if (page == MAP_FAILED)549atf_tc_fail("mmap(2) failed; errno=%d", errno);550551if (page[0] != '1')552atf_tc_fail("missing data ('%c' != '1')", page[0]);553554ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",555errno);556close(fd);557ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,558"shm_unlink failed; errno=%d", errno);559}560561ATF_TC_WITHOUT_HEAD(readonly_mmap_write);562ATF_TC_BODY(readonly_mmap_write, tc)563{564char *page;565int fd, pagesize;566567ATF_REQUIRE(0 < (pagesize = getpagesize()));568569gen_test_path();570571fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);572ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);573574/* PROT_WRITE should fail with EACCES. */575page = mmap(0, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);576if (page != MAP_FAILED)577atf_tc_fail("mmap(PROT_WRITE) succeeded unexpectedly");578579if (errno != EACCES)580atf_tc_fail("mmap(PROT_WRITE) didn't fail with EACCES; "581"errno=%d", errno);582583close(fd);584ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,585"shm_unlink failed; errno=%d", errno);586}587588ATF_TC_WITHOUT_HEAD(open_after_link);589ATF_TC_BODY(open_after_link, tc)590{591int fd;592593gen_test_path();594595fd = shm_open(test_path, O_RDONLY | O_CREAT, 0777);596ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);597close(fd);598599ATF_REQUIRE_MSG(shm_unlink(test_path) != -1, "shm_unlink failed: %d",600errno);601602shm_open_should_fail(test_path, O_RDONLY, 0777, ENOENT);603}604605ATF_TC_WITHOUT_HEAD(open_invalid_path);606ATF_TC_BODY(open_invalid_path, tc)607{608609shm_open_should_fail("blah", O_RDONLY, 0777, EINVAL);610}611612ATF_TC_WITHOUT_HEAD(open_write_only);613ATF_TC_BODY(open_write_only, tc)614{615616gen_test_path();617618shm_open_should_fail(test_path, O_WRONLY, 0777, EINVAL);619}620621ATF_TC_WITHOUT_HEAD(open_extra_flags);622ATF_TC_BODY(open_extra_flags, tc)623{624625gen_test_path();626627shm_open_should_fail(test_path, O_RDONLY | O_DIRECT, 0777, EINVAL);628}629630ATF_TC_WITHOUT_HEAD(open_anon);631ATF_TC_BODY(open_anon, tc)632{633int fd;634635fd = shm_open(SHM_ANON, O_RDWR, 0777);636ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);637close(fd);638}639640ATF_TC_WITHOUT_HEAD(open_anon_readonly);641ATF_TC_BODY(open_anon_readonly, tc)642{643644shm_open_should_fail(SHM_ANON, O_RDONLY, 0777, EINVAL);645}646647ATF_TC_WITHOUT_HEAD(open_bad_path_pointer);648ATF_TC_BODY(open_bad_path_pointer, tc)649{650651shm_open_should_fail((char *)1024, O_RDONLY, 0777, EFAULT);652}653654ATF_TC_WITHOUT_HEAD(open_path_too_long);655ATF_TC_BODY(open_path_too_long, tc)656{657char *page;658659page = malloc(MAXPATHLEN + 1);660memset(page, 'a', MAXPATHLEN);661page[MAXPATHLEN] = '\0';662shm_open_should_fail(page, O_RDONLY, 0777, ENAMETOOLONG);663free(page);664}665666ATF_TC_WITHOUT_HEAD(open_nonexisting_object);667ATF_TC_BODY(open_nonexisting_object, tc)668{669670shm_open_should_fail("/notreallythere", O_RDONLY, 0777, ENOENT);671}672673ATF_TC_WITHOUT_HEAD(open_create_existing_object);674ATF_TC_BODY(open_create_existing_object, tc)675{676int fd;677678gen_test_path();679680fd = shm_open(test_path, O_RDONLY|O_CREAT, 0777);681ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);682close(fd);683684shm_open_should_fail(test_path, O_RDONLY|O_CREAT|O_EXCL,6850777, EEXIST);686687ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,688"shm_unlink failed; errno=%d", errno);689}690691ATF_TC_WITHOUT_HEAD(trunc_resets_object);692ATF_TC_BODY(trunc_resets_object, tc)693{694struct stat sb;695int fd;696697gen_test_path();698699/* Create object and set size to 1024. */700fd = shm_open(test_path, O_RDWR | O_CREAT, 0777);701ATF_REQUIRE_MSG(fd >= 0, "shm_open(1) failed; errno=%d", errno);702ATF_REQUIRE_MSG(ftruncate(fd, 1024) != -1,703"ftruncate failed; errno=%d", errno);704ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,705"fstat(1) failed; errno=%d", errno);706ATF_REQUIRE_MSG(sb.st_size == 1024, "size %d != 1024", (int)sb.st_size);707close(fd);708709/* Open with O_TRUNC which should reset size to 0. */710fd = shm_open(test_path, O_RDWR | O_TRUNC, 0777);711ATF_REQUIRE_MSG(fd >= 0, "shm_open(2) failed; errno=%d", errno);712ATF_REQUIRE_MSG(fstat(fd, &sb) != -1,713"fstat(2) failed; errno=%d", errno);714ATF_REQUIRE_MSG(sb.st_size == 0,715"size was not 0 after truncation: %d", (int)sb.st_size);716close(fd);717ATF_REQUIRE_MSG(shm_unlink(test_path) != -1,718"shm_unlink failed; errno=%d", errno);719}720721ATF_TC_WITHOUT_HEAD(unlink_bad_path_pointer);722ATF_TC_BODY(unlink_bad_path_pointer, tc)723{724725shm_unlink_should_fail((char *)1024, EFAULT);726}727728ATF_TC_WITHOUT_HEAD(unlink_path_too_long);729ATF_TC_BODY(unlink_path_too_long, tc)730{731char *page;732733page = malloc(MAXPATHLEN + 1);734memset(page, 'a', MAXPATHLEN);735page[MAXPATHLEN] = '\0';736shm_unlink_should_fail(page, ENAMETOOLONG);737free(page);738}739740ATF_TC_WITHOUT_HEAD(object_resize);741ATF_TC_BODY(object_resize, tc)742{743pid_t pid;744struct stat sb;745char *page;746int fd, pagesize, status;747748ATF_REQUIRE(0 < (pagesize = getpagesize()));749750/* Start off with a size of a single page. */751fd = shm_open(SHM_ANON, O_CREAT|O_RDWR, 0777);752if (fd < 0)753atf_tc_fail("shm_open failed; errno=%d", errno);754755if (ftruncate(fd, pagesize) < 0)756atf_tc_fail("ftruncate(1) failed; errno=%d", errno);757758if (fstat(fd, &sb) < 0)759atf_tc_fail("fstat(1) failed; errno=%d", errno);760761if (sb.st_size != pagesize)762atf_tc_fail("first resize failed (%d != %d)",763(int)sb.st_size, pagesize);764765/* Write a '1' to the first byte. */766page = mmap(0, pagesize, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);767if (page == MAP_FAILED)768atf_tc_fail("mmap(1)");769770page[0] = '1';771772ATF_REQUIRE_MSG(munmap(page, pagesize) == 0, "munmap failed; errno=%d",773errno);774775/* Grow the object to 2 pages. */776if (ftruncate(fd, pagesize * 2) < 0)777atf_tc_fail("ftruncate(2) failed; errno=%d", errno);778779if (fstat(fd, &sb) < 0)780atf_tc_fail("fstat(2) failed; errno=%d", errno);781782if (sb.st_size != pagesize * 2)783atf_tc_fail("second resize failed (%d != %d)",784(int)sb.st_size, pagesize * 2);785786/* Check for '1' at the first byte. */787page = mmap(0, pagesize * 2, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);788if (page == MAP_FAILED)789atf_tc_fail("mmap(2) failed; errno=%d", errno);790791if (page[0] != '1')792atf_tc_fail("'%c' != '1'", page[0]);793794/* Write a '2' at the start of the second page. */795page[pagesize] = '2';796797/* Shrink the object back to 1 page. */798if (ftruncate(fd, pagesize) < 0)799atf_tc_fail("ftruncate(3) failed; errno=%d", errno);800801if (fstat(fd, &sb) < 0)802atf_tc_fail("fstat(3) failed; errno=%d", errno);803804if (sb.st_size != pagesize)805atf_tc_fail("third resize failed (%d != %d)",806(int)sb.st_size, pagesize);807808/*809* Fork a child process to make sure the second page is no810* longer valid.811*/812pid = fork();813if (pid == -1)814atf_tc_fail("fork failed; errno=%d", errno);815816if (pid == 0) {817struct rlimit lim;818char c;819820/* Don't generate a core dump. */821ATF_REQUIRE(getrlimit(RLIMIT_CORE, &lim) == 0);822lim.rlim_cur = 0;823ATF_REQUIRE(setrlimit(RLIMIT_CORE, &lim) == 0);824825/*826* The previous ftruncate(2) shrunk the backing object827* so that this address is no longer valid, so reading828* from it should trigger a SIGBUS.829*/830c = page[pagesize];831fprintf(stderr, "child: page 1: '%c'\n", c);832exit(0);833}834835if (wait(&status) < 0)836atf_tc_fail("wait failed; errno=%d", errno);837838if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGBUS)839atf_tc_fail("child terminated with status %x", status);840841/* Grow the object back to 2 pages. */842if (ftruncate(fd, pagesize * 2) < 0)843atf_tc_fail("ftruncate(2) failed; errno=%d", errno);844845if (fstat(fd, &sb) < 0)846atf_tc_fail("fstat(2) failed; errno=%d", errno);847848if (sb.st_size != pagesize * 2)849atf_tc_fail("fourth resize failed (%d != %d)",850(int)sb.st_size, pagesize);851852/*853* Note that the mapping at 'page' for the second page is854* still valid, and now that the shm object has been grown855* back up to 2 pages, there is now memory backing this page856* so the read will work. However, the data should be zero857* rather than '2' as the old data was thrown away when the858* object was shrunk and the new pages when an object are859* grown are zero-filled.860*/861if (page[pagesize] != 0)862atf_tc_fail("invalid data at %d: %x != 0",863pagesize, (int)page[pagesize]);864865close(fd);866}867868/* Signal handler which does nothing. */869static void870ignoreit(int sig __unused)871{872;873}874875ATF_TC_WITHOUT_HEAD(shm_functionality_across_fork);876ATF_TC_BODY(shm_functionality_across_fork, tc)877{878char *cp, c;879int error, desc, rv;880long scval;881sigset_t ss;882struct sigaction sa;883void *region;884size_t i, psize;885886#ifndef _POSIX_SHARED_MEMORY_OBJECTS887printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n");888#else889printf("_POSIX_SHARED_MEMORY_OBJECTS is defined as %ld\n",890(long)_POSIX_SHARED_MEMORY_OBJECTS - 0);891if (_POSIX_SHARED_MEMORY_OBJECTS - 0 == -1)892printf("***Indicates this feature may be unsupported!\n");893#endif894errno = 0;895scval = sysconf(_SC_SHARED_MEMORY_OBJECTS);896if (scval == -1 && errno != 0) {897atf_tc_fail("sysconf(_SC_SHARED_MEMORY_OBJECTS) failed; "898"errno=%d", errno);899} else {900printf("sysconf(_SC_SHARED_MEMORY_OBJECTS) returns %ld\n",901scval);902if (scval == -1)903printf("***Indicates this feature is unsupported!\n");904}905906errno = 0;907scval = sysconf(_SC_PAGESIZE);908if (scval == -1 && errno != 0) {909atf_tc_fail("sysconf(_SC_PAGESIZE) failed; errno=%d", errno);910} else if (scval <= 0) {911fprintf(stderr, "bogus return from sysconf(_SC_PAGESIZE): %ld",912scval);913psize = 4096;914} else {915printf("sysconf(_SC_PAGESIZE) returns %ld\n", scval);916psize = scval;917}918919gen_test_path();920desc = shm_open(test_path, O_EXCL | O_CREAT | O_RDWR, 0600);921922ATF_REQUIRE_MSG(desc >= 0, "shm_open failed; errno=%d", errno);923ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,924"shm_unlink failed; errno=%d", errno);925ATF_REQUIRE_MSG(ftruncate(desc, (off_t)psize) != -1,926"ftruncate failed; errno=%d", errno);927928region = mmap(NULL, psize, PROT_READ | PROT_WRITE, MAP_SHARED, desc, 0);929ATF_REQUIRE_MSG(region != MAP_FAILED, "mmap failed; errno=%d", errno);930memset(region, '\377', psize);931932sa.sa_flags = 0;933sa.sa_handler = ignoreit;934sigemptyset(&sa.sa_mask);935ATF_REQUIRE_MSG(sigaction(SIGUSR1, &sa, (struct sigaction *)0) == 0,936"sigaction failed; errno=%d", errno);937938sigemptyset(&ss);939sigaddset(&ss, SIGUSR1);940ATF_REQUIRE_MSG(sigprocmask(SIG_BLOCK, &ss, (sigset_t *)0) == 0,941"sigprocmask failed; errno=%d", errno);942943rv = fork();944ATF_REQUIRE_MSG(rv != -1, "fork failed; errno=%d", errno);945if (rv == 0) {946sigemptyset(&ss);947sigsuspend(&ss);948949for (cp = region; cp < (char *)region + psize; cp++) {950if (*cp != '\151')951_exit(1);952}953if (lseek(desc, 0, SEEK_SET) == -1)954_exit(1);955for (i = 0; i < psize; i++) {956error = read(desc, &c, 1);957if (c != '\151')958_exit(1);959}960_exit(0);961} else {962int status;963964memset(region, '\151', psize - 2);965error = pwrite(desc, region, 2, psize - 2);966if (error != 2) {967if (error >= 0)968atf_tc_fail("short write; %d bytes written",969error);970else971atf_tc_fail("shmfd write");972}973kill(rv, SIGUSR1);974waitpid(rv, &status, 0);975976if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {977printf("Functionality test successful\n");978} else if (WIFEXITED(status)) {979atf_tc_fail("Child process exited with status %d",980WEXITSTATUS(status));981} else {982atf_tc_fail("Child process terminated with %s",983strsignal(WTERMSIG(status)));984}985}986987ATF_REQUIRE_MSG(munmap(region, psize) == 0, "munmap failed; errno=%d",988errno);989shm_unlink(test_path);990}991992ATF_TC_WITHOUT_HEAD(cloexec);993ATF_TC_BODY(cloexec, tc)994{995int fd;996997gen_test_path();998999/* shm_open(2) is required to set FD_CLOEXEC */1000fd = shm_open(SHM_ANON, O_RDWR, 0777);1001ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1002ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);1003close(fd);10041005/* Also make sure that named shm is correct */1006fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);1007ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1008ATF_REQUIRE((fcntl(fd, F_GETFD) & FD_CLOEXEC) != 0);1009close(fd);1010}10111012ATF_TC_WITHOUT_HEAD(mode);1013ATF_TC_BODY(mode, tc)1014{1015struct stat st;1016int fd;1017mode_t restore_mask;10181019gen_test_path();10201021/* Remove inhibitions from umask */1022restore_mask = umask(0);1023fd = shm_open(test_path, O_CREAT | O_RDWR, 0600);1024ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1025ATF_REQUIRE(fstat(fd, &st) == 0);1026ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0600);1027close(fd);1028ATF_REQUIRE(shm_unlink(test_path) == 0);10291030fd = shm_open(test_path, O_CREAT | O_RDWR, 0660);1031ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1032ATF_REQUIRE(fstat(fd, &st) == 0);1033ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0660);1034close(fd);1035ATF_REQUIRE(shm_unlink(test_path) == 0);10361037fd = shm_open(test_path, O_CREAT | O_RDWR, 0666);1038ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1039ATF_REQUIRE(fstat(fd, &st) == 0);1040ATF_REQUIRE((st.st_mode & ACCESSPERMS) == 0666);1041close(fd);1042ATF_REQUIRE(shm_unlink(test_path) == 0);10431044umask(restore_mask);1045}10461047ATF_TC_WITHOUT_HEAD(fallocate);1048ATF_TC_BODY(fallocate, tc)1049{1050struct stat st;1051int error, fd, sz;10521053/*1054* Primitive test case for posix_fallocate with shmd. Effectively1055* expected to work like a smarter ftruncate that will grow the region1056* as needed in a race-free way.1057*/1058fd = shm_open(SHM_ANON, O_RDWR, 0666);1059ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno=%d", errno);1060/* Set the initial size. */1061sz = 32;1062ATF_REQUIRE(ftruncate(fd, sz) == 0);10631064/* Now grow it. */1065error = 0;1066sz *= 2;1067ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz)) == 0,1068"posix_fallocate failed; error=%d", error);1069ATF_REQUIRE(fstat(fd, &st) == 0);1070ATF_REQUIRE(st.st_size == sz);1071/* Attempt to shrink it; should succeed, but not change the size. */1072ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, sz / 2)) == 0,1073"posix_fallocate failed; error=%d", error);1074ATF_REQUIRE(fstat(fd, &st) == 0);1075ATF_REQUIRE(st.st_size == sz);1076/* Grow it using an offset of sz and len of sz. */1077ATF_REQUIRE_MSG((error = posix_fallocate(fd, sz, sz)) == 0,1078"posix_fallocate failed; error=%d", error);1079ATF_REQUIRE(fstat(fd, &st) == 0);1080ATF_REQUIRE(st.st_size == sz * 2);10811082close(fd);1083}10841085ATF_TC_WITHOUT_HEAD(fspacectl);1086ATF_TC_BODY(fspacectl, tc)1087{1088struct spacectl_range range;1089off_t offset, length, shm_sz;1090size_t page_size;1091int fd, error;10921093page_size = getpagesize();1094shm_sz = shm_max_pages * page_size;10951096fd = shm_open("/testtest", O_RDWR | O_CREAT, 0666);1097ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno);1098ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0,1099"posix_fallocate failed; error=%d", error);11001101/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) */1102ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1103range.r_offset = offset = page_size;1104range.r_len = length = ((shm_max_pages - 1) * page_size) -1105range.r_offset;1106ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1107"Aligned fspacectl failed; errno=%d", errno);1108ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1109"Aligned fspacectl content checking failed");11101111/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) */1112ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1113range.r_offset = offset = page_size / 2;1114range.r_len = length = (shm_max_pages - 1) * page_size +1115(page_size / 2) - offset;1116ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1117"Unaligned fspacectl failed; errno=%d", errno);1118ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1119"Unaligned fspacectl content checking failed");11201121/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */1122ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1123range.r_offset = offset = page_size;1124range.r_len = length = OFF_MAX - offset;1125ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1126"Aligned fspacectl to OFF_MAX failed; errno=%d", errno);1127ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1128"Aligned fspacectl to OFF_MAX content checking failed");11291130/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) to OFF_MAX */1131ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1132range.r_offset = offset = page_size / 2;1133range.r_len = length = OFF_MAX - offset;1134ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1135"Unaligned fspacectl to OFF_MAX failed; errno=%d", errno);1136ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1137"Unaligned fspacectl to OFF_MAX content checking failed");11381139/* Aligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */1140ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1141range.r_offset = offset = page_size;1142range.r_len = length = (shm_max_pages + 1) * page_size - offset;1143ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1144"Aligned fspacectl past shm_sz failed; errno=%d", errno);1145ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1146"Aligned fspacectl past shm_sz content checking failed");11471148/* Unaligned fspacectl(fd, SPACECTL_DEALLOC, ...) past shm_sz */1149ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1150range.r_offset = offset = page_size / 2;1151range.r_len = length = (shm_max_pages + 1) * page_size - offset;1152ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1153"Unaligned fspacectl past shm_sz failed; errno=%d", errno);1154ATF_CHECK_MSG(check_content_dealloc(fd, offset, length, shm_sz) == 0,1155"Unaligned fspacectl past shm_sz content checking failed");11561157ATF_REQUIRE(close(fd) == 0);1158}11591160ATF_TC_WITHOUT_HEAD(accounting);1161ATF_TC_BODY(accounting, tc)1162{1163struct spacectl_range range;1164struct stat st;1165off_t shm_sz, len;1166size_t page_size;1167int fd, error;11681169page_size = getpagesize();1170shm_sz = shm_max_pages * page_size;11711172fd = shm_open("/testtest1", O_RDWR | O_CREAT, 0666);1173ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; errno:%d", errno);1174ATF_REQUIRE_MSG((error = posix_fallocate(fd, 0, shm_sz)) == 0,1175"posix_fallocate failed; error=%d", error);11761177ATF_REQUIRE(shm_fill(fd, 0, shm_sz) == 0);1178ATF_REQUIRE(fstat(fd, &st) == 0);1179ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)shm_sz);11801181range.r_offset = page_size;1182range.r_len = len = (shm_max_pages - 1) * page_size -1183range.r_offset;1184ATF_CHECK_MSG(fspacectl(fd, SPACECTL_DEALLOC, &range, 0, &range) == 0,1185"SPACECTL_DEALLOC failed; errno=%d", errno);1186ATF_REQUIRE(fstat(fd, &st) == 0);1187ATF_REQUIRE(st.st_blksize * st.st_blocks == (blkcnt_t)(shm_sz - len));11881189ATF_REQUIRE(close(fd) == 0);1190}11911192ATF_TC_WITHOUT_HEAD(mmap_prot);1193ATF_TC_BODY(mmap_prot, tc)1194{1195void *p;1196int fd, pagesize;11971198ATF_REQUIRE((pagesize = getpagesize()) > 0);11991200gen_test_path();1201fd = shm_open(test_path, O_RDONLY | O_CREAT, 0644);1202ATF_REQUIRE(fd >= 0);12031204p = mmap(NULL, pagesize, PROT_READ, MAP_SHARED, fd, 0);1205ATF_REQUIRE(p != MAP_FAILED);1206ATF_REQUIRE(munmap(p, pagesize) == 0);1207p = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);1208ATF_REQUIRE_ERRNO(EACCES, p == MAP_FAILED);1209p = mmap(NULL, pagesize, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);1210ATF_REQUIRE(p != MAP_FAILED);1211ATF_REQUIRE(munmap(p, pagesize) == 0);12121213ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,1214"shm_unlink failed; errno=%d", errno);1215ATF_REQUIRE_MSG(close(fd) == 0,1216"close failed; errno=%d", errno);1217}12181219static int1220shm_open_large(int psind, int policy, size_t sz)1221{1222int error, fd;12231224fd = shm_create_largepage(SHM_ANON, O_CREAT | O_RDWR, psind, policy, 0);1225if (fd < 0 && errno == ENOTTY)1226atf_tc_skip("no large page support");1227ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; errno=%d", errno);12281229error = ftruncate(fd, sz);1230if (error != 0 && errno == ENOMEM)1231/*1232* The test system might not have enough memory to accommodate1233* the request.1234*/1235atf_tc_skip("failed to allocate %zu-byte superpage", sz);1236ATF_REQUIRE_MSG(error == 0, "ftruncate failed; errno=%d", errno);12371238return (fd);1239}12401241static int1242pagesizes(size_t ps[MAXPAGESIZES])1243{1244int pscnt;12451246pscnt = getpagesizes(ps, MAXPAGESIZES);1247ATF_REQUIRE_MSG(pscnt != -1, "getpagesizes failed; errno=%d", errno);1248ATF_REQUIRE_MSG(ps[0] != 0, "psind 0 is %zu", ps[0]);1249ATF_REQUIRE_MSG(pscnt <= MAXPAGESIZES, "invalid pscnt %d", pscnt);1250if (pscnt == 1)1251atf_tc_skip("no large page support");1252return (pscnt);1253}12541255ATF_TC_WITHOUT_HEAD(largepage_basic);1256ATF_TC_BODY(largepage_basic, tc)1257{1258char *zeroes;1259char *addr, *vec;1260size_t ps[MAXPAGESIZES];1261int error, fd, pscnt;12621263pscnt = pagesizes(ps);1264zeroes = calloc(1, ps[0]);1265ATF_REQUIRE(zeroes != NULL);1266for (int i = 1; i < pscnt; i++) {1267fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);12681269addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,12700);1271ATF_REQUIRE_MSG(addr != MAP_FAILED,1272"mmap(%zu bytes) failed; errno=%d", ps[i], errno);1273ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,1274"mmap(%zu bytes) returned unaligned mapping; addr=%p",1275ps[i], addr);12761277/* Force a page fault. */1278*(volatile char *)addr = 0;12791280vec = malloc(ps[i] / ps[0]);1281ATF_REQUIRE(vec != NULL);1282error = mincore(addr, ps[i], vec);1283ATF_REQUIRE_MSG(error == 0, "mincore failed; errno=%d", errno);12841285/* Verify that all pages in the run are mapped. */1286for (size_t p = 0; p < ps[i] / ps[0]; p++) {1287ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,1288"page %zu is not mapped", p);1289ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) ==1290MINCORE_PSIND(i),1291"page %zu is not in a %zu-byte superpage",1292p, ps[i]);1293}12941295/* Validate zeroing. */1296for (size_t p = 0; p < ps[i] / ps[0]; p++) {1297ATF_REQUIRE_MSG(memcmp(addr + p * ps[0], zeroes,1298ps[0]) == 0, "page %zu miscompare", p);1299}13001301free(vec);1302ATF_REQUIRE(munmap(addr, ps[i]) == 0);1303ATF_REQUIRE(close(fd) == 0);1304}13051306free(zeroes);1307}13081309extern int __sys_shm_open2(const char *, int, mode_t, int, const char *);13101311ATF_TC_WITHOUT_HEAD(largepage_config);1312ATF_TC_BODY(largepage_config, tc)1313{1314struct shm_largepage_conf lpc;1315char *addr, *buf;1316size_t ps[MAXPAGESIZES + 1]; /* silence warnings if MAXPAGESIZES == 1 */1317int error, fd;13181319(void)pagesizes(ps);13201321fd = shm_open(SHM_ANON, O_CREAT | O_RDWR, 0);1322ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);13231324/*1325* Configure a large page policy for an object created without1326* SHM_LARGEPAGE.1327*/1328lpc.psind = 1;1329lpc.alloc_policy = SHM_LARGEPAGE_ALLOC_DEFAULT;1330error = ioctl(fd, FIOSSHMLPGCNF, &lpc);1331ATF_REQUIRE(error != 0);1332ATF_REQUIRE_MSG(errno == ENOTTY, "ioctl(FIOSSHMLPGCNF) returned %d",1333errno);1334ATF_REQUIRE(close(fd) == 0);13351336/*1337* Create a largepage object and try to use it without actually1338* configuring anything.1339*/1340fd = __sys_shm_open2(SHM_ANON, O_CREAT | O_RDWR, 0, SHM_LARGEPAGE,1341NULL);1342if (fd < 0 && errno == ENOTTY)1343atf_tc_skip("no large page support");1344ATF_REQUIRE_MSG(fd >= 0, "shm_open2 failed; error=%d", errno);13451346error = ftruncate(fd, ps[1]);1347ATF_REQUIRE(error != 0);1348ATF_REQUIRE_MSG(errno == EINVAL, "ftruncate returned %d", errno);13491350addr = mmap(NULL, ps[1], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);1351ATF_REQUIRE(addr == MAP_FAILED);1352ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);1353addr = mmap(NULL, 0, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);1354ATF_REQUIRE(addr == MAP_FAILED);1355ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);13561357buf = calloc(1, ps[0]);1358ATF_REQUIRE(buf != NULL);1359ATF_REQUIRE(write(fd, buf, ps[0]) == -1);1360ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);1361free(buf);1362buf = calloc(1, ps[1]);1363ATF_REQUIRE(buf != NULL);1364ATF_REQUIRE(write(fd, buf, ps[1]) == -1);1365ATF_REQUIRE_MSG(errno == EINVAL, "write returned %d", errno);1366free(buf);13671368error = posix_fallocate(fd, 0, ps[0]);1369ATF_REQUIRE_MSG(error == EINVAL, "posix_fallocate returned %d", error);13701371ATF_REQUIRE(close(fd) == 0);1372}13731374ATF_TC_WITHOUT_HEAD(largepage_mmap);1375ATF_TC_BODY(largepage_mmap, tc)1376{1377char *addr, *addr1, *vec;1378size_t ps[MAXPAGESIZES];1379int fd, pscnt;13801381pscnt = pagesizes(ps);1382for (int i = 1; i < pscnt; i++) {1383fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);13841385/* For mincore(). */1386vec = malloc(ps[i]);1387ATF_REQUIRE(vec != NULL);13881389/*1390* Wrong mapping size.1391*/1392addr = mmap(NULL, ps[i - 1], PROT_READ | PROT_WRITE, MAP_SHARED,1393fd, 0);1394ATF_REQUIRE_MSG(addr == MAP_FAILED,1395"mmap(%zu bytes) succeeded", ps[i - 1]);1396ATF_REQUIRE_MSG(errno == EINVAL,1397"mmap(%zu bytes) failed; error=%d", ps[i - 1], errno);13981399/*1400* Fixed mappings.1401*/1402addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,14030);1404ATF_REQUIRE_MSG(addr != MAP_FAILED,1405"mmap(%zu bytes) failed; errno=%d", ps[i], errno);1406ATF_REQUIRE_MSG(((uintptr_t)addr & (ps[i] - 1)) == 0,1407"mmap(%zu bytes) returned unaligned mapping; addr=%p",1408ps[i], addr);14091410/* Try mapping a small page with anonymous memory. */1411addr1 = mmap(addr, ps[i - 1], PROT_READ | PROT_WRITE,1412MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);1413ATF_REQUIRE_MSG(addr1 == MAP_FAILED,1414"anon mmap(%zu bytes) succeeded", ps[i - 1]);1415ATF_REQUIRE_MSG(errno == EINVAL, "mmap returned %d", errno);14161417/* Check MAP_EXCL when creating a second largepage mapping. */1418addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,1419MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);1420ATF_REQUIRE_MSG(addr1 == MAP_FAILED,1421"mmap(%zu bytes) succeeded", ps[i]);1422/* XXX wrong errno */1423ATF_REQUIRE_MSG(errno == ENOSPC, "mmap returned %d", errno);14241425/* Overwrite a largepage mapping with a lagepage mapping. */1426addr1 = mmap(addr, ps[i], PROT_READ | PROT_WRITE,1427MAP_SHARED | MAP_FIXED, fd, 0);1428ATF_REQUIRE_MSG(addr1 != MAP_FAILED,1429"mmap(%zu bytes) failed; errno=%d", ps[i], errno);1430ATF_REQUIRE_MSG(addr == addr1,1431"mmap(%zu bytes) moved from %p to %p", ps[i], addr, addr1);14321433ATF_REQUIRE(munmap(addr, ps[i] == 0));14341435/* Clobber an anonymous mapping with a superpage. */1436addr1 = mmap(NULL, ps[i], PROT_READ | PROT_WRITE,1437MAP_ANON | MAP_PRIVATE | MAP_ALIGNED(ffsl(ps[i]) - 1), -1,14380);1439ATF_REQUIRE_MSG(addr1 != MAP_FAILED,1440"mmap failed; error=%d", errno);1441*(volatile char *)addr1 = '\0';1442addr = mmap(addr1, ps[i], PROT_READ | PROT_WRITE,1443MAP_SHARED | MAP_FIXED, fd, 0);1444ATF_REQUIRE_MSG(addr != MAP_FAILED,1445"mmap failed; error=%d", errno);1446ATF_REQUIRE_MSG(addr == addr1,1447"mmap disobeyed MAP_FIXED, %p %p", addr, addr1);1448*(volatile char *)addr = 0; /* fault */1449ATF_REQUIRE(mincore(addr, ps[i], vec) == 0);1450for (size_t p = 0; p < ps[i] / ps[0]; p++) {1451ATF_REQUIRE_MSG((vec[p] & MINCORE_INCORE) != 0,1452"page %zu is not resident", p);1453ATF_REQUIRE_MSG((vec[p] & MINCORE_SUPER) ==1454MINCORE_PSIND(i),1455"page %zu is not resident", p);1456}14571458/*1459* Copy-on-write mappings are not permitted.1460*/1461addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_PRIVATE,1462fd, 0);1463ATF_REQUIRE_MSG(addr == MAP_FAILED,1464"mmap(%zu bytes) succeeded", ps[i]);14651466ATF_REQUIRE(close(fd) == 0);1467}1468}14691470ATF_TC_WITHOUT_HEAD(largepage_munmap);1471ATF_TC_BODY(largepage_munmap, tc)1472{1473char *addr;1474size_t ps[MAXPAGESIZES], ps1;1475int fd, pscnt;14761477pscnt = pagesizes(ps);1478for (int i = 1; i < pscnt; i++) {1479fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1480ps1 = ps[i - 1];14811482addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,14830);1484ATF_REQUIRE_MSG(addr != MAP_FAILED,1485"mmap(%zu bytes) failed; errno=%d", ps[i], errno);14861487/* Try several unaligned munmap() requests. */1488ATF_REQUIRE(munmap(addr, ps1) != 0);1489ATF_REQUIRE_MSG(errno == EINVAL,1490"unexpected error %d from munmap", errno);1491ATF_REQUIRE(munmap(addr, ps[i] - ps1));1492ATF_REQUIRE_MSG(errno == EINVAL,1493"unexpected error %d from munmap", errno);1494ATF_REQUIRE(munmap(addr + ps1, ps1) != 0);1495ATF_REQUIRE_MSG(errno == EINVAL,1496"unexpected error %d from munmap", errno);1497ATF_REQUIRE(munmap(addr, 0));1498ATF_REQUIRE_MSG(errno == EINVAL,1499"unexpected error %d from munmap", errno);15001501ATF_REQUIRE(munmap(addr, ps[i]) == 0);1502ATF_REQUIRE(close(fd) == 0);1503}1504}15051506static void1507largepage_madvise(char *addr, size_t sz, int advice, int error)1508{1509if (error == 0) {1510ATF_REQUIRE_MSG(madvise(addr, sz, advice) == 0,1511"madvise(%zu, %d) failed; error=%d", sz, advice, errno);1512} else {1513ATF_REQUIRE_MSG(madvise(addr, sz, advice) != 0,1514"madvise(%zu, %d) succeeded", sz, advice);1515ATF_REQUIRE_MSG(errno == error,1516"unexpected error %d from madvise(%zu, %d)",1517errno, sz, advice);1518}1519}15201521ATF_TC_WITHOUT_HEAD(largepage_madvise);1522ATF_TC_BODY(largepage_madvise, tc)1523{1524char *addr;1525size_t ps[MAXPAGESIZES];1526int fd, pscnt;15271528pscnt = pagesizes(ps);1529for (int i = 1; i < pscnt; i++) {1530fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1531addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,15320);1533ATF_REQUIRE_MSG(addr != MAP_FAILED,1534"mmap(%zu bytes) failed; error=%d", ps[i], errno);15351536memset(addr, 0, ps[i]);15371538/* Advice that requires clipping. */1539largepage_madvise(addr, ps[0], MADV_NORMAL, EINVAL);1540largepage_madvise(addr, ps[i], MADV_NORMAL, 0);1541largepage_madvise(addr, ps[0], MADV_RANDOM, EINVAL);1542largepage_madvise(addr, ps[i], MADV_RANDOM, 0);1543largepage_madvise(addr, ps[0], MADV_SEQUENTIAL, EINVAL);1544largepage_madvise(addr, ps[i], MADV_SEQUENTIAL, 0);1545largepage_madvise(addr, ps[0], MADV_NOSYNC, EINVAL);1546largepage_madvise(addr, ps[i], MADV_NOSYNC, 0);1547largepage_madvise(addr, ps[0], MADV_AUTOSYNC, EINVAL);1548largepage_madvise(addr, ps[i], MADV_AUTOSYNC, 0);1549largepage_madvise(addr, ps[0], MADV_CORE, EINVAL);1550largepage_madvise(addr, ps[i], MADV_CORE, 0);1551largepage_madvise(addr, ps[0], MADV_NOCORE, EINVAL);1552largepage_madvise(addr, ps[i], MADV_NOCORE, 0);15531554/* Advice that does not result in clipping. */1555largepage_madvise(addr, ps[0], MADV_DONTNEED, 0);1556largepage_madvise(addr, ps[i], MADV_DONTNEED, 0);1557largepage_madvise(addr, ps[0], MADV_WILLNEED, 0);1558largepage_madvise(addr, ps[i], MADV_WILLNEED, 0);1559largepage_madvise(addr, ps[0], MADV_FREE, 0);1560largepage_madvise(addr, ps[i], MADV_FREE, 0);15611562ATF_REQUIRE(munmap(addr, ps[i]) == 0);1563ATF_REQUIRE(close(fd) == 0);1564}1565}15661567ATF_TC(largepage_mlock);1568ATF_TC_HEAD(largepage_mlock, tc)1569{1570/* Needed to set rlimit. */1571atf_tc_set_md_var(tc, "require.user", "root");1572}1573ATF_TC_BODY(largepage_mlock, tc)1574{1575struct rlimit rl;1576char *addr;1577size_t ps[MAXPAGESIZES], sz;1578u_long max_wired, wired;1579int fd, error, pscnt;15801581rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;1582ATF_REQUIRE_MSG(setrlimit(RLIMIT_MEMLOCK, &rl) == 0,1583"setrlimit failed; error=%d", errno);15841585sz = sizeof(max_wired);1586error = sysctlbyname("vm.max_user_wired", &max_wired, &sz, NULL, 0);1587ATF_REQUIRE_MSG(error == 0,1588"sysctlbyname(vm.max_user_wired) failed; error=%d", errno);15891590sz = sizeof(wired);1591error = sysctlbyname("vm.stats.vm.v_user_wire_count", &wired, &sz, NULL,15920);1593ATF_REQUIRE_MSG(error == 0,1594"sysctlbyname(vm.stats.vm.v_user_wire_count) failed; error=%d",1595errno);15961597pscnt = pagesizes(ps);1598for (int i = 1; i < pscnt; i++) {1599if (ps[i] / ps[0] > max_wired - wired) {1600/* Cannot wire past the limit. */1601atf_tc_skip("test would exceed wiring limit");1602}16031604fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1605addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,16060);1607ATF_REQUIRE_MSG(addr != MAP_FAILED,1608"mmap(%zu bytes) failed; error=%d", ps[i], errno);16091610ATF_REQUIRE(mlock(addr, ps[0]) != 0);1611ATF_REQUIRE_MSG(errno == EINVAL,1612"unexpected error %d from mlock(%zu bytes)", errno, ps[i]);1613ATF_REQUIRE(mlock(addr, ps[i] - ps[0]) != 0);1614ATF_REQUIRE_MSG(errno == EINVAL,1615"unexpected error %d from mlock(%zu bytes)", errno, ps[i]);16161617ATF_REQUIRE_MSG(mlock(addr, ps[i]) == 0,1618"mlock failed; error=%d", errno);16191620ATF_REQUIRE(munmap(addr, ps[i]) == 0);16211622ATF_REQUIRE(mlockall(MCL_FUTURE) == 0);1623addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,16240);1625ATF_REQUIRE_MSG(addr != MAP_FAILED,1626"mmap(%zu bytes) failed; error=%d", ps[i], errno);16271628ATF_REQUIRE(munmap(addr, ps[i]) == 0);1629ATF_REQUIRE(close(fd) == 0);1630}1631}16321633ATF_TC_WITHOUT_HEAD(largepage_msync);1634ATF_TC_BODY(largepage_msync, tc)1635{1636char *addr;1637size_t ps[MAXPAGESIZES];1638int fd, pscnt;16391640pscnt = pagesizes(ps);1641for (int i = 1; i < pscnt; i++) {1642fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1643addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,16440);1645ATF_REQUIRE_MSG(addr != MAP_FAILED,1646"mmap(%zu bytes) failed; error=%d", ps[i], errno);16471648memset(addr, 0, ps[i]);16491650/*1651* "Sync" requests are no-ops for SHM objects, so small1652* PAGE_SIZE-sized requests succeed.1653*/1654ATF_REQUIRE_MSG(msync(addr, ps[0], MS_ASYNC) == 0,1655"msync(MS_ASYNC) failed; error=%d", errno);1656ATF_REQUIRE_MSG(msync(addr, ps[i], MS_ASYNC) == 0,1657"msync(MS_ASYNC) failed; error=%d", errno);1658ATF_REQUIRE_MSG(msync(addr, ps[0], MS_SYNC) == 0,1659"msync(MS_SYNC) failed; error=%d", errno);1660ATF_REQUIRE_MSG(msync(addr, ps[i], MS_SYNC) == 0,1661"msync(MS_SYNC) failed; error=%d", errno);16621663ATF_REQUIRE_MSG(msync(addr, ps[0], MS_INVALIDATE) != 0,1664"msync(MS_INVALIDATE) succeeded");1665/* XXX wrong errno */1666ATF_REQUIRE_MSG(errno == EBUSY,1667"unexpected error %d from msync(MS_INVALIDATE)", errno);1668ATF_REQUIRE_MSG(msync(addr, ps[i], MS_INVALIDATE) == 0,1669"msync(MS_INVALIDATE) failed; error=%d", errno);1670memset(addr, 0, ps[i]);16711672ATF_REQUIRE(munmap(addr, ps[i]) == 0);1673ATF_REQUIRE(close(fd) == 0);1674}1675}16761677static void1678largepage_protect(char *addr, size_t sz, int prot, int error)1679{1680if (error == 0) {1681ATF_REQUIRE_MSG(mprotect(addr, sz, prot) == 0,1682"mprotect(%zu, %x) failed; error=%d", sz, prot, errno);1683} else {1684ATF_REQUIRE_MSG(mprotect(addr, sz, prot) != 0,1685"mprotect(%zu, %x) succeeded", sz, prot);1686ATF_REQUIRE_MSG(errno == error,1687"unexpected error %d from mprotect(%zu, %x)",1688errno, sz, prot);1689}1690}16911692ATF_TC_WITHOUT_HEAD(largepage_mprotect);1693ATF_TC_BODY(largepage_mprotect, tc)1694{1695char *addr, *addr1;1696size_t ps[MAXPAGESIZES];1697int fd, pscnt;16981699pscnt = pagesizes(ps);1700for (int i = 1; i < pscnt; i++) {1701/*1702* Reserve a contiguous region in the address space to avoid1703* spurious failures in the face of ASLR.1704*/1705addr = mmap(NULL, ps[i] * 2, PROT_NONE,1706MAP_ANON | MAP_ALIGNED(ffsl(ps[i]) - 1), -1, 0);1707ATF_REQUIRE_MSG(addr != MAP_FAILED,1708"mmap(%zu bytes) failed; error=%d", ps[i], errno);1709ATF_REQUIRE(munmap(addr, ps[i] * 2) == 0);17101711fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1712addr = mmap(addr, ps[i], PROT_READ | PROT_WRITE,1713MAP_SHARED | MAP_FIXED, fd, 0);1714ATF_REQUIRE_MSG(addr != MAP_FAILED,1715"mmap(%zu bytes) failed; error=%d", ps[i], errno);17161717/*1718* These should be no-ops from the pmap perspective since the1719* page is not yet entered into the pmap.1720*/1721largepage_protect(addr, ps[0], PROT_READ, EINVAL);1722largepage_protect(addr, ps[i], PROT_READ, 0);1723largepage_protect(addr, ps[0], PROT_NONE, EINVAL);1724largepage_protect(addr, ps[i], PROT_NONE, 0);1725largepage_protect(addr, ps[0],1726PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);1727largepage_protect(addr, ps[i],1728PROT_READ | PROT_WRITE | PROT_EXEC, 0);17291730/* Trigger creation of a mapping and try again. */1731*(volatile char *)addr = 0;1732largepage_protect(addr, ps[0], PROT_READ, EINVAL);1733largepage_protect(addr, ps[i], PROT_READ, 0);1734largepage_protect(addr, ps[0], PROT_NONE, EINVAL);1735largepage_protect(addr, ps[i], PROT_NONE, 0);1736largepage_protect(addr, ps[0],1737PROT_READ | PROT_WRITE | PROT_EXEC, EINVAL);1738largepage_protect(addr, ps[i],1739PROT_READ | PROT_WRITE | PROT_EXEC, 0);17401741memset(addr, 0, ps[i]);17421743/* Map two contiguous large pages and merge map entries. */1744addr1 = mmap(addr + ps[i], ps[i], PROT_READ | PROT_WRITE,1745MAP_SHARED | MAP_FIXED | MAP_EXCL, fd, 0);1746ATF_REQUIRE_MSG(addr1 != MAP_FAILED,1747"mmap(%zu bytes) failed; error=%d", ps[i], errno);17481749largepage_protect(addr1 - ps[0], ps[0] * 2,1750PROT_READ | PROT_WRITE, EINVAL);1751largepage_protect(addr, ps[i] * 2, PROT_READ | PROT_WRITE, 0);17521753memset(addr, 0, ps[i] * 2);17541755ATF_REQUIRE(munmap(addr, ps[i]) == 0);1756ATF_REQUIRE(munmap(addr1, ps[i]) == 0);1757ATF_REQUIRE(close(fd) == 0);1758}1759}17601761ATF_TC_WITHOUT_HEAD(largepage_minherit);1762ATF_TC_BODY(largepage_minherit, tc)1763{1764char *addr;1765size_t ps[MAXPAGESIZES];1766pid_t child;1767int fd, pscnt, status;17681769pscnt = pagesizes(ps);1770for (int i = 1; i < pscnt; i++) {1771fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1772addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,17730);1774ATF_REQUIRE_MSG(addr != MAP_FAILED,1775"mmap(%zu bytes) failed; error=%d", ps[i], errno);17761777ATF_REQUIRE(minherit(addr, ps[0], INHERIT_SHARE) != 0);17781779ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_SHARE) == 0,1780"minherit(%zu bytes) failed; error=%d", ps[i], errno);1781child = fork();1782ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);1783if (child == 0) {1784char v;17851786*(volatile char *)addr = 0;1787if (mincore(addr, ps[0], &v) != 0)1788_exit(1);1789if ((v & MINCORE_SUPER) == 0)1790_exit(2);1791_exit(0);1792}1793ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,1794"waitpid failed; error=%d", errno);1795ATF_REQUIRE_MSG(WIFEXITED(status),1796"child was killed by signal %d", WTERMSIG(status));1797ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,1798"child exited with status %d", WEXITSTATUS(status));17991800ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_NONE) == 0,1801"minherit(%zu bytes) failed; error=%d", ps[i], errno);1802child = fork();1803ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);1804if (child == 0) {1805char v;18061807if (mincore(addr, ps[0], &v) == 0)1808_exit(1);1809_exit(0);1810}1811ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,1812"waitpid failed; error=%d", errno);1813ATF_REQUIRE_MSG(WIFEXITED(status),1814"child was killed by signal %d", WTERMSIG(status));1815ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,1816"child exited with status %d", WEXITSTATUS(status));18171818/* Copy-on-write is not supported for static large pages. */1819ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_COPY) != 0,1820"minherit(%zu bytes) succeeded", ps[i]);18211822ATF_REQUIRE_MSG(minherit(addr, ps[i], INHERIT_ZERO) == 0,1823"minherit(%zu bytes) failed; error=%d", ps[i], errno);1824child = fork();1825ATF_REQUIRE_MSG(child != -1, "fork failed; error=%d", errno);1826if (child == 0) {1827char v;18281829*(volatile char *)addr = 0;1830if (mincore(addr, ps[0], &v) != 0)1831_exit(1);1832if ((v & MINCORE_SUPER) != 0)1833_exit(2);1834_exit(0);1835}1836ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,1837"waitpid failed; error=%d", errno);1838ATF_REQUIRE_MSG(WIFEXITED(status),1839"child was killed by signal %d", WTERMSIG(status));1840ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,1841"child exited with status %d", WEXITSTATUS(status));18421843ATF_REQUIRE(munmap(addr, ps[i]) == 0);1844ATF_REQUIRE(close(fd) == 0);1845}1846}18471848ATF_TC_WITHOUT_HEAD(largepage_pipe);1849ATF_TC_BODY(largepage_pipe, tc)1850{1851size_t ps[MAXPAGESIZES];1852char *addr;1853ssize_t len;1854int fd, pfd[2], pscnt, status;1855pid_t child;18561857pscnt = pagesizes(ps);18581859for (int i = 1; i < pscnt; i++) {1860fd = shm_open_large(i, SHM_LARGEPAGE_ALLOC_DEFAULT, ps[i]);1861addr = mmap(NULL, ps[i], PROT_READ | PROT_WRITE, MAP_SHARED, fd,18620);1863ATF_REQUIRE_MSG(addr != MAP_FAILED,1864"mmap(%zu bytes) failed; error=%d", ps[i], errno);18651866/* Trigger creation of a mapping. */1867*(volatile char *)addr = '\0';18681869ATF_REQUIRE(pipe(pfd) == 0);1870child = fork();1871ATF_REQUIRE_MSG(child != -1, "fork() failed; error=%d", errno);1872if (child == 0) {1873char buf[BUFSIZ];1874ssize_t resid;18751876(void)close(pfd[0]);1877for (resid = (size_t)ps[i]; resid > 0; resid -= len) {1878len = read(pfd[1], buf, sizeof(buf));1879if (len < 0)1880_exit(1);1881}1882_exit(0);1883}1884ATF_REQUIRE(close(pfd[1]) == 0);1885len = write(pfd[0], addr, ps[i]);1886ATF_REQUIRE_MSG(len >= 0, "write() failed; error=%d", errno);1887ATF_REQUIRE_MSG(len == (ssize_t)ps[i],1888"short write; len=%zd", len);1889ATF_REQUIRE(close(pfd[0]) == 0);18901891ATF_REQUIRE_MSG(waitpid(child, &status, 0) == child,1892"waitpid() failed; error=%d", errno);1893ATF_REQUIRE_MSG(WIFEXITED(status),1894"child was killed by signal %d", WTERMSIG(status));1895ATF_REQUIRE_MSG(WEXITSTATUS(status) == 0,1896"child exited with status %d", WEXITSTATUS(status));18971898ATF_REQUIRE(munmap(addr, ps[i]) == 0);1899ATF_REQUIRE(close(fd) == 0);1900}1901}19021903ATF_TC_WITHOUT_HEAD(largepage_reopen);1904ATF_TC_BODY(largepage_reopen, tc)1905{1906char *addr, *vec;1907size_t ps[MAXPAGESIZES];1908int fd, psind;19091910(void)pagesizes(ps);1911psind = 1;19121913gen_test_path();1914fd = shm_create_largepage(test_path, O_CREAT | O_RDWR, psind,1915SHM_LARGEPAGE_ALLOC_DEFAULT, 0600);1916if (fd < 0 && errno == ENOTTY)1917atf_tc_skip("no large page support");1918ATF_REQUIRE_MSG(fd >= 0, "shm_create_largepage failed; error=%d", errno);19191920ATF_REQUIRE_MSG(ftruncate(fd, ps[psind]) == 0,1921"ftruncate failed; error=%d", errno);19221923ATF_REQUIRE_MSG(close(fd) == 0, "close failed; error=%d", errno);19241925fd = shm_open(test_path, O_RDWR, 0);1926ATF_REQUIRE_MSG(fd >= 0, "shm_open failed; error=%d", errno);19271928addr = mmap(NULL, ps[psind], PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);1929ATF_REQUIRE_MSG(addr != MAP_FAILED, "mmap failed; error=%d", errno);19301931/* Trigger a fault and mapping creation. */1932*(volatile char *)addr = 0;19331934vec = malloc(ps[psind] / ps[0]);1935ATF_REQUIRE(vec != NULL);1936ATF_REQUIRE_MSG(mincore(addr, ps[psind], vec) == 0,1937"mincore failed; error=%d", errno);1938ATF_REQUIRE_MSG((vec[0] & MINCORE_SUPER) == MINCORE_PSIND(psind),1939"page not mapped into a %zu-byte superpage", ps[psind]);19401941ATF_REQUIRE_MSG(shm_unlink(test_path) == 0,1942"shm_unlink failed; errno=%d", errno);1943ATF_REQUIRE_MSG(close(fd) == 0,1944"close failed; errno=%d", errno);1945}19461947ATF_TP_ADD_TCS(tp)1948{1949ATF_TP_ADD_TC(tp, remap_object);1950ATF_TP_ADD_TC(tp, rename_from_anon);1951ATF_TP_ADD_TC(tp, rename_bad_path_pointer);1952ATF_TP_ADD_TC(tp, rename_from_nonexisting);1953ATF_TP_ADD_TC(tp, rename_to_anon);1954ATF_TP_ADD_TC(tp, rename_to_replace);1955ATF_TP_ADD_TC(tp, rename_to_noreplace);1956ATF_TP_ADD_TC(tp, rename_to_exchange);1957ATF_TP_ADD_TC(tp, rename_to_exchange_nonexisting);1958ATF_TP_ADD_TC(tp, rename_to_self);1959ATF_TP_ADD_TC(tp, rename_bad_flag);1960ATF_TP_ADD_TC(tp, reopen_object);1961ATF_TP_ADD_TC(tp, readonly_mmap_write);1962ATF_TP_ADD_TC(tp, open_after_link);1963ATF_TP_ADD_TC(tp, open_invalid_path);1964ATF_TP_ADD_TC(tp, open_write_only);1965ATF_TP_ADD_TC(tp, open_extra_flags);1966ATF_TP_ADD_TC(tp, open_anon);1967ATF_TP_ADD_TC(tp, open_anon_readonly);1968ATF_TP_ADD_TC(tp, open_bad_path_pointer);1969ATF_TP_ADD_TC(tp, open_path_too_long);1970ATF_TP_ADD_TC(tp, open_nonexisting_object);1971ATF_TP_ADD_TC(tp, open_create_existing_object);1972ATF_TP_ADD_TC(tp, shm_functionality_across_fork);1973ATF_TP_ADD_TC(tp, trunc_resets_object);1974ATF_TP_ADD_TC(tp, unlink_bad_path_pointer);1975ATF_TP_ADD_TC(tp, unlink_path_too_long);1976ATF_TP_ADD_TC(tp, object_resize);1977ATF_TP_ADD_TC(tp, cloexec);1978ATF_TP_ADD_TC(tp, mode);1979ATF_TP_ADD_TC(tp, fallocate);1980ATF_TP_ADD_TC(tp, fspacectl);1981ATF_TP_ADD_TC(tp, accounting);1982ATF_TP_ADD_TC(tp, mmap_prot);1983ATF_TP_ADD_TC(tp, largepage_basic);1984ATF_TP_ADD_TC(tp, largepage_config);1985ATF_TP_ADD_TC(tp, largepage_mmap);1986ATF_TP_ADD_TC(tp, largepage_munmap);1987ATF_TP_ADD_TC(tp, largepage_madvise);1988ATF_TP_ADD_TC(tp, largepage_mlock);1989ATF_TP_ADD_TC(tp, largepage_msync);1990ATF_TP_ADD_TC(tp, largepage_mprotect);1991ATF_TP_ADD_TC(tp, largepage_minherit);1992ATF_TP_ADD_TC(tp, largepage_pipe);1993ATF_TP_ADD_TC(tp, largepage_reopen);19941995return (atf_no_error());1996}199719981999