X-Git-Url: https://git.kernel.dk/?a=blobdiff_plain;f=options.c;h=dc55c985cc19b0d2940642cb1cac49dc3cd1aee7;hb=844ea60273f4e7862150d9c6430cdb15768e2f34;hp=82870112b06df1532e0b5607f444259942bbb892;hpb=363cffa71a96eb4c7595bb8c325a09eb01f766a5;p=fio.git diff --git a/options.c b/options.c index 82870112..dc55c985 100644 --- a/options.c +++ b/options.c @@ -729,11 +729,11 @@ static int str_random_distribution_cb(void *data, const char *str) } /* - * Return next file in the string. Files are separated with ':'. If the ':' + * Return next name in the string. Files are separated with ':'. If the ':' * is escaped with a '\', then that ':' is part of the filename and does not * indicate a new file. */ -static char *get_next_file_name(char **ptr) +static char *get_next_name(char **ptr) { char *str = *ptr; char *p, *start; @@ -774,6 +774,43 @@ static char *get_next_file_name(char **ptr) return start; } + +static int get_max_name_idx(char *input) +{ + unsigned int cur_idx; + char *str, *p; + + p = str = strdup(input); + for (cur_idx = 0; ; cur_idx++) + if (get_next_name(&str) == NULL) + break; + + free(p); + return cur_idx; +} + +/* + * Returns the directory at the index, indexes > entires will be + * assigned via modulo division of the index + */ +int set_name_idx(char *target, char *input, int index) +{ + unsigned int cur_idx; + int len; + char *fname, *str, *p; + + p = str = strdup(input); + + index %= get_max_name_idx(input); + for (cur_idx = 0; cur_idx <= index; cur_idx++) + fname = get_next_name(&str); + + len = sprintf(target, "%s/", fname); + free(p); + + return len; +} + static int str_filename_cb(void *data, const char *input) { struct thread_data *td = data; @@ -787,10 +824,10 @@ static int str_filename_cb(void *data, const char *input) if (!td->files_index) td->o.nr_files = 0; - while ((fname = get_next_file_name(&str)) != NULL) { + while ((fname = get_next_name(&str)) != NULL) { if (!strlen(fname)) break; - add_file(td, fname); + add_file(td, fname, 0); td->o.nr_files++; } @@ -798,23 +835,43 @@ static int str_filename_cb(void *data, const char *input) return 0; } -static int str_directory_cb(void *data, const char fio_unused *str) +static int str_directory_cb(void *data, const char fio_unused *unused) { struct thread_data *td = data; struct stat sb; + char *dirname, *str, *p; + int ret = 0; if (parse_dryrun()) return 0; - if (lstat(td->o.directory, &sb) < 0) { - int ret = errno; + p = str = strdup(td->o.directory); + while ((dirname = get_next_name(&str)) != NULL) { + if (lstat(dirname, &sb) < 0) { + ret = errno; - log_err("fio: %s is not a directory\n", td->o.directory); - td_verror(td, ret, "lstat"); - return 1; + log_err("fio: %s is not a directory\n", dirname); + td_verror(td, ret, "lstat"); + goto out; + } + if (!S_ISDIR(sb.st_mode)) { + log_err("fio: %s is not a directory\n", dirname); + ret = 1; + goto out; + } } - if (!S_ISDIR(sb.st_mode)) { - log_err("fio: %s is not a directory\n", td->o.directory); + +out: + free(p); + return ret; +} + +static int str_lockfile_cb(void *data, const char fio_unused *str) +{ + struct thread_data *td = data; + + if (td->files_index) { + log_err("fio: lockfile= option must precede filename=\n"); return 1; } @@ -1227,9 +1284,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_STR, .off1 = td_var_offset(file_lock_mode), .help = "Lock file when doing IO to it", + .prio = 1, .parent = "filename", .hide = 0, .def = "none", + .cb = str_lockfile_cb, .category = FIO_OPT_C_FILE, .group = FIO_OPT_G_FILENAME, .posval = { @@ -1373,6 +1432,11 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .ival = "windowsaio", .help = "Windows native asynchronous IO" }, +#endif +#ifdef CONFIG_RBD + { .ival = "rbd", + .help = "Rados Block Device asynchronous IO" + }, #endif { .ival = "mmap", .help = "Memory mapped IO" @@ -1764,6 +1828,13 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .category = FIO_OPT_C_IO, .group = FIO_OPT_G_RANDOM, }, + { + .name = "allrandrepeat", + .type = FIO_OPT_BOOL, + .off1 = td_var_offset(allrand_repeatable), + .help = "Use repeatable random numbers for everything", + .def = "0", + }, { .name = "nrfiles", .lname = "Number of files", @@ -1900,18 +1971,18 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { { .ival = "wait_before", .oval = SYNC_FILE_RANGE_WAIT_BEFORE, .help = "SYNC_FILE_RANGE_WAIT_BEFORE", - .or = 1, + .orval = 1, }, { .ival = "write", .oval = SYNC_FILE_RANGE_WRITE, .help = "SYNC_FILE_RANGE_WRITE", - .or = 1, + .orval = 1, }, { .ival = "wait_after", .oval = SYNC_FILE_RANGE_WAIT_AFTER, .help = "SYNC_FILE_RANGE_WAIT_AFTER", - .or = 1, + .orval = 1, }, }, .type = FIO_OPT_STR_MULTI, @@ -1992,6 +2063,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .lname = "Start delay", .type = FIO_OPT_STR_VAL_TIME, .off1 = td_var_offset(start_delay), + .off2 = td_var_offset(start_delay_high), .help = "Only start job when this period has passed", .def = "0", .category = FIO_OPT_C_GENERAL, @@ -2171,6 +2243,10 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .oval = VERIFY_SHA512, .help = "Use sha512 checksums for verification", }, + { .ival = "xxhash", + .oval = VERIFY_XXHASH, + .help = "Use xxhash checksums for verification", + }, { .ival = "meta", .oval = VERIFY_META, .help = "Use io information", @@ -2997,7 +3073,7 @@ struct fio_option fio_options[FIO_MAX_OPTS] = { .type = FIO_OPT_INT, .off1 = td_var_offset(compress_percentage), .maxval = 100, - .minval = 1, + .minval = 0, .help = "How compressible the buffer is (approximately)", .interval = 5, .category = FIO_OPT_C_IO, @@ -3726,7 +3802,7 @@ void options_mem_dupe(void *data, struct fio_option *options) if (o->type != FIO_OPT_STR_STORE) continue; - ptr = td_var(data, o->off1); + ptr = td_var(data, o, o->off1); if (*ptr) *ptr = strdup(*ptr); } @@ -3772,7 +3848,13 @@ int add_option(struct fio_option *o) __o++; } + if (opt_index + 1 == FIO_MAX_OPTS) { + log_err("fio: FIO_MAX_OPTS is too small\n"); + return 1; + } + memcpy(&fio_options[opt_index], o, sizeof(*o)); + fio_options[opt_index + 1].name = NULL; return 0; }