⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dtaio.c

📁 Linux磁盘测试的源代码,测试磁盘的读写性能
💻 C
📖 第 1 页 / 共 3 页
字号:
}#if defined(EEI)static intdtaio_restart(struct dinfo *dip, struct aiocb *first_acbp){    struct aiocb *acbp = first_acbp;    size_t bsize;    ssize_t count, adjust;    int index, error, status = SUCCESS;    /*     * Find starting index of this AIO request.     */    for (index = 0; index < aio_bufs; index++) {	if (first_acbp == &acbs[index]) break;    }    if (index == aio_bufs) abort(); /* Should NEVER happen! */    /*     * Now, wait for and restart all previously active I/O's.     */    do {	/*	 * Assumes the first request was already waited for!	 */	if (Debug_flag) {	    Printf ("Restarting request for acbp at %#lx...\n", acbp);	}	if (dip->di_mode == READ_MODE) {	    if ( (error = aio_read (acbp)) == FAILURE) {		acbp->aio_fildes = AIO_NotQed;		report_error ("aio_read", TRUE);		return (error);	    }	} else {	    if ( (error = aio_write (acbp)) == FAILURE) {		acbp->aio_fildes = AIO_NotQed;		report_error ("aio_write", TRUE);		return (error);	    }	}	if (++index == aio_bufs) index = 0;	if (index == aio_index) break;	acbp = &acbs[index];	if (acbp->aio_fildes == AIO_NotQed) abort();	error = dtaio_wait (dip, acbp);	(void) aio_return (acbp);    } while (TRUE);    return (status);}#endif /* defined(EEI) */static intdtaio_wait (struct dinfo *dip, struct aiocb *acbp){    int error, status;    if (Debug_flag) {	Printf ("Waiting for acbp at %#lx to complete...\n", acbp);    }    /*     * Loop waiting for an I/O request to complete.     */    while ((error = aio_error (acbp)) == EINPROGRESS) {#if defined(POSIX_4D11)	if ((status = aio_suspend (1, (const struct aiocb **)&acbp)) == FAILURE) {#else /* Beyond draft 11... */	if ((status = aio_suspend ((const struct aiocb **)&acbp,1,NULL)) == FAILURE) {#endif /* defined(POSIX_4D11) */	    if (errno != EINTR) {		report_error ("aio_suspend", TRUE);		return (status);	    }	}    }    if ( (error == FAILURE) && !terminating_flag) {	report_error ("aio_error", TRUE);    }    return (error);}static intdtaio_waitall(struct dinfo *dip, bool canceling){    struct aiocb *acbp;    register size_t bsize;    register ssize_t count;    ssize_t adjust;    int index, error, status = SUCCESS;    /*     * During EEI reset handling, don't touch the active requests,     * since dtaio_restart() needs this state to restart reqeusts.     */    if (dip->di_proc_eei) return (status);    /*     * Loop waiting for all I/O requests to complete.     */    for (index = 0; index < aio_bufs; index++) {	acbp = &acbs[aio_index];	if (++aio_index == aio_bufs) aio_index = 0;	if (acbp->aio_fildes == AIO_NotQed) continue;	if ( (error = dtaio_wait (dip, acbp))) {	    status = error;	    if (status == FAILURE) {		acbp->aio_fildes = AIO_NotQed;		continue;	/* aio_error() failed! */	    }	}	count = aio_return (acbp);	acbp->aio_fildes = AIO_NotQed;	errno = error;	if ( (count == FAILURE) && !dip->di_closing && !terminating_flag) {	    /*	     * 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) */		current_acb = acbp;		report_error ("aio_return", TRUE);		ReportDeviceInfo (dip, acbp->aio_nbytes, 0, (errno == EIO));		status = FAILURE;		/* adjust counts below */	    }	} else if (error) {	    count = FAILURE;	}	bsize = acbp->aio_nbytes;	/*	 * 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;	}	/*	 * Count files or records to adjust after I/O's complete.	 */	if ( is_Eof (dip, count, (int *) 0) ) {	    if (!dip->di_end_of_media) aio_file_adjust++;	} else if (count > (ssize_t) 0) {	    aio_record_adjust++;	    /*	     * Adjust counts for total statistics.	     */	    if (!canceling) {		if (dip->di_mode == READ_MODE) {		    dip->di_dbytes_read += count;		    dip->di_fbytes_read += count;		} else {		    dip->di_dbytes_written += count;		    dip->di_fbytes_written += count;		}		aio_data_adjust += count;		if (count == bsize) {		    records_processed++;		} else {		    partial_records++;		}	    }	}    }    return (status);}/* * Function to wait for and process read requests. */static intdtaio_wait_reads (struct dinfo *dip){    struct aiocb *acbp;    int index, error, status = SUCCESS;    /*     * Loop waiting for all I/O requests to complete.     */    for (index = 0; index < aio_bufs; index++) {	acbp = &acbs[aio_index];	if (++aio_index == aio_bufs) aio_index = 0;	if (acbp->aio_fildes == AIO_NotQed) continue;		if ( (error = dtaio_process_read (dip, acbp)) == FAILURE) {	    status = error;	}	if ( end_of_file ||	     (dip->di_records_read >= record_limit) || (dip->di_fbytes_read >= data_limit) ) {	    break;	}    }    return (status);}/* * Function to wait for and process write requests. */static intdtaio_wait_writes (struct dinfo *dip){    struct aiocb *acbp;    int index, error, status = SUCCESS;    /*     * Loop waiting for all I/O requests to complete.     */    for (index = 0; index < aio_bufs; index++) {	acbp = &acbs[aio_index];	if (++aio_index == aio_bufs) aio_index = 0;	if (acbp->aio_fildes == AIO_NotQed) continue;		if ( (error = dtaio_process_write (dip, acbp)) == FAILURE) {	    status = error;	    if (error_count >= error_limit) break;	}    }    return (status);}/************************************************************************ *									* * dtaio_read_data() - Read and optionally verify data read.		* *									* * Inputs:	dip = The device information pointer.			* *									* * Outputs:	Returns SUCCESS/FAILURE = Ok/Error.			* *									* ************************************************************************/intdtaio_read_data (struct dinfo *dip){    register struct aiocb *acbp;    int error, status = SUCCESS;    register size_t bsize, dsize;    if (dip->di_random_access) {	if (io_dir == REVERSE) {	    (void)set_position(dip, (off_t)rdata_limit);	}	aio_lba = get_lba(dip);	aio_offset = get_position(dip);    } else {	aio_offset = dip->di_offset;	aio_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 read and optionally verify the input records.     */    while ( (error_count < error_limit) &&	    (dip->di_fbytes_read < data_limit) &&	    (dip->di_records_read < 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	 * to the requested amount, and the outer loop checks the actual	 * data processed.  This is done mainly for tapes to handle short	 * reads & to efficiently handle multiple tape files.	 */	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 (rdelay_count) {			/* Optional read delay.	*/		mySleep (rdelay_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);	    }            if (debug_flag && (bsize != dsize) && !variable_flag) {                Printf ("Record #%lu, Reading a partial record of %lu bytes...\n",                                    (aio_record_count + 1), bsize);            }	    acbp->aio_nbytes = bsize;	    if (io_type == RANDOM_IO) {		acbp->aio_offset = do_random (dip, FALSE, bsize);	    } else {		acbp->aio_offset = aio_offset;	    }	    /*	     * If we'll be doing a data compare after the read, then	     * fill the data buffer with the inverted pattern to ensure	     * the buffer actually gets written into (driver debug mostly).	     */	    if ((io_mode == TEST_MODE) && compare_flag) {		init_buffer (data_buffer, bsize, ~pattern);		init_padbytes (data_buffer, bsize, ~pattern);	    }	    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_read + 1), (aio_record_count + 1),			lba, READ_MODE, (void *)acbp->aio_buf, acbp->aio_nbytes);	    }	    if ( (error = aio_read (acbp)) == FAILURE) {		acbp->aio_fildes = AIO_NotQed;		report_error ("aio_read", 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_read (dip, acbp)) == FAILURE) {		return (status);	    }	    if ( end_of_file ) return (status);	}	/*	 * 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_reads(dip);	if ( end_of_file ) break;	/* Stop reading at end of file. */    }    return (status);}/************************************************************************ *									* * dtaio_process_read() - Process AIO reads & optionally verify data.	* *									* * Description:								* *	This function does waits for the requested AIO read request,	* * checks the completion status, and optionally verifies the data read.	* *									* * Inputs:	dip = The device information pointer.			* *		acbp = The AIO control block.				* *									* * Outputs:	Returns SUCCESS/FAILURE/WARNING = Ok/Error/Warning.	* *									* ************************************************************************/static intdtaio_process_read (struct dinfo *dip, struct aiocb *acbp){    struct dtfuncs *dtf = dip->di_funcs;    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) ) {		int error = dtaio_restart(dip, acbp);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -