mirror of
https://github.com/openvswitch/ovs
synced 2025-10-21 14:49:41 +00:00
datapath-windows: Solved BSOD when uninstalling the driver (race condition)
The BSOD occurred because the FilterAttach routine released the switch context, while there were IRPs in processing. The solution was to add a reference count to prevent premature deallocation of the global switch context structure, gOvsSwitchContext. Signed-off-by: Sorin Vinturis <svinturis@cloudbasesolutions.com> Reported-by: Alin Gabriel Serdean <aserdean@cloudbasesolutions.com> Reported-at: https://github.com/openvswitch/ovs-issues/issues/58 Acked-by: Eitan Eliahu <eliahue@vmware.com> Signed-off-by: Gurucharan Shetty <gshetty@nicira.com>
This commit is contained in:
committed by
Gurucharan Shetty
parent
f293a803d9
commit
6c4e7adb08
@@ -717,8 +717,13 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject,
|
|||||||
|
|
||||||
/* Check if the extension is enabled. */
|
/* Check if the extension is enabled. */
|
||||||
if (NULL == gOvsSwitchContext) {
|
if (NULL == gOvsSwitchContext) {
|
||||||
status = STATUS_DEVICE_NOT_READY;
|
status = STATUS_NOT_FOUND;
|
||||||
goto done;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OvsAcquireSwitchContext()) {
|
||||||
|
status = STATUS_NOT_FOUND;
|
||||||
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Concurrent netlink operations are not supported. */
|
/* Concurrent netlink operations are not supported. */
|
||||||
@@ -908,6 +913,9 @@ OvsDeviceControl(PDEVICE_OBJECT deviceObject,
|
|||||||
status = InvokeNetlinkCmdHandler(&usrParamsCtx, nlFamilyOps, &replyLen);
|
status = InvokeNetlinkCmdHandler(&usrParamsCtx, nlFamilyOps, &replyLen);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
OvsReleaseSwitchContext(gOvsSwitchContext);
|
||||||
|
|
||||||
|
exit:
|
||||||
KeMemoryBarrier();
|
KeMemoryBarrier();
|
||||||
instance->inUse = 0;
|
instance->inUse = 0;
|
||||||
|
|
||||||
|
@@ -42,6 +42,12 @@ extern PNDIS_SPIN_LOCK gOvsCtrlLock;
|
|||||||
extern NDIS_HANDLE gOvsExtDriverHandle;
|
extern NDIS_HANDLE gOvsExtDriverHandle;
|
||||||
extern NDIS_HANDLE gOvsExtDriverObject;
|
extern NDIS_HANDLE gOvsExtDriverObject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reference count used to prevent premature deallocation of the global switch
|
||||||
|
* context structure, gOvsSwitchContext.
|
||||||
|
*/
|
||||||
|
volatile LONG gOvsSwitchContextRefCount = 1;
|
||||||
|
|
||||||
static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
|
static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle,
|
||||||
POVS_SWITCH_CONTEXT *switchContextOut);
|
POVS_SWITCH_CONTEXT *switchContextOut);
|
||||||
static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
|
static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext);
|
||||||
@@ -423,6 +429,7 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
|||||||
switchContext->isActivateFailed = FALSE;
|
switchContext->isActivateFailed = FALSE;
|
||||||
switchContext->dpNo = OVS_DP_NUMBER;
|
switchContext->dpNo = OVS_DP_NUMBER;
|
||||||
ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
|
ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000;
|
||||||
|
|
||||||
OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
|
OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p",
|
||||||
switchContext);
|
switchContext);
|
||||||
return NDIS_STATUS_SUCCESS;
|
return NDIS_STATUS_SUCCESS;
|
||||||
@@ -430,6 +437,12 @@ OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
|||||||
|
|
||||||
static VOID
|
static VOID
|
||||||
OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
||||||
|
{
|
||||||
|
OvsReleaseSwitchContext(switchContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
||||||
{
|
{
|
||||||
OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext);
|
OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext);
|
||||||
|
|
||||||
@@ -457,6 +470,49 @@ OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
|||||||
OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
|
OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID
|
||||||
|
OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext)
|
||||||
|
{
|
||||||
|
LONG ref = 0;
|
||||||
|
LONG newRef = 0;
|
||||||
|
LONG icxRef = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ref = gOvsSwitchContextRefCount;
|
||||||
|
newRef = (0 == ref) ? 0 : ref - 1;
|
||||||
|
icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
|
||||||
|
newRef,
|
||||||
|
ref);
|
||||||
|
} while (icxRef != ref);
|
||||||
|
|
||||||
|
if (ref == 1) {
|
||||||
|
OvsDeleteSwitchContext(switchContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
OvsAcquireSwitchContext(VOID)
|
||||||
|
{
|
||||||
|
LONG ref = 0;
|
||||||
|
LONG newRef = 0;
|
||||||
|
LONG icxRef = 0;
|
||||||
|
BOOLEAN ret = FALSE;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ref = gOvsSwitchContextRefCount;
|
||||||
|
newRef = (0 == ref) ? 0 : ref + 1;
|
||||||
|
icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount,
|
||||||
|
newRef,
|
||||||
|
ref);
|
||||||
|
} while (icxRef != ref);
|
||||||
|
|
||||||
|
if (ref != 0) {
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
* This function activates the switch by initializing it with all the runtime
|
* This function activates the switch by initializing it with all the runtime
|
||||||
|
@@ -202,7 +202,6 @@ OvsAcquireDatapathWrite(OVS_DATAPATH *datapath,
|
|||||||
dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);
|
dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static __inline VOID
|
static __inline VOID
|
||||||
OvsReleaseDatapath(OVS_DATAPATH *datapath,
|
OvsReleaseDatapath(OVS_DATAPATH *datapath,
|
||||||
LOCK_STATE_EX *lockState)
|
LOCK_STATE_EX *lockState)
|
||||||
@@ -211,6 +210,11 @@ OvsReleaseDatapath(OVS_DATAPATH *datapath,
|
|||||||
NdisReleaseRWLock(datapath->lock, lockState);
|
NdisReleaseRWLock(datapath->lock, lockState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
OvsAcquireSwitchContext(VOID);
|
||||||
|
|
||||||
|
VOID
|
||||||
|
OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext);
|
||||||
|
|
||||||
PVOID OvsGetExternalVport();
|
PVOID OvsGetExternalVport();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user