static unsigned ffsb_writeall_core(ffsb_thread_t *ft, ffsb_fs_t *fs, unsigned opnum, uint64_t *filesize_ret, int fsync_file) { struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum); struct ffsb_file *curfile = NULL; int fd; uint64_t filesize; char *buf = ft_getbuf(ft); uint32_t write_blocksize = ft_get_write_blocksize(ft); struct randdata *rd = ft_get_randdata(ft); unsigned iterations = 0; curfile = choose_file_reader(bf, rd); fd = fhopenwrite(curfile->name, ft, fs); filesize = ffsb_get_filesize(curfile->name); iterations = writefile_helper(fd, filesize, write_blocksize, buf, ft, fs); if (fsync_file) if (fsync(fd)) { perror("fsync"); printf("aborting\n"); exit(1); } unlock_file_reader(curfile); fhclose(fd, ft, fs); *filesize_ret = filesize; return iterations; }
/* Just like ffsb_readfile but we read the whole file from start to * finish regardless of file size. */ void ffsb_readall(ffsb_thread_t *ft, ffsb_fs_t *fs, unsigned opnum) { struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum); struct ffsb_file *curfile = NULL; int fd; uint64_t filesize; char *buf = ft_getbuf(ft); uint32_t read_blocksize = ft_get_read_blocksize(ft); struct randdata *rd = ft_get_randdata(ft); unsigned iterations = 0; curfile = choose_file_reader(bf, rd); fd = fhopenread(curfile->name, ft, fs); filesize = ffsb_get_filesize(curfile->name); iterations = readfile_helper(fd, filesize, read_blocksize, buf, ft, fs); unlock_file_reader(curfile); fhclose(fd, ft, fs); ft_incr_op(ft, opnum, iterations, filesize); ft_add_readbytes(ft, filesize); }
/* Do all the dirty work of recursing through a directory structure * check everything for validitiy and update everything properly. * Note it does not check filesizes !!!, it doesn't know anything * about them */ static int add_dir_to_filelist(struct benchfiles *bf, DIR *subdir, char *subdir_path, fl_validation_func_t vfunc, void *vf_data) { int retval = 0; struct dirent *d_ent = NULL; while ((d_ent = readdir(subdir)) != NULL) { DIR *tmp = NULL; char filename_buf[FILENAME_MAX*2]; if (FILENAME_MAX < snprintf(filename_buf, FILENAME_MAX, "%s/%s", subdir_path, d_ent->d_name)) { printf("filename \"%s\" too long aborting\n", filename_buf); return -1; } tmp = opendir(filename_buf); if (tmp == NULL) { struct ffsb_file *ffsb_file = NULL; if (validate_filename(bf, d_ent->d_name) < 0) { printf("filename \"%s\" is invalid aborting\n", d_ent->d_name); return -1; } /* Verify size/other attributes via callback */ if (vfunc(bf, filename_buf, vf_data)) { printf("filename \"%s\" didn't pass " "validation\n", d_ent->d_name); return -1; } /* Add file to data structure */ ffsb_file = add_file_named(bf, ffsb_get_filesize(filename_buf), filename_buf); unlock_file_writer(ffsb_file); } else { /* Check for the usual suspects and skip them */ if ((0 == strcmp(".", d_ent->d_name)) || (0 == strcmp("..", d_ent->d_name))) { closedir(tmp); continue; } if (validate_dirname(bf, d_ent->d_name) < 0) { printf("dirname \"%s\" is invalid aborting\n", d_ent->d_name); closedir(tmp); return -1; } if (vfunc(bf, filename_buf, vf_data)) { printf("dir \"%s\" didn't pass validation\n", d_ent->d_name); closedir(tmp); return -1; } /* Update filelist */ bf->numsubdirs++; /* recurse */ retval += add_dir_to_filelist(bf, tmp, filename_buf, vfunc, vf_data); /* clean up */ closedir(tmp); } } return retval; }
void ffsb_readfile(ffsb_thread_t *ft, ffsb_fs_t *fs, unsigned opnum) { struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum); struct ffsb_file *curfile = NULL; int fd; uint64_t filesize; char *buf = ft_getbuf(ft); int read_random = ft_get_read_random(ft); uint64_t read_size = ft_get_read_size(ft); uint32_t read_blocksize = ft_get_read_blocksize(ft); uint32_t read_skipsize = ft_get_read_skipsize(ft); int skip_reads = ft_get_read_skip(ft); struct randdata *rd = ft_get_randdata(ft); uint64_t iterations = 0; curfile = choose_file_reader(bf, rd); fd = fhopenread(curfile->name, ft, fs); filesize = ffsb_get_filesize(curfile->name); assert(filesize >= read_size); /* Sequential read, starting at a random point */ if (!read_random) { uint64_t range = filesize - read_size; uint64_t offset = 0; /* Skip or "stride" reads option */ if (skip_reads) { unsigned i, last; uint64_t minfilesize; iterations = read_size / read_blocksize; last = read_size % read_blocksize; /* Double check that the user hasn't specified * a read_size that is too large when combined * with the seeks */ if (last) minfilesize = last + iterations * (read_blocksize + read_skipsize); else minfilesize = read_blocksize + iterations - 1 * (read_blocksize + read_skipsize); if (minfilesize > filesize) { printf("Error: read size %llu bytes too big " "w/ skipsize %u and blocksize %u," " for file of size %llu bytes\n" " aborting\n\n", read_size, read_skipsize, read_blocksize, filesize); printf("minimum file size must be at least " " %llu bytes\n", minfilesize); exit(1); } for (i = 0; i < iterations; i++) { fhread(fd, buf, read_blocksize, ft, fs); fhseek(fd, (uint64_t)read_skipsize, SEEK_CUR, ft, fs); } if (last) { fhread(fd, buf, (uint64_t)last, ft, fs); iterations++; } } else { /* Regular sequential reads */ if (range) { offset = get_random_offset(rd, range, fs_get_alignio(fs)); fhseek(fd, offset, SEEK_SET, ft, fs); } iterations = readfile_helper(fd, read_size, read_blocksize, buf, ft, fs); } } else { /* Randomized read */ uint64_t range = filesize - read_blocksize; int i; iterations = read_size / read_blocksize; for (i = 0; i < iterations; i++) { uint64_t offset = get_random_offset(rd, range, fs_get_alignio(fs)); fhseek(fd, offset, SEEK_SET, ft, fs); fhread(fd, buf, read_blocksize, ft, fs); } } unlock_file_reader(curfile); fhclose(fd, ft, fs); ft_incr_op(ft, opnum, iterations, read_size); ft_add_readbytes(ft, read_size); }
static unsigned ffsb_writefile_core(ffsb_thread_t *ft, ffsb_fs_t *fs, unsigned opnum, uint64_t *filesize_ret, int fsync_file) { struct benchfiles *bf = (struct benchfiles *)fs_get_opdata(fs, opnum); struct ffsb_file *curfile = NULL; int fd; uint64_t filesize; char *buf = ft_getbuf(ft); int write_random = ft_get_write_random(ft); uint32_t write_size = ft_get_write_size(ft); uint32_t write_blocksize = ft_get_write_blocksize(ft); struct randdata *rd = ft_get_randdata(ft); unsigned iterations = 0; curfile = choose_file_reader(bf, rd); fd = fhopenwrite(curfile->name, ft, fs); filesize = ffsb_get_filesize(curfile->name); assert(filesize >= write_size); /* Sequential write, starting at a random point */ if (!write_random) { uint64_t range = filesize - write_size; uint64_t offset = 0; if (range) { offset = get_random_offset(rd, range, fs_get_alignio(fs)); fhseek(fd, offset, SEEK_SET, ft, fs); } iterations = writefile_helper(fd, write_size, write_blocksize, buf, ft, fs); } else { /* Randomized write */ uint64_t range = filesize - write_blocksize; int i; iterations = write_size / write_blocksize; for (i = 0; i < iterations; i++) { uint64_t offset = get_random_offset(rd, range, fs_get_alignio(fs)); fhseek(fd, offset, SEEK_SET, ft, fs); fhwrite(fd, buf, write_blocksize, ft, fs); } } if (fsync_file) { if (fsync(fd)) { perror("fsync"); printf("aborting\n"); exit(1); } } unlock_file_reader(curfile); fhclose(fd, ft, fs); *filesize_ret = filesize; return iterations; }