From: tzachid Date: Mon, 21 Nov 2005 12:00:33 +0000 (+0000) Subject: Kernel mode socket is being created based on the user code. (Rev 70) X-Git-Url: https://openfabrics.org/gitweb/?a=commitdiff_plain;h=b61d2cb677552bc1c971bbfc722bbab9d892c9fe;p=~shefty%2Frdma-win.git Kernel mode socket is being created based on the user code. (Rev 70) git-svn-id: svn://openib.tc.cornell.edu/gen1@159 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86 --- diff --git a/trunk/ulp/sdp/include/RefCount.h b/trunk/ulp/sdp/include/RefCount.h new file mode 100644 index 00000000..395f7374 --- /dev/null +++ b/trunk/ulp/sdp/include/RefCount.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2005 Mellanox. All rights reserved. + */ + +/* + This file includes two classes: One is used as a full refcount implmentation. + + The second class is only the ref count interface. It should be used by abstract + classes. + +*/ + + +class RefCountImpl { +public : + + RefCountImpl() { + m_ref = 1; + } + + ULONG AddRef(void) { + ASSERT(m_ref > 0); + LONG result = InterlockedIncrement(&m_ref); + return (ULONG)result; + } + + ULONG Release(void) { + ASSERT(m_ref > 0); + LONG result = InterlockedDecrement(&m_ref); + if ( result == 0 ) { + delete this; + } + return (ULONG)result; + } + + virtual ~RefCountImpl() {}; +private : + long m_ref; +}; diff --git a/trunk/ulp/sdp/include/SdpLib.h b/trunk/ulp/sdp/include/SdpLib.h deleted file mode 100644 index 59378d30..00000000 --- a/trunk/ulp/sdp/include/SdpLib.h +++ /dev/null @@ -1,7 +0,0 @@ -/* Copyright mellanox 2005 */ - - - -#define SDP_DEVICE_NAME L"\\Device\\SdpDriver" -#define SDP_LINK_NAME L"\\DosDevices\\Global\\SdpDriver" - diff --git a/trunk/ulp/sdp/include/SdpShared.h b/trunk/ulp/sdp/include/SdpShared.h index 15615b38..f470f36c 100644 --- a/trunk/ulp/sdp/include/SdpShared.h +++ b/trunk/ulp/sdp/include/SdpShared.h @@ -1,5 +1,8 @@ /* Copyright mellanox 2005 */ +#ifndef _SDP_SHARED_H +#define _SDP_SHARED_H + #define ProviderName L"SdpDriver" #define SDP_DEVICE_NAME L"\\Device\\"ProviderName @@ -30,3 +33,4 @@ struct WspConnectOut { int Errno; }; +#endif //_SDP_SHARED_H \ No newline at end of file diff --git a/trunk/ulp/sdp/kernel/Precompile.h b/trunk/ulp/sdp/kernel/Precompile.h new file mode 100644 index 00000000..e936c55d --- /dev/null +++ b/trunk/ulp/sdp/kernel/Precompile.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2005 Mellanox. All rights reserved. + */ + + +#ifndef _SDP_PRECOMP_ +#define _SDP_PRECOMP_ +extern "C" { +#include +} + +// External classes declrations +class SdpSocket; + + +#include "SdpTrace.h" +#include "RefCount.h" +#include "sdpdriver.h" +#include "SdpShared.h" +#include "SdpUserFile.h" +#include "SdpGenUtils.h" +#include "SdpSocket.h" + + +#endif // _SDP_PRECOMP_ diff --git a/trunk/ulp/sdp/kernel/SOURCES b/trunk/ulp/sdp/kernel/SOURCES index 4f8ce750..667b1fb4 100644 --- a/trunk/ulp/sdp/kernel/SOURCES +++ b/trunk/ulp/sdp/kernel/SOURCES @@ -2,7 +2,10 @@ TARGETNAME=Sdp TARGETPATH=..\..\..\bin\kernel\obj$(BUILD_ALT_DIR) TARGETTYPE=DRIVER -SOURCES= SdpDriver.cpp \ +SOURCES= SdpDriver.cpp \ + SdpUserFile.cpp \ + SdpGenUtils.cpp \ + SdpSocket.cpp INCLUDES=..\include;..\..\..\inc;..\..\..\inc\kernel; diff --git a/trunk/ulp/sdp/kernel/SdpDriver.cpp b/trunk/ulp/sdp/kernel/SdpDriver.cpp index f391c813..a7d1d0f9 100644 --- a/trunk/ulp/sdp/kernel/SdpDriver.cpp +++ b/trunk/ulp/sdp/kernel/SdpDriver.cpp @@ -1,11 +1,7 @@ /* Copyright mellanox */ -extern "C" { -#include -} -#include "sdpdriver.h" -#include "SdpShared.h" -#include "SdpTrace.h" + +#include "Precompile.h" SdpDriver *g_pSdpDriver = NULL; @@ -117,6 +113,8 @@ NTSTATUS SdpDriver::Dispatch( PVOID pInputBuffer = NULL; PVOID pOutputBuffer = NULL; ULONG OutputDataSize = 0; + int Method; + SdpUserFile *pSdpUserFile = NULL; @@ -127,6 +125,23 @@ NTSTATUS SdpDriver::Dispatch( case IRP_MJ_CREATE: { SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CREATE pIrpSp->FileObject = 0x%x\n", pIrpSp->FileObject )); + pSdpUserFile = new SdpUserFile; + if (pSdpUserFile == NULL) { + rc = STATUS_NO_MEMORY; + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpUserFile failed rc = 0x%x\n", rc )); + goto Cleanup; + } + rc = pSdpUserFile->Init(); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->Init failed rc = 0x%x\n", rc )); + goto Cleanup; + } + // Everything went well, and windows is still using this object. + // As a result we want to make sure that this object will not be + // freed + pIrpSp->FileObject->FsContext = pSdpUserFile; + pSdpUserFile = NULL; + break; } @@ -134,6 +149,14 @@ NTSTATUS SdpDriver::Dispatch( // All IRPs that were associated with this device should be cleaned SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CLEANUP pIrpSp->FileObject = 0x%x\n", pIrpSp->FileObject )); + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + // The object is being shutdown, and it's cleaning should + // be started + pSdpUserFile->Shutdown(); + // The file object is still holding referance to the object, + // so we set the pointer to NULL + pSdpUserFile = NULL; + break; } @@ -144,7 +167,9 @@ NTSTATUS SdpDriver::Dispatch( //released. All outstanding I/O requests have been completed or canceled. SDP_PRINT(SDP_TRACE, SDP_DRIVER, ("IRP_MJ_CLOSE pIrpSp->FileObject = 0x%x\n", pIrpSp->FileObject )); - + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + // Nothing to do, the referance count will be removed once + // we leave the function break; } case IRP_MJ_DEVICE_CONTROL: { @@ -158,12 +183,72 @@ NTSTATUS SdpDriver::Dispatch( } // Handle the mode of the request and get it's params + Method = pIrpSp->Parameters.DeviceIoControl.IoControlCode & 0x3; + switch (Method) { + case METHOD_BUFFERED: { + pInputBuffer = pOutputBuffer = + pIrp->AssociatedIrp.SystemBuffer; + break; + } + + case METHOD_IN_DIRECT: + case METHOD_OUT_DIRECT: { + pInputBuffer = pIrp->AssociatedIrp.SystemBuffer; + if (pIrp->MdlAddress && + pIrpSp->Parameters.DeviceIoControl.OutputBufferLength) { + if (NULL == (pOutputBuffer = + MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, LowPagePriority))) { + rc = STATUS_INSUFFICIENT_RESOURCES; + goto Cleanup; + } + } + break; + } + + case METHOD_NEITHER: { + pInputBuffer = + pIrpSp->Parameters.DeviceIoControl.Type3InputBuffer; + pOutputBuffer = pIrp->UserBuffer; + break; + } + } + + // If 'METHOD_NEITHER' probe the buffer + if (METHOD_NEITHER == Method) { + + __try { + + if (pInputBuffer) { + ProbeForRead( + pInputBuffer, + pIrpSp->Parameters.DeviceIoControl.InputBufferLength, + sizeof(UCHAR) + ); + } + if (pOutputBuffer) { + ProbeForWrite( + pOutputBuffer, + pIrpSp->Parameters.DeviceIoControl.OutputBufferLength, + sizeof(UCHAR) + ); + } + + } __except(EXCEPTION_EXECUTE_HANDLER) { + rc = STATUS_ACCESS_VIOLATION; + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("IRP_MJ_DEVICE_CONTROL Access " + "violition when trying to read/write data\n" )); + + ASSERT(FALSE); + goto Cleanup; + } + } // Handle the request itself rc = g_pSdpDriver->DispatchDeviceIoControl( pIrpSp->FileObject, pIrp, + pIrpSp, pInputBuffer, pIrpSp->Parameters.DeviceIoControl.InputBufferLength, pOutputBuffer, @@ -177,33 +262,71 @@ NTSTATUS SdpDriver::Dispatch( } } +Cleanup: if (rc != STATUS_PENDING) { pIrp->IoStatus.Status = rc; pIrp->IoStatus.Information = OutputDataSize; IoCompleteRequest(pIrp, IO_NO_INCREMENT); } + if (pSdpUserFile) { + pSdpUserFile->Release(); + } return rc; } +// A macro to verify input/output params length +#define VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, InStruct, OutStruct) \ +if ((InputBufferLength < sizeof (InStruct)) || \ + (OutputBufferLength < sizeof (OutStruct))) { \ + SDP_PRINT(SDP_ERR, SDP_DRIVER, \ + ("DispatchDeviceIoControl bad buffer sizes\n" )); \ + ASSERT(FALSE); \ + rc = STATUS_ACCESS_VIOLATION; \ + goto Cleanup; \ +} + + NTSTATUS SdpDriver::DispatchDeviceIoControl( IN PFILE_OBJECT pDeviceObject, IN PIRP pIrp, - PVOID pInputBuffer, - ULONG InputBufferLength, - PVOID pOutputBuffer, - ULONG OutputBufferLength, - ULONG IoControlCode, - ULONG &OutputDataSize + IN PIO_STACK_LOCATION pIrpSp, + IN PVOID pInputBuffer, + IN ULONG InputBufferLength, + IN PVOID pOutputBuffer, + IN ULONG OutputBufferLength, + IN ULONG IoControlCode, + OUT ULONG &OutputDataSize ) { NTSTATUS rc = STATUS_SUCCESS; + SdpUserFile *pSdpUserFile = NULL; + SdpSocket *pSdpSocket = NULL; + switch (IoControlCode) { case IOCTL_WSP_SOCKET : - SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_SOCKET recieved\n" )); - + SDP_PRINT(SDP_DEBUG, SDP_DRIVER, ("DispatchDeviceIoControl IOCTL_WSP_SOCKET recieved\n" )); + VERIFY_BUFFERS(InputBufferLength, OutputBufferLength, WspSocketIn, WspSocketOut); + pSdpUserFile = (SdpUserFile *)pIrpSp->FileObject->FsContext; + pSdpSocket = new SdpSocket; + if (pSdpSocket == NULL) { + rc = STATUS_NO_MEMORY; + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("new SdpSocket failed rc = 0x%x\n", rc )); + goto Cleanup; + } + rc = pSdpSocket->Init((WspSocketIn *)pInputBuffer, (WspSocketOut *)pOutputBuffer); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpSocket->Init failed rc = 0x%x\n", rc )); + goto Cleanup; + } + rc = pSdpUserFile->AddSocket(pSdpSocket); + if (!NT_SUCCESS(rc)) { + SDP_PRINT(SDP_ERR, SDP_DRIVER, ("pSdpUserFile->AddSocket failed rc = 0x%x\n", rc )); + goto Cleanup; + } break; + default: // This is an unrecgnized IOCTL ASSERT(FALSE); @@ -214,6 +337,9 @@ NTSTATUS SdpDriver::DispatchDeviceIoControl( } Cleanup: + if (pSdpSocket) { + pSdpSocket->Release(); + } return rc; } diff --git a/trunk/ulp/sdp/kernel/SdpDriver.h b/trunk/ulp/sdp/kernel/SdpDriver.h index 3ee01caf..d820c7ce 100644 --- a/trunk/ulp/sdp/kernel/SdpDriver.h +++ b/trunk/ulp/sdp/kernel/SdpDriver.h @@ -23,12 +23,13 @@ public: NTSTATUS DispatchDeviceIoControl( IN PFILE_OBJECT pDeviceObject, IN PIRP pIrp, - PVOID pInputBuffer, - ULONG InputBufferLength, - PVOID pOutputBuffer, - ULONG OutputBufferLength, - ULONG IoControlCode, - ULONG &OutputDataSize + IN PIO_STACK_LOCATION pIrpSp, + IN PVOID pInputBuffer, + IN ULONG InputBufferLength, + IN PVOID pOutputBuffer, + IN ULONG OutputBufferLength, + IN ULONG IoControlCode, + OUT ULONG &OutputDataSize ); diff --git a/trunk/ulp/sdp/kernel/SdpGenUtils.cpp b/trunk/ulp/sdp/kernel/SdpGenUtils.cpp new file mode 100644 index 00000000..1c7e08ef --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpGenUtils.cpp @@ -0,0 +1,14 @@ +/* Copyright mellanox */ + +#include "Precompile.h" + + + +void* __cdecl operator new(size_t n ) throw() { + return ExAllocatePoolWithTag(NonPagedPool , n, GLOBAL_ALLOCATION_TAG); +} + +void __cdecl operator delete(void* p) { + ExFreePoolWithTag(p, GLOBAL_ALLOCATION_TAG); +} + diff --git a/trunk/ulp/sdp/kernel/SdpGenUtils.h b/trunk/ulp/sdp/kernel/SdpGenUtils.h new file mode 100644 index 00000000..6ca20127 --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpGenUtils.h @@ -0,0 +1,42 @@ +/* Copyright mellanox */ +#ifndef _SDP_GEN_UTILS_H +#define _SDP_GEN_UTILS_H + + + +#define GLOBAL_ALLOCATION_TAG ' pdS' + + +class CSpinLockWrapper { + KSPIN_LOCK &m_SpinLock; + KIRQL m_OldIrql; + +public: + + CSpinLockWrapper (KSPIN_LOCK &SpinLock) : m_SpinLock(SpinLock){ + // Spinlock must already be initialized +#if DBG + m_OldIrql = 0xff; +#endif + } + + void Lock() { + ASSERT(m_OldIrql == 0xff); + KeAcquireSpinLock(&m_SpinLock, &m_OldIrql); + } + + void Unlock() { + ASSERT(m_OldIrql != 0xff); + KeReleaseSpinLock(&m_SpinLock, m_OldIrql); +#if DBG + m_OldIrql = 0xff; +#endif + } + + ~CSpinLockWrapper() { + ASSERT(m_OldIrql == 0xff); + } + +}; + +#endif // _SDP_GEN_UTILS_H diff --git a/trunk/ulp/sdp/kernel/SdpSocket.cpp b/trunk/ulp/sdp/kernel/SdpSocket.cpp new file mode 100644 index 00000000..3b9aeb76 --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpSocket.cpp @@ -0,0 +1,25 @@ +/* Copyright mellanox */ + + +#include "Precompile.h" + +NTSTATUS SdpSocket::Init( + WspSocketIn *pSocketInParam, + WspSocketOut *pSocketOutParam) +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Init this = 0x%x\n", this)); + + m_CreationFlags = pSocketInParam->dwFlags; + pSocketOutParam->Errno = 0;// No error + pSocketOutParam->pSocket = this; // give the user a handle to the socket + + return STATUS_SUCCESS; +} + +VOID SdpSocket::Shutdown() +{ + SDP_PRINT(SDP_TRACE, SDP_SOCKET, ("SdpSocket::Shutdown called this = 0x%x\n", this)); + + +} + diff --git a/trunk/ulp/sdp/kernel/SdpSocket.h b/trunk/ulp/sdp/kernel/SdpSocket.h new file mode 100644 index 00000000..876b1070 --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpSocket.h @@ -0,0 +1,34 @@ +/* Copyright mellanox */ + +/* +This class is being used to truck all the user objects that are being +created per user mode dll (each dll opens a handle to the driver once) + +It keeps a list of all the objects so we know when to remove them. + +*/ + +#ifndef _SDP_SOCKET_H +#define _SDP_SOCKET_H + + +class SdpSocket : public RefCountImpl { +private: + // This flags are being Initiated when the socket is being + // created + ULONG m_CreationFlags; + + +public: + NTSTATUS Init( + WspSocketIn *pSocketInParam, + WspSocketOut *pSocketOutParam); + + VOID Shutdown(); + + + LIST_ENTRY m_UserFileList; +}; + +#endif // _SDP_SOCKET_H + diff --git a/trunk/ulp/sdp/kernel/SdpTrace.h b/trunk/ulp/sdp/kernel/SdpTrace.h index c07318ef..556be794 100644 --- a/trunk/ulp/sdp/kernel/SdpTrace.h +++ b/trunk/ulp/sdp/kernel/SdpTrace.h @@ -10,14 +10,17 @@ #define SDP_ERR 0x00000010 // Debug toppics -#define SDP_API 0x000001 -#define SDP_CONNECT 0x000002 +#define SDP_API 0x000001 +#define SDP_CONNECT 0x000002 #define SDP_DRIVER 0x000004 +#define SDP_SOCKET 0x000008 +// BUGBUG: CONVERT TO A FUNCTION -BOOLEAN CheckCondition(int sev, int top, char *file, int line) { - return TRUE; -} +//BOOLEAN CheckCondition(int sev, int top, char *file, int line) { +// return TRUE; +//} +#define CheckCondition(a,b,c,d) TRUE #define SDP_PRINT(sev, toppic ,var_args) \ if (CheckCondition(sev, toppic ,__FILE__, __LINE__) != FALSE) \ diff --git a/trunk/ulp/sdp/kernel/SdpUserFile.cpp b/trunk/ulp/sdp/kernel/SdpUserFile.cpp new file mode 100644 index 00000000..ebe0b71b --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpUserFile.cpp @@ -0,0 +1,56 @@ +/* Copyright mellanox */ + +#include "Precompile.h" + +NTSTATUS SdpUserFile::Init() +{ + KeInitializeSpinLock(&m_Lock); + InitializeListHead(&m_SocketsList); + m_shutdown = false; + + return STATUS_SUCCESS; +} + +void SdpUserFile::Shutdown() +{ + // go over the entire list, and release it's objects + CSpinLockWrapper Lock(m_Lock); + Lock.Lock(); + if (m_shutdown) { + // Nothing to do + Lock.Unlock(); + return; + } + while (!IsListEmpty(&m_SocketsList)) { + PLIST_ENTRY pTemp = RemoveHeadList(&m_SocketsList); + SdpSocket *pSdpSocket = CONTAINING_RECORD(pTemp, SdpSocket, m_UserFileList ); + + // Don't call release with the lock being hold + Lock.Unlock(); + pSdpSocket->Shutdown(); + pSdpSocket->Release(); + // It seems that we shoule be protected by the m_shutdown + // flag, but will take the lock just in case + Lock.Lock(); + + } + Lock.Unlock(); +} + +NTSTATUS SdpUserFile::AddSocket(SdpSocket *pSdpSocket) +{ + CSpinLockWrapper Lock(m_Lock); + Lock.Lock(); + if (m_shutdown) { + Lock.Unlock(); + return STATUS_FILE_CLOSED; + } + InsertHeadList(&m_SocketsList, &pSdpSocket->m_UserFileList); + pSdpSocket->AddRef(); + + Lock.Unlock(); + return STATUS_SUCCESS; + +} + + diff --git a/trunk/ulp/sdp/kernel/SdpUserFile.h b/trunk/ulp/sdp/kernel/SdpUserFile.h new file mode 100644 index 00000000..92ded631 --- /dev/null +++ b/trunk/ulp/sdp/kernel/SdpUserFile.h @@ -0,0 +1,34 @@ +/* Copyright mellanox */ + +/* +This class is being used to truck all the user objects that are being +created per user mode dll (each dll opens a handle to the driver once) + +It keeps a list of all the objects so we know when to remove them. + +*/ + +#ifndef _SDP_USER_FILE_H +#define _SDP_USER_FILE_H + + + +class SdpUserFile : public RefCountImpl { +private: + KSPIN_LOCK m_Lock; + bool m_shutdown; + +// BUGBUG: Use something more effiecent for this storage + LIST_ENTRY m_SocketsList; + +public: + + NTSTATUS Init(); + VOID Shutdown(); + + NTSTATUS AddSocket(SdpSocket *pSdpSocket); + +}; + +#endif //_SDP_USER_FILE_H +