1 /**************************************************************************
2 *
3 * ior_test.c - the IORATE routines to do the test
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 static char rcsid[] = "$Header: /home/westiv/iorate/RCS/ior_test.c,v 3.23 2011/11/03 15:44:20 westiv Exp westiv $";
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "iorate.h"
34
35 /*
36 * ior_run_dev_test - run a test pass on a selected drive
37 */
ior_run_dev_test(ior_config * cfg)38 int ior_run_dev_test( ior_config *cfg )
39 /* ior_config *cfg; our configuration */
40 {
41 int result; /* final return code */
42 int done; /* is timing done? */
43 ior_test *cur_test; /* test we are running */
44 ior_device *cur_dev; /* current active device */
45 ior_skew_list *cur_skew; /* currrent skew group list */
46 ior_skew_area *cur_area; /* current skew area */
47 ior_clock cur_time; /* current time */
48 ior_clock elapsed_time; /* time gone by */
49 HUGE o_size; /* old size */
50 HUGE n_size; /* new size */
51 HUGE over_size; /* size we go over a set for this device */
52 HUGE tgt_size; /* size needed for test */
53 int area_copies; /* base copes of all areas */
54 double d_size; /* percent sizing of values */
55 long shuffle_count; /* how many areas to shuffle */
56 int group; /* skew group we are adding to */
57 int skew_count; /* skews in group for stats */
58 int skew_start; /* starting skew for stats */
59 int n_skew; /* current skew ID being added */
60 HUGE n_iops; /* iops for this group */
61 double n_resp_time; /* response time for this group */
62 char msg[ 200 ]; /* message buffer */
63 int i;
64
65 ior_debug_l( cfg, IOR_DEBUG_MAJOR, "ior_run_dev_test: Entering code -->>" );
66
67 result = strlen( rcsid ); /* STOP unused complaints from compiler */
68 result = 0; /* all OK so far */
69 done = 0; /* time not up yet */
70
71 cur_dev = &( cfg->c_devs[ cfg->c_cur_dev ]);
72 cur_test = &( cfg->c_tests[ cfg->c_cur_test ]);
73
74 sprintf( msg_buf, "Test starting on device %d.%d '%s'",
75 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1, cur_dev->d_name );
76 ior_debug( cfg, msg_buf );
77
78 /* fix sizing of this test */
79 /** NOTE: all locations are aligned when the random **/
80 /** positions for the next I/O are chosen later. **/
81 if ( cur_test->t_start_pct >= 0 ) {
82 d_size = cur_test->t_start_pct / 100.0;
83 d_size *= cur_dev->d_capacity;
84 cur_test->t_start = d_size;
85 sprintf( msg_buf,
86 " --> Sizing dev %d.%d test start at %.3lf%% of %0.2fm (%0.2fm)",
87 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1, cur_test->t_start_pct,
88 cur_dev->d_capacity / 1048576.0,
89 cur_test->t_start / 1048576.0 );
90 ior_debug( cfg, msg_buf );
91 };
92 if ( cur_test->t_start < cur_dev->d_offset ) {
93 cur_test->t_start = cur_dev->d_offset;
94 };
95
96 if ( cur_test->t_size_pct >= 0 ) {
97 d_size = cur_test->t_size_pct / 100.0 ;
98 d_size *= cur_dev->d_capacity;
99 cur_test->t_size = d_size;
100 sprintf( msg_buf,
101 " --> Sizing dev %d.%d test size to %.3lf%% of %0.2fm (%0.2fm)",
102 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1, cur_test->t_size_pct,
103 cur_dev->d_capacity / 1048576.0,
104 cur_test->t_size / 1048576.0 );
105 ior_debug( cfg, msg_buf );
106 };
107
108 if ( cur_test->t_size <= 0 ) { /* no size set yet */
109 cur_test->t_end = cur_dev->d_capacity - ( IOR_MAX_IO_SIZE * 2 );
110 cur_test->t_size = cur_test->t_end - cur_test->t_start;
111 };
112
113 cur_test->t_end = cur_test->t_start + cur_test->t_size;
114
115 /* wrapped, so limit the size (quiet) */
116 if ( cur_test->t_end < 0 ) {
117 cur_test->t_end = IOR_MAX_SEEK - IOR_MAX_IO_SIZE;
118 cur_test->t_size = cur_test->t_end - cur_test->t_start;
119 sprintf( msg_buf,
120 " --> Dev %d.%d test size over limit (wrapped) - fixed",
121 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
122 ior_debug( cfg, msg_buf );
123 };
124 if ( cur_test->t_end > cur_dev->d_capacity ) {
125 o_size = cur_test->t_end - cur_test->t_start;
126
127 cur_test->t_end = cur_dev->d_capacity;
128
129 n_size = cur_test->t_end - cur_test->t_start;
130
131 sprintf( msg_buf,
132 "Test size in test %d '%s' is too large for device %d.%d:\n\t-- Reduced to %0.2fm (from %0.2fm)",
133 cfg->c_cur_test + 1, cur_test->t_name,
134 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
135 n_size / 1048576.0, o_size / 1048576.0 );
136
137 /* note change if > .1% */
138 if (( o_size - n_size ) > ( o_size / 1000 )) {
139 ior_warn( cfg, msg_buf );
140 } else {
141 ior_debug( cfg, msg_buf );
142 };
143
144 cur_test->t_size = n_size;
145 };
146 if ( cur_test->t_end > ( IOR_MAX_SEEK - IOR_MAX_IO_SIZE )) {
147 o_size = cur_test->t_end - cur_test->t_start;
148
149 cur_test->t_end = IOR_MAX_SEEK - IOR_MAX_IO_SIZE;
150
151 n_size = cur_test->t_end - cur_test->t_start;
152
153 sprintf( msg_buf,
154 "Test size in test %d '%s' is too long for seek, reduced to %0.2fm",
155 cfg->c_cur_test + 1, cur_test->t_name, n_size / 1048576.0 );
156
157 /* note change if > .1% */
158 if (( o_size - n_size ) > ( o_size / 1000 )) {
159 ior_warn( cfg, msg_buf );
160 } else {
161 ior_debug( cfg, msg_buf );
162 };
163
164 cur_test->t_size = n_size;
165 };
166
167 /* checks for test if skew is on */
168 if ( cur_test->t_skew > 0 ) {
169
170 /* if skewed, check the size */
171 if ( cur_test->t_size <
172 cur_test->t_area * IOR_AREA_MIN_PER_DRIVE ) {
173 strcpy( msg, ior_size_to_ascii( cfg, cur_test->t_area ));
174 sprintf( msg_buf, "device '%s' %d.%d: size (%s) less than %d * skew area (%s)",
175 cur_dev->d_name,
176 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
177 ior_size_to_ascii( cfg, cur_test->t_size ),
178 (int)( IOR_AREA_MIN_PER_DRIVE ),
179 msg );
180 ior_error( cfg, msg_buf );
181
182 return( -10 );
183 };
184
185 /* note the overall sizes we are targeting */
186 /* how large without wrapping */
187 cfg->c_skew_set_size = cfg->c_num_areas * cur_test->t_area;
188 /* number of additional copies we MAY need */
189 area_copies = cur_test->t_size / cfg->c_skew_set_size;
190 /* size we target ABOVE the copies */
191 tgt_size = cur_test->t_size - area_copies * cfg->c_skew_set_size;
192
193 if ( cfg->c_cur_adev < 1 ) { /* only note for one copy of a device */
194 sprintf( msg_buf, "ior_test: device %d: unique mapped space %ldk, copies %d, overflow size %ldk",
195 cfg->c_cur_dev + 1,
196 (long)( cfg->c_skew_set_size / 1024L ),
197 (int)( area_copies ),
198 (long)( tgt_size / 1024L ));
199 ior_debug_l( cfg, IOR_DEBUG_MINOR, msg_buf );
200 };
201
202 /* no over capacity yet */
203 over_size = 0;
204 /* number of copies for this test */
205 for ( i = 0; i < cfg->c_num_areas; i++ ) { /* walk the areas */
206 cur_area = &( cfg->c_areas[ i ]);
207
208 /* at least base copies, 1 more if in range */
209 cur_area->a_copies = area_copies;
210 if ( over_size <= tgt_size ) {
211 cur_area->a_copies++;
212
213 /* note area added here */
214 over_size += cur_test->t_area;
215 };
216 };
217
218
219 /* now randomize the areas in each group for more realistic simulation */
220 /* this is done here so the pattern is unique per device copy */
221 /* --- note that a new random seed per test/device is set in iorate.c --- */
222 for ( group = 0; group < IOR_SKEW_LISTS; group++ ) {
223 cur_skew = &( cfg->c_skewed[ group ]);
224 cur_area = cur_skew->s_areas;
225
226 /* shuffle 100-300% - mix it up */
227 shuffle_count = ( cur_skew->s_area_current *
228 ( 100 + ior_rand( cfg ) % 200 )) / 100;
229
230 for ( ; shuffle_count > 0; shuffle_count-- ) {
231 /* pick a random area */
232 for ( i = ior_rand( cfg ) %
233 ( cur_skew->s_area_current - 2 );
234 i > 0; i-- ) {
235 cur_area = cur_area->a_next;
236 };
237
238 sprintf( msg_buf, "randomizing: area %ld to tail of group %d - %ld more to go, %ld in group",
239 cur_area->a_id, group,
240 (long)( shuffle_count - 1 ),
241 cur_skew->s_area_current );
242 ior_debug_l( cfg, IOR_DEBUG_SMALL, msg_buf );
243
244 /* move it to the end */
245 ior_area( cfg, IOR_AREA_TAIL, cur_area, cur_skew );
246
247 cur_area = cur_skew->s_areas;
248 };
249 };
250
251 };
252
253 sprintf( msg_buf,
254 " --> Ready to test dev %d.%d:\n\tStart %.2fm - Size %.2fm - End %.2fm",
255 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
256 cur_test->t_start / 1048576.0,
257 cur_test->t_size / 1048576.0,
258 cur_test->t_end / 1048576.0 );
259 ior_debug( cfg, msg_buf );
260
261 if ( cur_test->t_skew < IOR_SKEW_MIN ) {
262 result = ior_test_prep_std( cfg ); /* prep for all our patterns to run */
263 } else {
264 result = ior_test_prep_skew( cfg );
265 };
266
267 /* open the target device */
268 if ( result == 0 ) {
269 result = ior_open_dev( cfg, cfg->c_cur_dev );
270 };
271
272
273 if ( cur_test->t_ignore < 1 ) { /* no delay - start stats now */
274 cur_test->t_running = 1;
275 };
276
277 if ( cfg->c_target_resp > 0 ) { /* using target I/O rate */
278
279 /* since we will be waiting, sleep for a random desired time */
280 /* to avoid process contention on devices on startup */
281
282 ior_debug( cfg, "Using target iorate, so starting with random delay" );
283
284 ior_sleep_usec( cfg, ior_rand( cfg ) % cfg->c_target_resp );
285 };
286
287 cur_time = ior_get_time( cfg ); /* start with time */
288
289 while ( !done && !result ) {
290
291 if ( cur_test->t_skew > 0 ) {
292 result = ior_run_skew( cfg,
293 cur_test->t_patterns[ ior_rand( cfg ) % 100 ]);
294 } else {
295 result = ior_run_pat( cfg,
296 cur_test->t_patterns[ ior_rand( cfg ) % 100 ]);
297 };
298
299 cur_time = ior_get_time( cfg ); /* check for time done */
300 elapsed_time = cur_time - cfg->c_start_time;
301 cfg->c_io_time = elapsed_time; /* current I/O time */
302
303 if ( !cur_test->t_running ) {
304 if ( elapsed_time >= cur_test->t_ignore ) {
305 cur_test->t_running = 1;
306 cfg->c_reads = 0;
307 cfg->c_blocks_read = 0;
308 cfg->c_writes = 0;
309 cfg->c_blocks_written = 0;
310 cfg->c_read_time_msecs = 0;
311 cfg->c_write_time_msecs = 0;
312
313 /* and for each skew group */
314 if ( cur_test->t_skew > 0 ) {
315 for ( i = 0; i < IOR_SKEW_LISTS; i++ ) {
316 cur_skew = &( cfg->c_skewed[ i ]);
317
318 cur_skew->s_perf.sp_rand_reads = 0;
319 cur_skew->s_perf.sp_rand_read_resp = 0;
320 cur_skew->s_perf.sp_seq_reads = 0;
321 cur_skew->s_perf.sp_seq_read_resp = 0;
322 cur_skew->s_perf.sp_rand_writes = 0;
323 cur_skew->s_perf.sp_rand_write_resp = 0;
324 cur_skew->s_perf.sp_seq_writes = 0;
325 cur_skew->s_perf.sp_seq_write_resp = 0;
326 };
327 };
328
329 #ifdef IOR_ENGINEERIG
330 ior_eng_reset_stats( cfg );
331 #endif
332
333 };
334 } else {
335 cfg->c_io_time -= cur_test->t_ignore; /* no record of ignored I/Os */
336 };
337
338 if ( elapsed_time >= cur_test->t_duration ) {
339 done = 1;
340 };
341 };
342 /* close the target device */
343 if ( cfg->c_devs[ cfg->c_cur_dev ].d_is_active ) {
344 i = ior_close_dev( cfg, cfg->c_cur_dev );
345 } else {
346 i = 0;
347 };
348
349 if ( result == 0 ) {
350 result = i; /* set result to close status */
351
352 cur_dev = &( cfg->c_devs[ cfg->c_cur_dev ]);
353
354 fprintf( cfg->c_perf_file, "%d\t%s\t%d\t%s\t%ld\t%ld",
355 cfg->c_cur_test + 1,
356 cfg->c_tests[ cfg->c_cur_test ].t_name,
357 cfg->c_cur_dev + 1,
358 cur_dev->d_name,
359 cur_time - cfg->c_start_time,
360 cfg->c_io_time );
361
362 fprintf( cfg->c_perf_file, "\t%ld\t%ld\t%.3lf",
363 (long)( cfg->c_reads ),
364 (long)( cfg->c_blocks_read ),
365 cfg->c_reads == 0 ? (double) 0.0 : /* no div by zero */
366 cfg->c_read_time_msecs / cfg->c_reads );
367
368 fprintf( cfg->c_perf_file, "\t%ld\t%ld\t%.3lf",
369 (long)( cfg->c_writes ), (long)( cfg->c_blocks_written ),
370 cfg->c_writes == 0 ? (double) 0.0 : /* no div by zero */
371 cfg->c_write_time_msecs / cfg->c_writes );
372
373 fprintf( cfg->c_perf_file, "\t%ld\t%ld\t%.3lf",
374 (long)( cfg->c_reads + cfg->c_writes ),
375 (long)( cfg->c_blocks_read + cfg->c_blocks_written ),
376 ( cfg->c_reads + cfg->c_writes ) == 0 ? (double) 0.0 :
377 ( cfg->c_read_time_msecs + cfg->c_write_time_msecs ) /
378 ( cfg->c_reads + cfg->c_writes ));
379
380 fprintf( cfg->c_perf_file, "\t%ld\t%ld\t%ld",
381 (long)(( cfg->c_reads + cfg->c_writes ) / cfg->c_io_time ),
382 (long)(( cfg->c_blocks_read + cfg->c_blocks_written ) /
383 cfg->c_io_time ),
384 (long)( cfg->c_cur_adev + 1 ));
385
386 /* add skew area performance data as well */
387 if ( cur_test->t_skew > 0 ) {
388
389 /* for DEBUG, we give data for each skew group */
390 if ( cfg->c_debug_level >= IOR_DEBUG_MAJOR ) {
391 for ( i = 0; i < IOR_SKEW_LISTS; i++ ) {
392 cur_skew = &( cfg->c_skewed[ i ]);
393
394 fprintf( cfg->c_perf_file, "\t%ld\t%.2f\t%ld\t%.2f\t%ld\t%.2f\t%ld\t%.2f",
395 (long)( cur_skew->s_perf.sp_rand_reads ),
396 (float)( cur_skew->s_perf.sp_rand_reads == 0 ? 0 :
397 cur_skew->s_perf.sp_rand_read_resp /
398 cur_skew->s_perf.sp_rand_reads ),
399 (long)( cur_skew->s_perf.sp_seq_reads ),
400 (float)( cur_skew->s_perf.sp_seq_reads == 0 ? 0 :
401 cur_skew->s_perf.sp_seq_read_resp /
402 cur_skew->s_perf.sp_seq_reads ),
403 (long)( cur_skew->s_perf.sp_rand_writes ),
404 (float)( cur_skew->s_perf.sp_rand_writes == 0 ? 0 :
405 cur_skew->s_perf.sp_rand_write_resp /
406 cur_skew->s_perf.sp_rand_writes ),
407 (long)( cur_skew->s_perf.sp_seq_writes ),
408 (float)( cur_skew->s_perf.sp_seq_writes == 0 ? 0 :
409 cur_skew->s_perf.sp_seq_write_resp /
410 cur_skew->s_perf.sp_seq_writes ));
411 };
412 /* otherwise, we give data for the target regions */
413 } else {
414
415 skew_start = 0; /* none totaled yet */
416 for ( i = 0; i < 3; i++ ) {
417 skew_count = cfg->c_skew_group_count[ i ];
418
419 n_iops = 0;
420 n_resp_time = 0;
421 for ( n_skew = skew_start + skew_count - 1;
422 n_skew >= skew_start; n_skew-- ) {
423 cur_skew = &( cfg->c_skewed[ n_skew ]);
424 n_iops += cur_skew->s_perf.sp_rand_reads;
425 n_resp_time += cur_skew->s_perf.sp_rand_read_resp;
426 };
427 fprintf( cfg->c_perf_file, "\t%ld\t%.2f",
428 (long)( n_iops ),
429 (float)( n_iops == 0 ? 0 :
430 ( n_resp_time / n_iops )));
431
432 n_iops = 0;
433 n_resp_time = 0;
434 for ( n_skew = skew_start + skew_count - 1;
435 n_skew >= skew_start; n_skew-- ) {
436 cur_skew = &( cfg->c_skewed[ n_skew ]);
437 n_iops += cur_skew->s_perf.sp_seq_reads;
438 n_resp_time += cur_skew->s_perf.sp_seq_read_resp;
439 };
440 fprintf( cfg->c_perf_file, "\t%ld\t%.2f",
441 (long)( n_iops ),
442 (float)( n_iops == 0 ? 0 :
443 ( n_resp_time / n_iops )));
444
445 n_iops = 0;
446 n_resp_time = 0;
447 for ( n_skew = skew_start + skew_count - 1;
448 n_skew >= skew_start; n_skew-- ) {
449 cur_skew = &( cfg->c_skewed[ n_skew ]);
450 n_iops += cur_skew->s_perf.sp_rand_writes;
451 n_resp_time += cur_skew->s_perf.sp_rand_write_resp;
452 };
453 fprintf( cfg->c_perf_file, "\t%ld\t%.2f",
454 (long)( n_iops ),
455 (float)( n_iops == 0 ? 0 :
456 ( n_resp_time / n_iops )));
457
458 n_iops = 0;
459 n_resp_time = 0;
460 for ( n_skew = skew_start + skew_count - 1;
461 n_skew >= skew_start; n_skew-- ) {
462 cur_skew = &( cfg->c_skewed[ n_skew ]);
463 n_iops += cur_skew->s_perf.sp_seq_writes;
464 n_resp_time += cur_skew->s_perf.sp_seq_write_resp;
465 };
466 fprintf( cfg->c_perf_file, "\t%ld\t%.2f",
467 (long)( n_iops ),
468 (float)( n_iops == 0 ? 0 :
469 ( n_resp_time / n_iops )));
470
471 skew_start += skew_count;
472 };
473 };
474 };
475
476 #ifdef IOR_ENGINEERING
477 ior_eng_test_done( cfg );
478 #endif
479
480 fprintf( cfg->c_perf_file, "\n" );
481 fflush( cfg->c_perf_file );
482 } else {
483 fprintf( cfg->c_perf_file,
484 "TEST%03d,%s,FAILED,device %d copy %d\n",
485 cfg->c_cur_test + 1, cfg->c_devs[ cfg->c_cur_dev ].d_name,
486 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
487 fflush( cfg->c_perf_file );
488
489 ior_error( cfg, "BAILING out of test due to errors" );
490 };
491
492 ior_debug_l( cfg, IOR_DEBUG_MAJOR, "ior_run_dev_test: <<-- Leaving code" );
493
494 return( result );
495 }
496
497 /*
498 * ior_test_prep_std - prepare for a non-skew test run
499 */
ior_test_prep_std(ior_config * cfg)500 int ior_test_prep_std( ior_config *cfg )
501 /* ior_config *cfg; our configuration */
502 {
503 int result; /* final return code */
504 int cur; /* current item in loop */
505 ior_test *cur_test; /* test we are running */
506 ior_pattern *cur_pat; /* current active pattern */
507 ior_device *cur_dev; /* current active pattern */
508 HUGE saved_start; /* saved pattern start */
509 HUGE saved_end; /* saved pattern end */
510 HUGE o_size; /* old size */
511 HUGE n_size; /* new size */
512 HUGE h_tmp; /* huge temp value */
513 double d_size; /* percent sizing of values */
514 char msg[ 200 ]; /* message buffer */
515 int i;
516
517 ior_debug_l( cfg, IOR_DEBUG_MINOR, "ior_test_prep_std: Entering code -->>" );
518
519 result = 0; /* all OK so far */
520
521 cur_dev = &( cfg->c_devs[ cfg->c_cur_dev ]);
522 cur_test = &( cfg->c_tests[ cfg->c_cur_test ]);
523
524 /* start each pattern */
525 for ( cur = 0; cur < cfg->c_npat; cur++ ) {
526
527 cur_pat = &( cfg->c_pats[ cur ]);
528
529 /* only check on active patterns */
530 if (( !cur_pat->p_valid ) || ( cur_test->t_pat_pct[ cur ] < 1 )) {
531 continue;
532 };
533
534 /* fix sizing for this pattern */
535 if ( cur_pat->p_start_pct == 0 ) {
536 cur_pat->p_start = 0;
537 };
538 if ( cur_pat->p_start_pct > 0 ) {
539 d_size = cur_pat->p_start_pct / 100.0 ;
540 d_size *= cur_test->t_size;
541 cur_pat->p_start = d_size;
542 sprintf( msg_buf,
543 " --> Sizing dev %d.%d pat %d start to %.3lf%% of %0.2fm (%0.2fm)",
544 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
545 cur + 1, cur_pat->p_start_pct,
546 cur_test->t_size / 1048576.0,
547 cur_pat->p_start / 1048576.0 );
548 ior_debug( cfg, msg_buf );
549 };
550 if ( cur_test->t_start > 0 ) { /* include any offset from test */
551 cur_pat->p_start += cur_test->t_start;
552 sprintf( msg_buf,
553 " --> Adding test start of %ldk to dev %d.%d pat %d start",
554 (long)( cur_test->t_start / 1024L ),
555 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1, cur + 1 );
556 ior_debug( cfg, msg_buf );
557 };
558 if ( cur_pat->p_size_pct >= 0 ) {
559 d_size = cur_pat->p_size_pct / 100.0 ;
560 d_size *= cur_test->t_size;
561 cur_pat->p_size = d_size;
562 sprintf( msg_buf,
563 " --> Sizing dev %d.%d pat %d size to %.3lf%% of %0.2fm (%0.2fm)",
564 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
565 cur + 1, cur_pat->p_size_pct,
566 cur_test->t_size / 1048576.0,
567 cur_pat->p_size / 1048576.0 );
568 ior_debug( cfg, msg_buf );
569 };
570 cur_pat->p_end = cur_pat->p_start + cur_pat->p_size;
571
572 /* check for too large */
573 if ( cur_pat->p_end > cur_test->t_end ) {
574 o_size = cur_pat->p_end - cur_pat->p_start;
575
576 cur_pat->p_end = cur_test->t_end;
577
578 n_size = cur_pat->p_end - cur_pat->p_start;
579
580 sprintf( msg_buf,
581 " -->> Pattern '%s' (%d) size too large for test:\n\t-- Reduced to %0.2fm",
582 cur_pat->p_name, cur + 1, n_size / 1048576.0 );
583
584 /* note change if > .1% */
585 if (( o_size - n_size ) > ( o_size / 1000 )) {
586 ior_warn( cfg, msg_buf );
587 } else {
588 ior_debug( cfg, msg_buf );
589 };
590
591 cur_pat->p_size = n_size;
592 };
593 /* prep localities */
594 if ( cur_pat->p_local_pct > 0 ) {
595 cur_pat->p_local_size = (HUGE)(cur_pat->p_size *
596 cur_pat->p_local_pct / 100);
597 sprintf( msg_buf, "Setting locality size to %.0f%% (%ldk)",
598 cur_pat->p_local_pct,
599 (long)( cur_pat->p_local_size / 1024L ));
600 ior_debug( cfg, msg_buf );
601 };
602 if ( cur_pat->p_local_size > 0 ) {
603
604 if ( cur_pat->p_local_size < cur_pat->p_io_size * 5 ) {
605 sprintf( msg_buf,
606 "Locality size too small (%ldk) in pattern %d - increased to %ldk",
607 (long)( cur_pat->p_local_size / 1024L ), cur + 1,
608 (long)(( cur_pat->p_io_size * 5 ) / 1024L ));
609 ior_warn( cfg, msg_buf );
610 cur_pat->p_local_size = cur_pat->p_io_size * 5;
611 };
612
613 cur_pat->p_local_avail = cur_pat->p_size /
614 ( cur_pat->p_local_size * 2 );
615
616 if ( cur_pat->p_local_avail < 1 ) {
617 sprintf( msg_buf,
618 "Not enough space for even 1 locality buffer in pattern %d",
619 cur + 1 );
620 ior_error( cfg, msg_buf );
621 cur_pat->p_local_avail = 1; /* get through the code here */
622 result = -4;
623 };
624
625 if ( cur_pat->p_local_avail < cur_pat->p_local_count ) {
626 sprintf( msg_buf,
627 #ifdef IOR_LARGE_FILES
628 "Available localities (%llu) less than requested (%llu)",
629 (long long unsigned)( cur_pat->p_local_avail ),
630 (long long unsigned)( cur_pat->p_local_count ));
631 #else
632 "Available localities (%lu) less than requested (%lu)",
633 (long unsigned)( cur_pat->p_local_avail ),
634 (long unsigned)( cur_pat->p_local_count ));
635 #endif
636 ior_error( cfg, msg_buf );
637 result = -3;
638 };
639
640 sprintf( msg_buf,
641 " -->> Locality buffers: count %ld size %ldk avail %ld",
642 (long)( cur_pat->p_local_count ),
643 (long)( cur_pat->p_local_size / 1024L ),
644 (long)( cur_pat->p_local_avail ));
645 ior_debug( cfg, msg_buf );
646
647
648 saved_start = cur_pat->p_start;
649 saved_end = cur_pat->p_end;
650
651 for ( i = 0; i < cur_pat->p_local_count; i++) {
652
653 sprintf( msg_buf, "Preparing locality %d", i + 1 );
654 ior_verbose( cfg, msg_buf );
655
656 cur_pat->p_local_uses[ i ] = 0;
657 cur_pat->p_local_seqs[ i ] = 0;
658
659 h_tmp = ior_rand( cfg ) % cur_pat->p_local_avail;
660 h_tmp *= 2 * cur_pat->p_local_size;
661 cur_pat->p_local_starts[ i ] = saved_start + h_tmp;
662 cur_pat->p_local_ends[ i ] =
663 cur_pat->p_local_starts[ i ] + cur_pat->p_local_size;
664
665 cur_pat->p_start = cur_pat->p_local_starts[ i ];
666 cur_pat->p_end = cur_pat->p_local_ends[ i ];
667 cur_pat->p_size = cur_pat->p_end - cur_pat->p_start;
668
669 /* and a random starting location */
670 ior_set_rand_pos( cfg, cur );
671 cur_pat->p_local_pos[ i ] = cur_pat->p_pos;
672
673 sprintf( msg_buf,
674 " -->> Pattern %d locality %d -- from %ldk to %ldk pos %ldk",
675 cur + 1, i + 1,
676 (long)( cur_pat->p_local_starts[ i ] / 1024L ),
677 (long)( cur_pat->p_local_ends[ i ] / 1024L ),
678 (long)( cur_pat->p_local_pos[ i ] / 1024L ));
679 ior_debug( cfg, msg_buf );
680 };
681
682 cur_pat->p_start = saved_start;
683 cur_pat->p_end = saved_end;
684 cur_pat->p_size = cur_pat->p_end - cur_pat->p_start;
685 };
686
687 cur_pat->p_hist_active = 0; /* no active history records */
688 cur_pat->p_hist_next = 0; /* start with item 0 */
689
690 /* help wih code debug */
691 sprintf( msg, "Pattern %d dev %d.%d: Test from %0.2fm to %0.2fm (size %0.2fm)",
692 cur + 1, cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
693 cur_pat->p_start / 1048576.0,
694 cur_pat->p_end / 1048576.0,
695 cur_pat->p_size / 1048576.0 );
696 ior_debug( cfg, msg );
697 /* check for bad pattern sizing */
698 if ( cur_pat->p_size <= ( cur_pat->p_io_size * 2 )) {
699 sprintf( msg, "Device %d.%d: Pattern %d: Too small a size (%ldk)",
700 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1, cur + 1,
701 (long) ( cur_pat->p_size / 1024L ));
702 ior_error( cfg, msg );
703 result = -5; /* note we took an error */
704 };
705 /* with no sequential history */
706 cur_pat->p_cur_seq = 0;
707 /* and a random starting location */
708 ior_set_rand_pos( cfg, cur );
709 };
710
711 ior_debug_l( cfg, IOR_DEBUG_MINOR, "ior_test_prep_std: <<-- Leaving code" );
712
713 return( result );
714 }
715
716 /*
717 * ior_run_pat - run the pattern on the given device
718 */
ior_run_pat(ior_config * cfg,long pat)719 int ior_run_pat( ior_config *cfg, long pat )
720 /* ior_config *cfg; our configuration */
721 /* long pat; pattern to use */
722 {
723 int result; /* final return code */
724 ior_pattern *cur_pat; /* current active pattern */
725 ior_pattern saved_pat; /* save area for local stuff */
726 long hist; /* which history record to use */
727 long local; /* local we are using */
728 HUGE h_tmp; /* huge temp value */
729
730 ior_debug_l( cfg, IOR_DEBUG_SMALL, "ior_run_pat: Entering code -->>" );
731
732 result = 0; /* all OK so far */
733
734 cfg->c_cur_pat = pat; /* note which pattern we are using */
735
736 cur_pat = &( cfg->c_pats[ pat ]);
737 /* use history if appropriate */
738 /* ONLY if history is FULL */
739 if ( cur_pat->p_history
740 && ( cur_pat->p_hist_active >= cur_pat->p_history )
741 && cur_pat->p_hist_use[ ior_rand( cfg ) % 100 ]) {
742
743 hist = ior_rand( cfg ) % cur_pat->p_hist_active;
744
745 sprintf( msg_buf, "-> Using history I/O %ld at %ldk",
746 hist + 1, (long) ( cur_pat->p_hist_records[ hist ]/ 1024L ));
747 ior_verbose( cfg, msg_buf );
748
749 result = ior_io( cfg, cur_pat->p_read_use[ ior_rand( cfg ) % 100 ],
750 cur_pat->p_io_size, cur_pat->p_hist_records[ hist ], NULL );
751
752 } else if ( cur_pat->p_local_size > 0 ) { /* do locality stuff */
753
754 /* choose which local to use */
755 local = ior_rand( cfg ) % cur_pat->p_local_count;
756 cur_pat->p_cur_local = local;
757
758 sprintf( msg_buf, "Using I/O locality %ld (%ldk -> %ldk) [%d.%d]",
759 local + 1,
760 (long) ( cur_pat->p_local_starts[ local ] / 1024L ),
761 (long) ( cur_pat->p_local_ends[ local ] / 1024L ),
762 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
763 ior_verbose( cfg, msg_buf );
764
765 saved_pat.p_pos = cur_pat->p_pos; /* save current pattern info */
766 saved_pat.p_cur_seq = cur_pat->p_cur_seq;
767 saved_pat.p_start = cur_pat->p_start;
768 saved_pat.p_end = cur_pat->p_end;
769 cur_pat->p_pos = cur_pat->p_local_pos[ local ];
770 cur_pat->p_cur_seq = cur_pat->p_local_seqs[ local ];
771 cur_pat->p_start = cur_pat->p_local_starts[ local ];
772 cur_pat->p_end = cur_pat->p_local_ends[ local ];
773 cur_pat->p_size = cur_pat->p_end - cur_pat->p_start;
774
775 result = ior_run_sel_pat( cfg, pat );
776
777 cur_pat->p_local_uses[ local ]++;
778
779 if (( cur_pat->p_local_limit > 0 )
780 && ( cur_pat->p_local_uses[ local ]
781 >= cur_pat->p_local_limit )) {
782
783 cur_pat->p_local_uses[ local ] = 0;
784 cur_pat->p_local_seqs[ local ] = 0;
785
786
787
788 h_tmp = ior_rand( cfg ) % cur_pat->p_local_avail;
789 h_tmp *= 2 * cur_pat->p_local_size;
790 cur_pat->p_local_starts[ local ] = saved_pat.p_start + h_tmp;
791 cur_pat->p_local_ends[ local ] =
792 cur_pat->p_local_starts[ local ]
793 + cur_pat->p_local_size;
794
795 cur_pat->p_start = cur_pat->p_local_starts[ local ];
796 cur_pat->p_end = cur_pat->p_local_ends[ local ];
797 cur_pat->p_size = cur_pat->p_end - cur_pat->p_start;
798 /* and a random starting location */
799 ior_set_rand_pos( cfg, pat );
800 cur_pat->p_local_pos[ local ] = cur_pat->p_pos;
801
802 sprintf( msg_buf,
803 " -->> Pattern %ld locality %ld NOW from %ldk to %ldk pos %ldk [%d.%d]",
804 pat + 1, local + 1,
805 (long)( cur_pat->p_local_starts[ local ] / 1024L ),
806 (long)( cur_pat->p_local_ends[ local ] / 1024L ),
807 (long)( cur_pat->p_local_pos[ local ] / 1024L ),
808 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
809 ior_debug( cfg, msg_buf );
810 } else {
811 cur_pat->p_local_pos[ local ] = cur_pat->p_pos;
812 cur_pat->p_local_seqs[ local ] = cur_pat->p_cur_seq;
813 };
814
815 /* restore saved pattern info */
816 cur_pat->p_pos = saved_pat.p_pos;
817 cur_pat->p_cur_seq = saved_pat.p_cur_seq;
818 cur_pat->p_start = saved_pat.p_start;
819 cur_pat->p_end = saved_pat.p_end;
820 cur_pat->p_size = cur_pat->p_end - cur_pat->p_start;
821
822 } else {
823 result = ior_run_sel_pat( cfg, pat );
824 };
825
826 ior_debug_l( cfg, IOR_DEBUG_SMALL, "ior_run_pat: <<-- Leaving code" );
827
828 return( result );
829 }
830
831 /*
832 * ior_run_sel_pat - run the selected pattern on the given device
833 */
ior_run_sel_pat(ior_config * cfg,long pat)834 int ior_run_sel_pat( ior_config *cfg, long pat )
835 /* ior_config *cfg; our configuration */
836 /* long pat; pattern to use */
837 {
838 int result; /* final return code */
839 ior_pattern *cur_pat; /* current active pattern */
840
841 result = 0; /* all OK so far */
842
843 cur_pat = &( cfg->c_pats[ pat ]);
844
845 cfg->c_cur_pat = pat; /* note which pattern we are using */
846
847 result = ior_io( cfg, cur_pat->p_read_use[ ior_rand( cfg ) % 100 ],
848 cur_pat->p_io_size, cur_pat->p_pos, NULL );
849
850 cur_pat->p_pos = cfg->c_pos; /* note new position for pattern */
851
852 if ( cur_pat->p_history > 0 ) { /* record new history item */
853
854 sprintf( msg_buf, "-->> Recording pattern %ld I/O as history element %ld [%d.%d]",
855 pat + 1, cur_pat->p_hist_next + 1,
856 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
857 ior_verbose( cfg, msg_buf );
858 /* note position I/O STARTED at */
859 cur_pat->p_hist_records[ cur_pat->p_hist_next++ ] =
860 cur_pat->p_pos - cur_pat->p_io_size;
861 if ( cur_pat->p_hist_active < cur_pat->p_hist_next ) {
862 cur_pat->p_hist_active = cur_pat->p_hist_next;
863 };
864 if ( cur_pat->p_hist_next >= cur_pat->p_history ) {
865 cur_pat->p_hist_next = 0;
866 };
867 };
868 /* if not random or seq. too long */
869 if ( !( cur_pat->p_is_seq ) ||
870 (( cur_pat->p_max_seq > 0 ) &&
871 ( ++( cur_pat->p_cur_seq ) >= cur_pat->p_max_seq ))) {
872 ior_set_rand_pos( cfg, pat );
873 cur_pat->p_cur_seq = 0;
874 sprintf( msg_buf, "I/O pattern %ld new random location chosen (%ldk) [%d.%d]",
875 pat + 1, (long) ( cur_pat->p_pos / 1024L ),
876 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
877 ior_verbose( cfg, msg_buf );
878 } else {
879 if ( cur_pat->p_pos + cur_pat->p_io_size >= cur_pat->p_end ) {
880 sprintf( msg_buf, "I/O pattern %ld wrapped to %ldk (%ldk >= %ldk) [%d.%d]",
881 pat + 1, (long) ( cur_pat->p_start / 1024L ),
882 (long) (( cur_pat->p_pos + cur_pat->p_io_size ) / 1024L ),
883 (long) ( cur_pat->p_end / 1024L ),
884 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
885 ior_verbose( cfg, msg_buf );
886 cur_pat->p_pos = cur_pat->p_start;
887 cur_pat->p_cur_seq = 0;
888 };
889 };
890
891 return( result );
892 }
893
894 /*
895 * ior_test_prep_skew - prepare for a skew test run
896 */
ior_test_prep_skew(ior_config * cfg)897 int ior_test_prep_skew( ior_config *cfg )
898 /* ior_config *cfg; our configuration */
899 {
900 int result; /* final return code */
901 int cur; /* current item in loop */
902 ior_test *cur_test; /* test we are running */
903 ior_pattern *cur_pat; /* current active pattern */
904 ior_device *cur_dev; /* current active pattern */
905 char msg[ 200 ]; /* message buffer */
906
907 ior_debug_l( cfg, IOR_DEBUG_MINOR, "ior_test_prep_skew: Entering code -->>" );
908
909 result = 0; /* all OK so far */
910
911 cur_dev = &( cfg->c_devs[ cfg->c_cur_dev ]);
912 cur_test = &( cfg->c_tests[ cfg->c_cur_test ]);
913
914 /* start each pattern */
915 for ( cur = 0; cur < cfg->c_npat; cur++ ) {
916
917 cur_pat = &( cfg->c_pats[ cur ]);
918
919 /* only check on active patterns */
920 if (( !cur_pat->p_valid ) || ( cur_test->t_pat_pct[ cur ] < 1 )) {
921 continue;
922 };
923
924 /* limit sequential */
925 if ( cur_pat->p_max_seq > IOR_SKEW_MAX_SEQ ) {
926 sprintf( msg, "limiting sequential operations from %ld to %d due to skew testing",
927 (long) cur_pat->p_max_seq, IOR_SKEW_MAX_SEQ );
928 ior_verbose( cfg, msg );
929
930 cur_pat->p_max_seq = IOR_SKEW_MAX_SEQ;
931 };
932
933 cur_pat->p_hist_active = 0; /* no active history records */
934 cur_pat->p_hist_next = 0; /* start with item 0 */
935
936 /* with no sequential history */
937 cur_pat->p_cur_seq = 0;
938
939 /* NOTE: position chosen at I/O time with skew.... */
940 };
941
942 ior_debug_l( cfg, IOR_DEBUG_MINOR, "ior_test_prep_skew: <<-- Leaving code" );
943
944 return( result );
945 }
946
947 /*
948 * ior_run_skew - run an I/O with the skew profile
949 */
ior_run_skew(ior_config * cfg,long pat)950 int ior_run_skew( ior_config *cfg, long pat )
951 /* ior_config *cfg; our configuration */
952 /* long pat; pattern to use */
953 {
954 int result; /* final return code */
955 int group; /* group for I/O */
956 int do_seq_next; /* do next sequential I/O */
957 int next; /* ID of next history item */
958 ior_skew_list *cur_skew; /* current target skew group */
959 ior_skew_pat *cur_pat; /* current target group pattern */
960 ior_skew_area *cur_area; /* current target group area */
961 int align; /* alignment size */
962 long cur_copy; /* which copy of area to use */
963 long hist; /* which history record to use */
964 HUGE area_end; /* end address of target area */
965 HUGE block; /* new position block offset */
966 HUGE n_pos; /* new position */
967
968 result = 0; /* all OK so far */
969
970 /* choose a skew group to process against */
971 group = ior_odds_pick( cfg, &( cfg->c_odds ));
972 cur_skew = &( cfg->c_skewed[ group ]);
973 cur_pat = &( cur_skew->s_pats[ pat ]);
974 cfg->c_cur_pat = pat;
975 cur_area = cur_skew->s_areas; /* assume this target area */
976
977 while ( cur_area->a_copies < 1 ) { /* for empty areas, pick again */
978
979 sprintf( msg_buf, "ior_run_skew: (starting) - skipping empty area %ld",
980 cur_area->a_id );
981 ior_debug_l( cfg, IOR_DEBUG_ALL, msg_buf );
982
983 ior_area( cfg, IOR_AREA_TAIL, cur_area, cur_skew );
984
985 cur_area = cur_skew->s_areas; /* pick the new head */
986 };
987
988 sprintf( msg_buf, "ior_run_skew: Entering code -->> pattern %d, skew group %d, area %d",
989 (int)( pat + 1 ), group, (int)( cur_area->a_id ));
990 ior_debug_l( cfg, IOR_DEBUG_SMALL, msg_buf );
991
992 /* use history if appropriate */
993 /* ONLY if history is FULL */
994 if ( cur_pat->p_history
995 && ( cur_pat->p_hist_active >= cur_pat->p_history )
996 && cur_pat->p_hist_use[ ior_rand( cfg ) % 100 ]) {
997
998 hist = ior_rand( cfg ) % cur_pat->p_hist_active;
999
1000 cur_area = cur_pat->p_hist_areas[ hist ];
1001 /* NOT setting pattern position to save next sequential */
1002
1003 sprintf( msg_buf, "-> Using history I/O %ld at %ldk in area %ld",
1004 hist + 1, (long) ( cur_pat->p_hist_records[ hist ]/ 1024L ),
1005 cur_area->a_id );
1006 ior_verbose( cfg, msg_buf );
1007
1008 result = ior_io( cfg, cur_pat->p_read_use[ ior_rand( cfg ) % 100 ],
1009 cur_pat->p_io_size, cur_pat->p_hist_records[ hist ],
1010 cur_skew );
1011
1012 } else { /* not history - a new, unique I/O */
1013
1014 do_seq_next = FALSE; /* assume not sequential */
1015
1016 if (( cur_pat->p_is_seq ) &&
1017 cur_pat->p_seq_area != NULL ) { /* if a chance of sequential */
1018
1019 /* HOPEFULL for sequential */
1020 cur_copy = cur_pat->p_seq_copy; /* remember the copy */
1021 cur_area = cur_pat->p_seq_area; /* remember the area */
1022
1023 area_end = cur_area->a_end +
1024 cur_copy * cfg->c_skew_set_size;
1025
1026 /* if seq. too long, do random */
1027 if (( cur_pat->p_max_seq > 0 ) &&
1028 ( ++( cur_pat->p_cur_seq ) >= cur_pat->p_max_seq )) {
1029
1030 /* nope, not sequential */
1031
1032 } else if ( cur_pat->p_pos + cur_pat->p_io_size >= area_end ) {
1033 sprintf( msg_buf, "ior_run_skew: seq I/O pattern %ld went over end of area %ld (%ldk), sequence interrupted",
1034 pat + 1, cur_area->a_id,
1035 (long) ( area_end / 1024L ));
1036 ior_verbose( cfg, msg_buf );
1037
1038 /* and not sequential */
1039
1040 } else {
1041 do_seq_next = TRUE; /* finally a good one! */
1042 };
1043 };
1044
1045 if ( do_seq_next ) {
1046
1047 /* the position stays where it was from the last I/O */
1048
1049 } else { /* random new location */
1050
1051 ior_debug_l( cfg, IOR_DEBUG_SMALL, "ior_run_skew: -- start new random" );
1052
1053 cur_area = cur_skew->s_areas; /* pick target area */
1054
1055 cur_copy = ior_rand( cfg ) % cur_area->a_copies;
1056 n_pos = ior_rand( cfg ) % cur_area->a_size +
1057 cur_area->a_start +
1058 cur_copy * cfg->c_skew_set_size;
1059
1060 /* now fix the alignment */
1061 /* -- first is by I/O size */
1062 align = cur_pat->p_io_size / (HUGE) IOR_BLOCK_SIZE;
1063 /* -- or larger if align needed */
1064 if ( align < cfg->c_align ) {
1065 align = cfg->c_align;
1066 };
1067
1068 block = n_pos / (HUGE)( IOR_BLOCK_SIZE );
1069 block = ( block / align ) * align; /* aligned! */
1070 if ( block < 1 ) { /* we want to align by starting at 1 */
1071 block = align;
1072 };
1073 cur_pat->p_pos = block * (HUGE) IOR_BLOCK_SIZE;
1074
1075 /* save these, even if the pattern is not sequential */
1076 cur_pat->p_cur_seq = 0;
1077 cur_pat->p_seq_area = cur_area;
1078
1079 sprintf( msg_buf, "ior_run_skew: I/O pattern %ld new random location chosen (%ldk) [%d.%d], copy %ld of area %ld (start %.2fm)",
1080 pat + 1, (long) ( cur_pat->p_pos / 1024L ),
1081 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
1082 cur_copy, cur_area->a_id,
1083 (float)(( cur_area->a_start + cur_copy * cfg->c_skew_set_size ) / ( 1024.0 * 1024.0 )));
1084 ior_verbose( cfg, msg_buf );
1085 if ( !( cfg->c_verbose )) {
1086 ior_debug_l( cfg, IOR_DEBUG_MINOR, msg_buf );
1087 };
1088 };
1089
1090 if ( cur_pat->p_history > 0 ) { /* record new history item */
1091
1092 sprintf( msg_buf, "-->> Recording pattern %ld I/O as history element %ld [%d.%d]",
1093 pat + 1, cur_pat->p_hist_next + 1,
1094 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1095 ior_verbose( cfg, msg_buf );
1096
1097 next = cur_pat->p_hist_next++;
1098
1099 cur_pat->p_hist_records[ next ] = cur_pat->p_pos;
1100 cur_pat->p_hist_areas[ next ] = cur_area;
1101
1102 if ( cur_pat->p_hist_active < cur_pat->p_hist_next ) {
1103 cur_pat->p_hist_active = cur_pat->p_hist_next;
1104 };
1105 if ( cur_pat->p_hist_next >= cur_pat->p_history ) {
1106 cur_pat->p_hist_next = 0;
1107 };
1108 };
1109
1110 result = ior_io( cfg, cur_pat->p_read_use[ ior_rand( cfg ) % 100 ],
1111 cur_pat->p_io_size, cur_pat->p_pos, cur_skew );
1112
1113 cur_pat->p_pos = cfg->c_pos; /* note new position for pattern */
1114 };
1115
1116 /* avoid selecting this area next */
1117 ior_area( cfg, IOR_AREA_TAIL, cur_area, cur_skew );
1118
1119 ior_debug_l( cfg, IOR_DEBUG_SMALL, "ior_run_skew: <<-- Leaving code" );
1120
1121 return( result );
1122 }
1123
1124
1125 /*
1126 * ior_io - perform an I/O against the target device
1127 */
ior_io(ior_config * cfg,long io,long io_size,HUGE pos,ior_skew_list * skew)1128 int ior_io( ior_config *cfg, long io, long io_size, HUGE pos, ior_skew_list *skew )
1129 /* ior_config *cfg; our configuration */
1130 /* long io; type of I/O to do */
1131 /* long io_size; size of this I/O */
1132 /* HUGE pos; position for I/O */
1133 /* double *io_resp; RETURN response time */
1134 {
1135 int result; /* final return code */
1136 double target_time; /* how long should we have taken? */
1137 ior_device *cur_dev; /* our current device */
1138 ior_skew_pat *cur_pat; /* our current pattern */
1139 double cur_resp; /* response time on the I/O */
1140
1141 result = 0; /* all OK so far */
1142
1143 cur_dev = &( cfg->c_devs[ cfg->c_cur_dev ]);
1144
1145 sprintf( msg_buf, "ior_io: Entering code: %s position %ldk size %ldk [%d.%d]",
1146 ( io == IOR_READ ? "Read from" : "Write to" ),
1147 (long) ( pos / 1024L ),
1148 (long) ( io_size / 1024L ),
1149 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1150 ior_debug_l( cfg, IOR_DEBUG_SMALL, msg_buf );
1151
1152 /* valid position? */
1153 if (( pos < 0 ) ||
1154 ( pos + io_size > cur_dev->d_capacity )) {
1155 if ( cfg->c_debug_level < IOR_DEBUG_ALL ) {
1156 ior_debug( cfg, msg_buf );
1157 };
1158
1159 sprintf( msg_buf,
1160 "internal: bad position in 'ior_io', file %d.%d, pattern %d",
1161 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1,
1162 cfg->c_cur_pat + 1 );
1163 ior_error( cfg, msg_buf );
1164
1165 if ( pos < 0 ) {
1166 sprintf( msg_buf, "starting position (%ldk) too small (0k) [%d.%d]",
1167 (long) ( pos / 1024L ),
1168 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1169 ior_error( cfg, msg_buf );
1170 } else {
1171 sprintf( msg_buf, "ending position (%ldk) too large (%ldk) [%d.%d]",
1172 (long) (( pos + io_size )/ 1024L ),
1173 (long) ( cur_dev->d_capacity / 1024L ),
1174 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1175 ior_error( cfg, msg_buf );
1176 };
1177
1178 ior_debug( cfg, "ior_io: <<-- Leaving code ** DUE TO ERRORS **" );
1179 return( -1 );
1180 };
1181
1182 if ( pos != cfg->c_pos ) { /* seek if needed */
1183 if ( ior_seek( cfg, pos ) != 0 ) {
1184 ior_debug( cfg, "ior_io: <<-- Leaving code ** DUE TO ERRORS ** SEEK Failed" );
1185 return( -2 );
1186 };
1187 };
1188
1189 if ( io == IOR_READ ) { /* perform a read? */
1190 result = ior_read( cfg, io_size, &cur_resp );
1191 if ( result != 0 ) {
1192 sprintf( msg_buf, "ior_io: <<-- Leaving code ** READ Failed position %ldk, size %ldk [%d.%d], code %d",
1193 (long) ( pos / 1024L ),
1194 (long) ( io_size / 1024L ),
1195 cfg->c_cur_dev + 1,
1196 cfg->c_cur_adev + 1,
1197 result );
1198 ior_debug( cfg, msg_buf );
1199
1200 return( -3 );
1201 };
1202
1203 cfg->c_reads++;
1204 cfg->c_blocks_read += io_size / 1024L;
1205
1206 if ( skew != NULL ) {
1207 cur_pat = &( skew->s_pats[ cfg->c_cur_pat ]);
1208
1209 if ( cur_pat->p_is_seq ) {
1210 skew->s_perf.sp_seq_reads++;
1211 skew->s_perf.sp_seq_read_resp += cur_resp;
1212 } else {
1213 skew->s_perf.sp_rand_reads++;
1214 skew->s_perf.sp_rand_read_resp += cur_resp;
1215 };
1216 };
1217 } else {
1218 result = ior_write( cfg, io_size, &cur_resp );
1219 if ( result != 0 ) {
1220 sprintf( msg_buf, "ior_io: <<-- Leaving code ** WRITE Failed position %ldk, size %ldk [%d.%d], code %d",
1221 (long) ( pos / 1024L ),
1222 (long) ( io_size / 1024L ),
1223 cfg->c_cur_dev + 1,
1224 cfg->c_cur_adev + 1,
1225 result );
1226 ior_debug( cfg, msg_buf );
1227
1228 return( -4 );
1229 };
1230
1231 cfg->c_writes++;
1232 cfg->c_blocks_written += io_size / 1024L;
1233
1234 if ( skew != NULL ) {
1235 cur_pat = &( skew->s_pats[ cfg->c_cur_pat ]);
1236
1237 if ( cur_pat->p_is_seq ) {
1238 skew->s_perf.sp_seq_writes++;
1239 skew->s_perf.sp_seq_write_resp += cur_resp;
1240 } else {
1241 skew->s_perf.sp_rand_writes++;
1242 skew->s_perf.sp_rand_write_resp += cur_resp;
1243 };
1244 };
1245 };
1246
1247 if ( cfg->c_target_resp > 0 ) { /* slow down if desired */
1248
1249 /* Using the target time for the number of I/Os per second, */
1250 /* decide if we need to go faster (no delay), slower (delay */
1251 /* of a full target response time), or we are about on target */
1252 /* (and sleep for a random average of half a target response */
1253 /* time. */
1254
1255 target_time = cfg->c_target_sec * ( cfg->c_reads + cfg->c_writes );
1256
1257 if ( target_time > cfg->c_io_time ) { /* too fast - slow it down */
1258 ior_sleep_usec( cfg, cfg->c_target_resp );
1259 } else if ( target_time >= cfg->c_io_time ) { /* about right */
1260 ior_sleep_usec( cfg, ior_rand( cfg ) % cfg->c_target_resp );
1261 } else {
1262 /* if neither, then too slow, so go flat out */
1263 };
1264 };
1265
1266 ior_debug_l( cfg, IOR_DEBUG_SMALL, "ior_io: <<-- Leaving code" );
1267 return( result );
1268 }
1269
1270 /*
1271 * ior_set_rand_pos - set a new, random position for next I/O
1272 */
ior_set_rand_pos(ior_config * cfg,long pat)1273 int ior_set_rand_pos( ior_config *cfg, long pat )
1274 /* ior_config *cfg; our configuration */
1275 /* long pat; pattern being worked on */
1276 {
1277 HUGE block; /* chosen block to perform I/O at */
1278 HUGE pat_blocks; /* blocks in the pattern */
1279 HUGE h_tmp; /* huge temp value */
1280 int result; /* final return code */
1281 int align; /* alignment size */
1282 ior_pattern *cur_pat; /* current active pattern */
1283
1284 result = 0; /* all OK so far */
1285
1286 /* find current pattern */
1287 cur_pat = &( cfg->c_pats[ pat ]);
1288
1289 pat_blocks = cur_pat->p_size / (HUGE) IOR_BLOCK_SIZE;
1290 if ( pat_blocks < 1 ) {
1291 sprintf( msg_buf, "Pattern size invalid (%ldk) for pattern %ld [%d.%d]",
1292 (long)( cur_pat->p_size / 1024L ), pat + 1,
1293 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1294 ior_error( cfg, msg_buf );
1295 cur_pat->p_pos = cur_pat->p_start;
1296 return( -1 );
1297 };
1298 /* pick a block to start with */
1299 h_tmp = ior_rand( cfg ) % pat_blocks;
1300 block = cur_pat->p_start / (HUGE) IOR_BLOCK_SIZE + h_tmp;
1301
1302 /* now fix the alignment */
1303 /* -- first is by I/O size */
1304 align = cur_pat->p_io_size / (HUGE) IOR_BLOCK_SIZE;
1305 /* -- or larger if align needed */
1306 if ( align < cfg->c_align ) {
1307 align = cfg->c_align;
1308 };
1309 block = ( block / align ) * align; /* aligned! */
1310 if ( block < 1 ) { /* we want to align by starting at 1 */
1311 block = align;
1312 };
1313
1314 cur_pat->p_pos = block * (HUGE) IOR_BLOCK_SIZE;
1315
1316 /* just in case we go outside -- */
1317 if (( cur_pat->p_pos < cur_pat->p_start ) ||
1318 ( cur_pat->p_pos + cur_pat->p_io_size > cur_pat->p_end )) {
1319 sprintf( msg_buf, "Pattern position invalid (%ldk) for pattern %ld [%d.%d]",
1320 (long)( cur_pat->p_pos / 1024L ), pat + 1,
1321 cfg->c_cur_dev + 1, cfg->c_cur_adev + 1 );
1322 ior_warn( cfg, msg_buf );
1323 cur_pat->p_pos = cur_pat->p_start; /* default to start of device */
1324 };
1325
1326 return( result );
1327 }
1328
1329