X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=fio.h;h=7a4b9c69fbe3b94dc62a8a828f2238ebc493c6ea;hp=d3a03795c9ecec7e1764f9b33408ac4f88e8fa42;hb=29c8e868723e1b539d402d1accac97f872f355ea;hpb=4f5af7b2370a6d3e64bc5128905c1aa8b0dc51b0 diff --git a/fio.h b/fio.h index d3a03795..7a4b9c69 100644 --- a/fio.h +++ b/fio.h @@ -26,6 +26,8 @@ #include "debug.h" #include "file.h" #include "io_ddir.h" +#include "ioengine.h" +#include "iolog.h" #ifdef FIO_HAVE_GUASI #include @@ -35,139 +37,6 @@ #include #endif -/* - * Use for maintaining statistics - */ -struct io_stat { - unsigned long max_val; - unsigned long min_val; - unsigned long samples; - - double mean; - double S; -}; - -/* - * A single data sample - */ -struct io_sample { - unsigned long time; - unsigned long val; - enum fio_ddir ddir; - unsigned int bs; -}; - -/* - * Dynamically growing data sample log - */ -struct io_log { - unsigned long nr_samples; - unsigned long max_samples; - struct io_sample *log; -}; - -/* - * When logging io actions, this matches a single sent io_u - */ -struct io_piece { - union { - struct rb_node rb_node; - struct flist_head list; - }; - union { - int fileno; - struct fio_file *file; - }; - unsigned long long offset; - unsigned long len; - enum fio_ddir ddir; - union { - unsigned long delay; - unsigned int file_action; - }; -}; - -enum { - IO_U_F_FREE = 1 << 0, - IO_U_F_FLIGHT = 1 << 1, -}; - -struct thread_data; - -/* - * The io unit - */ -struct io_u { - union { -#ifdef FIO_HAVE_LIBAIO - struct iocb iocb; -#endif -#ifdef FIO_HAVE_POSIXAIO - struct aiocb aiocb; -#endif -#ifdef FIO_HAVE_SGIO - struct sg_io_hdr hdr; -#endif -#ifdef FIO_HAVE_GUASI - guasi_req_t greq; -#endif -#ifdef FIO_HAVE_SOLARISAIO - aio_result_t resultp; -#endif - void *mmap_data; - }; - struct timeval start_time; - struct timeval issue_time; - - /* - * Allocated/set buffer and length - */ - void *buf; - unsigned long buflen; - unsigned long long offset; - - /* - * IO engine state, may be different from above when we get - * partial transfers / residual data counts - */ - void *xfer_buf; - unsigned long xfer_buflen; - - unsigned int resid; - unsigned int error; - - enum fio_ddir ddir; - - /* - * io engine private data - */ - union { - unsigned int index; - unsigned int seen; - void *engine_data; - }; - - unsigned int flags; - - struct fio_file *file; - - struct flist_head list; - - /* - * Callback for io completion - */ - int (*end_io)(struct thread_data *, struct io_u *); -}; - -/* - * io_ops->queue() return values - */ -enum { - FIO_Q_COMPLETED = 0, /* completed sync */ - FIO_Q_QUEUED = 1, /* queued, will complete async */ - FIO_Q_BUSY = 2, /* no more room, call ->commit() */ -}; - struct group_run_stats { unsigned long long max_run[2], min_run[2]; unsigned long long max_bw[2], min_bw[2]; @@ -186,17 +55,6 @@ enum fio_memtype { MEM_MMAPHUGE, /* memory mapped huge file */ }; -enum fio_ioengine_flags { - FIO_SYNCIO = 1 << 0, /* io engine has synchronous ->queue */ - FIO_RAWIO = 1 << 1, /* some sort of direct/raw io */ - FIO_DISKLESSIO = 1 << 2, /* no disk involved */ - FIO_NOEXTEND = 1 << 3, /* engine can't extend file */ - FIO_NODISKUTIL = 1 << 4, /* diskutil can't handle filename */ - FIO_UNIDIR = 1 << 5, /* engine is uni-directional */ - FIO_NOIO = 1 << 6, /* thread does only pseudo IO */ - FIO_SIGQUIT = 1 << 7, /* needs SIGQUIT to exit */ -}; - /* * How many depth levels to log */ @@ -474,12 +332,10 @@ struct thread_data { struct timeval start; /* start of this loop */ struct timeval epoch; /* time job was started */ - struct timeval rw_end[2]; struct timeval last_issue; struct timeval tv_cache; unsigned int tv_cache_nr; unsigned int tv_cache_mask; - unsigned int rw_end_set[2]; unsigned int ramp_time_over; /* @@ -515,16 +371,6 @@ struct thread_data { os_random_state_t file_size_state; }; -/* - * roundrobin available files, or choose one at random, or do each one - * serially. - */ -enum { - FIO_FSERVICE_RANDOM = 1, - FIO_FSERVICE_RR = 2, - FIO_FSERVICE_SEQ = 3, -}; - /* * when should interactive ETA output be generated */ @@ -567,12 +413,6 @@ extern int fio_gtod_cpu; extern struct thread_data *threads; -#define td_read(td) ((td)->o.td_ddir & TD_DDIR_READ) -#define td_write(td) ((td)->o.td_ddir & TD_DDIR_WRITE) -#define td_rw(td) (((td)->o.td_ddir & TD_DDIR_RW) == TD_DDIR_RW) -#define td_random(td) ((td)->o.td_ddir & TD_DDIR_RAND) -#define file_randommap(td, f) (!(td)->o.norandommap && (f)->file_map) - static inline void fio_ro_check(struct thread_data *td, struct io_u *io_u) { assert(!(io_u->ddir == DDIR_WRITE && !td_write(td))); @@ -597,112 +437,6 @@ static inline int should_fsync(struct thread_data *td) return 0; } -/* - * Disk utils as read in /sys/block//stat - */ -struct disk_util_stat { - unsigned ios[2]; - unsigned merges[2]; - unsigned long long sectors[2]; - unsigned ticks[2]; - unsigned io_ticks; - unsigned time_in_queue; -}; - -/* - * Per-device disk util management - */ -struct disk_util { - struct flist_head list; - /* If this disk is a slave, hook it into the master's - * list using this head. - */ - struct flist_head slavelist; - - char *name; - char *sysfs_root; - char path[256]; - int major, minor; - - struct disk_util_stat dus; - struct disk_util_stat last_dus; - - /* For software raids, this entry maintains pointers to the - * entries for the slave devices. The disk_util entries for - * the slaves devices should primarily be maintained through - * the disk_list list, i.e. for memory allocation and - * de-allocation, etc. Whereas this list should be used only - * for aggregating a software RAID's disk util figures. - */ - struct flist_head slaves; - - unsigned long msec; - struct timeval time; - - struct fio_mutex *lock; - unsigned long users; -}; - -static inline void disk_util_inc(struct disk_util *du) -{ - if (du) { - fio_mutex_down(du->lock); - du->users++; - fio_mutex_up(du->lock); - } -} - -static inline void disk_util_dec(struct disk_util *du) -{ - if (du) { - fio_mutex_down(du->lock); - du->users--; - fio_mutex_up(du->lock); - } -} - -#define DISK_UTIL_MSEC (250) - -/* - * Log exports - */ -enum file_log_act { - FIO_LOG_ADD_FILE, - FIO_LOG_OPEN_FILE, - FIO_LOG_CLOSE_FILE, - FIO_LOG_UNLINK_FILE, -}; - -extern int __must_check read_iolog_get(struct thread_data *, struct io_u *); -extern void log_io_u(struct thread_data *, struct io_u *); -extern void log_file(struct thread_data *, struct fio_file *, enum file_log_act); -extern int __must_check init_iolog(struct thread_data *td); -extern void log_io_piece(struct thread_data *, struct io_u *); -extern void queue_io_piece(struct thread_data *, struct io_piece *); -extern void prune_io_piece_log(struct thread_data *); -extern void write_iolog_close(struct thread_data *); - -/* - * Logging - */ -extern void add_clat_sample(struct thread_data *, enum fio_ddir, unsigned long, - unsigned int); -extern void add_slat_sample(struct thread_data *, enum fio_ddir, unsigned long, - unsigned int); -extern void add_bw_sample(struct thread_data *, enum fio_ddir, unsigned int, - struct timeval *); -extern void show_run_stats(void); -extern void init_disk_util(struct thread_data *); -extern void update_rusage_stat(struct thread_data *); -extern void update_io_ticks(void); -extern void setup_log(struct io_log **); -extern void finish_log(struct thread_data *, struct io_log *, const char *); -extern void finish_log_named(struct thread_data *, struct io_log *, const char *, const char *); -extern void __finish_log(struct io_log *, const char *); -extern struct io_log *agg_io_log[2]; -extern int write_bw_log; -extern void add_agg_sample(unsigned long, enum fio_ddir, unsigned int); - /* * Time functions */ @@ -738,48 +472,12 @@ extern void td_fill_rand_seeds(struct thread_data *); #define FIO_GETOPT_JOB 0x89988998 #define FIO_NR_OPTIONS 128 -/* - * File setup/shutdown - */ -extern void close_files(struct thread_data *); -extern void close_and_free_files(struct thread_data *); -extern int __must_check setup_files(struct thread_data *); -extern int __must_check file_invalidate_cache(struct thread_data *, struct fio_file *); -extern int __must_check generic_open_file(struct thread_data *, struct fio_file *); -extern int __must_check generic_close_file(struct thread_data *, struct fio_file *); -extern int __must_check generic_get_file_size(struct thread_data *, struct fio_file *); -extern int __must_check pre_read_files(struct thread_data *); -extern int add_file(struct thread_data *, const char *); -extern void get_file(struct fio_file *); -extern int __must_check put_file(struct thread_data *, struct fio_file *); -extern void lock_file(struct thread_data *, struct fio_file *, enum fio_ddir); -extern void unlock_file(struct thread_data *, struct fio_file *); -extern void unlock_file_all(struct thread_data *, struct fio_file *); -extern int add_dir_files(struct thread_data *, const char *); -extern int init_random_map(struct thread_data *); -extern void dup_files(struct thread_data *, struct thread_data *); -extern int get_fileno(struct thread_data *, const char *); -extern void free_release_files(struct thread_data *); - /* * ETA/status stuff */ extern void print_thread_status(void); extern void print_status_init(int); -/* - * disk util stuff - */ -#ifdef FIO_HAVE_DISK_UTIL -extern void show_disk_util(void); -extern void init_disk_util(struct thread_data *); -extern void update_io_ticks(void); -#else -#define show_disk_util() -#define init_disk_util(td) -#define update_io_ticks() -#endif - /* * Thread life cycle. Once a thread has a runstate beyond TD_INITIALIZED, it * will never back again. It may cycle between running/verififying/fsyncing. @@ -809,41 +507,11 @@ extern void fio_unpin_memory(void); extern int __must_check allocate_io_mem(struct thread_data *); extern void free_io_mem(struct thread_data *); -/* - * io unit handling - */ -#define queue_full(td) flist_empty(&(td)->io_u_freelist) -extern struct io_u *__get_io_u(struct thread_data *); -extern struct io_u *get_io_u(struct thread_data *); -extern void put_io_u(struct thread_data *, struct io_u *); -extern void requeue_io_u(struct thread_data *, struct io_u **); -extern long __must_check io_u_sync_complete(struct thread_data *, struct io_u *); -extern long __must_check io_u_queued_complete(struct thread_data *, int); -extern void io_u_queued(struct thread_data *, struct io_u *); -extern void io_u_log_error(struct thread_data *, struct io_u *); -extern void io_u_mark_depth(struct thread_data *, unsigned int); -extern void io_u_fill_buffer(struct thread_data *td, struct io_u *, unsigned int); -void io_u_mark_complete(struct thread_data *, unsigned int); -void io_u_mark_submit(struct thread_data *, unsigned int); - /* * Reset stats after ramp time completes */ extern void reset_all_stats(struct thread_data *); -/* - * io engine entry points - */ -extern int __must_check td_io_init(struct thread_data *); -extern int __must_check td_io_prep(struct thread_data *, struct io_u *); -extern int __must_check td_io_queue(struct thread_data *, struct io_u *); -extern int __must_check td_io_sync(struct thread_data *, struct fio_file *); -extern int __must_check td_io_getevents(struct thread_data *, unsigned int, unsigned int, struct timespec *); -extern int __must_check td_io_commit(struct thread_data *); -extern int __must_check td_io_open_file(struct thread_data *, struct fio_file *); -extern int td_io_close_file(struct thread_data *, struct fio_file *); -extern int __must_check td_io_get_file_size(struct thread_data *, struct fio_file *); - /* * blktrace support */ @@ -852,34 +520,6 @@ extern int is_blktrace(const char *); extern int load_blktrace(struct thread_data *, const char *); #endif -struct ioengine_ops { - struct flist_head list; - char name[16]; - int version; - int flags; - int (*setup)(struct thread_data *); - int (*init)(struct thread_data *); - int (*prep)(struct thread_data *, struct io_u *); - int (*queue)(struct thread_data *, struct io_u *); - int (*commit)(struct thread_data *); - int (*getevents)(struct thread_data *, unsigned int, unsigned int, struct timespec *); - struct io_u *(*event)(struct thread_data *, int); - int (*cancel)(struct thread_data *, struct io_u *); - void (*cleanup)(struct thread_data *); - int (*open_file)(struct thread_data *, struct fio_file *); - int (*close_file)(struct thread_data *, struct fio_file *); - int (*get_file_size)(struct thread_data *, struct fio_file *); - void *data; - void *dlhandle; -}; - -#define FIO_IOOPS_VERSION 10 - -extern struct ioengine_ops *load_ioengine(struct thread_data *, const char *); -extern void register_ioengine(struct ioengine_ops *); -extern void unregister_ioengine(struct ioengine_ops *); -extern void close_ioengine(struct thread_data *); - /* * Mark unused variables passed to ops functions as unused, to silence gcc */ @@ -905,39 +545,6 @@ extern void close_ioengine(struct thread_data *); } \ } while (0) -static inline void fio_file_reset(struct fio_file *f) -{ - f->last_free_lookup = 0; - f->last_pos = f->file_offset; - if (f->file_map) - memset(f->file_map, 0, f->num_maps * sizeof(int)); -} - -static inline void clear_error(struct thread_data *td) -{ - td->error = 0; - td->verror[0] = '\0'; -} - -#ifdef FIO_INC_DEBUG -static inline void dprint_io_u(struct io_u *io_u, const char *p) -{ - struct fio_file *f = io_u->file; - - dprint(FD_IO, "%s: io_u %p: off=%llu/len=%lu/ddir=%d", p, io_u, - (unsigned long long) io_u->offset, - io_u->buflen, io_u->ddir); - if (fio_debug & (1 << FD_IO)) { - if (f) - log_info("/%s", f->file_name); - - log_info("\n"); - } -} -#else -#define dprint_io_u(io_u, p) -#endif - static inline int fio_fill_issue_time(struct thread_data *td) { if (td->o.read_iolog_file || @@ -947,4 +554,47 @@ static inline int fio_fill_issue_time(struct thread_data *td) return 0; } +/* + * Cheesy number->string conversion, complete with carry rounding error. + */ +static inline char *num2str(unsigned long num, int maxlen, int base, int pow2) +{ + char postfix[] = { ' ', 'K', 'M', 'G', 'P', 'E' }; + unsigned int thousand; + char *buf; + int i; + + if (pow2) + thousand = 1024; + else + thousand = 1000; + + buf = malloc(128); + + for (i = 0; base > 1; i++) + base /= thousand; + + do { + int len, carry = 0; + + len = sprintf(buf, "%'lu", num); + if (len <= maxlen) { + if (i >= 1) { + buf[len] = postfix[i]; + buf[len + 1] = '\0'; + } + return buf; + } + + if ((num % thousand) >= (thousand / 2)) + carry = 1; + + num /= thousand; + num += carry; + i++; + } while (i <= 5); + + return buf; +} + #endif