Files winaoe-0.97g/bin/aoe.exe and winaoe-0.97g.deadlock_fix.1/bin/aoe.exe differ
Files winaoe-0.97g/bin/aoe32.sys and winaoe-0.97g.deadlock_fix.1/bin/aoe32.sys differ
Files winaoe-0.97g/bin/aoe64.sys and winaoe-0.97g.deadlock_fix.1/bin/aoe64.sys differ
diff -ru winaoe-0.97g/src/aoe.c winaoe-0.97g.deadlock_fix.1/src/aoe.c
--- winaoe-0.97g/src/aoe.c 2008-03-12 00:23:04.000000000 -0500
+++ winaoe-0.97g.deadlock_fix.1/src/aoe.c 2008-12-09 14:29:05.112016000 -0600
@@ -111,14 +111,20 @@
} DISKSEARCH, *PDISKSEARCH;
BOOLEAN Stop = FALSE;
-KSPIN_LOCK SpinLock;
+static KSPIN_LOCK SpinLock;
+static KSPIN_LOCK ReplySpinLock;
KEVENT ThreadSignalEvent;
PTAG TagList = NULL;
PTAG TagListLast = NULL;
PTAG ProbeTag = NULL;
+PTAG ReplyTagListLast = NULL;
+PTAG ReplyTagListHead = NULL;
PDISKSEARCH DiskSearchList = NULL;
LONG OutstandingTags = 0;
HANDLE ThreadHandle;
+UCHAR GlobalSourceMac[6];
+
+
NTSTATUS STDCALL AoEStart() {
NTSTATUS Status;
@@ -145,6 +151,7 @@
ProbeTag->PacketData->Count = 1;
KeInitializeSpinLock(&SpinLock);
+ KeInitializeSpinLock(&ReplySpinLock);
KeInitializeEvent(&ThreadSignalEvent, SynchronizationEvent, FALSE);
InitializeObjectAttributes(&ObjectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
@@ -240,7 +247,7 @@
Timeout.QuadPart = -500000LL; // 500.000 * 100ns = 50.000.000 ns = 50ms
KeWaitForSingleObject(&DeviceExtension->Disk.SearchEvent, Executive, KernelMode, FALSE, &Timeout);
if (Stop) {
- DbgPrint("AoESearchBootDrive cancled\n");
+ DbgPrint("AoESearchBootDrive canceled\n");
return FALSE;
}
@@ -513,27 +520,81 @@
return STATUS_PENDING;
}
-NTSTATUS STDCALL AoEReply(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN UINT DataSize) {
+
+
+
+// Call from protocolReceive/NDIS to add packets to receive queue
+NTSTATUS STDCALL AoEReplyQueue(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN UINT DataSize) {
PAOE Reply = (PAOE)Data;
LONGLONG LBASize;
- PTAG Tag;
+ PTAG ReplyTag;
KIRQL Irql;
- BOOLEAN Found = FALSE;
- LARGE_INTEGER CurrentTime;
if (!Reply->ResponseFlag) return STATUS_SUCCESS;
+
+ // Special case for AoE probe response
if (ProbeTag->Id == Reply->Tag) {
RtlCopyMemory(&LBASize, &Reply->Data[200], sizeof(LONGLONG));
BusAddTarget(DestinationMac, SourceMac, ntohs(Reply->Major), Reply->Minor, LBASize);
return STATUS_SUCCESS;
}
+
+ // allocate storage
+ if ((ReplyTag = (PTAG)ExAllocatePool(NonPagedPool, sizeof(TAG))) == NULL) {
+ DbgPrint("AoERequest ExAllocatePool ReplyTag\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ RtlZeroMemory(ReplyTag, sizeof(TAG));
+ // - not using all the TAG fields, just PacketData, PacketSize, Next, and Previous
+ ReplyTag->PacketSize = DataSize;
+ if ((ReplyTag->PacketData = (PAOE)ExAllocatePool(NonPagedPool, ReplyTag->PacketSize)) == NULL) {
+ DbgPrint("AoERequest ExAllocatePool ReplyTag->PacketData\n");
+ ExFreePool(ReplyTag);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ // copy packet data to list item
+ RtlCopyMemory(ReplyTag->PacketData, Reply, ReplyTag->PacketSize);
+
+ // AoEProcessReply needs the SourceMac, so save it
+ RtlCopyMemory(GlobalSourceMac, SourceMac, 6);
+
+ // add to the end of the reply list
+ KeAcquireSpinLock(&ReplySpinLock, &Irql);
+ if (ReplyTagListLast == NULL) {
+ ReplyTagListHead = ReplyTag;
+ } else {
+ ReplyTagListLast->Next = ReplyTag;
+ ReplyTag->Previous = ReplyTagListLast;
+ ReplyTag->Next = NULL;
+ }
+ ReplyTagListLast = ReplyTag;
+ KeReleaseSpinLock(&ReplySpinLock, Irql);
+
+ // tell Thread we have a reply
+ KeSetEvent(&ThreadSignalEvent, 0, FALSE);
+ return STATUS_SUCCESS;
+}
+
+
+// changed this to process receive list; call from Thread before processing sends
+NTSTATUS STDCALL AoEProcessReply(IN PUCHAR Data, IN UINT DataSize) {
+ PAOE Reply = (PAOE) Data;
+ LONGLONG LBASize;
+ PTAG Tag;
+ KIRQL Irql;
+ BOOLEAN Found = FALSE;
+ LARGE_INTEGER CurrentTime;
+
+
KeAcquireSpinLock(&SpinLock, &Irql);
if (TagList == NULL) {
KeReleaseSpinLock(&SpinLock, Irql);
return STATUS_SUCCESS;
}
+ // see if we need this packet
Tag = TagList;
while (Tag != NULL) {
if ((Tag->Id == Reply->Tag) && (Tag->PacketData->Major == Reply->Major) && (Tag->PacketData->Minor == Reply->Minor)) {
@@ -546,24 +607,29 @@
KeReleaseSpinLock(&SpinLock, Irql);
return STATUS_SUCCESS;
} else {
+ // we need this packet, remove from TagList, and decrement count
if (Tag->Previous == NULL) TagList = Tag->Next;
else Tag->Previous->Next = Tag->Next;
if (Tag->Next == NULL) TagListLast = Tag->Previous;
else Tag->Next->Previous = Tag->Previous;
OutstandingTags--;
if (OutstandingTags < 0) DbgPrint("!!OutstandingTags < 0 (AoEReply)!!\n");
- KeSetEvent(&ThreadSignalEvent, 0, FALSE);
}
KeReleaseSpinLock(&SpinLock, Irql);
+ // get MAC from a global
if (RtlCompareMemory(Tag->DeviceExtension->Disk.ServerMac, "\xff\xff\xff\xff\xff\xff", 6) == 6) {
- RtlCopyMemory(Tag->DeviceExtension->Disk.ServerMac, SourceMac, 6);
- DbgPrint("Major: %d minor: %d found on server %02x:%02x:%02x:%02x:%02x:%02x\n", Tag->DeviceExtension->Disk.Major, Tag->DeviceExtension->Disk.Minor, SourceMac[0], SourceMac[1], SourceMac[2], SourceMac[3], SourceMac[4], SourceMac[5]);
+ RtlCopyMemory(Tag->DeviceExtension->Disk.ServerMac, GlobalSourceMac, 6);
+ DbgPrint("Major: %d minor: %d found on server %02x:%02x:%02x:%02x:%02x:%02x\n", Tag->DeviceExtension->Disk.Major, Tag->DeviceExtension->Disk.Minor,
+ GlobalSourceMac[0], GlobalSourceMac[1], GlobalSourceMac[2], GlobalSourceMac[3], GlobalSourceMac[4], GlobalSourceMac[5]);
}
KeQuerySystemTime(&CurrentTime);
+ // timeout -= (timeout - delta time) / 1024
Tag->DeviceExtension->Disk.Timeout -= (ULONG)((Tag->DeviceExtension->Disk.Timeout - (CurrentTime.QuadPart - Tag->FirstSendTime.QuadPart)) / 1024);
if (Tag->DeviceExtension->Disk.Timeout > 100000000) Tag->DeviceExtension->Disk.Timeout = 100000000;
+ // min timeout = 7 msec
+ //if (Tag->DeviceExtension->Disk.Timeout < 70000) Tag->DeviceExtension->Disk.Timeout = 70000;
switch (Tag->Type) {
case SearchDriveType:
@@ -615,7 +681,6 @@
break;
}
- KeSetEvent(&ThreadSignalEvent, 0, FALSE);
ExFreePool(Tag->PacketData);
ExFreePool(Tag);
return STATUS_SUCCESS;
@@ -629,14 +694,15 @@
LARGE_INTEGER Timeout, CurrentTime, ProbeTime, ReportTime;
ULONG NextTagId = 1;
PTAG Tag;
- KIRQL Irql;
+ PTAG Next=NULL;
+ KIRQL Irql, Irq2;
ULONG Sends = 0;
ULONG Resends = 0;
ULONG ResendFails = 0;
ULONG Fails = 0;
ULONG RequestTimeout = 0;
- DbgPrint("Thread\n");
+ DbgPrint("Thread - entry\n");
ReportTime.QuadPart = 0LL;
ProbeTime.QuadPart = 0LL;
@@ -652,7 +718,7 @@
KeQuerySystemTime(&CurrentTime);
if (CurrentTime.QuadPart > (ReportTime.QuadPart + 10000000LL)) {
-// DbgPrint("Sends: %d Resends: %d ResendFails: %d Fails: %d OutstandingTags: %d RequestTimeout: %d\n", Sends, Resends, ResendFails, Fails, OutstandingTags, RequestTimeout);
+ DbgPrint("Sends: %d Resends: %d ResendFails: %d Fails: %d OutstandingTags: %d RequestTimeout: %d\n", Sends, Resends, ResendFails, Fails, OutstandingTags, RequestTimeout);
Sends = 0;
Resends = 0;
ResendFails = 0;
@@ -660,6 +726,7 @@
KeQuerySystemTime(&ReportTime);
}
+ // send the probe every 100 seconds
if (CurrentTime.QuadPart > (ProbeTag->SendTime.QuadPart + 100000000LL)) {
ProbeTag->Id = NextTagId++;
if (NextTagId == 0) NextTagId++;
@@ -668,6 +735,21 @@
KeQuerySystemTime(&ProbeTag->SendTime);
}
+
+ // process the reply list, deleting each item after processing
+ KeAcquireSpinLock(&ReplySpinLock, &Irq2);
+ for (Tag = ReplyTagListHead; Tag != NULL; Tag=Next) {
+ AoEProcessReply ((PUCHAR) Tag->PacketData, Tag->PacketSize);
+ Next= Tag->Next;
+ ExFreePool (Tag->PacketData);
+ ExFreePool(Tag);
+ }
+ ReplyTagListHead = NULL;
+ ReplyTagListLast = NULL;
+ KeReleaseSpinLock(&ReplySpinLock, Irq2);
+
+
+ // process the Tag list
KeAcquireSpinLock(&SpinLock, &Irql);
if (TagList == NULL) {
KeReleaseSpinLock(&SpinLock, Irql);
@@ -676,6 +758,7 @@
Tag = TagList;
while (Tag != NULL) {
RequestTimeout = Tag->DeviceExtension->Disk.Timeout;
+ // if this is a new packet to send
if (Tag->Id == 0) {
if (OutstandingTags <= 64) {
//if (OutstandingTags <= 102400) {
@@ -687,20 +770,25 @@
KeQuerySystemTime(&Tag->FirstSendTime);
KeQuerySystemTime(&Tag->SendTime);
OutstandingTags++;
- Sends++;
+ Sends++;
} else {
Fails++;
Tag->Id = 0;
break;
}
}
+ // else this is a previously sent packet; see if we need to re-send it
} else {
KeQuerySystemTime(&CurrentTime);
+ // if we've waited longer than the 2*timeout, resend packet, and raise the timeout value a little
if (CurrentTime.QuadPart > (Tag->SendTime.QuadPart + (LONGLONG)(Tag->DeviceExtension->Disk.Timeout * 2))) {
if (ProtocolSend(Tag->DeviceExtension->Disk.ClientMac, Tag->DeviceExtension->Disk.ServerMac, (PUCHAR)Tag->PacketData, Tag->PacketSize, Tag)) {
KeQuerySystemTime(&Tag->SendTime);
+ // timeout += timeout/1000
Tag->DeviceExtension->Disk.Timeout += Tag->DeviceExtension->Disk.Timeout / 1000;
if (Tag->DeviceExtension->Disk.Timeout > 100000000) Tag->DeviceExtension->Disk.Timeout = 100000000;
+ // min timeout = 7 msec
+ //if (Tag->DeviceExtension->Disk.Timeout < 70000) Tag->DeviceExtension->Disk.Timeout = 70000;
Resends++;
} else {
ResendFails++;
diff -ru winaoe-0.97g/src/aoe.h winaoe-0.97g.deadlock_fix.1/src/aoe.h
--- winaoe-0.97g/src/aoe.h 2008-02-19 08:46:08.000000000 -0600
+++ winaoe-0.97g.deadlock_fix.1/src/aoe.h 2008-12-04 17:50:30.376059800 -0600
@@ -23,6 +23,7 @@
#include "portable.h"
#include "driver.h"
+
#define htons(x) (USHORT)((((x) << 8) & 0xff00) | (((x) >> 8) & 0xff))
#define ntohs(x) (USHORT)((((x) << 8) & 0xff00) | (((x) >> 8) & 0xff))
@@ -30,7 +31,8 @@
BOOLEAN STDCALL AoESearchDrive(IN PDEVICEEXTENSION DeviceExtension);
NTSTATUS STDCALL AoERequest(IN PDEVICEEXTENSION DeviceExtension, IN REQUESTMODE Mode, IN LONGLONG StartSector, IN ULONG SectorCount, IN PUCHAR Buffer, IN PIRP Irp);
-NTSTATUS STDCALL AoEReply(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN UINT DataSize);
+NTSTATUS STDCALL AoEReplyQueue(IN PUCHAR SourceMac, IN PUCHAR DestinationMac, IN PUCHAR Data, IN UINT DataSize);
+NTSTATUS STDCALL AoEProcessReply(IN PUCHAR Data, IN UINT DataSize);
VOID STDCALL AoEResetProbe();
#endif
diff -ru winaoe-0.97g/src/debug.c winaoe-0.97g.deadlock_fix.1/src/debug.c
--- winaoe-0.97g/src/debug.c 2008-02-19 08:46:08.000000000 -0600
+++ winaoe-0.97g.deadlock_fix.1/src/debug.c 2008-12-03 12:51:37.992681100 -0600
@@ -38,7 +38,7 @@
} IRPLIST, *PIRPLIST;
PIRPLIST IrpList = NULL;
-KSPIN_LOCK SpinLock;
+static KSPIN_LOCK SpinLock;
ULONG Number = 0;
extern int sprintf(char*, const char *, ...);
diff -ru winaoe-0.97g/src/protocol.c winaoe-0.97g.deadlock_fix.1/src/protocol.c
--- winaoe-0.97g/src/protocol.c 2008-02-19 08:46:08.000000000 -0600
+++ winaoe-0.97g.deadlock_fix.1/src/protocol.c 2008-12-04 17:55:02.874315800 -0600
@@ -71,7 +71,7 @@
} BINDINGCONTEXT, *PBINDINGCONTEXT;
KEVENT ProtocolStopEvent;
-KSPIN_LOCK SpinLock;
+static KSPIN_LOCK SpinLock;
PBINDINGCONTEXT BindingContextList = NULL;
NDIS_HANDLE ProtocolHandle = NULL;
@@ -259,7 +259,7 @@
} else {
DbgPrint("ProtocolTransferDataComplete Header (back) Buffer == NULL\n");
}
- if (Header != NULL && Data != NULL) AoEReply(Header->SourceMac, Header->DestinationMac, Data, DataSize);
+ if (Header != NULL && Data != NULL) AoEReplyQueue(Header->SourceMac, Header->DestinationMac, Data, DataSize);
if (Header != NULL) ExFreePool(Header);
if (Data != NULL) ExFreePool(Data);
NdisFreePacket(Packet);
@@ -303,7 +303,7 @@
if (ntohs(Header->Protocol) != AOEPROTOCOLID) return NDIS_STATUS_NOT_ACCEPTED;
if (LookaheadBufferSize == PacketSize) {
- AoEReply(Header->SourceMac, Header->DestinationMac, LookAheadBuffer, PacketSize);
+ AoEReplyQueue(Header->SourceMac, Header->DestinationMac, LookAheadBuffer, PacketSize);
return NDIS_STATUS_SUCCESS;
}