X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=init.c;h=d44eb5b1eaa2fb086afe25b3a6bda335320decf7;hp=9d3c960870a89e0412094b5d5ee4ba6754462061;hb=550b1db6d1ca6f059f9c543bf441554e7816b156;hpb=23ed19b0e10749dca2389511f78d89db886c064a diff --git a/init.c b/init.c index 9d3c9608..d44eb5b1 100644 --- a/init.c +++ b/init.c @@ -24,10 +24,13 @@ #include "profile.h" #include "server.h" #include "idletime.h" +#include "filelock.h" #include "lib/getopt.h" #include "lib/strcasestr.h" +#include "crc/test.h" + const char fio_version_string[] = FIO_VERSION; #define FIO_RANDSEED (0xb1899bedUL) @@ -35,20 +38,21 @@ const char fio_version_string[] = FIO_VERSION; static char **ini_file; static int max_jobs = FIO_MAX_JOBS; static int dump_cmdline; -static int def_timeout; +static long long def_timeout; static int parse_only; static struct thread_data def_thread; struct thread_data *threads = NULL; +static char **job_sections; +static int nr_job_sections; int exitall_on_terminate = 0; int output_format = FIO_OUTPUT_NORMAL; +int append_terse_output = 0; int eta_print = FIO_ETA_AUTO; int eta_new_line = 0; FILE *f_out = NULL; FILE *f_err = NULL; -char **job_sections = NULL; -int nr_job_sections = 0; char *exec_profile = NULL; int warnings_fatal = 0; int terse_version = 3; @@ -108,6 +112,11 @@ static struct option l_opts[FIO_NR_OPTIONS] = { .has_arg = optional_argument, .val = 'F' | FIO_CLIENT_FLAG, }, + { + .name = (char *) "append-terse", + .has_arg = optional_argument, + .val = 'f', + }, { .name = (char *) "version", .has_arg = no_argument, @@ -229,19 +238,23 @@ static struct option l_opts[FIO_NR_OPTIONS] = { void free_threads_shm(void) { - struct shmid_ds sbuf; - if (threads) { void *tp = threads; +#ifndef CONFIG_NO_SHM + struct shmid_ds sbuf; threads = NULL; shmdt(tp); shmctl(shm_id, IPC_RMID, &sbuf); shm_id = -1; +#else + threads = NULL; + free(tp); +#endif } } -void free_shm(void) +static void free_shm(void) { if (threads) { file_hash_exit(); @@ -251,6 +264,7 @@ void free_shm(void) } options_free(fio_options, &def_thread); + fio_filelock_exit(); scleanup(); } @@ -277,6 +291,7 @@ static int setup_thread_area(void) size += file_hash_size; size += sizeof(unsigned int); +#ifndef CONFIG_NO_SHM shm_id = shmget(0, size, IPC_CREAT | 0600); if (shm_id != -1) break; @@ -284,10 +299,16 @@ static int setup_thread_area(void) perror("shmget"); break; } +#else + threads = malloc(size); + if (threads) + break; +#endif max_jobs >>= 1; } while (max_jobs); +#ifndef CONFIG_NO_SHM if (shm_id == -1) return 1; @@ -296,6 +317,7 @@ static int setup_thread_area(void) perror("shmat"); return 1; } +#endif memset(threads, 0, max_jobs * sizeof(struct thread_data)); hash = (void *) threads + max_jobs * sizeof(struct thread_data); @@ -308,6 +330,14 @@ static int setup_thread_area(void) return 0; } +static void set_cmd_options(struct thread_data *td) +{ + struct thread_options *o = &td->o; + + if (!o->timeout) + o->timeout = def_timeout; +} + /* * Return a free job structure. */ @@ -316,8 +346,10 @@ static struct thread_data *get_new_job(int global, struct thread_data *parent, { struct thread_data *td; - if (global) + if (global) { + set_cmd_options(&def_thread); return &def_thread; + } if (setup_thread_area()) { log_err("error: failed to setup shm segment\n"); return NULL; @@ -344,9 +376,10 @@ static struct thread_data *get_new_job(int global, struct thread_data *parent, td->thread_number = thread_number; - if (!parent || !parent->o.group_reporting) + if (!parent->o.group_reporting) stat_number++; + set_cmd_options(td); return td; } @@ -670,6 +703,11 @@ static int fixup_options(struct thread_data *td) if (td->o.rand_seed) td->o.rand_repeatable = 0; + if ((td->io_ops->flags & FIO_NOEXTEND) && td->o.file_append) { + log_err("fio: can't append/extent with IO engine %s\n", td->io_ops->name); + ret = 1; + } + return ret; } @@ -911,11 +949,12 @@ static struct fpre_keyword { { .keyword = NULL, }, }; -static char *make_filename(char *buf, struct thread_options *o, +static char *make_filename(char *buf, size_t buf_size,struct thread_options *o, const char *jobname, int jobnum, int filenum) { struct fpre_keyword *f; char copy[PATH_MAX]; + size_t dst_left = PATH_MAX - 1; if (!o->filename_format || !strlen(o->filename_format)) { sprintf(buf, "%s.%d.%d", jobname, jobnum, filenum); @@ -925,7 +964,9 @@ static char *make_filename(char *buf, struct thread_options *o, for (f = &fpre_keywords[0]; f->keyword; f++) f->strlen = strlen(f->keyword); - strcpy(buf, o->filename_format); + buf[buf_size - 1] = '\0'; + strncpy(buf, o->filename_format, buf_size - 1); + memset(copy, 0, sizeof(copy)); for (f = &fpre_keywords[0]; f->keyword; f++) { do { @@ -943,27 +984,49 @@ static char *make_filename(char *buf, struct thread_options *o, if (pre_len) { strncpy(dst, buf, pre_len); dst += pre_len; + dst_left -= pre_len; } switch (f->key) { - case FPRE_JOBNAME: - dst += sprintf(dst, "%s", jobname); + case FPRE_JOBNAME: { + int ret; + + ret = snprintf(dst, dst_left, "%s", jobname); + if (ret < 0) + break; + dst += ret; + dst_left -= ret; break; - case FPRE_JOBNUM: - dst += sprintf(dst, "%d", jobnum); + } + case FPRE_JOBNUM: { + int ret; + + ret = snprintf(dst, dst_left, "%d", jobnum); + if (ret < 0) + break; + dst += ret; + dst_left -= ret; break; - case FPRE_FILENUM: - dst += sprintf(dst, "%d", filenum); + } + case FPRE_FILENUM: { + int ret; + + ret = snprintf(dst, dst_left, "%d", filenum); + if (ret < 0) + break; + dst += ret; + dst_left -= ret; break; + } default: assert(0); break; } if (post_start) - strcpy(dst, buf + post_start); + strncpy(dst, buf + post_start, dst_left); - strcpy(buf, copy); + strncpy(buf, copy, buf_size - 1); } while (1); } @@ -1020,10 +1083,10 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, file_alloced = 1; if (o->nr_files == 1 && exists_and_not_file(jobname)) - add_file(td, jobname); + add_file(td, jobname, job_add_num, 0); else { for (i = 0; i < o->nr_files; i++) - add_file(td, make_filename(fname, o, jobname, td->thread_number, i)); + add_file(td, make_filename(fname, sizeof(fname), o, jobname, job_add_num, i), job_add_num, 0); } } @@ -1076,12 +1139,12 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, if (setup_rate(td)) goto err; - if (o->lat_log_file) { + if (o->lat_log_file || write_lat_log) { setup_log(&td->lat_log, o->log_avg_msec, IO_LOG_TYPE_LAT); setup_log(&td->slat_log, o->log_avg_msec, IO_LOG_TYPE_SLAT); setup_log(&td->clat_log, o->log_avg_msec, IO_LOG_TYPE_CLAT); } - if (o->bw_log_file) + if (o->bw_log_file || write_bw_log) setup_log(&td->bw_log, o->log_avg_msec, IO_LOG_TYPE_BW); if (o->iops_log_file) setup_log(&td->iops_log, o->log_avg_msec, IO_LOG_TYPE_IOPS); @@ -1149,26 +1212,25 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, td_new->o.new_group = 0; if (file_alloced) { - td_new->files_index = 0; - td_new->files_size = 0; if (td_new->files) { struct fio_file *f; for_each_file(td_new, f, i) { if (f->file_name) - free(f->file_name); - free(f); + sfree(f->file_name); + sfree(f); } + free(td_new->files); td_new->files = NULL; } + td_new->files_index = 0; + td_new->files_size = 0; if (td_new->o.filename) { free(td_new->o.filename); td_new->o.filename = NULL; } } - job_add_num = numjobs - 1; - - if (add_job(td_new, jobname, job_add_num, 1, client_type)) + if (add_job(td_new, jobname, numjobs, 1, client_type)) goto err; } @@ -1410,9 +1472,6 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type) i++; } - for (i = 0; i < num_opts; i++) - free(opts[i]); - free(string); free(name); free(opts); @@ -1426,8 +1485,8 @@ static int fill_def_thread(void) memset(&def_thread, 0, sizeof(def_thread)); fio_getaffinity(getpid(), &def_thread.o.cpumask); - def_thread.o.timeout = def_timeout; def_thread.o.error_dump = 1; + /* * fill default options */ @@ -1648,13 +1707,11 @@ static int client_flag_set(char c) return 0; } -void parse_cmd_client(void *client, char *opt) +static void parse_cmd_client(void *client, char *opt) { fio_client_add_cmd_option(client, opt); } -extern int fio_crctest(const char *); - int parse_cmd_line(int argc, char *argv[], int client_type) { struct thread_data *td = NULL; @@ -1671,8 +1728,6 @@ int parse_cmd_line(int argc, char *argv[], int client_type) optind = 1; while ((c = getopt_long_only(argc, argv, ostr, l_opts, &lidx)) != -1) { - did_arg = 1; - if ((c & FIO_CLIENT_FLAG) || client_flag_set(c)) { parse_cmd_client(cur_client, argv[optind - 1]); c &= ~FIO_CLIENT_FLAG; @@ -1683,7 +1738,11 @@ int parse_cmd_line(int argc, char *argv[], int client_type) smalloc_pool_size = atoi(optarg); break; case 't': - def_timeout = atoi(optarg); + if (check_str_time(optarg, &def_timeout, 1)) { + log_err("fio: failed parsing time %s\n", optarg); + do_exit++; + exit_val = 1; + } break; case 'l': write_lat_log = 1; @@ -1692,6 +1751,9 @@ int parse_cmd_line(int argc, char *argv[], int client_type) write_bw_log = 1; break; case 'o': + if (f_out && f_out != stdout) + fclose(f_out); + f_out = fopen(optarg, "w+"); if (!f_out) { perror("fopen output"); @@ -1718,31 +1780,39 @@ int parse_cmd_line(int argc, char *argv[], int client_type) else output_format = FIO_OUTPUT_NORMAL; break; + case 'f': + append_terse_output = 1; + break; case 'h': + did_arg = 1; if (!cur_client) { usage(argv[0]); do_exit++; } break; case 'c': + did_arg = 1; if (!cur_client) { fio_show_option_help(optarg); do_exit++; } break; case 'i': + did_arg = 1; if (!cur_client) { fio_show_ioengine_help(optarg); do_exit++; } break; case 's': + did_arg = 1; dump_cmdline = 1; break; case 'r': read_only = 1; break; case 'v': + did_arg = 1; if (!cur_client) { log_info("%s\n", fio_version_string); do_exit++; @@ -1766,7 +1836,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) case 'E': { long long t = 0; - if (str_to_decimal(optarg, &t, 0, NULL)) { + if (str_to_decimal(optarg, &t, 0, NULL, 1)) { log_err("fio: failed parsing eta time %s\n", optarg); exit_val = 1; do_exit++; @@ -1779,6 +1849,7 @@ int parse_cmd_line(int argc, char *argv[], int client_type) do_exit++; break; case 'P': + did_arg = 1; parse_only = 1; break; case 'x': { @@ -1798,6 +1869,9 @@ int parse_cmd_line(int argc, char *argv[], int client_type) break; } case 'p': + did_arg = 1; + if (exec_profile) + free(exec_profile); exec_profile = strdup(optarg); break; case FIO_GETOPT_JOB: { @@ -1807,8 +1881,9 @@ int parse_cmd_line(int argc, char *argv[], int client_type) if (!strncmp(opt, "name", 4) && td) { ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); if (ret) - return 0; + goto out_free; td = NULL; + did_arg = 1; } if (!td) { int is_section = !strncmp(opt, "name", 4); @@ -1821,8 +1896,14 @@ int parse_cmd_line(int argc, char *argv[], int client_type) continue; td = get_new_job(global, &def_thread, 1); - if (!td || ioengine_load(td)) - return 0; + if (!td || ioengine_load(td)) { + if (td) { + put_job(td); + td = NULL; + } + do_exit++; + break; + } fio_options_set_ioengine_opts(l_opts, td); } @@ -1843,8 +1924,14 @@ int parse_cmd_line(int argc, char *argv[], int client_type) if (!ret && !strcmp(opt, "ioengine")) { free_ioengine(td); - if (ioengine_load(td)) - return 0; + if (ioengine_load(td)) { + if (td) { + put_job(td); + td = NULL; + } + do_exit++; + break; + } fio_options_set_ioengine_opts(l_opts, td); } break; @@ -1852,6 +1939,10 @@ int parse_cmd_line(int argc, char *argv[], int client_type) case FIO_GETOPT_IOENGINE: { const char *opt = l_opts[lidx].name; char *val = optarg; + + if (!td) + break; + ret = fio_cmd_ioengine_option_parse(td, opt, val); break; } @@ -1867,6 +1958,8 @@ int parse_cmd_line(int argc, char *argv[], int client_type) } break; case 'S': + did_arg = 1; +#ifndef CONFIG_NO_SHM if (nr_clients) { log_err("fio: can't be both client and server\n"); do_exit++; @@ -1877,19 +1970,28 @@ int parse_cmd_line(int argc, char *argv[], int client_type) fio_server_set_arg(optarg); is_backend = 1; backend = 1; +#else + log_err("fio: client/server requires SHM support\n"); + do_exit++; + exit_val = 1; +#endif break; case 'D': + if (pid_file) + free(pid_file); pid_file = strdup(optarg); break; case 'I': if ((ret = fio_idle_prof_parse_opt(optarg))) { /* exit on error and calibration only */ + did_arg = 1; do_exit++; - if (ret == -1) + if (ret == -1) exit_val = 1; } break; case 'C': + did_arg = 1; if (is_backend) { log_err("fio: can't be both client and server\n"); do_exit++; @@ -1916,17 +2018,19 @@ int parse_cmd_line(int argc, char *argv[], int client_type) } break; case 'T': + did_arg = 1; do_exit++; exit_val = fio_monotonic_clocktest(); break; case 'G': + did_arg = 1; do_exit++; exit_val = fio_crctest(optarg); break; case 'L': { long long val; - if (check_str_time(optarg, &val)) { + if (check_str_time(optarg, &val, 0)) { log_err("fio: failed parsing time %s\n", optarg); do_exit++; exit_val = 1; @@ -1950,18 +2054,20 @@ int parse_cmd_line(int argc, char *argv[], int client_type) if (do_exit && !(is_backend || nr_clients)) exit(exit_val); - if (nr_clients && fio_clients_connect()) { - do_exit++; - exit_val = 1; - return -1; - } + if (nr_clients && fio_clients_connect()) + exit(1); if (is_backend && backend) return fio_start_server(pid_file); + else if (pid_file) + free(pid_file); if (td) { - if (!ret) + if (!ret) { ret = add_job(td, td->o.name ?: "fio", 0, 0, client_type); + if (ret) + did_arg = 1; + } } while (!ret && optind < argc) { @@ -1971,6 +2077,10 @@ int parse_cmd_line(int argc, char *argv[], int client_type) optind++; } +out_free: + if (pid_file) + free(pid_file); + return ini_idx; } @@ -2006,7 +2116,7 @@ int parse_options(int argc, char *argv[]) if (job_files > 0) { for (i = 0; i < job_files; i++) { - if (fill_def_thread()) + if (i && fill_def_thread()) return 1; if (nr_clients) { if (fio_clients_send_ini(ini_file[i])) @@ -2027,6 +2137,7 @@ int parse_options(int argc, char *argv[]) free(ini_file); fio_options_free(&def_thread); + filesetup_mem_free(); if (!thread_number) { if (parse_dryrun())