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 
     37 /*
     38  * Just expose an empty list, if the OS does not support disk util stats
     39  */
     40 #ifndef FIO_HAVE_DISK_UTIL
     41 FLIST_HEAD(disk_list);
     42 #endif
     43 
     44 unsigned long arch_flags = 0;
     45 
     46 uintptr_t page_mask = 0;
     47 uintptr_t page_size = 0;
     48 
     49 static const char *fio_os_strings[os_nr] = {
     50 	"Invalid",
     51 	"Linux",
     52 	"AIX",
     53 	"FreeBSD",
     54 	"HP-UX",
     55 	"OSX",
     56 	"NetBSD",
     57 	"OpenBSD",
     58 	"Solaris",
     59 	"Windows",
     60 	"Android",
     61 };
     62 
     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 	"generic"
     77 };
     78 
     79 static void reset_io_counters(struct thread_data *td)
     80 {
     81 	int ddir;
     82 
     83 	for (ddir = 0; ddir < DDIR_RWDIR_CNT; ddir++) {
     84 		td->stat_io_bytes[ddir] = 0;
     85 		td->this_io_bytes[ddir] = 0;
     86 		td->stat_io_blocks[ddir] = 0;
     87 		td->this_io_blocks[ddir] = 0;
     88 		td->rate_bytes[ddir] = 0;
     89 		td->rate_blocks[ddir] = 0;
     90 	}
     91 	td->zone_bytes = 0;
     92 
     93 	td->last_was_sync = 0;
     94 	td->rwmix_issues = 0;
     95 
     96 	/*
     97 	 * reset file done count if we are to start over
     98 	 */
     99 	if (td->o.time_based || td->o.loops || td->o.do_verify)
    100 		td->nr_done_files = 0;
    101 }
    102 
    103 void clear_io_state(struct thread_data *td)
    104 {
    105 	struct fio_file *f;
    106 	unsigned int i;
    107 
    108 	reset_io_counters(td);
    109 
    110 	close_files(td);
    111 	for_each_file(td, f, i)
    112 		fio_file_clear_done(f);
    113 
    114 	/*
    115 	 * Set the same seed to get repeatable runs
    116 	 */
    117 	td_fill_rand_seeds(td);
    118 }
    119 
    120 void reset_all_stats(struct thread_data *td)
    121 {
    122 	struct timeval tv;
    123 	int i;
    124 
    125 	reset_io_counters(td);
    126 
    127 	for (i = 0; i < DDIR_RWDIR_CNT; i++) {
    128 		td->io_bytes[i] = 0;
    129 		td->io_blocks[i] = 0;
    130 		td->io_issues[i] = 0;
    131 		td->ts.total_io_u[i] = 0;
    132 		td->ts.runtime[i] = 0;
    133 		td->rwmix_issues = 0;
    134 	}
    135 
    136 	fio_gettime(&tv, NULL);
    137 	memcpy(&td->epoch, &tv, sizeof(tv));
    138 	memcpy(&td->start, &tv, sizeof(tv));
    139 
    140 	lat_target_reset(td);
    141 }
    142 
    143 void reset_fio_state(void)
    144 {
    145 	groupid = 0;
    146 	thread_number = 0;
    147 	stat_number = 0;
    148 	done_secs = 0;
    149 }
    150 
    151 const char *fio_get_os_string(int nr)
    152 {
    153 	if (nr < os_nr)
    154 		return fio_os_strings[nr];
    155 
    156 	return NULL;
    157 }
    158 
    159 const char *fio_get_arch_string(int nr)
    160 {
    161 	if (nr < arch_nr)
    162 		return fio_arch_strings[nr];
    163 
    164 	return NULL;
    165 }
    166 
    167 void td_set_runstate(struct thread_data *td, int runstate)
    168 {
    169 	if (td->runstate == runstate)
    170 		return;
    171 
    172 	dprint(FD_PROCESS, "pid=%d: runstate %d -> %d\n", (int) td->pid,
    173 						td->runstate, runstate);
    174 	td->runstate = runstate;
    175 }
    176 
    177 int td_bump_runstate(struct thread_data *td, int new_state)
    178 {
    179 	int old_state = td->runstate;
    180 
    181 	td_set_runstate(td, new_state);
    182 	return old_state;
    183 }
    184 
    185 void td_restore_runstate(struct thread_data *td, int old_state)
    186 {
    187 	td_set_runstate(td, old_state);
    188 }
    189 
    190 void fio_terminate_threads(int group_id)
    191 {
    192 	struct thread_data *td;
    193 	pid_t pid = getpid();
    194 	int i;
    195 
    196 	dprint(FD_PROCESS, "terminate group_id=%d\n", group_id);
    197 
    198 	for_each_td(td, i) {
    199 		if (group_id == TERMINATE_ALL || groupid == td->groupid) {
    200 			dprint(FD_PROCESS, "setting terminate on %s/%d\n",
    201 						td->o.name, (int) td->pid);
    202 			td->terminate = 1;
    203 			td->o.start_delay = 0;
    204 
    205 			/*
    206 			 * if the thread is running, just let it exit
    207 			 */
    208 			if (!td->pid || pid == td->pid)
    209 				continue;
    210 			else if (td->runstate < TD_RAMP)
    211 				kill(td->pid, SIGTERM);
    212 			else {
    213 				struct ioengine_ops *ops = td->io_ops;
    214 
    215 				if (ops && ops->terminate)
    216 					ops->terminate(td);
    217 			}
    218 		}
    219 	}
    220 }
    221 
    222 int fio_running_or_pending_io_threads(void)
    223 {
    224 	struct thread_data *td;
    225 	int i;
    226 
    227 	for_each_td(td, i) {
    228 		if (td->flags & TD_F_NOIO)
    229 			continue;
    230 		if (td->runstate < TD_EXITED)
    231 			return 1;
    232 	}
    233 
    234 	return 0;
    235 }
    236 
    237 int fio_set_fd_nonblocking(int fd, const char *who)
    238 {
    239 	int flags;
    240 
    241 	flags = fcntl(fd, F_GETFL);
    242 	if (flags < 0)
    243 		log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
    244 	else {
    245 		int new_flags = flags | O_NONBLOCK;
    246 
    247 		new_flags = fcntl(fd, F_SETFL, new_flags);
    248 		if (new_flags < 0)
    249 			log_err("fio: %s failed to get file flags: %s\n", who, strerror(errno));
    250 	}
    251 
    252 	return flags;
    253 }
    254 
    255 static int endian_check(void)
    256 {
    257 	union {
    258 		uint8_t c[8];
    259 		uint64_t v;
    260 	} u;
    261 	int le = 0, be = 0;
    262 
    263 	u.v = 0x12;
    264 	if (u.c[7] == 0x12)
    265 		be = 1;
    266 	else if (u.c[0] == 0x12)
    267 		le = 1;
    268 
    269 #if defined(CONFIG_LITTLE_ENDIAN)
    270 	if (be)
    271 		return 1;
    272 #elif defined(CONFIG_BIG_ENDIAN)
    273 	if (le)
    274 		return 1;
    275 #else
    276 	return 1;
    277 #endif
    278 
    279 	if (!le && !be)
    280 		return 1;
    281 
    282 	return 0;
    283 }
    284 
    285 int initialize_fio(char *envp[])
    286 {
    287 	long ps;
    288 
    289 	if (endian_check()) {
    290 		log_err("fio: endianness settings appear wrong.\n");
    291 		log_err("fio: please report this to fio (at) vger.kernel.org\n");
    292 		return 1;
    293 	}
    294 
    295 #if !defined(CONFIG_GETTIMEOFDAY) && !defined(CONFIG_CLOCK_GETTIME)
    296 #error "No available clock source!"
    297 #endif
    298 
    299 	arch_init(envp);
    300 
    301 	sinit();
    302 
    303 	if (fio_filelock_init()) {
    304 		log_err("fio: failed initializing filelock subsys\n");
    305 		return 1;
    306 	}
    307 
    308 	/*
    309 	 * We need locale for number printing, if it isn't set then just
    310 	 * go with the US format.
    311 	 */
    312 	if (!getenv("LC_NUMERIC"))
    313 		setlocale(LC_NUMERIC, "en_US");
    314 
    315 	ps = sysconf(_SC_PAGESIZE);
    316 	if (ps < 0) {
    317 		log_err("Failed to get page size\n");
    318 		return 1;
    319 	}
    320 
    321 	page_size = ps;
    322 	page_mask = ps - 1;
    323 
    324 	fio_keywords_init();
    325 	return 0;
    326 }
    327