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/ma…
==============================================================================
--- 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/wr…
==============================================================================
--- 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/includ…
==============================================================================
--- 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 */