0001
0002
0003
0004
0005
0006
0007
0008 #define _GNU_SOURCE
0009
0010 #include <stdio.h>
0011 #include <errno.h>
0012 #include <unistd.h>
0013 #include <stdlib.h>
0014 #include <sys/mman.h>
0015 #include <string.h>
0016 #include <fcntl.h>
0017
0018 #include "../kselftest.h"
0019 #include "../kselftest_harness.h"
0020
0021
0022 #define MB (1UL << 20)
0023 #define FILE_SIZE (4 * MB)
0024
0025
0026
0027
0028
0029
0030 TEST(basic_interface)
0031 {
0032 int retval;
0033 int page_size;
0034 unsigned char vec[1];
0035 char *addr;
0036
0037 page_size = sysconf(_SC_PAGESIZE);
0038
0039
0040 retval = mincore(0, 0, vec);
0041 EXPECT_EQ(0, retval);
0042
0043
0044 errno = 0;
0045 retval = mincore(NULL, page_size, vec);
0046 EXPECT_EQ(-1, retval);
0047 EXPECT_EQ(ENOMEM, errno);
0048
0049 errno = 0;
0050 addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
0051 MAP_SHARED | MAP_ANONYMOUS, -1, 0);
0052 ASSERT_NE(MAP_FAILED, addr) {
0053 TH_LOG("mmap error: %s", strerror(errno));
0054 }
0055
0056
0057 errno = 0;
0058 retval = mincore(addr + 1, page_size, vec);
0059 EXPECT_EQ(-1, retval);
0060 EXPECT_EQ(EINVAL, errno);
0061
0062
0063 errno = 0;
0064 retval = mincore(addr, -1, vec);
0065 EXPECT_EQ(-1, retval);
0066 EXPECT_EQ(ENOMEM, errno);
0067
0068
0069 errno = 0;
0070 retval = mincore(addr, page_size, NULL);
0071 EXPECT_EQ(-1, retval);
0072 EXPECT_EQ(EFAULT, errno);
0073 munmap(addr, page_size);
0074 }
0075
0076
0077
0078
0079
0080
0081
0082
0083 TEST(check_anonymous_locked_pages)
0084 {
0085 unsigned char vec[1];
0086 char *addr;
0087 int retval;
0088 int page_size;
0089
0090 page_size = sysconf(_SC_PAGESIZE);
0091
0092
0093 errno = 0;
0094 addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
0095 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
0096 ASSERT_NE(MAP_FAILED, addr) {
0097 TH_LOG("mmap error: %s", strerror(errno));
0098 }
0099 retval = mincore(addr, page_size, vec);
0100 ASSERT_EQ(0, retval);
0101 ASSERT_EQ(0, vec[0]) {
0102 TH_LOG("Page found in memory before use");
0103 }
0104
0105
0106 addr[0] = 1;
0107 mlock(addr, page_size);
0108 retval = mincore(addr, page_size, vec);
0109 ASSERT_EQ(0, retval);
0110 ASSERT_EQ(1, vec[0]) {
0111 TH_LOG("Page not found in memory after use");
0112 }
0113
0114
0115
0116
0117
0118 munlock(addr, page_size);
0119 madvise(addr, page_size, MADV_DONTNEED);
0120 retval = mincore(addr, page_size, vec);
0121 ASSERT_EQ(0, retval);
0122 ASSERT_EQ(0, vec[0]) {
0123 TH_LOG("Page in memory after being zapped");
0124 }
0125 munmap(addr, page_size);
0126 }
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139 TEST(check_huge_pages)
0140 {
0141 unsigned char vec[1];
0142 char *addr;
0143 int retval;
0144 int page_size;
0145
0146 page_size = sysconf(_SC_PAGESIZE);
0147
0148 errno = 0;
0149 addr = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
0150 MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
0151 -1, 0);
0152 if (addr == MAP_FAILED) {
0153 if (errno == ENOMEM)
0154 SKIP(return, "No huge pages available.");
0155 else
0156 TH_LOG("mmap error: %s", strerror(errno));
0157 }
0158 retval = mincore(addr, page_size, vec);
0159 ASSERT_EQ(0, retval);
0160 ASSERT_EQ(0, vec[0]) {
0161 TH_LOG("Page found in memory before use");
0162 }
0163
0164 addr[0] = 1;
0165 mlock(addr, page_size);
0166 retval = mincore(addr, page_size, vec);
0167 ASSERT_EQ(0, retval);
0168 ASSERT_EQ(1, vec[0]) {
0169 TH_LOG("Page not found in memory after use");
0170 }
0171
0172 munlock(addr, page_size);
0173 munmap(addr, page_size);
0174 }
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187 TEST(check_file_mmap)
0188 {
0189 unsigned char *vec;
0190 int vec_size;
0191 char *addr;
0192 int retval;
0193 int page_size;
0194 int fd;
0195 int i;
0196 int ra_pages = 0;
0197
0198 page_size = sysconf(_SC_PAGESIZE);
0199 vec_size = FILE_SIZE / page_size;
0200 if (FILE_SIZE % page_size)
0201 vec_size++;
0202
0203 vec = calloc(vec_size, sizeof(unsigned char));
0204 ASSERT_NE(NULL, vec) {
0205 TH_LOG("Can't allocate array");
0206 }
0207
0208 errno = 0;
0209 fd = open(".", O_TMPFILE | O_RDWR, 0600);
0210 if (fd < 0) {
0211 ASSERT_EQ(errno, EOPNOTSUPP) {
0212 TH_LOG("Can't create temporary file: %s",
0213 strerror(errno));
0214 }
0215 SKIP(goto out_free, "O_TMPFILE not supported by filesystem.");
0216 }
0217 errno = 0;
0218 retval = fallocate(fd, 0, 0, FILE_SIZE);
0219 if (retval) {
0220 ASSERT_EQ(errno, EOPNOTSUPP) {
0221 TH_LOG("Error allocating space for the temporary file: %s",
0222 strerror(errno));
0223 }
0224 SKIP(goto out_close, "fallocate not supported by filesystem.");
0225 }
0226
0227
0228
0229
0230 errno = 0;
0231 addr = mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE,
0232 MAP_SHARED, fd, 0);
0233 ASSERT_NE(MAP_FAILED, addr) {
0234 TH_LOG("mmap error: %s", strerror(errno));
0235 }
0236 retval = mincore(addr, FILE_SIZE, vec);
0237 ASSERT_EQ(0, retval);
0238 for (i = 0; i < vec_size; i++) {
0239 ASSERT_EQ(0, vec[i]) {
0240 TH_LOG("Unexpected page in memory");
0241 }
0242 }
0243
0244
0245
0246
0247
0248 addr[FILE_SIZE / 2] = 1;
0249 retval = mincore(addr, FILE_SIZE, vec);
0250 ASSERT_EQ(0, retval);
0251 ASSERT_EQ(1, vec[FILE_SIZE / 2 / page_size]) {
0252 TH_LOG("Page not found in memory after use");
0253 }
0254
0255 i = FILE_SIZE / 2 / page_size + 1;
0256 while (i < vec_size && vec[i]) {
0257 ra_pages++;
0258 i++;
0259 }
0260 EXPECT_GT(ra_pages, 0) {
0261 TH_LOG("No read-ahead pages found in memory");
0262 }
0263
0264 EXPECT_LT(i, vec_size) {
0265 TH_LOG("Read-ahead pages reached the end of the file");
0266 }
0267
0268
0269
0270
0271 if (i < vec_size) {
0272 while (i < vec_size && !vec[i])
0273 i++;
0274 EXPECT_EQ(vec_size, i) {
0275 TH_LOG("Unexpected page in memory beyond readahead window");
0276 }
0277 }
0278
0279 munmap(addr, FILE_SIZE);
0280 out_close:
0281 close(fd);
0282 out_free:
0283 free(vec);
0284 }
0285
0286
0287
0288
0289
0290
0291
0292 TEST(check_tmpfs_mmap)
0293 {
0294 unsigned char *vec;
0295 int vec_size;
0296 char *addr;
0297 int retval;
0298 int page_size;
0299 int fd;
0300 int i;
0301 int ra_pages = 0;
0302
0303 page_size = sysconf(_SC_PAGESIZE);
0304 vec_size = FILE_SIZE / page_size;
0305 if (FILE_SIZE % page_size)
0306 vec_size++;
0307
0308 vec = calloc(vec_size, sizeof(unsigned char));
0309 ASSERT_NE(NULL, vec) {
0310 TH_LOG("Can't allocate array");
0311 }
0312
0313 errno = 0;
0314 fd = open("/dev/shm", O_TMPFILE | O_RDWR, 0600);
0315 ASSERT_NE(-1, fd) {
0316 TH_LOG("Can't create temporary file: %s",
0317 strerror(errno));
0318 }
0319 errno = 0;
0320 retval = fallocate(fd, 0, 0, FILE_SIZE);
0321 ASSERT_EQ(0, retval) {
0322 TH_LOG("Error allocating space for the temporary file: %s",
0323 strerror(errno));
0324 }
0325
0326
0327
0328
0329 errno = 0;
0330 addr = mmap(NULL, FILE_SIZE, PROT_READ | PROT_WRITE,
0331 MAP_SHARED, fd, 0);
0332 ASSERT_NE(MAP_FAILED, addr) {
0333 TH_LOG("mmap error: %s", strerror(errno));
0334 }
0335 retval = mincore(addr, FILE_SIZE, vec);
0336 ASSERT_EQ(0, retval);
0337 for (i = 0; i < vec_size; i++) {
0338 ASSERT_EQ(0, vec[i]) {
0339 TH_LOG("Unexpected page in memory");
0340 }
0341 }
0342
0343
0344
0345
0346
0347 addr[FILE_SIZE / 2] = 1;
0348 retval = mincore(addr, FILE_SIZE, vec);
0349 ASSERT_EQ(0, retval);
0350 ASSERT_EQ(1, vec[FILE_SIZE / 2 / page_size]) {
0351 TH_LOG("Page not found in memory after use");
0352 }
0353
0354 i = FILE_SIZE / 2 / page_size + 1;
0355 while (i < vec_size && vec[i]) {
0356 ra_pages++;
0357 i++;
0358 }
0359 ASSERT_EQ(ra_pages, 0) {
0360 TH_LOG("Read-ahead pages found in memory");
0361 }
0362
0363 munmap(addr, FILE_SIZE);
0364 close(fd);
0365 free(vec);
0366 }
0367
0368 TEST_HARNESS_MAIN