ntdll: Don't bother with async I/O on regular files.

This commit is contained in:
Alexandre Julliard 2006-11-20 14:15:43 +01:00
parent 83ce958793
commit a902632483
1 changed files with 91 additions and 76 deletions

View File

@ -286,7 +286,6 @@ typedef struct async_fileio
void* apc_user;
char* buffer;
unsigned int count;
off_t offset;
int queue_apc_on_error;
BOOL avail_mode;
HANDLE event;
@ -371,6 +370,7 @@ NTSTATUS FILE_GetNtStatus(void)
case ENOTTY:
case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
case EFAULT: return STATUS_ACCESS_VIOLATION;
case ENOEXEC: /* ?? */
case ESPIPE: /* ?? */
case EEXIST: /* ?? */
@ -402,16 +402,7 @@ static void WINAPI FILE_AsyncReadService(void *user, PIO_STATUS_BLOCK iosb, ULON
fileio_terminate(fileio, iosb);
break;
}
if ( fileio->avail_mode )
result = read(fd, &fileio->buffer[already], fileio->count - already);
else
{
result = pread(fd, &fileio->buffer[already],
fileio->count - already,
fileio->offset + already);
if ((result < 0) && (errno == ESPIPE))
result = read(fd, &fileio->buffer[already], fileio->count - already);
}
result = read(fd, &fileio->buffer[already], fileio->count - already);
if (needs_close) close( fd );
if (result < 0)
@ -487,7 +478,8 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
PIO_STATUS_BLOCK io_status, void* buffer, ULONG length,
PLARGE_INTEGER offset, PULONG key)
{
int unix_handle, needs_close, flags;
int result, unix_handle, needs_close, flags;
enum server_fd_type type;
TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p),partial stub!\n",
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
@ -496,9 +488,45 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
io_status->Information = 0;
io_status->u.Status = server_get_unix_fd( hFile, FILE_READ_DATA, &unix_handle,
&needs_close, NULL, &flags );
&needs_close, &type, &flags );
if (io_status->u.Status) return io_status->u.Status;
if (type == FD_TYPE_FILE && offset)
{
/* async I/O doesn't make sense on regular files */
if (flags & FD_FLAG_OVERLAPPED)
{
while ((result = pread( unix_handle, buffer, length, offset->QuadPart )) == -1)
{
if (errno == EINTR) continue;
if (errno == EAGAIN || errno == ESPIPE)
{
io_status->u.Status = STATUS_PENDING;
break;
}
result = 0;
io_status->u.Status = FILE_GetNtStatus();
goto done;
}
if (result >= 0)
{
io_status->Information = result;
io_status->u.Status = result ? STATUS_SUCCESS : STATUS_END_OF_FILE;
if (hEvent) NtSetEvent( hEvent, NULL );
if (apc && !io_status->u.Status) apc( apc_user, io_status, io_status->Information );
goto done;
}
}
else
{
if (lseek( unix_handle, offset->QuadPart, SEEK_SET ) == (off_t)-1)
{
io_status->u.Status = FILE_GetNtStatus();
goto done;
}
}
}
if (flags & FD_FLAG_RECV_SHUTDOWN)
{
if (needs_close) close( unix_handle );
@ -535,14 +563,6 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
}
fileio->handle = hFile;
fileio->count = length;
if ( offset == NULL )
fileio->offset = 0;
else
{
fileio->offset = offset->QuadPart;
if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
FIXME("High part of offset is lost\n");
}
fileio->apc = apc;
fileio->apc_user = apc_user;
fileio->buffer = buffer;
@ -589,27 +609,15 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent,
return io_status->u.Status;
}
if (offset)
{
FILE_POSITION_INFORMATION fpi;
fpi.CurrentByteOffset = *offset;
io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
FilePositionInformation);
if (io_status->u.Status) goto done;
}
/* code for synchronous reads */
while ((io_status->Information = read( unix_handle, buffer, length )) == -1)
while ((result = read( unix_handle, buffer, length )) == -1)
{
if ((errno == EAGAIN) || (errno == EINTR)) continue;
if (errno == EFAULT)
{
io_status->Information = 0;
io_status->u.Status = STATUS_ACCESS_VIOLATION;
}
else io_status->u.Status = FILE_GetNtStatus();
break;
io_status->u.Status = FILE_GetNtStatus();
result = 0;
break;
}
io_status->Information = result;
if (io_status->u.Status == STATUS_SUCCESS && io_status->Information == 0)
{
struct stat st;
@ -645,15 +653,7 @@ static void WINAPI FILE_AsyncWriteService(void *ovp, IO_STATUS_BLOCK *iosb, ULON
fileio_terminate(fileio, iosb);
break;
}
if ( fileio->avail_mode )
result = write(fd, &fileio->buffer[already], fileio->count - already);
else
{
result = pwrite(fd, &fileio->buffer[already],
fileio->count - already, fileio->offset + already);
if ((result < 0) && (errno == ESPIPE))
result = write(fd, &fileio->buffer[already], fileio->count - already);
}
result = write(fd, &fileio->buffer[already], fileio->count - already);
if (needs_close) close( fd );
if (result < 0)
@ -708,7 +708,8 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
const void* buffer, ULONG length,
PLARGE_INTEGER offset, PULONG key)
{
int unix_handle, needs_close, flags;
int result, unix_handle, needs_close, flags;
enum server_fd_type type;
TRACE("(%p,%p,%p,%p,%p,%p,0x%08x,%p,%p)!\n",
hFile,hEvent,apc,apc_user,io_status,buffer,length,offset,key);
@ -717,9 +718,46 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
io_status->Information = 0;
io_status->u.Status = server_get_unix_fd( hFile, FILE_WRITE_DATA, &unix_handle,
&needs_close, NULL, &flags );
&needs_close, &type, &flags );
if (io_status->u.Status) return io_status->u.Status;
if (type == FD_TYPE_FILE && offset)
{
if (flags & FD_FLAG_OVERLAPPED)
{
/* async I/O doesn't make sense on regular files */
while ((result = pwrite( unix_handle, buffer, length, offset->QuadPart )) == -1)
{
if (errno == EINTR) continue;
if (errno == EAGAIN || errno == ESPIPE)
{
io_status->u.Status = STATUS_PENDING;
break;
}
result = 0;
if (errno == EFAULT) io_status->u.Status = STATUS_INVALID_USER_BUFFER;
else io_status->u.Status = FILE_GetNtStatus();
goto done;
}
if (result >= 0)
{
io_status->Information = result;
io_status->u.Status = STATUS_SUCCESS;
if (hEvent) NtSetEvent( hEvent, NULL );
if (apc) apc( apc_user, io_status, io_status->Information );
goto done;
}
}
else
{
if (lseek( unix_handle, offset->QuadPart, SEEK_SET ) == (off_t)-1)
{
io_status->u.Status = FILE_GetNtStatus();
goto done;
}
}
}
if (flags & FD_FLAG_SEND_SHUTDOWN)
{
if (needs_close) close( unix_handle );
@ -756,16 +794,6 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
}
fileio->handle = hFile;
fileio->count = length;
if (offset)
{
fileio->offset = offset->QuadPart;
if (offset->u.HighPart && fileio->offset == offset->u.LowPart)
FIXME("High part of offset is lost\n");
}
else
{
fileio->offset = 0;
}
fileio->apc = apc;
fileio->apc_user = apc_user;
fileio->buffer = (void*)buffer;
@ -812,29 +840,16 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent,
return io_status->u.Status;
}
if (offset)
{
FILE_POSITION_INFORMATION fpi;
fpi.CurrentByteOffset = *offset;
io_status->u.Status = NtSetInformationFile(hFile, io_status, &fpi, sizeof(fpi),
FilePositionInformation);
if (io_status->u.Status) goto done;
}
/* synchronous file write */
while ((io_status->Information = write( unix_handle, buffer, length )) == -1)
while ((result = write( unix_handle, buffer, length )) == -1)
{
if ((errno == EAGAIN) || (errno == EINTR)) continue;
if (errno == EFAULT)
{
io_status->Information = 0;
io_status->u.Status = STATUS_INVALID_USER_BUFFER;
}
else if (errno == ENOSPC) io_status->u.Status = STATUS_DISK_FULL;
result = 0;
if (errno == EFAULT) io_status->u.Status = STATUS_INVALID_USER_BUFFER;
else io_status->u.Status = FILE_GetNtStatus();
break;
}
io_status->Information = result;
done:
if (needs_close) close( unix_handle );
return io_status->u.Status;