Always use IO completion ports on Windows since some drives benefit from
using it even with direct or sync io.
Remove PrintError function since logging of errors is done in the core.
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
HANDLE iocomplete_event;
CANCELIOEX pCancelIoEx;
BOOL iothread_running;
HANDLE iocomplete_event;
CANCELIOEX pCancelIoEx;
BOOL iothread_running;
struct windowsaio_data *wd;
};
struct windowsaio_data *wd;
};
-static void PrintError(LPCSTR lpszFunction);
static int fio_windowsaio_cancel(struct thread_data *td,
struct io_u *io_u);
static BOOL timeout_expired(DWORD start_count, DWORD end_count);
static int fio_windowsaio_cancel(struct thread_data *td,
struct io_u *io_u);
static BOOL timeout_expired(DWORD start_count, DWORD end_count);
-static void PrintError(LPCSTR lpszFunction)
-{
- // Retrieve the system error message for the last-error code
-
- LPSTR lpMsgBuf;
- DWORD dw = GetLastError();
-
- FormatMessage(
- FORMAT_MESSAGE_ALLOCATE_BUFFER |
- FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL,
- dw,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPTSTR)&lpMsgBuf,
- 0, NULL );
-
- log_err("%s - %s", lpszFunction, lpMsgBuf);
- LocalFree(lpMsgBuf);
-}
-
static int fio_windowsaio_init(struct thread_data *td)
{
struct windowsaio_data *wd;
static int fio_windowsaio_init(struct thread_data *td)
{
struct windowsaio_data *wd;
if (wd != NULL) {
if (wd->ovls != NULL)
free(wd->ovls);
if (wd != NULL) {
if (wd->ovls != NULL)
free(wd->ovls);
wd->pCancelIoEx = GetProcAddress(hKernel32Dll, "CancelIoEx");
td->io_ops->data = wd;
wd->pCancelIoEx = GetProcAddress(hKernel32Dll, "CancelIoEx");
td->io_ops->data = wd;
}
static void fio_windowsaio_cleanup(struct thread_data *td)
}
static void fio_windowsaio_cleanup(struct thread_data *td)
{
int rc = 0;
HANDLE hFile;
{
int rc = 0;
HANDLE hFile;
- DWORD flags = FILE_FLAG_POSIX_SEMANTICS;
+ DWORD flags = FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_OVERLAPPED;
DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD openmode = OPEN_ALWAYS;
DWORD access;
DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD openmode = OPEN_ALWAYS;
DWORD access;
- if (!td->o.odirect && !td->o.sync_io && td->io_ops->data != NULL)
- flags |= FILE_FLAG_OVERLAPPED;
-
if (td->o.odirect)
flags |= FILE_FLAG_NO_BUFFERING;
if (td->o.sync_io)
flags |= FILE_FLAG_WRITE_THROUGH;
if (td->o.odirect)
flags |= FILE_FLAG_NO_BUFFERING;
if (td->o.sync_io)
flags |= FILE_FLAG_WRITE_THROUGH;
if (td->o.td_ddir == TD_DDIR_READ ||
td->o.td_ddir == TD_DDIR_WRITE)
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
if (td->o.td_ddir == TD_DDIR_READ ||
td->o.td_ddir == TD_DDIR_WRITE)
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
f->hFile = CreateFile(f->file_name, access, sharemode,
NULL, openmode, flags, NULL);
f->hFile = CreateFile(f->file_name, access, sharemode,
NULL, openmode, flags, NULL);
- if (f->hFile == INVALID_HANDLE_VALUE) {
- PrintError(__func__);
+ if (f->hFile == INVALID_HANDLE_VALUE)
/* Only set up the competion port and thread if we're not just
* querying the device size */
/* Only set up the competion port and thread if we're not just
* querying the device size */
- if (!rc && td->io_ops->data != NULL && !td->o.odirect && !td->o.sync_io) {
+ if (!rc && td->io_ops->data != NULL) {
struct thread_ctx *ctx;
struct windowsaio_data *wd;
hFile = CreateIoCompletionPort(f->hFile, NULL, 0, 0);
wd = td->io_ops->data;
struct thread_ctx *ctx;
struct windowsaio_data *wd;
hFile = CreateIoCompletionPort(f->hFile, NULL, 0, 0);
wd = td->io_ops->data;
- if (!td->o.odirect && !td->o.sync_io)
- wd->use_iocp = 1;
- else
- wd->use_iocp = 0;
-
wd->iothread_running = TRUE;
if (!rc) {
wd->iothread_running = TRUE;
if (!rc) {
wd->iothread = CreateThread(NULL, 0, IoCompletionRoutine, ctx, 0, NULL);
}
wd->iothread = CreateThread(NULL, 0, IoCompletionRoutine, ctx, 0, NULL);
}
- if (rc || wd->iothread == NULL) {
- PrintError(__func__);
+ if (rc || wd->iothread == NULL)
static int fio_windowsaio_close_file(struct thread_data fio_unused *td, struct fio_file *f)
{
static int fio_windowsaio_close_file(struct thread_data fio_unused *td, struct fio_file *f)
{
dprint(FD_FILE, "fd close %s\n", f->file_name);
if (f->hFile != INVALID_HANDLE_VALUE) {
if (!CloseHandle(f->hFile))
dprint(FD_FILE, "fd close %s\n", f->file_name);
if (f->hFile != INVALID_HANDLE_VALUE) {
if (!CloseHandle(f->hFile))
}
f->hFile = INVALID_HANDLE_VALUE;
}
f->hFile = INVALID_HANDLE_VALUE;
}
static BOOL timeout_expired(DWORD start_count, DWORD end_count)
}
static BOOL timeout_expired(DWORD start_count, DWORD end_count)
- if (wd->use_iocp) {
- for (index = 0; index < td->o.iodepth; index++) {
- if (wd->ovls[index].io_free) {
- wd->ovls[index].io_free = FALSE;
- ResetEvent(wd->ovls[index].o.hEvent);
- break;
- }
+ for (index = 0; index < td->o.iodepth; index++) {
+ if (wd->ovls[index].io_free) {
+ wd->ovls[index].io_free = FALSE;
+ ResetEvent(wd->ovls[index].o.hEvent);
+ break;
- assert(index < td->o.iodepth);
+ assert(index < td->o.iodepth);
- lpOvl = &wd->ovls[index].o;
- wd->ovls[index].io_u = io_u;
- lpOvl->Internal = STATUS_PENDING;
- lpOvl->InternalHigh = 0;
- lpOvl->Offset = io_u->offset & 0xFFFFFFFF;
- lpOvl->OffsetHigh = io_u->offset >> 32;
- lpOvl->Pointer = NULL;
- io_u->engine_data = &wd->ovls[index];
- }
+ lpOvl = &wd->ovls[index].o;
+ wd->ovls[index].io_u = io_u;
+ lpOvl->Internal = STATUS_PENDING;
+ lpOvl->InternalHigh = 0;
+ lpOvl->Offset = io_u->offset & 0xFFFFFFFF;
+ lpOvl->OffsetHigh = io_u->offset >> 32;
+ lpOvl->Pointer = NULL;
+ io_u->engine_data = &wd->ovls[index];
switch (io_u->ddir) {
case DDIR_WRITE:
switch (io_u->ddir) {
case DDIR_WRITE:
- if (wd->use_iocp && (success || GetLastError() == ERROR_IO_PENDING)) {
+ if (success || GetLastError() == ERROR_IO_PENDING) {
- } else if (success && !wd->use_iocp) {
- io_u->resid = io_u->xfer_buflen - iobytes;
- io_u->error = 0;
io_u->error = GetLastError();
io_u->resid = io_u->xfer_buflen;
}
io_u->error = GetLastError();
io_u->resid = io_u->xfer_buflen;
}