X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=init.c;h=6b29aa702407a69799f54ff15a60011a105be5d8;hp=c3996a76c12840e3ab3cf6514e5d5dce611a1077;hb=ef3d8e53c01456f22a61c162e4e5a3997af14a5d;hpb=10aa136bddbaa7c845ab4eacb4a9a4a88d6657a3 diff --git a/init.c b/init.c index c3996a76..6b29aa70 100644 --- a/init.c +++ b/init.c @@ -24,6 +24,7 @@ #include "profile.h" #include "server.h" #include "idletime.h" +#include "filelock.h" #include "lib/getopt.h" #include "lib/strcasestr.h" @@ -37,7 +38,7 @@ 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; @@ -237,15 +238,19 @@ 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 } } @@ -259,6 +264,7 @@ static void free_shm(void) } options_free(fio_options, &def_thread); + fio_filelock_exit(); scleanup(); } @@ -285,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; @@ -292,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; @@ -304,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); @@ -316,16 +330,26 @@ 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. */ static struct thread_data *get_new_job(int global, struct thread_data *parent, - int preserve_eo) + int preserve_eo, const char *jobname) { 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; @@ -352,9 +376,13 @@ 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 (jobname) + td->o.name = strdup(jobname); + + if (!parent->o.group_reporting) stat_number++; + set_cmd_options(td); return td; } @@ -373,6 +401,9 @@ static void put_job(struct thread_data *td) if (td->io_ops) free_ioengine(td); + if (td->o.name) + free(td->o.name); + memset(&threads[td->thread_number - 1], 0, sizeof(*td)); thread_number--; } @@ -924,11 +955,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); @@ -938,7 +970,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 { @@ -956,27 +990,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); } @@ -1036,7 +1092,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, 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, job_add_num, i), job_add_num, 0); + add_file(td, make_filename(fname, sizeof(fname), o, jobname, job_add_num, i), job_add_num, 0); } } @@ -1152,7 +1208,7 @@ static int add_job(struct thread_data *td, const char *jobname, int job_add_num, */ numjobs = o->numjobs; while (--numjobs) { - struct thread_data *td_new = get_new_job(0, td, 1); + struct thread_data *td_new = get_new_job(0, td, 1, jobname); if (!td_new) goto err; @@ -1210,11 +1266,11 @@ void add_job_opts(const char **o, int client_type) sprintf(jobname, "%s", o[i] + 5); } if (in_global && !td_parent) - td_parent = get_new_job(1, &def_thread, 0); + td_parent = get_new_job(1, &def_thread, 0, jobname); else if (!in_global && !td) { if (!td_parent) td_parent = &def_thread; - td = get_new_job(0, td_parent, 0); + td = get_new_job(0, td_parent, 0, jobname); } if (in_global) fio_options_parse(td_parent, (char **) &o[i], 1, 0); @@ -1349,7 +1405,7 @@ int parse_jobs_ini(char *file, int is_buf, int stonewall_flag, int type) first_sect = 0; } - td = get_new_job(global, &def_thread, 0); + td = get_new_job(global, &def_thread, 0, name); if (!td) { ret = 1; break; @@ -1422,9 +1478,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); @@ -1438,8 +1491,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 */ @@ -1681,8 +1734,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; @@ -1693,7 +1744,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; @@ -1702,6 +1757,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"); @@ -1732,30 +1790,35 @@ int parse_cmd_line(int argc, char *argv[], int client_type) 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++; @@ -1792,6 +1855,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': { @@ -1811,6 +1875,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: { @@ -1820,8 +1887,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); @@ -1833,9 +1901,15 @@ int parse_cmd_line(int argc, char *argv[], int client_type) if (is_section && skip_this_section(val)) continue; - td = get_new_job(global, &def_thread, 1); - if (!td || ioengine_load(td)) - return 0; + td = get_new_job(global, &def_thread, 1, NULL); + if (!td || ioengine_load(td)) { + if (td) { + put_job(td); + td = NULL; + } + do_exit++; + break; + } fio_options_set_ioengine_opts(l_opts, td); } @@ -1856,8 +1930,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; @@ -1865,6 +1945,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; } @@ -1880,6 +1964,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++; @@ -1890,19 +1976,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++; @@ -1929,10 +2024,12 @@ 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; @@ -1963,18 +2060,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) { @@ -1984,6 +2083,10 @@ int parse_cmd_line(int argc, char *argv[], int client_type) optind++; } +out_free: + if (pid_file) + free(pid_file); + return ini_idx; } @@ -2019,7 +2122,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]))