Author: cgutman Date: Wed Jun 22 00:17:19 2011 New Revision: 52415
URL: http://svn.reactos.org/svn/reactos?rev=52415&view=rev Log: [AFD] - Hold on to the disconnect IRP until all pending sending IRPs are sent to the transport driver if a controlled disconnect was requested
Modified: trunk/reactos/drivers/network/afd/afd/main.c trunk/reactos/drivers/network/afd/afd/write.c trunk/reactos/drivers/network/afd/include/afd.h
Modified: trunk/reactos/drivers/network/afd/afd/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/mai... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/main.c [iso-8859-1] Wed Jun 22 00:17:19 2011 @@ -440,6 +440,7 @@ ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])); ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_RECV])); ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_PREACCEPT])); + ASSERT(IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT]))
while (!IsListEmpty(&FCB->PendingConnections)) { @@ -531,58 +532,44 @@ return STATUS_SUCCESS; }
-static NTSTATUS NTAPI -AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, - PIO_STACK_LOCATION IrpSp) { - PFILE_OBJECT FileObject = IrpSp->FileObject; - PAFD_FCB FCB = FileObject->FsContext; +static +NTSTATUS +DoDisconnect(PAFD_FCB FCB, PIRP CurrentIrp) +{ PAFD_DISCONNECT_INFO DisReq; IO_STATUS_BLOCK Iosb; PTDI_CONNECTION_INFORMATION ConnectionReturnInfo; - NTSTATUS Status = STATUS_SUCCESS; + PIO_STACK_LOCATION CurrentIrpSp; USHORT Flags = 0; - - if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); - - if( !(DisReq = LockRequest( Irp, IrpSp )) ) - return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, - Irp, 0 ); + NTSTATUS Status; + + CurrentIrpSp = IoGetCurrentIrpStackLocation(CurrentIrp); + DisReq = GetLockedData(CurrentIrp, CurrentIrpSp);
if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) Flags |= TDI_DISCONNECT_RELEASE; if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) Flags |= TDI_DISCONNECT_ABORT; - - if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) - { - if( !FCB->ConnectInfo ) - return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, - Irp, 0 ); - - ASSERT(FCB->RemoteAddress); - - Status = TdiBuildNullConnectionInfo - ( &ConnectionReturnInfo, FCB->RemoteAddress->Address[0].AddressType ); - - if( !NT_SUCCESS(Status) ) - return UnlockAndMaybeComplete( FCB, Status, - Irp, 0 ); - + + Status = TdiBuildNullConnectionInfo(&ConnectionReturnInfo, + FCB->RemoteAddress->Address[0].AddressType); + if (NT_SUCCESS(Status)) + { FCB->ConnectInfo->UserData = FCB->DisconnectData; FCB->ConnectInfo->UserDataLength = FCB->DisconnectDataSize; FCB->ConnectInfo->Options = FCB->DisconnectOptions; FCB->ConnectInfo->OptionsLength = FCB->DisconnectOptionsSize; - - Status = TdiDisconnect( FCB->Connection.Object, - &DisReq->Timeout, - Flags, - &Iosb, - NULL, - NULL, - FCB->ConnectInfo, - ConnectionReturnInfo); - + + Status = TdiDisconnect(FCB->Connection.Object, + &DisReq->Timeout, + Flags, + &Iosb, + NULL, + NULL, + FCB->ConnectInfo, + ConnectionReturnInfo); + if (NT_SUCCESS(Status)) { FCB->FilledDisconnectData = MIN(FCB->DisconnectDataSize, ConnectionReturnInfo->UserDataLength); if (FCB->FilledDisconnectData) @@ -591,7 +578,7 @@ ConnectionReturnInfo->UserData, FCB->FilledDisconnectData); } - + FCB->FilledDisconnectOptions = MIN(FCB->DisconnectOptionsSize, ConnectionReturnInfo->OptionsLength); if (FCB->FilledDisconnectOptions) { @@ -600,15 +587,90 @@ FCB->FilledDisconnectOptions); } } - + ExFreePool( ConnectionReturnInfo ); - + if (Flags & TDI_DISCONNECT_RELEASE) FCB->PollState |= AFD_EVENT_DISCONNECT; else FCB->PollState |= AFD_EVENT_ABORT; - FCB->PollStatus[FD_CLOSE_BIT] = STATUS_SUCCESS; + FCB->PollStatus[FD_CLOSE_BIT] = Status; PollReeval( FCB->DeviceExt, FCB->FileObject ); + } + + CurrentIrp->IoStatus.Status = Status; + CurrentIrp->IoStatus.Information = 0; + UnlockRequest(CurrentIrp, CurrentIrpSp); + (void)IoSetCancelRoutine(CurrentIrp, NULL); + + IoCompleteRequest(CurrentIrp, IO_NETWORK_INCREMENT); + + return Status; +} + +VOID +RetryDisconnectCompletion(PAFD_FCB FCB) +{ + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND])) + { + PIRP CurrentIrp; + PLIST_ENTRY CurrentEntry; + + ASSERT(FCB->RemoteAddress); + + while (!IsListEmpty(&FCB->PendingIrpList[FUNCTION_DISCONNECT])) + { + CurrentEntry = RemoveHeadList(&FCB->PendingIrpList[FUNCTION_DISCONNECT]); + CurrentIrp = CONTAINING_RECORD(CurrentEntry, IRP, Tail.Overlay.ListEntry); + + DoDisconnect(FCB, CurrentIrp); + } + } +} + +static NTSTATUS NTAPI +AfdDisconnect(PDEVICE_OBJECT DeviceObject, PIRP Irp, + PIO_STACK_LOCATION IrpSp) { + PFILE_OBJECT FileObject = IrpSp->FileObject; + PAFD_FCB FCB = FileObject->FsContext; + PAFD_DISCONNECT_INFO DisReq; + NTSTATUS Status = STATUS_SUCCESS; + USHORT Flags = 0; + + if( !SocketAcquireStateLock( FCB ) ) return LostSocket( Irp ); + + if( !(DisReq = LockRequest( Irp, IrpSp )) ) + return UnlockAndMaybeComplete( FCB, STATUS_NO_MEMORY, + Irp, 0 ); + + if( DisReq->DisconnectType & AFD_DISCONNECT_SEND ) + Flags |= TDI_DISCONNECT_RELEASE; + if( DisReq->DisconnectType & AFD_DISCONNECT_RECV || + DisReq->DisconnectType & AFD_DISCONNECT_ABORT ) + Flags |= TDI_DISCONNECT_ABORT; + + if (!(FCB->Flags & AFD_ENDPOINT_CONNECTIONLESS)) + { + if( !FCB->ConnectInfo ) + return UnlockAndMaybeComplete( FCB, STATUS_INVALID_PARAMETER, + Irp, 0 ); + + if (IsListEmpty(&FCB->PendingIrpList[FUNCTION_SEND]) || (Flags & TDI_DISCONNECT_ABORT)) + { + /* Go ahead an execute the disconnect because we're ready for it */ + Status = DoDisconnect(FCB, Irp); + + /* DoDisconnect takes care of the IRP */ + SocketStateUnlock(FCB); + + return Status; + } + else + { + /* We have a graceful disconnect waiting on pending sends to complete */ + return LeaveIrpUntilLater(FCB, Irp, FUNCTION_DISCONNECT); + } + } else { @@ -924,6 +986,10 @@ DbgPrint("WARNING!!! IRP cancellation race could lead to a process hang! (IOCTL_AFD_SELECT)\n"); return;
+ case IOCTL_AFD_DISCONNECT: + Function = FUNCTION_DISCONNECT; + break; + default: ASSERT(FALSE); UnlockAndMaybeComplete(FCB, STATUS_CANCELLED, Irp, 0);
Modified: trunk/reactos/drivers/network/afd/afd/write.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/afd/wri... ============================================================================== --- trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/afd/write.c [iso-8859-1] Wed Jun 22 00:17:19 2011 @@ -59,8 +59,11 @@ (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } - SocketStateUnlock( FCB ); - return STATUS_FILE_CLOSED; + + RetryDisconnectCompletion(FCB); + + SocketStateUnlock( FCB ); + return STATUS_FILE_CLOSED; }
if( !NT_SUCCESS(Status) ) { @@ -85,6 +88,8 @@ (void)IoSetCancelRoutine(NextIrp, NULL); IoCompleteRequest( NextIrp, IO_NETWORK_INCREMENT ); } + + RetryDisconnectCompletion(FCB);
SocketStateUnlock( FCB );
@@ -164,6 +169,8 @@ &FCB->SendIrp.Iosb, SendComplete, FCB ); + + RetryDisconnectCompletion(FCB); } else { FCB->PollState |= AFD_EVENT_SEND; FCB->PollStatus[FD_WRITE_BIT] = STATUS_SUCCESS; @@ -410,6 +417,8 @@ Status, TotalBytesCopied)); }
+ RetryDisconnectCompletion(FCB); + return UnlockAndMaybeComplete ( FCB, Status, Irp, TotalBytesCopied ); }
Modified: trunk/reactos/drivers/network/afd/include/afd.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/network/afd/include... ============================================================================== --- trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] (original) +++ trunk/reactos/drivers/network/afd/include/afd.h [iso-8859-1] Wed Jun 22 00:17:19 2011 @@ -99,8 +99,9 @@ #define FUNCTION_SEND 2 #define FUNCTION_PREACCEPT 3 #define FUNCTION_ACCEPT 4 -#define FUNCTION_CLOSE 5 -#define MAX_FUNCTIONS 6 +#define FUNCTION_DISCONNECT 5 +#define FUNCTION_CLOSE 6 +#define MAX_FUNCTIONS 7
#define IN_FLIGHT_REQUESTS 4
@@ -309,6 +310,7 @@ VOID DestroySocket( PAFD_FCB FCB ); VOID NTAPI AfdCancelHandler(PDEVICE_OBJECT DeviceObject, PIRP Irp); +VOID RetryDisconnectCompletion(PAFD_FCB FCB);
/* read.c */