diff options
-rw-r--r-- | tests/fs-tests/integrity/integck.c | 151 |
1 files changed, 131 insertions, 20 deletions
diff --git a/tests/fs-tests/integrity/integck.c b/tests/fs-tests/integrity/integck.c index 8a53c05..1919034 100644 --- a/tests/fs-tests/integrity/integck.c +++ b/tests/fs-tests/integrity/integck.c @@ -29,6 +29,7 @@ #include <errno.h> #include <limits.h> #include <dirent.h> +#include <sys/mman.h> #include "tests.h" @@ -107,6 +108,13 @@ static uint64_t initial_free_space = 0; /* Free space on file system when test starts */ static unsigned log10_initial_free_space = 0; /* log10 of initial_free_space */ +static int check_nospc_files = 0; /* Also check data in files that incurred a + "no space" error */ + +static int can_mmap = 0; /* Can write via mmap */ + +static long mem_page_size; /* Page size for mmap */ + static char *copy_string(const char *s) { char *str; @@ -422,7 +430,7 @@ static void file_info_display(struct file_info *file) (file->deleted == 0) ? "false" : "true"); fprintf(stderr, " File was out of space: %s\n", (file->no_space_error == 0) ? "false" : "true"); - fprintf(stderr, " Write Info:\n"); + fprintf(stderr, " File Data:\n"); wcnt = 0; w = file->writes; while (w) { @@ -437,7 +445,7 @@ static void file_info_display(struct file_info *file) } fprintf(stderr, " %u writes\n", wcnt); fprintf(stderr, " ============================================\n"); - fprintf(stderr, " Raw Write Info:\n"); + fprintf(stderr, " Write Info:\n"); wcnt = 0; w = file->raw_writes; while (w) { @@ -461,11 +469,13 @@ static void file_info_display(struct file_info *file) static struct fd_info *file_open(struct file_info *file) { - int fd; + int fd, flags = O_RDWR; char *path; path = dir_path(file->parent, file->name); - fd = open(path, O_RDWR); + if (tests_random_no(100) == 1) + flags |= O_SYNC; + fd = open(path, flags); CHECK(fd != -1); free(path); return fd_new(file, fd); @@ -654,7 +664,7 @@ static int file_ftruncate(struct file_info *file, int fd, off_t new_length) CHECK(errno = ENOSPC); file->no_space_error = 1; /* Delete errored files */ - if (!file->deleted) { + if (!check_nospc_files && !file->deleted) { struct fd_info *fdi; fdi = file->fds; @@ -669,6 +679,71 @@ static int file_ftruncate(struct file_info *file, int fd, off_t new_length) return 1; } +static void file_mmap_write(struct file_info *file) +{ + size_t write_cnt = 0, r, i, len, size; + struct write_info *w = file->writes; + void *addr; + char *waddr; + off_t offs, offset; + unsigned seed; + uint64_t free_space; + int fd; + char *path; + + free_space = tests_get_free_space(); + if (!free_space) + return; + /* Randomly pick a written area of the file */ + if (!w) + return; + while (w) { + write_cnt += 1; + w = w->next; + } + r = tests_random_no(write_cnt); + w = file->writes; + for (i = 0; w && w->next && i < r; i++) + w = w->next; + + offs = (w->offset / mem_page_size) * mem_page_size; + len = w->size + (w->offset - offs); + if (len > 1 << 24) + len = 1 << 24; + + /* Open it */ + path = dir_path(file->parent, file->name); + fd = open(path, O_RDWR); + CHECK(fd != -1); + free(path); + + /* mmap it */ + addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offs); + CHECK(close(fd) != -1); + CHECK(addr != MAP_FAILED); + + /* Randomly select a part of the mmapped area to write */ + size = tests_random_no(w->size); + if (size > free_space) + size = free_space; + if (size == 0) + size = 1; + offset = w->offset + tests_random_no(w->size - size); + + /* Write it */ + seed = tests_random_no(10000000); + srand(seed); + waddr = addr + (offset - offs); + for (i = 0; i < size; i++) + waddr[i] = rand(); + + /* Unmap it */ + CHECK(munmap(addr, len) != -1); + + /* Record what was written */ + file_write_info(file, offset, size, seed); +} + static void file_write(struct file_info *file, int fd) { off_t offset; @@ -676,6 +751,11 @@ static void file_write(struct file_info *file, int fd) unsigned seed; int truncate = 0; + if (can_mmap && !full && !file->deleted && tests_random_no(100) == 1) { + file_mmap_write(file); + return; + } + get_offset_and_size(file, &offset, &size); seed = tests_random_no(10000000); actual = file_write_data(file, fd, offset, size, seed); @@ -690,7 +770,7 @@ static void file_write(struct file_info *file, int fd) file_write_info(file, offset, actual, seed); /* Delete errored files */ - if (file->no_space_error) { + if (!check_nospc_files && file->no_space_error) { if (!file->deleted) { struct fd_info *fdi; @@ -867,7 +947,7 @@ static void save_file(int fd, struct file_info *file) /* Start at the beginning */ CHECK(lseek(fd, 0, SEEK_SET) != (off_t) -1); - + for (;;) { ssize_t r = read(fd, buf, BUFFER_SIZE); CHECK(r != -1); @@ -966,7 +1046,7 @@ static void file_check(struct file_info *file, int fd) struct write_info *w; /* Do not check files that have errored */ - if (file->no_space_error) + if (!check_nospc_files && file->no_space_error) return; if (fd == -1) open_and_close = 1; @@ -1135,7 +1215,15 @@ static char *make_name(struct dir_info *dir) do { found = 0; - sprintf(name, "%u", (unsigned) tests_random_no(1000000)); + if (tests_random_no(5) == 1) { + int i, n = tests_random_no(255) + 1; + + CHECK(n > 0 && n < 256); + for (i = 0; i < n; i++) + name[i] = 'a' + tests_random_no(26); + name[i] = '\0'; + } else + sprintf(name, "%u", (unsigned) tests_random_no(1000000)); for (entry = dir->first; entry; entry = entry->next) { if (strcmp(dir_entry_name(entry), name) == 0) { found = 1; @@ -1221,6 +1309,9 @@ static void operate_on_file(struct file_info *file) } /* Mostly just write */ file_write_file(file); + /* Once in a while check it too */ + if (tests_random_no(100) == 1) + file_check(file, -1); } /* Randomly select something to do with an open file */ @@ -1235,8 +1326,15 @@ static void operate_on_open_file(struct fd_info *fdi) file_close(fdi); else if (shrink && r < 121 && !fdi->file->deleted) file_delete(fdi->file); - else + 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 */ @@ -1257,16 +1355,18 @@ static void operate_on_an_open_file(void) } } /* Close any open files that have errored */ - 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; + 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) @@ -1357,6 +1457,9 @@ void integck(void) 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); @@ -1449,6 +1552,14 @@ int main(int argc, char *argv[]) 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; |