📄 dtaio.c
字号:
if (error) return (error); goto retry; } } else if (eei_flag) { (void) get_eei_status(dip->di_fd, dip->di_mt); } }#endif /* defined(EEI) */ acbp->aio_fildes = AIO_NotQed; errno = error; if (volumes_flag && (multi_volume >= volume_limit) && (dip->di_volume_records == volume_records)) { return (SUCCESS); } if (count == FAILURE) { /* * End of media is handled below. */#if defined(SCO) || defined(HP_UX) if ( (error != ENOSPC) && (error != ENXIO) ) {#else /* !defined(SCO) && !defined(HP_UX) */ if (error != ENOSPC) {#endif /* defined(SCO) || defined(HP_UX) */ report_error ("aio_return", TRUE); ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO)); return (FAILURE); } } else if (error) { count = FAILURE; } bsize = acbp->aio_nbytes; data_buffer = (u_char *)acbp->aio_buf; if (min_size) { dsize = bsize; } else { dsize = block_size; } /* * Adjust for short records or no data transferred. */ if (count == FAILURE) { aio_data_bytes -= bsize; aio_file_bytes -= bsize; } else if (adjust = (bsize - count)) { if (debug_flag) { Printf("Adjusting byte counts by %d bytes...\n", adjust); } aio_data_bytes -= adjust; aio_file_bytes -= adjust; } /* * Process end of file/media conditions and handle multi-volume. */ if ( is_Eof (dip, count, &status) ) { if (multi_flag) { if ( (dip->di_dtype->dt_dtype == DT_TAPE) && !dip->di_end_of_logical ) { return (status); /* Expect two file marks @ EOM. */ } status = HandleMultiVolume (dip); aio_record_count = dip->di_records_read; /*aio_file_bytes = dip->di_dbytes_read;*/ aio_offset = (off_t) 0; } return (status); } else { dip->di_end_of_file = FALSE; /* Reset saved end of file state. */ if (count > (ssize_t) 0) { dip->di_dbytes_read += count; dip->di_fbytes_read += count; dip->di_vbytes_read += count; if (count == dsize) { records_processed++; } else { partial_records++; } dip->di_offset = (acbp->aio_offset + count); } if ((status = check_read (dip, count, bsize)) == FAILURE) { if (error_count >= error_limit) return (status); } else if (io_mode == COPY_MODE) { status = copy_record (output_dinfo, data_buffer, count); if ( (error_count >= error_limit) || end_of_file) return (status); } else if (io_mode == VERIFY_MODE) { status = verify_record (output_dinfo, data_buffer, count); if ( (error_count >= error_limit) || end_of_file) return (status); } } /* * Verify the data (unless disabled). */ if ( (status != FAILURE) && compare_flag && (io_mode == TEST_MODE)) { ssize_t vsize = count; if (lbdata_flag || iot_pattern) { aio_lba = make_lbdata(dip, (dip->di_volume_bytes + acbp->aio_offset)); if (iot_pattern) { aio_lba = init_iotdata (vsize, aio_lba, lbdata_size); } } status = (*dtf->tf_verify_data)(dip, data_buffer, vsize, pattern, &aio_lba); /* * Verify the pad bytes (if enabled). */ if ( (status == SUCCESS) && pad_check) { (void) verify_padbytes (dip, data_buffer, vsize, ~pattern, bsize); } } dip->di_records_read++; dip->di_volume_records++; if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) || (step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) { set_Eof(dip); } return (status);}/************************************************************************ * * * dtaio_write_data() - Write specified data to the output file. * * * * Inputs: dip = The device information pointer. * * * * Outputs: Returns SUCCESS/FAILURE = Ok/Error. * * * ************************************************************************/intdtaio_write_data (struct dinfo *dip){ register struct aiocb *acbp; int error, status = SUCCESS; register size_t bsize, dsize; u_int32 lba = lbdata_addr; if (dip->di_random_access) { if (io_dir == REVERSE) { (void)set_position(dip, (off_t)rdata_limit); } aio_lba = lba = get_lba(dip); aio_offset = get_position(dip); } else { aio_offset = dip->di_offset; aio_lba = lba = make_lbdata (dip, aio_offset); } aio_data_bytes = aio_file_bytes = aio_record_count = 0; /* * For variable length records, initialize to minimum record size. */ if (min_size) { dsize = min_size; } else { dsize = block_size; } /* * Now write the specifed number of records. */ while ( (error_count < error_limit) && (dip->di_fbytes_written < data_limit) && (dip->di_records_written < record_limit) ) { if (volumes_flag && (multi_volume >= volume_limit) && (dip->di_volume_records >= volume_records)) { dip->di_volume_records = volume_records; break; } /* * Two loops are used with AIO. The inner loop queues requests up * tto the requested amount, and the outer loop checks the actual * data processed. This is done to handle short reads, which can * happen frequently with random I/O and large block sizes. */ while ( (error_count < error_limit) && (aio_record_count < record_limit) && (aio_file_bytes < data_limit) ) { if (volumes_flag && (multi_volume >= volume_limit) && (dip->di_volume_records >= volume_records)) { break; } if (wdelay_count) { /* Optional write delay */ mySleep (wdelay_count); } /* * If data limit was specified, ensure we don't exceed it. */ if ( (aio_file_bytes + dsize) > data_limit) { bsize = (data_limit - aio_file_bytes); } else { bsize = dsize; } acbp = &acbs[aio_index]; /* * If requested, rotate the data buffer through ROTATE_SIZE bytes * to force various unaligned buffer accesses. */ if (rotate_flag) { data_buffer = aiobufs[aio_index]; data_buffer += (rotate_offset++ % ROTATE_SIZE); acbp->aio_buf = data_buffer; } else { data_buffer = (u_char *) acbp->aio_buf; } acbp->aio_fildes = dip->di_fd; if (io_dir == REVERSE) { /*debug*/ if (!aio_offset) abort(); /*debug*/ bsize = MIN((aio_offset-file_position), bsize); aio_offset = (off_t)(aio_offset - bsize); } acbp->aio_nbytes = bsize; if (debug_flag && (bsize != dsize) && !variable_flag) { Printf ("Record #%lu, Writing a partial record of %d bytes...\n", (aio_record_count + 1), bsize); } if (io_type == RANDOM_IO) { acbp->aio_offset = do_random (dip, FALSE, bsize); } else { acbp->aio_offset = aio_offset; } if (iot_pattern || lbdata_flag) { lba = make_lbdata (dip, (dip->di_volume_bytes + acbp->aio_offset)); } /* * Initialize the data buffer with a pattern. */ if ((io_mode == TEST_MODE) && compare_flag) { if (iot_pattern) { lba = init_iotdata(bsize, lba, lbdata_size); } fill_buffer (data_buffer, bsize, pattern); } /* * Initialize the logical block data (if enabled). */ if (lbdata_flag && lbdata_size && !iot_pattern) { lba = winit_lbdata (dip, (dip->di_volume_bytes + acbp->aio_offset), data_buffer, bsize, lba, lbdata_size); } if (Debug_flag) { u_int32 lba = NO_LBA; if (dip->di_random_access || lbdata_flag || iot_pattern) { lba = make_lbdata(dip, (dip->di_volume_bytes + acbp->aio_offset)); } report_record(dip, (dip->di_files_written + 1), (aio_record_count + 1), lba, WRITE_MODE, (void *)acbp->aio_buf, acbp->aio_nbytes); } if ( (error = aio_write (acbp)) == FAILURE) { acbp->aio_fildes = AIO_NotQed; report_error ("aio_write", TRUE); return (error); } /* * Must adjust record/data counts here to avoid writing * too much data, even though the writes are incomplete. */ aio_data_bytes += bsize; aio_file_bytes += bsize; aio_record_count++; if (io_dir == FORWARD) { aio_offset += bsize; } if (step_offset) { if (io_dir == FORWARD) { aio_offset += step_offset; } else if ((aio_offset -= step_offset) <= (off_t) file_position) { aio_offset = (off_t) file_position; } } /* * For variable length records, adjust the next record size. */ if (min_size) { if (variable_flag) { dsize = get_variable (dip); } else { dsize += incr_count; if (dsize > max_size) dsize = min_size; } } /* * Always ensure the next control block has completed. */ if (++aio_index == aio_bufs) aio_index = 0; if ( (io_dir == REVERSE) && (aio_offset == (off_t) file_position) ) { break; } acbp = &acbs[aio_index]; if (acbp->aio_fildes == AIO_NotQed) continue; /* Never Q'ed. */ if ( (status = dtaio_process_write (dip, acbp)) == FAILURE) { return (status); } if (end_of_file) break; } /* * We get to this point after we've Q'ed enough requests to * fulfill the requested record and/or data limit. We now * wait for these Q'ed requests to complete, adjusting the * global transfer statistics appropriately which reflects * the actual data processed. */ status = dtaio_wait_writes(dip); if (end_of_file) break; } return (status);}/************************************************************************ * * * dtaio_process_write() - Process AIO write requests. * * * * Description: * * This function does waits for the requested AIO write request * * and checks the completion status. * * * * Inputs: dip = The device info pointer. * * acbp = The AIO control block. * * * * Outputs: Returns SUCCESS/FAILURE/WARNING = Ok/Error/Partial. * * * ************************************************************************/static intdtaio_process_write (struct dinfo *dip, struct aiocb *acbp){ register size_t bsize, dsize; register ssize_t count; ssize_t adjust; int error, status = SUCCESS;#if defined(EEI)retry:#endif current_acb = acbp; error = dtaio_wait (dip, acbp); count = aio_return (acbp);#if defined(EEI) if (dip->di_dtype->dt_dtype == DT_TAPE) { if ( (errno == EIO) && eei_resets) { if ( HandleTapeResets(dip) ) { dtaio_restart(dip, acbp); goto retry; } } else if (eei_flag) { (void) get_eei_status(dip->di_fd, dip->di_mt); } }#endif /* defined(EEI) */ acbp->aio_fildes = AIO_NotQed; errno = error; if (volumes_flag && (multi_volume >= volume_limit) && (dip->di_volume_records == volume_records)) { return (SUCCESS); } if (count == FAILURE) {#if defined(SCO) || defined(HP_UX) if ( (error != ENOSPC) && (error != ENXIO) ) {#else /* !defined(SCO) && !defined(HP_UX) */ if (error != ENOSPC) {#endif /* defined(SCO) || defined(HP_UX) */ report_error ("aio_return", TRUE); ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO)); return (FAILURE); } } else if (error) { count = FAILURE; } bsize = acbp->aio_nbytes; if (min_size) { dsize = bsize; /* Can lead to wrong partial record count :-) */ } else { dsize = block_size; } /* * Adjust for short records or no data transferred. */ if (count == FAILURE) { aio_data_bytes -= bsize; aio_file_bytes -= bsize; } else if (adjust = (bsize - count)) { aio_data_bytes -= adjust; aio_file_bytes -= adjust; } if (count > (ssize_t) 0) { dip->di_dbytes_written += count; dip->di_fbytes_written += count; dip->di_vbytes_written += count; } /* * Process end of file/media conditions and handle multi-volume. */ if ( is_Eof (dip, count, &status) ) { if (multi_flag) { status = HandleMultiVolume (dip); aio_record_count = dip->di_records_written; /*aio_file_bytes = dip->di_dbytes_written;*/ aio_offset = (off_t) 0; } return (status); } if (count > (ssize_t) 0) { if (count == dsize) { records_processed++; } else { partial_records++; } dip->di_offset = (acbp->aio_offset + count); } if ((status = check_write (dip, count, bsize)) == FAILURE) { if (error_count >= error_limit) return (status); } if ( (status != FAILURE) && raw_flag) { status = write_verify(dip, (u_char *)acbp->aio_buf, count, dsize, acbp->aio_offset); if ( (status == FAILURE) && (error_count >= error_limit) ) { return (status); } } dip->di_records_written++; dip->di_volume_records++; if ( ((io_dir == REVERSE) && (acbp->aio_offset == (off_t) file_position)) || (step_offset && ((acbp->aio_offset - step_offset) <= (off_t) file_position)) ) { set_Eof(dip); } return (status);}#endif /* defined(AIO) */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -