diff --git a/f3read.c b/f3read.c index 81d90f8..03d696f 100644 --- a/f3read.c +++ b/f3read.c @@ -39,21 +39,20 @@ uint64_t offset_from_filename (const char *filename) return number * GIGABYTES; } -#define ERRMSG_SIZE 256 +#define TOLERANCE 2 -void validate_file (const char *path, const char *filename) +void validate_file (const char *path, const char *filename, + uint64_t *ptr_ok, uint64_t *ptr_corrupted, uint64_t *ptr_changed, + uint64_t *ptr_overwritten, uint64_t *ptr_size) { uint8_t sector[SECTOR_SIZE], *p, *ptr_end; FILE *f; - int fine; + int offset_match, error_count; size_t sectors_read; uint64_t offset, expected_offset; struct drand48_data state; long int rand_int; - char full_fn[PATH_MAX], err_msg[ERRMSG_SIZE]; - - printf("Validating file %s ...", filename); - fflush(stdout); + char full_fn[PATH_MAX]; snprintf(full_fn, PATH_MAX, "%s/%s", path, filename); f = fopen(full_fn, "rb"); @@ -61,67 +60,127 @@ void validate_file (const char *path, const char *filename) err(errno, "Can't open file %s", full_fn); ptr_end = sector + SECTOR_SIZE; - fine = 1; sectors_read = fread(sector, SECTOR_SIZE, 1, f); expected_offset = offset_from_filename(filename); - err_msg[0] = '\0'; - while (fine && sectors_read > 0) + while (sectors_read > 0) { assert(sectors_read == 1); offset = *((uint64_t *)sector); - fine = offset == expected_offset; + offset_match = offset == expected_offset; - if (fine) + srand48_r(offset, &state); + p = sector + sizeof(offset); + error_count = 0; + for (; error_count <= TOLERANCE && p < ptr_end; p += sizeof(long int)) { - srand48_r(offset, &state); - p = sector + sizeof(offset); - for (; fine && p < ptr_end; p += sizeof(long int)) - { - lrand48_r(&state, &rand_int); - fine = rand_int == *((long int *)p); - } - - if (fine) - { - sectors_read = fread(sector, SECTOR_SIZE, 1, f); - expected_offset += SECTOR_SIZE; - } - else - snprintf(err_msg, ERRMSG_SIZE, "Lost bits in sector %llu", offset); + lrand48_r(&state, &rand_int); + if (rand_int != *((long int *)p)) + error_count++; } + + sectors_read = fread(sector, SECTOR_SIZE, 1, f); + expected_offset += SECTOR_SIZE; + + if (offset_match) + { + if (error_count == 0) + (*ptr_ok)++; + else if (error_count <= TOLERANCE) + (*ptr_changed)++; + else + (*ptr_corrupted)++; + } + else if (error_count <= TOLERANCE) + (*ptr_overwritten)++; else - snprintf(err_msg, ERRMSG_SIZE, - "Sector mismatch, expected %llu, found %llu", expected_offset, offset); + (*ptr_corrupted)++; } - assert(!fine || feof(f)); + assert(feof(f)); + *ptr_size += ftell(f); fclose(f); +} - if (fine) - printf(" OK!\n"); - else - printf(" ERROR: %s\n", err_msg); +char *adjust_unit (double *ptr_bytes) +{ + char *units[] = {"Byte", "KB", "MB", "GB", "TB"}; + int i = 0; + double final = *ptr_bytes; + + while (i < 5 && final >= 1024) + { + final /= 1024; + i++; + } + *ptr_bytes = final; + return units[i]; +} + +void report (const char *prefix, uint64_t i) +{ + double f = (double)(i * SECTOR_SIZE); + char *unit = adjust_unit(&f); + printf("%s %.2f %s (%llu sectors)\n", prefix, f, unit, i); } void iterate_path (const char *path) { DIR *ptr_dir; struct dirent *entry; - const char *filename; + const char *filename, *unit; + uint64_t tot_ok, tot_corrupted, tot_changed, tot_overwritten, tot_size; + time_t t1, t2, dt; + double read_speed; ptr_dir = opendir(path); + if (!ptr_dir) + err(errno, "Can't open path %s", path); assert(ptr_dir); + /* Obtain initial time. */ + t1 = time(NULL); + entry = readdir(ptr_dir); + tot_ok = tot_corrupted = tot_changed = tot_overwritten = tot_size = 0; + printf(" SECTORS ok/corrupted/changed/overwritten\n"); while (entry) { filename = entry->d_name; if (is_my_file(filename)) - validate_file(path, filename); + { + uint64_t sec_ok, sec_corrupted, sec_changed, sec_overwritten, file_size; + printf("Validating file %s ...", filename); + fflush(stdout); + sec_ok = sec_corrupted = sec_changed = sec_overwritten = file_size = 0; + validate_file(path, filename, &sec_ok, &sec_corrupted, + &sec_changed, &sec_overwritten, &file_size); + printf(" %llu/%llu/%llu/%llu\n", sec_ok, sec_corrupted, + sec_changed, sec_overwritten); + tot_ok += sec_ok; + tot_corrupted += sec_corrupted; + tot_changed += sec_changed; + tot_overwritten += sec_overwritten; + tot_size += file_size; + } entry = readdir(ptr_dir); } + t2 = time(NULL); + assert(tot_size/SECTOR_SIZE == + (tot_ok + tot_corrupted + tot_changed + tot_overwritten)); closedir(ptr_dir); + report("\n Data OK:", tot_ok); + report( "Data LOST:", tot_corrupted + tot_changed + tot_overwritten); + report("\t Corrupted:", tot_corrupted); + report("\tSlightly changed:", tot_changed); + report("\t Overwritten:", tot_overwritten); + + /* Reading speed. */ + dt = t2 - t1; + dt = dt > 0 ? dt : 1; + read_speed = (double)tot_size / (double)dt; + unit = adjust_unit(&read_speed); + printf("Reading speed: %.2f %s/s\n", read_speed, unit); } int main (int argc, char *argv[]) diff --git a/f3write.c b/f3write.c index 15129b4..cc6f7dc 100644 --- a/f3write.c +++ b/f3write.c @@ -9,6 +9,7 @@ #include #include #include +#include #define SECTOR_SIZE 512 #define GIGABYTES (1024 * 1024 * 1024) @@ -58,7 +59,14 @@ int create_and_fill_file (const char *path, int number, fflush(stdout); fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR|S_IWUSR); if (fd < 0) + { + if (errno == ENOSPC) + { + printf(" No space left.\n"); + return 0; + } err(errno, "Can't create file %s", filename); + } assert(fd >= 0); /* Obtain the buffer. */ @@ -67,7 +75,7 @@ int create_and_fill_file (const char *path, int number, /* Write content. */ fine = 1; - offset = number * GIGABYTES; + offset = (uint64_t)number * GIGABYTES; while (size > 0) { offset = fill_buffer(buf, block_size, offset); @@ -95,18 +103,41 @@ int create_and_fill_file (const char *path, int number, return fine; } +char *adjust_unit (double *ptr_bytes) +{ + char *units[] = {"Byte", "KB", "MB", "GB", "TB"}; + int i = 0; + double final = *ptr_bytes; + + while (i < 5 && final >= 1024) + { + final /= 1024; + i++; + } + *ptr_bytes = final; + return units[i]; +} + void fill_fs (const char *path) { struct statvfs fs; - uint64_t free_space; + double free_space1, free_space2; + time_t t1, t2, dt; int i, fine; size_t block_size; + double f, write_speed; + char *unit; /* Obtain initial free_space, and block_size. */ assert(statvfs(path, &fs) == 0); - free_space = (uint64_t)fs.f_bsize * (uint64_t)fs.f_bfree; + free_space1 = (double)fs.f_bsize * (double)fs.f_bfree; block_size = fs.f_bsize; - printf("Free space: %lli\n", free_space); + f = free_space1; + unit = adjust_unit(&f); + printf("Free space: %.2f %s\n", f, unit); + + /* Obtain initial time. */ + t1 = time(NULL); i = 0; fine = 1; @@ -118,8 +149,18 @@ void fill_fs (const char *path) /* Final report. */ assert(statvfs(path, &fs) == 0); - free_space = (uint64_t)fs.f_bsize * (uint64_t)fs.f_bfree; - printf("Free space: %lli\n", free_space); + free_space2 = (double)fs.f_bsize * (double)fs.f_bfree; + f = free_space2; + unit = adjust_unit(&f); + printf("Free space: %.2f %s\n", f, unit); + + /* Writing speed. */ + t2 = time(NULL); + dt = t2 - t1; + dt = dt > 0 ? dt : 1; + write_speed = (free_space1 - free_space2) / (double)dt; + unit = adjust_unit(&write_speed); + printf("Writing speed: %.2f %s/s\n", write_speed, unit); } int main (int argc, char *argv[])