📄 integck.c
字号:
if (errno == ENOSPC) full = 1; CHECK(errno == ENOSPC || errno == EBUSY); free(path); free(name); free(to); return; } free(path); free(to); if (rename_entry && rename_entry->type == entry->type && rename_entry->entry.target == entry->entry.target) { free(name); return; } add_dir_entry(parent, entry->type, name, entry->entry.target); if (rename_entry) remove_dir_entry(rename_entry); remove_dir_entry(entry); free(name);}static size_t str_count(const char *s, char c){ size_t count = 0; char cc; while ((cc = *s++) != '\0') if (cc == c) count += 1; return count;}static char *relative_path(const char *path1, const char *path2){ const char *p1, *p2; char *rel; size_t up, len, len2, i; p1 = path1; p2 = path2; while (*p1 == *p2 && *p1) { p1 += 1; p2 += 1; } len2 = strlen(p2); up = str_count(p1, '/'); if (up == 0 && len2 != 0) return copy_string(p2); if (up == 0 && len2 == 0) { p2 = strrchr(path2, '/'); return copy_string(p2); } if (up == 1 && len2 == 0) return copy_string("."); if (len2 == 0) up -= 1; len = up * 3 + len2 + 1; rel = malloc(len); CHECK(rel != NULL); rel[0] = '\0'; if (up) { strcat(rel, ".."); for (i = 1; i < up; i++) strcat(rel, "/.."); if (len2) strcat(rel, "/"); } if (len2) strcat(rel, p2); return rel;}static char *pick_symlink_target(const char *symlink_path){ struct dir_info *dir; struct dir_entry_info *entry; size_t r; char *path, *rel_path; dir = pick_dir(); if (tests_random_no(100) < 10) return dir_path(dir, make_name(dir)); r = tests_random_no(dir->number_of_entries); entry = dir->first; while (entry && r) { entry = entry->next; --r; } if (!entry) entry = dir->first; if (!entry) return dir_path(dir, make_name(dir)); path = dir_path(dir, entry->name); if (tests_random_no(20) < 10) return path; rel_path = relative_path(symlink_path, path); free(path); return rel_path;}static void symlink_new(struct dir_info *dir, const char *name_){ struct symlink_info *s; char *path, *target, *name = copy_string(name_); size_t sz; path = dir_path(dir, name); target = pick_symlink_target(path); if (symlink(target, path) == -1) { CHECK(errno == ENOSPC || errno == ENAMETOOLONG); if (errno == ENOSPC) full = 1; free(target); free(path); free(name); return; } free(path); sz = sizeof(struct symlink_info); s = malloc(sz); CHECK(s != NULL); memset(s, 0, sz); add_dir_entry(dir, 's', name, s); s->target_pathname = target; free(name);}static void symlink_remove(struct symlink_info *symlink){ char *path; path = dir_path(symlink->entry->parent, symlink->entry->name); remove_dir_entry(symlink->entry); CHECK(unlink(path) != -1); free(path);}static void operate_on_dir(struct dir_info *dir);static void operate_on_file(struct file_info *file);/* Randomly select something to do with a directory entry */static void operate_on_entry(struct dir_entry_info *entry){ /* 1 time in 1000 rename */ if (tests_random_no(1000) == 0) { rename_entry(entry); return; } if (entry->type == 's') { symlink_check(entry->entry.symlink); /* If shrinking, 1 time in 50, remove a symlink */ if (shrink && tests_random_no(50) == 0) symlink_remove(entry->entry.symlink); return; } if (entry->type == 'd') { /* If shrinking, 1 time in 50, remove a directory */ if (shrink && tests_random_no(50) == 0) { dir_remove(entry->entry.dir); return; } operate_on_dir(entry->entry.dir); } if (entry->type == 'f') { /* If shrinking, 1 time in 10, remove a file */ if (shrink && tests_random_no(10) == 0) { file_delete(entry->entry.file); return; } /* If not growing, 1 time in 10, unlink a file with links > 1 */ if (!grow && entry->entry.file->link_count > 1 && tests_random_no(10) == 0) { file_unlink_file(entry->entry.file); return; } operate_on_file(entry->entry.file); }}/* Randomly select something to do with a directory */static void operate_on_dir(struct dir_info *dir){ size_t r; struct dir_entry_info *entry; struct file_info *file; r = tests_random_no(14); if (r == 0 && grow) /* When growing, 1 time in 14 create a file */ file_new(dir, make_name(dir)); else if (r == 1 && grow) /* When growing, 1 time in 14 create a directory */ dir_new(dir, make_name(dir)); else if (r == 2 && grow && (file = pick_file()) != NULL) /* When growing, 1 time in 14 create a hard link */ link_new(dir, make_name(dir), file); else if (r == 3 && grow && tests_random_no(5) == 0) /* When growing, 1 time in 70 create a symbolic link */ symlink_new(dir, make_name(dir)); else { /* Otherwise randomly select an entry to operate on */ r = tests_random_no(dir->number_of_entries); entry = dir->first; while (entry && r) { entry = entry->next; --r; } if (entry) operate_on_entry(entry); }}/* Randomly select something to do with a file */static void operate_on_file(struct file_info *file){ /* Try to keep at least 10 files open */ if (open_files_count < 10) { file_open(file); return; } /* Try to keep about 20 files open */ if (open_files_count < 20 && tests_random_no(2) == 0) { file_open(file); return; } /* Try to keep up to 40 files open */ if (open_files_count < 40 && tests_random_no(20) == 0) { file_open(file); return; } /* Occasionly truncate */ if (shrink && tests_random_no(100) == 0) { file_truncate_file(file); return; } /* Mostly just write */ file_write_file(file); /* Once in a while check it too */ if (tests_random_no(100) == 1) { int fd = -2; if (file->links) fd = -1; else if (file->fds) fd = file->fds->fd; if (fd != -2) { check_run_no += 1; file_check(file, fd); } }}/* Randomly select something to do with an open file */static void operate_on_open_file(struct fd_info *fdi){ size_t r; r = tests_random_no(1000); if (shrink && r < 5) file_truncate(fdi->file, fdi->fd); else if (r < 21) file_close(fdi); else if (shrink && r < 121 && !fdi->file->deleted) file_delete(fdi->file); else { file_write(fdi->file, fdi->fd); if (r >= 999) { if (tests_random_no(100) >= 50) CHECK(fsync(fdi->fd) != -1); else CHECK(fdatasync(fdi->fd) != -1); } }}/* Select an open file at random */static void operate_on_an_open_file(void){ size_t r; struct open_file_info *ofi; /* When shrinking, close all open files 1 time in 128 */ if (shrink) { static int x = 0; x += 1; x &= 127; if (x == 0) { close_open_files(); return; } } /* Close any open files that have errored */ if (!check_nospc_files) { ofi = open_files; while (ofi) { if (ofi->fdi->file->no_space_error) { struct fd_info *fdi; fdi = ofi->fdi; ofi = ofi->next; file_close(fdi); } else ofi = ofi->next; } } r = tests_random_no(open_files_count); for (ofi = open_files; ofi; ofi = ofi->next, --r) if (!r) { operate_on_open_file(ofi->fdi); return; }}static void do_an_operation(void){ /* Half the time operate on already open files */ if (tests_random_no(100) < 50) operate_on_dir(top_dir); else operate_on_an_open_file();}static void create_test_data(void){ uint64_t i, n; grow = 1; shrink = 0; full = 0; operation_count = 0; while (!full) { do_an_operation(); ++operation_count; } grow = 0; shrink = 1; /* Drop to less than 90% full */ n = operation_count / 40; while (n--) { uint64_t free; uint64_t total; for (i = 0; i < 10; ++i) do_an_operation(); free = tests_get_free_space(); total = tests_get_total_space(); if ((free * 100) / total >= 10) break; } grow = 0; shrink = 0; full = 0; n = operation_count * 2; for (i = 0; i < n; ++i) do_an_operation();}static void update_test_data(void){ uint64_t i, n; grow = 1; shrink = 0; full = 0; while (!full) do_an_operation(); grow = 0; shrink = 1; /* Drop to less than 50% full */ n = operation_count / 10; while (n--) { uint64_t free; uint64_t total; for (i = 0; i < 10; ++i) do_an_operation(); free = tests_get_free_space(); total = tests_get_total_space(); if ((free * 100) / total >= 50) break; } grow = 0; shrink = 0; full = 0; n = operation_count * 2; for (i = 0; i < n; ++i) do_an_operation();}void integck(void){ pid_t pid; int64_t rpt; uint64_t z; char dir_name[256]; /* Get memory page size for mmap */ mem_page_size = sysconf(_SC_PAGE_SIZE); CHECK(mem_page_size > 0); /* Make our top directory */ pid = getpid(); printf("pid is %u\n", (unsigned) pid); tests_cat_pid(dir_name, "integck_test_dir_", pid); if (chdir(dir_name) != -1) { /* Remove it if it is already there */ tests_clear_dir("."); CHECK(chdir("..") != -1); CHECK(rmdir(dir_name) != -1); } initial_free_space = tests_get_free_space(); log10_initial_free_space = 0; for (z = initial_free_space; z >= 10; z /= 10) ++log10_initial_free_space; top_dir = dir_new(NULL, dir_name); if (!top_dir) return; srand(pid); create_test_data(); if (!tests_fs_is_rootfs()) { close_open_files(); tests_remount(); /* Requires root access */ } /* Check everything */ check_run_no += 1; dir_check(top_dir); check_deleted_files(); for (rpt = 0; tests_repeat_parameter == 0 || rpt < tests_repeat_parameter; ++rpt) { update_test_data(); if (!tests_fs_is_rootfs()) { close_open_files(); tests_remount(); /* Requires root access */ } /* Check everything */ check_run_no += 1; dir_check(top_dir); check_deleted_files(); } /* Tidy up by removing everything */ close_open_files(); tests_clear_dir(dir_name); CHECK(rmdir(dir_name) != -1);}/* Title of this test */const char *integck_get_title(void){ return "Test file system integrity";}/* Description of this test */const char *integck_get_description(void){ return "Create a directory named integck_test_dir_pid " \ "where pid is the process id. " \ "Randomly create and delete files and directories. " \ "Randomly write to and truncate files. " \ "Un-mount and re-mount test file " \ "system (if it is not the root file system ). " \ "Check data. Make more random changes. " \ "Un-mount and re-mount again. Check again. " \ "Repeat some number of times. " "The repeat count is set by the -n or --repeat option, " \ "otherwise it defaults to 1. " \ "A repeat count of zero repeats forever.";}int main(int argc, char *argv[]){ int run_test; /* Set default test repetition */ tests_repeat_parameter = 1; /* Handle common arguments */ run_test = tests_get_args(argc, argv, integck_get_title(), integck_get_description(), "n"); if (!run_test) return 1; /* Change directory to the file system and check it is ok for testing */ tests_check_test_file_system(); /* * We expect accurate file size from ubifs even after "no space" * errors. And we can mmap. */ if (strcmp(tests_file_system_type, "ubifs") == 0) { check_nospc_files = 1; can_mmap = 1; } /* Do the actual test */ integck(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -