📄 dt.c
字号:
"Please specify a record or data limit for random I/O.\n"); exit (FATAL_ERROR); } /* * Sanity check the random I/O data limits. */ if ( (io_type == RANDOM_IO) && ((file_position + block_size + random_align) > rdata_limit)) { LogMsg (efp, logLevelCrit, 0, "The max block size is too large for random data limits!\n"); if (Debug_flag) { Printf ("file position " FUF ", bs=%ld, ralign=%ld, rlimit=" LUF "\n", file_position, block_size, random_align, rdata_limit); } exit (FATAL_ERROR); } /* * Ensure either a data limit and/or a record count was specified. */ if (!record_limit) { LogMsg (efp, logLevelCrit, 0, "You must specify a data limit, a record count, or both.\n"); exit (FATAL_ERROR); } /* * Allocate buffer for pre-formatting messages. */ msg_buffer = (char *)Malloc(LOG_BUFSIZE);#if defined(LOG_DIAG_INFO) /* * If logging of diagnostic info is enabled, save copy of cmd line. */ if (logdiag_flag) { int arg; char *bp; bp = cmd_line = (char *)Malloc(LOG_BUFSIZE); for (arg = 0; arg < argc; arg++) { (void)sprintf(bp, "%s ", argv[arg]); bp += strlen(bp); } sprintf(bp, "\n"); }#endif /* defined(LOG_DIAG_INFO) */ /* * Catch a couple signals to do elegant cleanup. */ (void) signal (SIGHUP, terminate); (void) signal (SIGINT, terminate); (void) signal (SIGTERM, terminate); (void) signal (SIGPIPE, terminate); /* * If both an input and an output files were specified, then * fork and make child process the reader, parent the writer. */ if ( (io_mode == TEST_MODE) && input_file && output_file) { if ( (child_pid = fork()) == (pid_t) -1) { report_error ("fork", TRUE); exit (exit_status); } forked_flag = TRUE; if (child_pid) { /* Parent = writer. */ struct dinfo *dip = input_dinfo; (void) close_file (dip); input_file = NULL; if (debug_flag) { Printf ("Parent PID (Writer) = %d, Child PID (Reader) = %d\n", getpid(), child_pid); }#if !defined(__MSDOS__) || defined(__NUTC__) signal (SIGCHLD, terminate);#endif } else { /* Child = reader. */ struct dinfo *dip = output_dinfo; (void) close_file (dip); output_file = NULL; } } /* * Some drivers require the input device to open before we start * writing. For example, terminal devices must have speed, parity, * and flow control setup before we start writing. The parallel * input device must open before we send the "readya" interrupt. */ if (output_file && (sdelay_count != 0)) { mySleep (sdelay_count); /* Allow reader to start. */ } /* * Calculate size necessary for the data buffer & the pad bytes. */ data_size = (block_size + PADBUFR_SIZE); if (rotate_flag) data_size += ROTATE_SIZE; /* * For read-after-write (raw) option, we need a verification buffer. * Note: Other tests can benefit from this too, switch to later. */ if (raw_flag) { verify_buffer = myalloc(data_size, align_offset); } /* * Do the device / test specific initialization. * * This function is responsible for allocating the necessary * data buffers and performing special device setup/checking. */ if (input_file) { dip = input_dinfo; status = (*dip->di_funcs->tf_initialize)(dip); if (status == FAILURE) exit (FATAL_ERROR); } if (output_file) { dip = output_dinfo; status = (*dip->di_funcs->tf_initialize)(dip); if (status == FAILURE) exit (FATAL_ERROR); } /* * Re-adjust size of data buffer to avoid init'ing too much. */ if (rotate_flag) data_size -= ROTATE_SIZE; /* * Finally format the prefix string (if any), after the device is * setup and processes are forked so we can setup a unique prefix. */ if (prefix_string) { status = FmtPrefix(dip, &prefix_string, &prefix_size); if (status == FAILURE) exit (FATAL_ERROR); if ((prefix_size) > lbdata_size) { LogMsg (efp, logLevelCrit, 0, "The prefix size (%d) is larger than lbdata size (%d)!\n", prefix_size, lbdata_size); exit (FATAL_ERROR); } } /* * Start an alarm timer if the run time was specified. */ if (runtime) { (void) signal (SIGALRM, terminate); (void) alarm (runtime); TimerActive = TRUE; } /* * Start of main test loop. */ start_time = times (&stimes);#if defined(LOG_DIAG_INFO) if (logdiag_flag) { sprintf(msg_buffer, "Starting: %s", cmd_line); LogDiagMsg(msg_buffer); }#endif /* defined(LOG_DIAG_INFO) */#if defined(DEC) if (table_flag) { status = table(TBL_SYSINFO,0,(char *)&s_table,1,sizeof(struct tbl_sysinfo)); if (status == FAILURE) report_error ("table", FALSE); }#endif /* defined(DEC) */ /* * We support multiple modes of operation: copy, test, & verify */ if ( (io_mode == COPY_MODE) || (io_mode == VERIFY_MODE) ) { /* * This is ugly, but I'm using pattern buffer as verify buffer. */ if ( (io_mode == VERIFY_MODE) || verify_flag) { pattern_buffer = myalloc (data_size, align_offset); setup_pattern (pattern_buffer, data_size); } pass_time = times (&ptimes); /* Start the pass timer */#if defined(DEC) if (table_flag) { status = table(TBL_SYSINFO,0,(char *)&p_table,1,sizeof(struct tbl_sysinfo)); if (status == FAILURE) report_error ("table", FALSE); }#endif /* defined(DEC) */ dip = active_dinfo = input_dinfo; dtf = dip->di_funcs; dip->di_mode = READ_MODE; (void) (*dtf->tf_start_test)(dip); (void) (*dtf->tf_read_file)(dip); (void) (*dtf->tf_end_test)(dip); gather_stats(output_dinfo); /* * Now verify the data copied (if requested). */ if ( (io_mode == COPY_MODE) && verify_flag && !stdin_flag && (error_count < error_limit) ) { struct dinfo *odip = output_dinfo; int open_mode = (ropen_mode | open_flags); report_pass (dip, COPY_STATS); /* Report copy statistics. */ /* * Verify Pass. */ status = (*dtf->tf_reopen_file)(dip, open_mode); if (status != SUCCESS) terminate(status); odip->di_mode = READ_MODE; /* Switch to read mode. */ status = (*odip->di_funcs->tf_reopen_file)(odip, open_mode); if (status != SUCCESS) terminate(status); pass_time = times (&ptimes); /* Time the verify. */#if defined(DEC) if (table_flag) { status = table(TBL_SYSINFO,0,(char *)&p_table,1,sizeof(struct tbl_sysinfo)); if (status == FAILURE) report_error ("table", FALSE); }#endif /* defined(DEC) */ io_mode = VERIFY_MODE; (void) (*dtf->tf_start_test)(dip); (void) (*dtf->tf_read_file)(dip); (void) (*dtf->tf_end_test)(dip); pass_count++; /* End of copy/verify pass. */ gather_stats(output_dinfo); /* Gather device statistics. */ report_pass (dip, VERIFY_STATS); /* Report the verify stats. */ } else { pass_count++; /* End of copy pass. */ } } else { /* not Copy or Verify modes, Test Mode! */ while ( (total_errors < error_limit) && ((pass_count < pass_limit) || runtime) ) { if (pattern_buffer) { pattern_bufptr = pattern_buffer; } /* * Use a different data pattern for each pass. */ if ( !user_pattern && !ttyport_flag && (loopback || output_file || stdin_flag || (input_file && num_slices)) ) { /* * Logic: * - If multiple slices, choose a different pattern * for each pass, factoring in the process number. * - Else, each pass gets a different data pattern * unless multiple processes were selected. */ if ( unique_pattern && ( (!num_procs && num_slices) || (num_procs && (dip->di_dtype->dt_dtype == DT_REGULAR)) ) ) { int pindex = ((cur_proc - 1) + pass_count); pattern = data_patterns[pindex % npatterns]; } else if (!num_procs) { pattern = data_patterns[pass_count % npatterns]; } if (pattern_buffer) copy_pattern (pattern, pattern_buffer); if (debug_flag) { Printf ("Using data pattern 0x%08x for pass %u\n", pattern, (pass_count + 1)); } } /* * Use time for random # generator seed so different areas * of disk get affected during multiple passes. Seed set * here, since it must be the same seed during read pass. * NOTE: Pid is added so seed different for each process. */ if ( (io_type == RANDOM_IO) || variable_flag) { if ( !user_rseed ) { random_seed = (u_int) times(&ptimes) + getpid(); } set_rseed (random_seed); } pass_time = times (&ptimes); /* Start the pass timer */#if defined(DEC) if (table_flag) { status = table(TBL_SYSINFO,0,(char *)&p_table,1,sizeof(struct tbl_sysinfo)); if (status == FAILURE) report_error ("table", FALSE); }#endif /* defined(DEC) */ if (output_file) { /* Write/read the file. */ bool do_read_pass; dip = active_dinfo = output_dinfo; dtf = dip->di_funcs; dip->di_mode = WRITE_MODE; (void) (*dtf->tf_start_test)(dip); (void) (*dtf->tf_write_file)(dip); (void) (*dtf->tf_flush_data)(dip); (void) (*dtf->tf_end_test)(dip); if (error_count >= error_limit) break; do_read_pass = (dip->di_dbytes_written != (large_t) 0); /* * Now verify (read and data compare) the data just written. */ if (verify_flag && do_read_pass && !raw_flag) { /* Verify data written. */ int open_mode = (ropen_mode | open_flags); report_pass (dip, WRITE_STATS); /* Report write stats. */ if (multi_flag && media_changed) { status = RequestFirstVolume(dip, open_flags); } else { status = (*dtf->tf_reopen_file)(dip, open_mode); } if (status != SUCCESS) break; if ( (io_type == RANDOM_IO) || variable_flag) { set_rseed (random_seed); } pass_time = times (&ptimes); /* Time just the read. */#if defined(DEC) if (table_flag) { status = table(TBL_SYSINFO,0,(char *)&p_table,1,sizeof(struct tbl_sysinfo)); if (status == FAILURE) report_error ("table", FALSE); }#endif /* defined(DEC) */ /*rotate_offset = 0;*/ if (pattern_buffer) { pattern_bufptr = pattern_buffer; } dip->di_mode = READ_MODE; (void) (*dtf->tf_start_test)(dip); (void) (*dtf->tf_read_file)(dip); (void) (*dtf->tf_end_test)(dip); pass_count++; /* End read/write pass. */ report_pass (dip, READ_STATS); /* Report read stats. */ } else { pass_count++; /* End of write pass. */ if ( (pass_limit > 1) || runtime) { /* Report write stats. */ if (raw_flag) { report_pass (dip, RAW_STATS); } else { report_pass (dip, WRITE_STATS); } } } if ( (pass_count < pass_limit) || runtime) { int open_mode; if (skip_count || raw_flag) { open_mode = (O_RDWR | wopen_flags | open_flags); } else { open_mode = (wopen_mode | wopen_flags | open_flags); } status = (*dtf->tf_reopen_file)(dip, open_mode); if (status != SUCCESS) break; } } else { /* Reading only. */ dip = active_dinfo = input_dinfo; dtf = dip->di_funcs; dip->di_mode = READ_MODE; (void) (*dtf->tf_start_test)(dip); (void) (*dtf->tf_read_file)(dip); (void) (*dtf->tf_end_test)(dip); pass_count++; /* End of read pass. */ /* * Prevent pass unless looping, since terminate reports * the total statistics when called (prevents dup stats). */ if ( (pass_limit > 1) || runtime) { report_pass (dip, READ_STATS); /* Report read stats. */ } if ( (total_errors < err
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -