summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Cran <BCran@fusionio.com>2011-05-04 07:54:13 -0600
committerJens Axboe <jaxboe@fusionio.com>2011-05-04 07:54:13 -0600
commitea4500d8d709ed4aa9587f35b2edc55b5b2c7695 (patch)
tree71a9bc2768bbc8611b0452e9e666c35311bd287d
parentac18ea38de2a23018f9f953c3028d519df3a1177 (diff)
downloadfio-ea4500d8d709ed4aa9587f35b2edc55b5b2c7695.tar.gz
fio-ea4500d8d709ed4aa9587f35b2edc55b5b2c7695.tar.bz2
Windows fixes
- Fix XP support: get pointer to CancelIoEx at runtime. - Fix overlapped IO. - Don't use overlapped IO if direct or synchronous options are set. - Check if write option is set before opening file in read-only mode: fixes 'rw=rw'. Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
-rw-r--r--engines/windowsaio.c125
-rwxr-xr-xos/windows/cygwin.wxs16
-rwxr-xr-xos/windows/dobuild.cmd8
3 files changed, 74 insertions, 75 deletions
diff --git a/engines/windowsaio.c b/engines/windowsaio.c
index f66b9a2e..2d3ed837 100644
--- a/engines/windowsaio.c
+++ b/engines/windowsaio.c
@@ -1,6 +1,6 @@
/*
* Native Windows async IO engine
- * Copyright (C) 2010 Bruce Cran <bruce@cran.org.uk>
+ * Copyright (C) 2011 Bruce Cran <bruce@cran.org.uk>
*/
#include <stdio.h>
@@ -12,6 +12,8 @@
#include "../fio.h"
+typedef BOOL (WINAPI *CANCELIOEX)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
+
typedef struct {
OVERLAPPED o;
struct io_u *io_u;
@@ -28,7 +30,8 @@ struct windowsaio_data {
struct io_u **aio_events;
HANDLE iocomplete_event;
- BOOL have_cancelioex;
+ CANCELIOEX pCancelIoEx;
+ BOOL useIOCP;
};
struct thread_ctx {
@@ -51,14 +54,6 @@ static int fio_windowsaio_init(struct thread_data *td);
static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f);
static int fio_windowsaio_close_file(struct thread_data fio_unused *td, struct fio_file *f);
-/* CancelIoEx isn't in Cygwin's w32api */
-BOOL WINAPI CancelIoEx(
- HANDLE hFile,
- LPOVERLAPPED lpOverlapped
-);
-
-
-
int sync_file_range(int fd, off64_t offset, off64_t nbytes,
unsigned int flags)
{
@@ -94,10 +89,10 @@ static int fio_windowsaio_cancel(struct thread_data *td,
struct windowsaio_data *wd = td->io_ops->data;
- /* If we're running on Vista, we can cancel individual IO requests */
- if (wd->have_cancelioex) {
+ /* If we're running on Vista or newer, we can cancel individual IO requests */
+ if (wd->pCancelIoEx != NULL) {
FIO_OVERLAPPED *ovl = io_u->engine_data;
- if (!CancelIoEx(io_u->file->hFile, &ovl->o))
+ if (!wd->pCancelIoEx(io_u->file->hFile, &ovl->o))
rc = 1;
} else
rc = 1;
@@ -141,8 +136,8 @@ static int fio_windowsaio_getevents(struct thread_data *td, unsigned int min,
flist_for_each(entry, &td->io_u_busylist) {
io_u = flist_entry(entry, struct io_u, list);
- if (io_u->seen == 1) {
- io_u->seen = 2;
+ if (io_u->seen == 0) {
+ io_u->seen = 1;
wd->aio_events[dequeued] = io_u;
dequeued++;
}
@@ -151,9 +146,8 @@ static int fio_windowsaio_getevents(struct thread_data *td, unsigned int min,
break;
}
- if (dequeued < min) {
+ if (dequeued < min)
WaitForSingleObject(wd->iocomplete_event, mswait);
- }
if (t != NULL && TimedOut(start_count, end_count))
timedout = TRUE;
@@ -172,6 +166,7 @@ static int fio_windowsaio_queue(struct thread_data *td,
struct io_u *io_u)
{
struct windowsaio_data *wd;
+ LPOVERLAPPED lpOvl;
DWORD iobytes;
BOOL success = TRUE;
int ind;
@@ -183,40 +178,47 @@ static int fio_windowsaio_queue(struct thread_data *td,
ind = wd->io_index;
ResetEvent(wd->io_handles[ind]);
- wd->ovls[ind].o.Internal = 0;
- wd->ovls[ind].o.InternalHigh = 0;
- wd->ovls[ind].o.Offset = io_u->offset & 0xFFFFFFFF;
- wd->ovls[ind].o.OffsetHigh = io_u->offset >> 32;
- wd->ovls[ind].o.hEvent = wd->io_handles[ind];
- wd->ovls[ind].io_u = io_u;
+
+ if (wd->useIOCP) {
+ lpOvl = &wd->ovls[ind].o;
+
+ lpOvl->Internal = STATUS_PENDING;
+ lpOvl->InternalHigh = 0;
+ lpOvl->Offset = io_u->offset & 0xFFFFFFFF;
+ lpOvl->OffsetHigh = io_u->offset >> 32;
+ lpOvl->hEvent = wd->io_handles[ind];
+ lpOvl->Pointer = NULL;
+ wd->ovls[ind].io_u = io_u;
+ } else {
+ lpOvl = NULL;
+ }
io_u->engine_data = &wd->ovls[ind];
io_u->seen = 0;
if (io_u->ddir == DDIR_WRITE) {
- success = WriteFile(io_u->file->hFile, io_u->xfer_buf, io_u->xfer_buflen, &iobytes, &wd->ovls[ind].o);
+ success = WriteFile(io_u->file->hFile, io_u->xfer_buf, io_u->xfer_buflen, &iobytes, lpOvl);
} else if (io_u->ddir == DDIR_READ) {
- success = ReadFile(io_u->file->hFile, io_u->xfer_buf, io_u->xfer_buflen, &iobytes, &wd->ovls[ind].o);
+ success = ReadFile(io_u->file->hFile, io_u->xfer_buf, io_u->xfer_buflen, &iobytes, lpOvl);
} else if (io_u->ddir == DDIR_SYNC ||
- io_u->ddir == DDIR_DATASYNC ||
- io_u->ddir == DDIR_SYNC_FILE_RANGE)
+ io_u->ddir == DDIR_DATASYNC ||
+ io_u->ddir == DDIR_SYNC_FILE_RANGE)
{
FlushFileBuffers(io_u->file->hFile);
return FIO_Q_COMPLETED;
} else if (io_u->ddir == DDIR_TRIM) {
- log_info("explicit TRIM isn't supported on Windows");
+ log_info("Manual TRIM isn't supported on Windows");
return FIO_Q_COMPLETED;
} else
assert(0);
- if (success) {
- io_u->seen = 1;
+ if (wd->useIOCP && (success || GetLastError() == ERROR_IO_PENDING)) {
+ wd->io_index = (wd->io_index + 1) % td->o.iodepth;
+ rc = FIO_Q_QUEUED;
+ } else if (success && !wd->useIOCP) {
io_u->resid = io_u->xfer_buflen - iobytes;
io_u->error = 0;
rc = FIO_Q_COMPLETED;
- } else if (!success && GetLastError() == ERROR_IO_PENDING) {
- wd->io_index = (wd->io_index + 1) % (2 * td->o.iodepth);
- rc = FIO_Q_QUEUED;
} else {
PrintError(__func__);
io_u->error = GetLastError();
@@ -241,7 +243,7 @@ static void fio_windowsaio_cleanup(struct thread_data *td)
CloseHandle(wd->iothread_stopped);
CloseHandle(wd->iocomplete_event);
- for (i = 0; i < 2 * td->o.iodepth; i++) {
+ for (i = 0; i < td->o.iodepth; i++) {
CloseHandle(wd->io_handles[i]);
}
@@ -268,16 +270,13 @@ static DWORD WINAPI IoCompletionRoutine(LPVOID lpParameter)
ctx = (struct thread_ctx*)lpParameter;
wd = ctx->wd;
- while (ctx->wd->iothread_running) {
+ do {
if (!GetQueuedCompletionStatus(ctx->iocp, &bytes, &ulKey, &ovl, 250))
continue;
fov = CONTAINING_RECORD(ovl, FIO_OVERLAPPED, o);
io_u = fov->io_u;
- if (io_u->seen != 0)
- continue;
-
if (ovl->Internal == ERROR_SUCCESS) {
io_u->resid = io_u->xfer_buflen - ovl->InternalHigh;
io_u->error = 0;
@@ -286,9 +285,8 @@ static DWORD WINAPI IoCompletionRoutine(LPVOID lpParameter)
io_u->error = ovl->Internal;
}
- io_u->seen = 1;
SetEvent(wd->iocomplete_event);
- }
+ } while (ctx->wd->iothread_running);
CloseHandle(ctx->iocp);
SetEvent(ctx->wd->iothread_stopped);
@@ -300,7 +298,7 @@ static DWORD WINAPI IoCompletionRoutine(LPVOID lpParameter)
static int fio_windowsaio_init(struct thread_data *td)
{
struct windowsaio_data *wd;
- OSVERSIONINFO osInfo;
+ HANDLE hKernel32Dll;
int rc = 0;
wd = malloc(sizeof(struct windowsaio_data));
@@ -316,13 +314,13 @@ static int fio_windowsaio_init(struct thread_data *td)
}
if (!rc) {
- wd->io_handles = malloc(2 * td->o.iodepth * sizeof(HANDLE));
+ wd->io_handles = malloc(td->o.iodepth * sizeof(HANDLE));
if (wd->io_handles == NULL)
rc = 1;
}
if (!rc) {
- wd->ovls = malloc(2 * td->o.iodepth * sizeof(FIO_OVERLAPPED));
+ wd->ovls = malloc(td->o.iodepth * sizeof(FIO_OVERLAPPED));
if (wd->ovls == NULL)
rc = 1;
}
@@ -334,16 +332,6 @@ static int fio_windowsaio_init(struct thread_data *td)
rc = 1;
}
- if (!rc) {
- osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx(&osInfo);
-
- if (osInfo.dwMajorVersion >= 6)
- wd->have_cancelioex = TRUE;
- else
- wd->have_cancelioex = FALSE;
- }
-
if (rc) {
PrintError(__func__);
if (wd != NULL) {
@@ -358,6 +346,9 @@ static int fio_windowsaio_init(struct thread_data *td)
}
}
+ hKernel32Dll = GetModuleHandle("kernel32.dll");
+ wd->pCancelIoEx = GetProcAddress(hKernel32Dll, "CancelIoEx");
+
td->io_ops->data = wd;
return 0;
}
@@ -366,7 +357,7 @@ static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f)
{
int rc = 0;
HANDLE hFile;
- DWORD flags = FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_POSIX_SEMANTICS | FILE_FLAG_OVERLAPPED;
+ DWORD flags = FILE_FLAG_POSIX_SEMANTICS;
DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
DWORD openmode = OPEN_ALWAYS;
DWORD access;
@@ -384,6 +375,9 @@ static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f)
return 1;
}
+ 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)
@@ -391,17 +385,12 @@ static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f)
if (td->o.td_ddir == TD_DDIR_READ ||
- td->o.td_ddir == TD_DDIR_WRITE ||
- td->o.td_ddir == TD_DDIR_RANDRW)
- {
+ td->o.td_ddir == TD_DDIR_WRITE)
flags |= FILE_FLAG_SEQUENTIAL_SCAN;
- }
else
- {
flags |= FILE_FLAG_RANDOM_ACCESS;
- }
- if (td_read(td) || read_only)
+ if (!td_write(td) || read_only)
access = GENERIC_READ;
else
access = (GENERIC_READ | GENERIC_WRITE);
@@ -421,12 +410,18 @@ static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f)
/* Only set up the competion port and thread if we're not just
* querying the device size */
- if (!rc && td->io_ops->data != NULL) {
- struct windowsaio_data *wd;
+ if (!rc && td->io_ops->data != NULL && !td->o.odirect && !td->o.sync_io) {
struct thread_ctx *ctx;
+ struct windowsaio_data *wd;
hFile = CreateIoCompletionPort(f->hFile, NULL, 0, 0);
- wd = td->io_ops->data;
+
+ wd = td->io_ops->data;
+
+ if (!td->o.odirect && !td->o.sync_io)
+ wd->useIOCP = 1;
+ else
+ wd->useIOCP = 0;
wd->io_index = 0;
wd->iothread_running = TRUE;
@@ -437,7 +432,7 @@ static int fio_windowsaio_open_file(struct thread_data *td, struct fio_file *f)
rc = 1;
if (!rc) {
- for (i = 0; i < 2 * td->o.iodepth; i++) {
+ for (i = 0; i < td->o.iodepth; i++) {
/* Create a manual-reset event for putting in OVERLAPPED */
wd->io_handles[i] = CreateEvent(NULL, TRUE, FALSE, NULL);
if (wd->io_handles[i] == NULL) {
diff --git a/os/windows/cygwin.wxs b/os/windows/cygwin.wxs
index f74b422d..c33c1335 100755
--- a/os/windows/cygwin.wxs
+++ b/os/windows/cygwin.wxs
@@ -24,11 +24,14 @@
<Component Id="cmp229D68D422FB0EB697971491C1475142" Guid="{027945EC-DA28-41C8-9AFF-7AE1BD0F7078}">
<File Id="fil7FD65A67872AB00D44EE1419EED402F3" KeyPath="yes" Source="fio\bin\cygintl-8.dll" />
</Component>
- <Component Id="cmpFCBAB68E4A226C62E32EF283AA1ABC5A" Guid="{2FE224F7-DF14-4D19-8154-77BF6A81B895}">
- <File Id="filF29BC713B2D6CF3C73FAC7EBD9E7DA59" KeyPath="yes" Source="fio\bin\cygncurses++-9.dll" />
+ <Component Id="cygncursespp_10" Guid="{02ecd011-d86c-4400-97b3-65dbcddbb5d9}">
+ <File Id="cygncursespp_10" KeyPath="yes" Source="fio\bin\cygncurses++-10.dll" />
</Component>
- <Component Id="cmp30425E1537382CBE87A8582C3712DA6D" Guid="{43895BDD-58DD-4EA9-96A2-A17EADD13C65}">
- <File Id="fil346312AAE49BBD0EDE977120B93991EE" KeyPath="yes" Source="fio\bin\cygncurses-9.dll" />
+ <Component Id="cygncurses_10" Guid="{2ce11a26-c1d8-46d3-86ef-8545685a44b2}">
+ <File Id="cygncurses_10" KeyPath="yes" Source="fio\bin\cygncurses-10.dll" />
+ </Component>
+ <Component Id="cygncursesw_10" Guid="44fe569a-375f-4103-93e9-0dc4195efb89">
+ <File Id="cygncursesw_10" KeyPath="yes" Source="fio\bin\cygncursesw-10.dll" />
</Component>
<Component Id="cmp9B2CF01422C767668980462815CBD1FC" Guid="{55DD475C-5E0B-4C46-93BF-6D9E44B44CDC}">
<File Id="filC2E6ED6705CC982EC3E7FE8F1089AD7A" KeyPath="yes" Source="fio\bin\cygreadline7.dll" />
@@ -6408,6 +6411,7 @@
</Fragment>
<Fragment>
<ComponentGroup Id="cygwin">
+ <ComponentRef Id="cygncursesw_10" />
<ComponentRef Id="cmpB647D75194B1BE4C7C89501B755FB631" />
<ComponentRef Id="cmp0632DB51E5BC3C2DABB6D68937C68C14" />
<ComponentRef Id="cmpB4B196A767932EB43E26C3FDB12F34A5" />
@@ -6415,8 +6419,8 @@
<ComponentRef Id="cmp426BE94F315430D90C59934ECCE4A484" />
<ComponentRef Id="cmpB233C0A559F9EB1AFE292982562F1ECC" />
<ComponentRef Id="cmp229D68D422FB0EB697971491C1475142" />
- <ComponentRef Id="cmpFCBAB68E4A226C62E32EF283AA1ABC5A" />
- <ComponentRef Id="cmp30425E1537382CBE87A8582C3712DA6D" />
+ <ComponentRef Id="cygncursespp_10" />
+ <ComponentRef Id="cygncurses_10" />
<ComponentRef Id="cmp9B2CF01422C767668980462815CBD1FC" />
<ComponentRef Id="cmpF04F051EF4B7C676F1989889D664CEBF" />
<ComponentRef Id="cmp6B8D3319D753D33FA084D14C712FFE56" />
diff --git a/os/windows/dobuild.cmd b/os/windows/dobuild.cmd
index fa855a2e..95543d75 100755
--- a/os/windows/dobuild.cmd
+++ b/os/windows/dobuild.cmd
@@ -1,4 +1,4 @@
-"%WIX%\bin\candle" cygwin.wxs
-"%WIX%\bin\candle" install.wxs
-"%WIX%\bin\candle" examples.wxs
-"%WIX%\bin\light" install.wixobj cygwin.wixobj examples.wixobj -ext WixUIExtension -out fio.msi \ No newline at end of file
+"%WIX%bin\candle" cygwin.wxs
+"%WIX%bin\candle" install.wxs
+"%WIX%bin\candle" examples.wxs
+"%WIX%bin\light" install.wixobj cygwin.wixobj examples.wixobj -ext WixUIExtension -out fio.msi \ No newline at end of file