1 /* 2 * Copyright (c) 2021 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29 #include <darwintest.h> 30 #include <TargetConditionals.h> 31 32 #include <errno.h> 33 #include <fcntl.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <unistd.h> 38 39 #include <sys/mman.h> 40 #include <sys/sysctl.h> 41 #include <sys/types.h> 42 43 #include <mach/vm_page_size.h> 44 45 T_GLOBAL_META( 46 T_META_NAMESPACE("xnu.vm"), 47 T_META_RADAR_COMPONENT_NAME("xnu"), 48 T_META_RADAR_COMPONENT_VERSION("VM")); 49 50 #define FILENAME "/tmp/test-77350114.data" 51 #define MAPSIZE (2*1024*1024) 52 53 T_DECL(mmap_resilient_media, 54 "test mmap(MAP_RESILIENT_MEDIA)", 55 T_META_ASROOT(true), T_META_TAG_VM_PREFERRED) 56 { 57 int ret; 58 int new_rate, old_rate1, old_rate2, old_rate3; 59 size_t old_size; 60 int fd; 61 ssize_t nbytes; 62 unsigned char *addr; 63 int i; 64 65 /* 66 * SETUP 67 */ 68 /* save error injection rates and set new ones */ 69 old_size = sizeof(old_rate1); 70 new_rate = 4; 71 ret = sysctlbyname("vm.fault_resilient_media_inject_error1_rate", 72 &old_rate1, &old_size, 73 &new_rate, sizeof(new_rate)); 74 if (ret < 0) { 75 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error1_rate) error %d (%s)", 76 errno, strerror(errno)); 77 } 78 old_size = sizeof(old_rate2); 79 new_rate = 6; 80 ret = sysctlbyname("vm.fault_resilient_media_inject_error2_rate", 81 &old_rate2, &old_size, 82 &new_rate, sizeof(new_rate)); 83 if (ret < 0) { 84 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error2_rate) error %d (%s)", 85 errno, strerror(errno)); 86 } 87 old_size = sizeof(old_rate3); 88 new_rate = 8; 89 ret = sysctlbyname("vm.fault_resilient_media_inject_error3_rate", 90 &old_rate3, &old_size, 91 &new_rate, sizeof(new_rate)); 92 if (ret < 0) { 93 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error3_rate) error %d (%s)", 94 errno, strerror(errno)); 95 } 96 T_WITH_ERRNO; 97 fd = open(FILENAME, O_RDWR | O_CREAT | O_TRUNC, 0644); 98 T_QUIET; T_ASSERT_POSIX_SUCCESS(fd, "open(%s)", FILENAME); 99 T_WITH_ERRNO; 100 nbytes = write(fd, "x", 1); 101 T_QUIET; T_ASSERT_EQ(nbytes, (ssize_t)1, "write 1 byte"); 102 T_WITH_ERRNO; 103 addr = mmap(NULL, 104 MAPSIZE, 105 PROT_READ | PROT_WRITE, 106 MAP_FILE | MAP_PRIVATE | MAP_RESILIENT_MEDIA, 107 fd, 108 0); 109 T_QUIET; T_ASSERT_NE((void *)addr, MAP_FAILED, "mmap()"); 110 111 /* 112 * TEST 113 */ 114 T_ASSERT_EQ(addr[0], 'x', "first byte is 'x'"); 115 T_LOG("checking that the rest of the mapping is accessible..."); 116 for (i = 1; i < MAPSIZE; i++) { 117 if (i % (2 * (int)vm_page_size) == 0) { 118 /* trigger a write fault every other page */ 119 addr[i] = 'y'; 120 T_QUIET; T_ASSERT_EQ(addr[i], 'y', "byte #0x%x is 'y'", i); 121 } else { 122 T_QUIET; T_ASSERT_EQ(addr[i], 0, "byte #0x%x is 0", i); 123 } 124 } 125 T_PASS("rest of resilient mapping is accessible"); 126 127 /* 128 * CLEANUP 129 */ 130 T_WITH_ERRNO; 131 ret = close(fd); 132 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "close()"); 133 T_WITH_ERRNO; 134 ret = unlink(FILENAME); 135 T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "unlink(%s)", FILENAME); 136 /* restore old error injection rates */ 137 ret = sysctlbyname("vm.fault_resilient_media_inject_error1_rate", 138 NULL, NULL, 139 &old_rate1, sizeof(old_rate1)); 140 if (ret < 0) { 141 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error1_rate) error %d (%s)", 142 errno, strerror(errno)); 143 } 144 ret = sysctlbyname("vm.fault_resilient_media_inject_error2_rate", 145 NULL, NULL, 146 &old_rate2, sizeof(old_rate2)); 147 if (ret < 0) { 148 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error2_rate) error %d (%s)", 149 errno, strerror(errno)); 150 } 151 ret = sysctlbyname("vm.fault_resilient_media_inject_error3_rate", 152 NULL, NULL, 153 &old_rate3, sizeof(old_rate3)); 154 if (ret < 0) { 155 T_LOG("sysctlbyname(vm.fault_resilient_media_inject_error2_rate) error %d (%s)", 156 errno, strerror(errno)); 157 } 158 159 T_PASS("mmap(MAP_RESILIENT_MEDIA)"); 160 } 161