diff --git a/tools/testing/selftests/filesystems/incfs/Makefile b/tools/testing/selftests/filesystems/incfs/Makefile index 5a2f6301c4b2..7a44efad0b37 100644 --- a/tools/testing/selftests/filesystems/incfs/Makefile +++ b/tools/testing/selftests/filesystems/incfs/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -CFLAGS += -D_FILE_OFFSET_BITS=64 -Wall -Werror -I../.. -I../../../../.. -fno-omit-frame-pointer -fsanitize=address -g +CFLAGS += -D_FILE_OFFSET_BITS=64 -Wall -Werror -Wno-deprecated-declarations -I../.. -I../../../../.. -fno-omit-frame-pointer -fsanitize=address -g LDLIBS := -llz4 -lzstd -lcrypto -lpthread -fsanitize=address TEST_GEN_PROGS := incfs_test incfs_stress incfs_perf diff --git a/tools/testing/selftests/filesystems/incfs/incfs_test.c b/tools/testing/selftests/filesystems/incfs/incfs_test.c index 10c15fadc959..eb7cc862ff5b 100644 --- a/tools/testing/selftests/filesystems/incfs/incfs_test.c +++ b/tools/testing/selftests/filesystems/incfs/incfs_test.c @@ -60,7 +60,6 @@ struct { int file; - int test; bool verbose; } options; @@ -935,12 +934,13 @@ static int load_hash_tree(const char *mount_dir, struct test_file *file) struct incfs_fill_blocks fill_blocks = { .count = file->mtree_block_count, }; - struct incfs_fill_block *fill_block_array = - calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); + struct incfs_fill_block *fill_block_array; if (fill_blocks.count == 0) return 0; + fill_block_array = + calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); if (!fill_block_array) return -ENOMEM; fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); @@ -1070,6 +1070,7 @@ static int cant_touch_index_test(const char *mount_dir) free(index_path); free(dst_name); free(filename_in_index); + free(file_path); if (umount(mount_dir) != 0) { print_error("Can't unmout FS"); goto failure; @@ -1082,6 +1083,7 @@ failure: free(dst_name); free(index_path); free(filename_in_index); + free(file_path); close(cmd_fd); umount(mount_dir); return TEST_FAILURE; @@ -1353,9 +1355,13 @@ static int basic_file_ops_test(const char *mount_dir) goto failure; } + free(subdir1); + free(subdir2); return TEST_SUCCESS; failure: + free(subdir1); + free(subdir2); close(cmd_fd); umount(mount_dir); return TEST_FAILURE; @@ -2637,13 +2643,14 @@ static int emit_partial_test_file_hash(const char *mount_dir, struct incfs_fill_blocks fill_blocks = { .count = 1, }; - struct incfs_fill_block *fill_block_array = - calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); + struct incfs_fill_block *fill_block_array; uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE]; if (file->size <= 4096 / 32 * 4096) return 0; + fill_block_array = + calloc(fill_blocks.count, sizeof(struct incfs_fill_block)); if (!fill_block_array) return -ENOMEM; fill_blocks.fill_blocks = ptr_to_u64(fill_block_array); @@ -2678,7 +2685,7 @@ failure: static int validate_hash_ranges(const char *mount_dir, struct test_file *file) { int block_cnt = 1 + (file->size - 1) / INCFS_DATA_FILE_BLOCK_SIZE; - char *filename = concat_file_name(mount_dir, file->name); + char *filename = NULL; int fd; struct incfs_filled_range ranges[128]; struct incfs_get_filled_blocks_args fba = { @@ -2694,6 +2701,7 @@ static int validate_hash_ranges(const char *mount_dir, struct test_file *file) if (file->size <= 4096 / 32 * 4096) return 0; + filename = concat_file_name(mount_dir, file->name); fd = open(filename, O_RDONLY | O_CLOEXEC); free(filename); if (fd <= 0) @@ -2805,12 +2813,8 @@ static int large_file_test(const char *mount_dir) int result = TEST_FAILURE, ret; uint8_t data[INCFS_DATA_FILE_BLOCK_SIZE] = {}; int block_count = THREE_GB / INCFS_DATA_FILE_BLOCK_SIZE; - struct incfs_fill_block *block_buf = - calloc(block_count, sizeof(struct incfs_fill_block)); - struct incfs_fill_blocks fill_blocks = { - .count = block_count, - .fill_blocks = ptr_to_u64(block_buf), - }; + struct incfs_fill_block *block_buf = NULL; + struct incfs_fill_blocks fill_blocks; incfs_uuid_t id; int fd = -1; struct statvfs svfs; @@ -2846,6 +2850,14 @@ static int large_file_test(const char *mount_dir) NULL) < 0) goto failure; + block_buf = calloc(block_count, sizeof(struct incfs_fill_block)); + if (!block_buf) + goto failure; + fill_blocks = (struct incfs_fill_blocks) { + .count = block_count, + .fill_blocks = ptr_to_u64(block_buf), + }; + for (i = 0; i < block_count; i++) { block_buf[i].compression = COMPRESSION_NONE; block_buf[i].block_index = i; @@ -2872,6 +2884,7 @@ failure: unlink("very_large_file"); umount(mount_dir); free(backing_dir); + free(block_buf); return result; } @@ -3429,7 +3442,7 @@ out: static int is_close(struct timespec *start, int expected_ms) { - const int allowed_variance = 100; + const int allowed_variance = 500; int result = TEST_FAILURE; struct timespec finish; int diff; @@ -3438,7 +3451,11 @@ static int is_close(struct timespec *start, int expected_ms) diff = (finish.tv_sec - start->tv_sec) * 1000 + (finish.tv_nsec - start->tv_nsec) / 1000000; - TESTCOND(diff >= expected_ms - allowed_variance); + if(diff < expected_ms - allowed_variance || diff > expected_ms + allowed_variance) { + printf("%d %d %d\n", diff, expected_ms, allowed_variance); + } + + TESTCOND(diff >= expected_ms); TESTCOND(diff <= expected_ms + allowed_variance); result = TEST_SUCCESS; out: @@ -3519,13 +3536,13 @@ static int per_uid_read_timeouts_test(const char *mount_dir) purt_set[0].max_pending_time_us); /* Still 1000 in UID 2 */ - TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0); TEST(pid = fork(), pid != -1); if (pid == 0) { TESTEQUAL(setuid(2), 0); TESTEQUAL(pread(fd, buffer, sizeof(buffer), 0), -1); exit(0); } + TESTEQUAL(clock_gettime(CLOCK_MONOTONIC, &start), 0); TESTNE(wait(&status), -1); TESTEQUAL(WEXITSTATUS(status), 0); TESTEQUAL(is_close(&start, 1000), 0); @@ -3965,7 +3982,7 @@ static int memzero(const unsigned char *buf, size_t size) static int validate_verity(const char *mount_dir, struct test_file *file) { int result = TEST_FAILURE; - char *filename = concat_file_name(mount_dir, file->name); + char *filename = 0; int fd = -1; uint64_t flags; struct fsverity_digest *digest; @@ -4226,6 +4243,8 @@ static int mmap_test(const char *mount_dir) char *filename = NULL; int fd = -1; char *addr = (void *)-1; + int pid = -1; + int status; TEST(backing_dir = create_backing_dir(mount_dir), backing_dir); TESTEQUAL(mount_fs(mount_dir, backing_dir, 0), 0); @@ -4242,23 +4261,26 @@ static int mmap_test(const char *mount_dir) TEST(fd = open(filename, O_RDONLY | O_CLOEXEC), fd != -1); TEST(addr = mmap(NULL, file.size, PROT_READ, MAP_PRIVATE, fd, 0), addr != (void *) -1); - TESTEQUAL(mlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0); - TESTEQUAL(munlock(addr, INCFS_DATA_FILE_BLOCK_SIZE), 0); - TESTEQUAL(mlock(addr + shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE, - INCFS_DATA_FILE_BLOCK_SIZE), -1); - TESTEQUAL(mlock(addr + (shas_per_block - 1) * - INCFS_DATA_FILE_BLOCK_SIZE, - INCFS_DATA_FILE_BLOCK_SIZE), 0); - TESTEQUAL(munlock(addr + (shas_per_block - 1) * - INCFS_DATA_FILE_BLOCK_SIZE, - INCFS_DATA_FILE_BLOCK_SIZE), 0); - TESTEQUAL(mlock(addr + (shas_per_block - 1) * - INCFS_DATA_FILE_BLOCK_SIZE, - INCFS_DATA_FILE_BLOCK_SIZE * 2), -1); + TESTEQUAL(addr[0], 57); + + TEST(pid = fork(), pid != -1); + if (pid == 0) { + fclose(stderr); + TESTEQUAL(addr[shas_per_block * INCFS_DATA_FILE_BLOCK_SIZE], + -71); + exit(0); + } + TESTNE(wait(&status), -1); + TESTEQUAL(status, 256); + + TESTEQUAL(addr[(shas_per_block - 1) * INCFS_DATA_FILE_BLOCK_SIZE], 76); TESTEQUAL(munmap(addr, file.size), 0); + addr = (void *) -1; result = TEST_SUCCESS; out: + if (addr != (void *) -1) + munmap(addr, file.size); free(file.mtree); close(fd); free(filename); @@ -4677,7 +4699,50 @@ static char *setup_mount_dir() return mount_dir; } -int parse_options(int argc, char *const *argv) +static void parse_range(const char *ranges, bool *run_test, size_t tests) +{ + size_t i; + char *range; + + for (i = 0; i < tests; ++i) + run_test[i] = false; + + range = strtok(optarg, ","); + while (range) { + char *dash = strchr(range, '-'); + + if (dash) { + size_t start = 1, end = tests; + char *end_ptr; + + if (dash > range) { + start = strtol(range, &end_ptr, 10); + if (*end_ptr != '-' || start <= 0 || start > tests) + ksft_exit_fail_msg("Bad range\n"); + } + + if (dash[1]) { + end = strtol(dash + 1, &end_ptr, 10); + if (*end_ptr || end <= start || end > tests) + ksft_exit_fail_msg("Bad range\n"); + } + + for (i = start; i <= end; ++i) + run_test[i - 1] = true; + } else { + char *end; + long value = strtol(range, &end, 10); + + if (*end || value <= 0 || value > tests) + ksft_exit_fail_msg("Bad range\n"); + run_test[value - 1] = true; + } + range = strtok(NULL, ","); + } +} + +int parse_options(int argc, char *const *argv, bool *run_test, + size_t tests) { signed char c; @@ -4688,7 +4753,7 @@ int parse_options(int argc, char *const *argv) break; case 't': - options.test = strtol(optarg, NULL, 10); + parse_range(optarg, run_test, tests); break; case 'v': @@ -4728,9 +4793,6 @@ int main(int argc, char *argv[]) int i; int fd, count; - if (parse_options(argc, argv)) - ksft_exit_fail_msg("Bad options\n"); - // Seed randomness pool for testing on QEMU // NOTE - this abuses the concept of randomness - do *not* ever do this // on a machine for production use - the device will think it has good @@ -4784,18 +4846,20 @@ int main(int argc, char *argv[]) MAKE_TEST(stacked_mount_test), }; #undef MAKE_TEST + bool run_test[ARRAY_SIZE(cases)]; - if (options.test) { - if (options.test <= 0 || options.test > ARRAY_SIZE(cases)) - ksft_exit_fail_msg("Invalid test\n"); + for (int i = 0; i < ARRAY_SIZE(cases); ++i) + run_test[i] = true; - ksft_set_plan(1); - run_one_test(mount_dir, &cases[options.test - 1]); - } else { - ksft_set_plan(ARRAY_SIZE(cases)); - for (i = 0; i < ARRAY_SIZE(cases); ++i) + if (parse_options(argc, argv, run_test, ARRAY_SIZE(cases))) + ksft_exit_fail_msg("Bad options\n"); + + ksft_set_plan(ARRAY_SIZE(cases)); + for (i = 0; i < ARRAY_SIZE(run_test); ++i) + if (run_test[i]) run_one_test(mount_dir, &cases[i]); - } + else + ksft_cnt.ksft_xskip++; umount2(mount_dir, MNT_FORCE); rmdir(mount_dir);