Home | History | Annotate | Download | only in fio
      1 /*
      2  * fio - the flexible io tester
      3  *
      4  * Copyright (C) 2005 Jens Axboe <axboe (at) suse.de>
      5  * Copyright (C) 2006-2012 Jens Axboe <axboe (at) kernel.dk>
      6  *
      7  * The license below covers all files distributed with fio unless otherwise
      8  * noted in the file itself.
      9  *
     10  *  This program is free software; you can redistribute it and/or modify
     11  *  it under the terms of the GNU General Public License version 2 as
     12  *  published by the Free Software Foundation.
     13  *
     14  *  This program is distributed in the hope that it will be useful,
     15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17  *  GNU General Public License for more details.
     18  *
     19  *  You should have received a copy of the GNU General Public License
     20  *  along with this program; if not, write to the Free Software
     21  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     22  *
     23  */
     24 
     25 #include <string.h>
     26 #include <sys/types.h>
     27 #include <signal.h>
     28 #include <stdint.h>
     29 #include <locale.h>
     30 #include <fcntl.h>
     31 
     32 #include "fio.h"
     33 #include "smalloc.h"
     34 #include "os/os.h"
     35 #include "filelock.h"
     36 #include "helper_thread.h"
     37 #include "filehash.h"
     38 
     39 FLIST_HEAD(disk_list);
     40 
     41 unsigned long arch_flags = 0;
     42 
     43 uintptr_t page_mask = 0;
     44 uintptr_t page_size = 0;
     45 
     46 /* see os/os.h */
     47 static const char *fio_os_strings[os_nr] = {
     48 	"Invalid",
     49 	"Linux",
     50 	"AIX",
     51 	"FreeBSD",
     52 	"HP-UX",
     53 	"OSX",
     54 	"NetBSD",
     55 	"OpenBSD",
     56 	"Solaris",
     57 	"Windows",
     58 	"Android",
     59 	"DragonFly",
     60 };
     61 
     62 /* see arch/arch.h */
     63 static const char *fio_arch_strings[arch_nr] = {
     64 	"Invalid",
     65 	"x86-64",
     66 	"x86",
     67 	"ppc",
     68 	"ia64",
     69 	"s390",
     70 	"alpha",
     71 	"sparc",
     72 	"sparc64",
     73 	"arm",
     74 	"sh",
     75 	"hppa",
     76 	"mips",
     77 	"aarch64",
     78 	"generic"
     79 };
     80 
     81 static void reset_io_counters(struct thread_data *td, int all)
     82 {
     83 	int ddir;
     84 
     85 	if (all) {
     86 		for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) {
     87 			td->stat_io_bytes[ddir] = 0;
     88 			td->this_io_bytes[ddir] = 0;
     89 			td->stat_io_blocks[ddir] = 0;
     90 			td->this_io_blocks[ddir] = 0;
     91 			td->rate_bytes[ddir] = 0;
     92 			td->rate_blocks[ddir] = 0;
     93 			td->bytes_done[ddir] = 0;
     94 			td->rate_io_issue_bytes[ddir] = 0;
     95 			td->rate_next_io_time[ddir] = 0;
     96 		}
     97 	}
     98 
     99 	td->zone_bytes = 0;
    100 
    101 	td->last_was_sync = 0;
    102 	td->rwmix_issues = 0;
    103 
    104 	/*
    105 	 * reset file done count if we are to start over
    106 	 */
    107 	if (td->o.time_based || td->o.loops || td->o.do_verify)
    108 		td->nr_done_files = 0;
    109 }
    110 
    111 void clear_io_state(struct thread_data *td, int all)
    112 {
    113 	struct fio_file *f;
    114 	unsigned int i;
    115 
    116 	reset_io_counters(td, all);
    117 
    118 	close_files(td);
    119 	for_each_file(td, f, i) {
    120 		fio_file_clear_done(f);
    121 		f->file_offset = get_start_offset(td, f);
    122 	}
    123 
    124 	/*
    125 	 * Re-Seed random number generator if rand_repeatable is true
    126 	 */
    127 	if (td->o.rand_repeatable)
    128 		td_fill_rand_seeds(td);
    129 }
    130 
    131 void reset_all_stats(struct thread_data *td)
    132 {
    133 	int i;
    134 
    135 	reset_io_counters(td, 1);
    136 
    137 	for (i = 0; i < DDIR_RWDIR_CNT; i++) {
    138 		td->io_bytes[i] = 0;
    139 		td->io_blocks[i] = 0;
    140 		td->io_issues[i] = 0;
    141 		td->ts.total_io_u[i] = 0;
    142 		td->ts.runtime[i] = 0;
    143 		td->rwmix_issues = 0;
    144 	}
    145 
    146 	set_epoch_time(td, td->o.log_unix_epoch);
    147 	memcpy(&td->start, &td->epoch, sizeof(struct timeval));
    148 	memcpy(&td->iops_sample_time, &td->epoch, sizeof(struct timeval));
    149 	memcpy(&td->bw_sample_time, &td->epoch, sizeof(struct timeval));
    150 	memcpy(&td->ss.prev_time, &td->epoch, sizeof(struct timeval));
    151 
    152 	lat_target_reset(td);
    153 	clear_rusage_stat(td);
    154 	helper_reset();
    155 }
    156 
    157 void reset_fio_state(void)
    158 {
    159 	groupid = 0;
    160 	thread_number = 0;
    161 	stat_number = 0;
    162 	done_secs = 0;
    163 }
    164 
    165 const char *fio_get_os_string(int nr)
    166 {
    167 	if (nr < os_nr)
    168 		return fio_os_strings[nr];
    169 
    170 	return NULL;
    171 }
    172 
    173 const char *fio_get_arch_string(int nr)
    174 {
    175 	if (nr < arch_nr)
    176 		return fio_arch_strings[nr];
    177 
    178 	return NULL;
    179 }
    180 
    181 static const char *td_runstates[] = {
    182 	"NOT_CREATED",
    183 	"CREATED",
    184 	"INITIALIZED",
    185 	"RAMP",
    186 	"SETTING_UP",
    187 	"RUNNING",
    188 	"PRE_READING",
    189 	"VERIFYING",
    190 	"FSYNCING",
    191 	"FINISHING",
    192 	"EXITED",
    193 	"REAPED",
    194 };
    195 
    196 const char *runstate_to_name(int runstate)
    197 {
    198 	compiletime_assert(TD_LAST == 12, "td runstate list");
    199 	if (runstate >= 0 && runstate < TD_LAST)
    200 		return td_runstates[runstate];
    201 
    202 	return "invalid";
    203 }
    204 
    205 void td_set_runstate(struct thread_data *td, int runstate)
    206 {
    207 	if (td->runstate == runstate)
    208 		return;
    209 
    210 	dprint(FD_PROCESS, "pid=%d: runstate %s -> %s\n", (int) td->pid,
    211 						runstate_to_name(td->runstate),
    212 						runstate_to_name(runstate));
    213 	td->runstate = runstate;
    214 }
    215 
    216 int td_bump_runstate(struct thread_data *td, int new_state)
    217 {
    218 	int old_state = td->runstate;
    219 
    220 	td_set_runstate(td, new_state);
    221 	return old_state;
    222 }
    223 
    224 void td_restore_runstate(struct thread_data *td, int old_state)
    225 {
    226 	td_set_runstate(td, old_state);
    227 }
    228 
    229 void fio_mark_td_terminate(struct thread_data *td)
    230 {
    231 	fio_gettime(&td->terminate_time, NULL);
    232 	write_barrier();
    233 	td->terminate = 1;
    234 }
    235 
    236 void fio_terminate_threads(unsigned int group_id)
    237 {
    238 	struct thread_data *td;
    239 	pid_t pid = getpid();
    240 	int i;
    241 
    242 	dprint(FD_PROCESS, "terminate group_id=%d\n", group_id);
    243 
    244 	for_each_td(td, i) {
    245 		if (group_id == TERMINATE_ALL || group_id == td->groupid) {
    246 			dprint(FD_PROCESS, "setting terminate on %s/%d\n",
    247 						td->o.name, (int) td->pid);
    248 
    249 			if (td->terminate)
    250 				continue;
    251 
    252 			fio_mark_td_terminate(td);
    253 			td->o.start_delay = 0;
    254 
    255 			/*
    256 			 * if the thread is running, just let it exit
    257 			 */
    258 			if (!td->pid || pid == td->pid)
    259 				continue;
    260 			else if (td->runstate < TD_RAMP)
    261 				kill(td->pid, SIGTERM);
    262 			else {
    263 				struct ioengine_ops *ops = td->io_ops;
    264 
    265 				if (ops && ops->terminate)
    266 					ops->terminate(td);
    267 			}
    268 		}
    269 	}
    270 }
    271 
    272 int fio_running_or_pending_io_threads(void)
    273 {
    274 	struct thread_data *td;
    275 	int i;
    276 	int nr_io_threads = 0;
    277 
    278 	for_each_td(td, i) {
    279 		if (td->io_ops_init && td_ioengine_flagged(td, FIO_NOIO))
    280 			continue;
    281 		nr_io_threads++;
    282 		if (td->runstate < TD_EXITED)
    283 			return 1;
    284 	}
    285 
    286 	if (!nr_io_threads)
    287 		return -1; /* we only had cpuio threads to begin with */
    288 	return 0;
    289 }
    290 
    291 int fio_set_fd_nonblocking(int fd, const char *who)
    292 {
    293 	int flags;
    294 
    295 	flags = fcntl(fd, F_GETFL);
    296 	if (flags < 0)
    297 		log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
    298 	else {
    299 		int new_flags = flags | O_NONBLOCK;
    300 
    301 		new_flags = fcntl(fd, F_SETFL, new_flags);
    302 		if (new_flags < 0)
    303 			log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
    304 	}
    305 
    306 	return flags;
    307 }
    308 
    309 enum {
    310 	ENDIAN_INVALID_BE = 1,
    311 	ENDIAN_INVALID_LE,
    312 	ENDIAN_INVALID_CONFIG,
    313 	ENDIAN_BROKEN,
    314 };
    315 
    316 static int endian_check(void)
    317 {
    318 	union {
    319 		uint8_t c[8];
    320 		uint64_t v;
    321 	} u;
    322 	int le = 0, be = 0;
    323 
    324 	u.v = 0x12;
    325 	if (u.c[7] == 0x12)
    326 		be = 1;
    327 	else if (u.c[0] == 0x12)
    328 		le = 1;
    329 
    330 #if defined(CONFIG_LITTLE_ENDIAN)
    331 	if (be)
    332 		return ENDIAN_INVALID_BE;
    333 #elif defined(CONFIG_BIG_ENDIAN)
    334 	if (le)
    335 		return ENDIAN_INVALID_LE;
    336 #else
    337 	return ENDIAN_INVALID_CONFIG;
    338 #endif
    339 
    340 	if (!le && !be)
    341 		return ENDIAN_BROKEN;
    342 
    343 	return 0;
    344 }
    345 
    346 int initialize_fio(char *envp[])
    347 {
    348 	long ps;
    349 	int err;
    350 
    351 	/*
    352 	 * We need these to be properly 64-bit aligned, otherwise we
    353 	 * can run into problems on archs that fault on unaligned fp
    354 	 * access (ARM).
    355 	 */
    356 	compiletime_assert((offsetof(struct thread_stat, percentile_list) % 8) == 0, "stat percentile_list");
    357 	compiletime_assert((offsetof(struct thread_stat, total_run_time) % 8) == 0, "total_run_time");
    358 	compiletime_assert((offsetof(struct thread_stat, total_err_count) % 8) == 0, "total_err_count");
    359 	compiletime_assert((offsetof(struct thread_stat, latency_percentile) % 8) == 0, "stat latency_percentile");
    360 	compiletime_assert((offsetof(struct thread_options_pack, zipf_theta) % 8) == 0, "zipf_theta");
    361 	compiletime_assert((offsetof(struct thread_options_pack, pareto_h) % 8) == 0, "pareto_h");
    362 	compiletime_assert((offsetof(struct thread_options_pack, percentile_list) % 8) == 0, "percentile_list");
    363 	compiletime_assert((offsetof(struct thread_options_pack, latency_percentile) % 8) == 0, "latency_percentile");
    364 
    365 	err = endian_check();
    366 	if (err) {
    367 		log_err("fio: endianness settings appear wrong.\n");
    368 		switch (err) {
    369 		case ENDIAN_INVALID_BE:
    370 			log_err("fio: got big-endian when configured for little\n");
    371 			break;
    372 		case ENDIAN_INVALID_LE:
    373 			log_err("fio: got little-endian when configured for big\n");
    374 			break;
    375 		case ENDIAN_INVALID_CONFIG:
    376 			log_err("fio: not configured to any endianness\n");
    377 			break;
    378 		case ENDIAN_BROKEN:
    379 			log_err("fio: failed to detect endianness\n");
    380 			break;
    381 		default:
    382 			assert(0);
    383 			break;
    384 		}
    385 		log_err("fio: please report this to fio (at) vger.kernel.org\n");
    386 		return 1;
    387 	}
    388 
    389 #if !defined(CONFIG_GETTIMEOFDAY) && !defined(CONFIG_CLOCK_GETTIME)
    390 #error "No available clock source!"
    391 #endif
    392 
    393 	arch_init(envp);
    394 
    395 	sinit();
    396 
    397 	if (fio_filelock_init()) {
    398 		log_err("fio: failed initializing filelock subsys\n");
    399 		return 1;
    400 	}
    401 
    402 	file_hash_init();
    403 
    404 	/*
    405 	 * We need locale for number printing, if it isn't set then just
    406 	 * go with the US format.
    407 	 */
    408 	if (!getenv("LC_NUMERIC"))
    409 		setlocale(LC_NUMERIC, "en_US");
    410 
    411 	ps = sysconf(_SC_PAGESIZE);
    412 	if (ps < 0) {
    413 		log_err("Failed to get page size\n");
    414 		return 1;
    415 	}
    416 
    417 	page_size = ps;
    418 	page_mask = ps - 1;
    419 
    420 	fio_keywords_init();
    421 	return 0;
    422 }
    423 
    424 void deinitialize_fio(void)
    425 {
    426 	fio_keywords_exit();
    427 }
    428