int drop_cache(const char * path) { #ifdef __linux__ struct stat st; int r = stat(path, &st); if(r < 0) { perror(path); return r; } if(S_ISDIR(st.st_mode)) { struct dirent * entry; DIR * dir = opendir(path); if(!dir) { perror(path); return -1; } while((entry = readdir(dir))) { char * full = NULL; if(!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; r = asprintf(&full, "%s/%s", path, entry->d_name); if(r < 0) { perror(entry->d_name); continue; } drop_cache(full); free(full); } closedir(dir); } else { int fd = open(path, O_RDONLY); if(fd < 0) { perror(path); return fd; } r = posix_fadvise(fd, 0, 0, POSIX_FADV_DONTNEED); if(r < 0) { perror(path); return r; } close(fd); } return 0; #else printf("%s(): not supported\n", __FUNCTION__); return -ENOSYS; #endif }
static int filedev_bwrite(struct ext4_blockdev *bdev, const void *buf, uint64_t blk_id, uint32_t blk_cnt) { if (fseek(dev_file, blk_id * bdev->ph_bsize, SEEK_SET)) return EIO; if (!fwrite(buf, bdev->ph_bsize * blk_cnt, 1, dev_file)) return EIO; drop_cache(); return EOK; }
static int measured_exec(const char *device, char *const *args) { struct disk_stats stats0; struct disk_stats stats1; char stat_path[PATH_MAX]; uint64_t time0; uint64_t time1; uint32_t bytes; uint32_t milli_io; float milli_tot; float seconds; int status; pid_t pid; uint16_t sector_sz; if (find_device_stat(device, stat_path) == -1) return -1; if ((sector_sz = sector_size(device)) == -1) { fprintf(stderr, "%s: failed to determine sector size: %s\n", prog, strerror(errno)); return -1; } if (drop_cache() == -1) return -1; /* collect opening data */ if (read_disk_stats(prog, stat_path, &stats0) == -1) return -1; time0 = clock_monotonic(); /* start child */ if ((pid = fork()) == -1) { fprintf(stderr, "%s: fork failed: %s\n", prog, strerror(errno)); return -1; } else if (!pid) { execvp(*args, args); fprintf(stderr, "%s: exec failed: %s\n", prog, strerror(errno)); exit(0xff); } /* wait for child */ status = 0; for (;;) { if (waitpid(pid, &status, 0) == -1) { if (errno == EINTR) continue; fprintf(stderr, "%s: wait failed: %s\n", prog, strerror(errno)); return -1; } break; } /* collect closing data */ if (read_disk_stats(prog, stat_path, &stats1) == -1) return -1; time1 = clock_monotonic(); /* check for child error */ if (WIFSIGNALED(status)) { fprintf(stderr, "%s: child terminated by signal %s\n", prog, signame(WTERMSIG(status))); return -1; } else if (WEXITSTATUS(status)) { if (WEXITSTATUS(status) != 0xff) fprintf(stderr, "%s: child exited with %d\n", prog, WEXITSTATUS(status)); return -1; } /* process data */ bytes = ((stats1.sectors_read + stats1.sectors_written) - (stats0.sectors_read + stats0.sectors_written)) * sector_sz; milli_io = stats1.milli_io - stats0.milli_io; milli_tot = (time1 - time0) / 1000000.0f; seconds = (time1 - time0) / 1000000000.0f; /* print data */ printf("RATE_KBPS\t%.10e\n", bytes / (seconds * 1024)); printf("RATE_MBPS\t%.10e\n", bytes / (seconds * 1048576)); printf("TIME_S\t\t%.10e\n", seconds); printf("UTIL\t\t%.10e\n", milli_io / milli_tot); return 0; }