1 /**************************************************************************
2  *
3  *  iorate.h - General information for IORATE
4  *
5  *  Copyright by EMC Corporation, 1997-2011.
6  *  All rights reserved.
7  *
8  *  Written by Vince Westin (vince.westin@emc.com), with a lot of
9  *  assistance from the EMC Engineering Team.
10  *
11  *  This code is the property of EMC Corporation.  However, it may be used,
12  *  reproduced, and passed on to others as long as the contents, including
13  *  all copyright notices, remain intact.  Modifications to, or modified
14  *  versions of these files, may also be distributed, provided that they
15  *  are clearly labeled as having been modified from the original.  In the
16  *  event that modified files are created, the original files are to be
17  *  included with every distribution of those modified files.  Inclusion of
18  *  this code into a commercial product by any company other than EMC is
19  *  prohibited without prior written consent.
20  *
21  *  Having said the legal stuff, this code is designed to provide a good,
22  *  generic tool for testing I/O subsystems under various kinds of loads.
23  *  If you have suggestions for improvements in this tool, please send them
24  *  along to the above address.
25  *
26  *************************************************************************/
27 
28 /*
29  *  Defines for general structures, funtions, etc.
30  *
31  * $Header: /home/westiv/iorate/RCS/iorate.h,v 3.18 2011/11/03 15:49:26 westiv Exp westiv $
32  */
33 
34 #ifndef	IORATE_INCLUDE
35 #define	IORATE_INCLUDE
36 
37 #include "ior_mach.h"			/* machine dependent stuff */
38 
39 #define	IOR_MAX_IO_SIZE		((HUGE)(4*1024*1024))
40 #define	IOR_MAX_DEVICES		1024
41 #define	IOR_MAX_PATTERNS	96
42 #define	IOR_MAX_TESTS		256
43 #define	IOR_MAX_DEV_COPIES	256
44 
45 #define	IOR_OVER_MAX		60	/* limit to 60 seconds over */
46 
47 #define	IOR_BUFFER_SIZE		1024
48 
49 #define	IOR_READ		1L
50 #define	IOR_WRITE		2L
51 
52 #define	IOR_HISTORY_DEFAULT	32
53 
54 #define	IOR_ZONES_DEFAULT	1
55 #define	IOR_ZONE_LIMIT_DEFAULT	32
56 
57 #define	IOR_SKEW_MIN		50	/* minimum skew we allow */
58 #define	IOR_SKEW_SEED		1939	/* default seed for skew */
59 #define IOR_SKEW_MAX_SEQ	100	/* max seq. for skew test */
60 #define	IOR_SKEW_LISTS		16	/* skew lists to drive I/O against */
61 #define	IOR_CORRELATE_ODDS	20	/* correlation factors we use */
62 #define	IOR_AREA_MIN		(1024 * 1024)
63 #define	IOR_AREA_MAX		(100*IOR_AREA_MIN)
64 #define	IOR_AREA_MIN_PER_DRIVE	1000	/* minimum areas per drive */
65 #define	IOR_AREA_GROUPING	10000	/* above this level, scale size by reusing areas */
66 
67 #define	IOR_DEBUG_MAJOR		10
68 #define	IOR_DEBUG_MINOR		100
69 #define	IOR_DEBUG_SMALL		500
70 #define	IOR_DEBUG_ALL		1000
71 
72 #ifndef	NULL
73 #define	NULL			0
74 #endif
75 
76 #ifndef	FALSE
77 #define	FALSE			0
78 #endif
79 
80 #ifndef	TRUE
81 #define	TRUE			1
82 #endif
83 
84 
85 #define	PROC_PERF_FILE		"%s/iorate-%d.%d.%d.per"
86 
87 
88 /*
89  * ior_odds_item_struct - odds item tracking structure
90  */
91 typedef	struct	ior_odds_item_struct {
92     int		i_id;			/* ID of the item with these odds */
93     long	i_odds_start;		/* odds starting value */
94     long	i_odds_count;		/* number of chances this item has */
95     long	i_odds_end;		/* odds ending value */
96     void	*i_id_ptr;		/* pointer to the item with odds */
97 }	ior_odds_item;
98 
99 /*
100  * ior_odds_struct - odds tracking structure
101  */
102 typedef	struct	ior_odds_struct {
103     int		o_items_count;		/* how many are we choosing between */
104     long	o_odds_count;		/* total options to pick from */
105     ior_odds_item *o_odds;		/* the true odds list */
106 }	ior_odds;
107 
108 
109 /*
110  * ior_skew_perf - performace record for a skew area group
111  *
112  *    Could have these per I/O size or pattern, but a LOT more data
113  */
114 typedef	struct	ior_skew_perf_struct {
115     HUGE	sp_rand_reads;		/* random reads against this profile */
116     HUGE	sp_seq_reads;		/* sequentail reads against this profile */
117     HUGE	sp_rand_writes;		/* random writes against this profile */
118     HUGE	sp_seq_writes;		/* sequential writes against this profile */
119     double	sp_rand_read_resp;	/* response time on random reads */
120     double	sp_seq_read_resp;	/* response time on sequential reads */
121     double	sp_rand_write_resp;	/* response time on random writes */
122     double	sp_seq_write_resp;	/* response time on sequential writes */
123 }	ior_skew_perf;
124 
125 /*
126  * ior_skew_area - areas of skew performance I/O
127  */
128 typedef	struct	ior_skew_area_struct {
129     long	a_id;			/* ID of this area */
130 
131     long	a_copies;		/* how many copies on THIS device */
132 
133     HUGE	a_start;		/* starting location */
134     HUGE	a_end;			/* ending location */
135     HUGE	a_size;			/* size of this area */
136 
137     struct ior_skew_area_struct *a_prev; /* previous area in our linked list */
138     struct ior_skew_area_struct *a_next; /* next area in our linked list */
139 
140     struct ior_skew_list_struct *a_list; /* the list we are a part of */
141 }	ior_skew_area;
142 
143 /*
144  * ior_skew_pat_struct - pattern information structure for skew groups
145  */
146 typedef	struct	ior_skew_pat_struct {	/* I/O pattern definitions */
147     char	*p_name;		/* name of this pattern */
148     ior_skew_area *p_seq_area;		/* area for sequntial I/O */
149     long	p_seq_copy;		/* which copy of the area */
150     HUGE	*p_hist_records;	/* history of recent I/Os */
151     ior_skew_area **p_hist_areas;	/* area for historical I/Os */
152     BYTE	p_read_use[ 100 ];	/* % lookup for read access */
153     BYTE	p_hist_use[ 100 ];	/* % lookup for history access */
154     long	p_io_size;		/* size of each I/O */
155     long	p_history;		/* limit of history count */
156     long	p_hist_active;		/* count of active history records */
157     long	p_hist_next;		/* next history record to replace */
158     long	p_max_seq;		/* maximum seqential I/Os */
159     long	p_cur_seq;		/* current seq. completed */
160     HUGE	p_pos;			/* position of next I/O */
161     float	p_read_pct;		/* read percentage */
162     float	p_reuse_pct;		/* reuse % - I/O hits */
163     BYTE	p_is_seq;		/* seq/random toggle */
164     BYTE	p_valid;		/* is this pattern OK to use? */
165 }	ior_skew_pat;
166 
167 /*
168  * ior_skew_list - collection of areas where testing will happen
169  */
170 typedef	struct	ior_skew_list_struct {
171     int		s_id;			/* ID of this skew list */
172     ior_skew_area *s_areas;		/* areas to be tested */
173     ior_skew_pat s_pats[ IOR_MAX_PATTERNS + 2 ]; /* partial I/O patterns */
174     long	s_area_goal;		/* how many areas should we get */
175     long	s_area_current;		/* how many areas do we already have */
176     ior_skew_perf s_perf;		/* performance tracking items */
177 }	ior_skew_list;
178 
179 
180 /*
181  * ior_dev_struct - device information structure
182  */
183 typedef	struct	ior_dev_struct {	/* device to do I/O against */
184     char	*d_name;		/* name of the file */
185     HUGE	d_offset;		/* offset to start of test */
186     HUGE	d_capacity;		/* active test size */
187     long	d_block_size;		/* minimum block size */
188     long	d_procs[ IOR_MAX_DEV_COPIES + 2 ]; /* PIDs active on dev */
189     int		d_count;		/* number of copies to run */
190     int		d_fid;			/* file ID for open file */
191     BYTE	d_is_async;		/* use async I/O? */
192     BYTE	d_read_only;		/* reads only? */
193     BYTE	d_is_temp;		/* make temporary FS file for test? */
194     BYTE	d_create;		/* create (and leave) if needed? */
195     BYTE	d_lock;			/* use advisory locks on this file? */
196     BYTE	d_is_created;		/* temp file already built? */
197     BYTE	d_is_active;		/* is this device active? */
198     BYTE	d_valid;		/* is this device OK to use? */
199 }	ior_device;
200 
201 /*
202  * ior_pat_struct - pattern information structure
203  *
204  * p_max_seq - maximum number of seqential I/Os that will be performed
205  *	before picking a new (random) starting location for the next batch
206  *	of sequentail I/O.  This can simulate log file type activity.
207  */
208 typedef	struct	ior_pat_struct {	/* I/O pattern definitions */
209     char	*p_name;		/* name of this pattern */
210     BYTE	p_read_use[ 100 ];	/* % lookup for read access */
211     BYTE	p_hist_use[ 100 ];	/* % lookup for history access */
212     HUGE	*p_local_uses;		/* locality I/O count */
213     HUGE	*p_local_seqs;		/* locality seq. I/O count */
214     HUGE	*p_local_pos;		/* position within localities */
215     HUGE	*p_local_starts;	/* starts of localities */
216     HUGE	*p_local_ends;		/* ends of localities */
217     HUGE	*p_hist_records;	/* history of recent I/Os */
218     long	p_io_size;		/* size of each I/O */
219     long	p_history;		/* limit of history count */
220     long	p_hist_active;		/* count of active history records */
221     long	p_hist_next;		/* next history record to replace */
222     HUGE	p_max_seq;		/* maximum seqential I/Os */
223     HUGE	p_cur_seq;		/* current seq. completed */
224     HUGE	p_pos;			/* position of next I/O */
225     HUGE	p_start;		/* where do we start? */
226     HUGE	p_size;			/* how much do we test? */
227     HUGE	p_end;			/* end of test area - start + size */
228     HUGE	p_local_size;		/* size of locality areas */
229     HUGE	p_local_count;		/* number of active localities */
230     HUGE	p_local_limit;		/* limit on I/Os to a locality */
231     HUGE	p_cur_local;		/* active locality */
232     HUGE	p_local_avail;		/* number of localities in test size */
233     float	p_start_pct;		/* starting percentage */
234     float	p_size_pct;		/* size percentage */
235     float	p_read_pct;		/* read percentage */
236     float	p_local_pct;		/* locality use % */
237     float	p_reuse_pct;		/* reuse % - I/O hits */
238     BYTE	p_is_seq;		/* seq/random toggle */
239     BYTE	p_valid;		/* is this pattern OK to use? */
240 }	ior_pattern;
241 
242 /*
243  * ior_test - definitions of the tests that will be run
244  *
245  * t_patterns - an array of 100 pattern IDs.  For each test run, a random
246  *	number (mod 100) is used to select which pattern will be used next.
247  */
248 typedef	struct	ior_test_struct {	/* I/O test definitions */
249     char	*t_name;		/* name of this test */
250     long	t_duration;		/* duration in seconds */
251     long	t_ignore;		/* seconds of 'start-up' stats */
252     long	t_pause;		/* seconds of waiting before test */
253     long	t_iops;			/* maximum I/Os per sec. to drive */
254 
255     int		t_skew;			/* sub-LUN skew level to emulate */
256     long	t_seed;			/* random seed for skew data */
257     int		t_shift;		/* sub-LUN skew shift */
258     int		t_correlate;		/* correlation of skewed data */
259     HUGE	t_area;			/* size of each area for skew */
260 
261     HUGE	t_start;		/* where do we start? */
262     HUGE	t_size;			/* how much do we test? */
263     HUGE	t_end;			/* end of test area - start + size */
264     float	t_start_pct;		/* starting percentage */
265     float	t_size_pct;		/* size percentage */
266     int		t_pat_pct[ IOR_MAX_PATTERNS + 2 ]; /* percent of each pattern */
267     int		t_patterns[ 100 ];	/* patterns to run */
268     BYTE	t_running;		/* running with stats on */
269     BYTE	t_valid;		/* is this test OK to use? */
270 }	ior_test;
271 
272 /*
273  * ior_config - overall configuration information for iorate
274  *
275  * c_sleep - will give any outstanding data (like that stored in cache for
276  *	a cached array) time to destage, enabling the next test to be more
277  *	accurate of what the particular test is trying to measure.
278  *
279  * c_ignore - stats for this many seconds at the start of each test will be
280  *	dropped from the test totals, to give a 'steady state' measure of
281  *	the I/O rate for the particular test.
282  */
283 typedef	struct	ior_config_struct {	/* overall iorate config info */
284     char	*c_program;		/* name of this program */
285     BYTE	c_verbose;		/* be chatty about work in progress */
286     BYTE	c_debug;		/* ONLY used for program debugging */
287     BYTE	c_silent;		/* be silent to stdout */
288     BYTE	c_show_limit;		/* display size limits and exit */
289     BYTE	c_no_testing;		/* don't actually do any testing */
290     BYTE	c_is_active;		/* are tests in progress */
291     BYTE	c_tollerate_short_reads; /* be OK with reads that are short */
292     BYTE	c_direct_io;		/* set direct I/O when opening files */
293     int		c_debug_level;		/* level of debug messages to show */
294     char	*c_log_name;		/* name of log info file */
295     char	*c_perf_name;		/* name of perf info file */
296     char	*c_perf_dir;		/* directory for performance info */
297     FILE	*c_log_file;		/* file for log info */
298     FILE	*c_perf_file;		/* file for performance info */
299     int		c_sleep;		/* seconds to sleep between tests */
300     int		c_ignore;		/* seconds of I/O to not rate */
301     long	c_target_resp;		/* target response time - slowed */
302     double	c_target_sec;		/* target response time - in seconds */
303     int		c_target_rate;		/* percent of target iops to use */
304 
305     int		c_shift;		/* sub-LUN skew shift for all tests */
306     float	c_area_count;		/* how many area groups on the device */
307     long	c_num_areas;		/* number of used areas */
308     ior_skew_area *c_areas;		/* the areas holding our data */
309     HUGE	c_max_area;		/* largest area size for skew testing */
310     HUGE	c_area;			/* current area size for skew testing */
311     HUGE	c_skew_set_size;	/* the size of the device covered by a full set of all areas */
312     HUGE	c_max_dev_size;		/* size of the largest active device */
313     HUGE	c_min_dev_size;		/* size of the smallest active device */
314     float	c_skew_capacities[ 5 ];	/* capacities for skewed data */
315     float	c_skew_workloads[ 5 ];	/* iops for skewed data */
316     int		c_skew_group_count[ 5 ]; /* number of skew groups in each target range */
317     ior_skew_list c_skewed[ IOR_SKEW_LISTS + 2 ]; /* our skew lists */
318     ior_odds_item c_odds_i[ IOR_SKEW_LISTS + 2 ]; /* odds of I/O to each skew list */
319     ior_odds	c_odds;			/* odds for I/Os */
320 
321     int		c_ndev;			/* number of target devices */
322     int		c_vdev;			/* number of valid target devices */
323     int		c_adev;			/* number of active target devices */
324     					/* note active includes copies */
325     int		c_npat;			/* number of defined patterns */
326     int		c_ntest;		/* number of defined tests */
327     char	*c_dev_name;		/* device file name */
328     char	*c_pat_name;		/* pattern file name */
329     char	*c_test_name;		/* test file name */
330     char	*c_iops_name;		/* iops file name */
331     ior_device	c_devs[ IOR_MAX_DEVICES + 2 ]; /* target device list */
332     ior_pattern	c_pats[ IOR_MAX_PATTERNS + 2 ]; /* available patterns to run */
333     ior_test	c_tests[ IOR_MAX_TESTS + 2 ]; /* the tests that will be run */
334 
335     long	c_fid;			/* file descriptor */
336     HUGE	c_pos;			/* current file position */
337     HUGE	c_start;		/* where do we start? */
338     HUGE	c_size;			/* how much do we test? */
339     HUGE	c_end;			/* end of test area - start + size */
340     HUGE	c_align;		/* block count to align on */
341     HUGE	c_blocks_read;		/* count of blocks read */
342     HUGE	c_blocks_written;	/* count of blocks written */
343     HUGE	c_reads;		/* number of reads performed */
344     HUGE	c_writes;		/* number of writes performed */
345     double	c_read_time_msecs;	/* read perf time in milisecs */
346     double	c_write_time_msecs;	/* write perf time in milisecs */
347     ior_clock	c_io_time;		/* elapsed time for counted I/Os */
348     int		c_errors;		/* # of errors seen this pass */
349     int		c_cur_dev;		/* active device */
350     int		c_cur_adev;		/* active within count on device */
351     int		c_cur_test;		/* test we are running */
352     int		c_cur_pat;		/* pattern we are using */
353     ior_clock	c_start_time;		/* time we started this test run */
354 
355 				/* file parsing records */
356     char	c_l_str[ 256 ];		/* contents of found strings */
357     double	c_l_value;		/* values of parsed numbers */
358     int		c_l_line;		/* line number being parsed */
359     char	*c_l_name;		/* name of file being parsed */
360     char	*c_l_cur_txt;		/* text of current line being read */
361     int		c_l_cur_pos;		/* location of current read */
362     char	c_l_error[ 256 ];	/* string of error message */
363 
364     BYTE	*c_read_buf;		/* buffers for the real I/O */
365     BYTE	*c_write_buf;
366 }	ior_config;
367 
368 extern char msg_buf[];			/* message buffer */
369 
370 /*
371  * functions from ior_file.c
372  */
373 extern int ior_read_devs( ior_config *cfg );
374 extern int ior_read_pats( ior_config *cfg );
375 extern int ior_read_tests( ior_config *cfg );
376 extern int ior_log_devs( ior_config *cfg );
377 extern int ior_log_pats( ior_config *cfg );
378 extern int ior_log_tests( ior_config *cfg );
379 extern char *ior_size_to_ascii( ior_config *cfg, HUGE t_size );
380 extern char *ior_time_to_ascii( ior_config *cfg, long t_time );
381 
382 /*
383  * functions from ior_mach.c
384  */
385 extern int ior_open_dev( ior_config *cfg, int dev );
386 extern int ior_close_dev( ior_config *cfg, int dev );
387 extern int ior_read( ior_config *cfg, long io_size, double *io_resp );
388 extern int ior_write( ior_config *cfg, long io_size, double *io_resp );
389 extern int ior_seek( ior_config *cfg, HUGE pos );
390 extern int ior_get_capacity( ior_config *cfg, long dev );
391 extern HUGE ior_rand( ior_config *cfg );
392 extern int ior_random_seed( ior_config *cfg, long seed );
393 extern int ior_randomize( ior_config *cfg );
394 extern long ior_get_time( ior_config *cfg );
395 extern int ior_date_string( ior_config *cfg, ior_clock clk, char *str );
396 extern int ior_sleep( ior_config *cfg, int sec );
397 extern int ior_sleep_usec( ior_config *cfg, long usec );
398 extern int ior_set_lock( ior_config *cfg );
399 extern int ior_clear_lock( ior_config *cfg );
400 
401 /*
402  * functions from ior_test.c
403  */
404 extern int ior_run_dev_test( ior_config *cfg );
405 extern int ior_test_prep_std( ior_config *cfg );
406 extern int ior_test_prep_skew( ior_config *cfg );
407 extern int ior_run_pat( ior_config *cfg, long pat );
408 extern int ior_run_skew( ior_config *cfg, long pat );
409 extern int ior_run_sel_pat( ior_config *cfg, long pat );
410 extern int ior_io( ior_config *cfg, long io, long io_size, HUGE pos, ior_skew_list *skew );
411 extern int ior_set_rand_pos( ior_config *cfg, long pat );
412 
413 /*
414  * functions from iorate.c
415  */
416 extern int ior_read_args( ior_config *cfg, int argc, char **argv );
417 extern int ior_read_config( ior_config *cfg );
418 extern int ior_prepare( ior_config *cfg );
419 extern int ior_run_tests( ior_config *cfg );
420 extern int ior_cleanup( ior_config *cfg );
421 extern int ior_usage( ior_config *cfg );
422 extern int ior_error( ior_config *cfg, char *msg );
423 extern int ior_warn( ior_config *cfg, char *msg );
424 extern int ior_msg( ior_config *cfg, char *msg_type, char *msg );
425 extern int ior_verbose( ior_config *cfg, char *msg );
426 extern int ior_log( ior_config *cfg, char *msg );
427 extern int ior_write_log( ior_config *cfg, char *str );
428 extern char *ior_strdup( ior_config *cfg, char *str );
429 #define	IOR_AREA_HEAD		TRUE
430 #define	IOR_AREA_TAIL		FALSE
431 extern int ior_area( ior_config *cfg, int to_head, ior_skew_area *area, ior_skew_list *list );
432 extern int ior_odds_pick( ior_config *cfg, ior_odds *odds );
433 extern int ior_signal_kids( ior_config *cfg, int sig );
434 extern void ior_signal( int sig );
435 
436 extern int ior_read_iops( ior_config *cfg );
437 
438 extern int ior_parse_prep( ior_config *cfg, char *f_name );
439 
440 extern int yyparse();
441 extern int ior_debug( ior_config *cfg, char *msg );
442 extern int ior_debug_l( ior_config *cfg, int level, char *msg );
443 extern int ior_dev_lock( ior_config *cfg, long dev );
444 extern int ior_dev_unlock( ior_config *cfg, long dev );
445 extern int ior_time_usec( ior_config *cfg, long *sec, long *usec );
446 
447 extern int ior_lex_prep( ior_config *cfg);
448 extern int ior_parse_dev_clear( ior_config *cfg );
449 extern int ior_parse_pat_clear( ior_config *cfg );
450 extern int ior_parse_test_clear( ior_config *cfg );
451 extern int ior_lex_done( ior_config *cfg);
452 
453 extern int yylex();
454 
455 extern int ior_lex_is_sep( ior_config *cfg, char c );
456 
457 #ifdef	IOR_ENGINEERING
458 extern int ior_eng_prep( ior_config *cfg );
459 extern int ior_eng_pre_test( ior_config *cfg );
460 extern int ior_eng_test_done( ior_config *cfg );
461 extern int ior_eng_clean( ior_config *cfg );
462 extern int ior_eng_read( ior_config *cfg, long io_size,
463 		long bytes_trans, double resp_time );
464 extern int ior_eng_write( ior_config *cfg, long io_size,
465 		long bytes_trans, double resp_time );
466 #endif
467 
468 #endif
469 
470