<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META content="text/html; charset=us-ascii" http-equiv=Content-Type>
<META name=GENERATOR content="MSHTML 8.00.6001.18876"></HEAD>
<BODY>
<DIV><FONT size=2 face=Arial>This patch fixes the race (and BSOD) within IRP 
cancellation mechanism.<BR>The original problem:<BR>1.Function 
al_dev_cancel_ioctl() called from the 2 places:<BR>directly from IBAL and by OS 
(as a callback)<BR>2. This is because I/O request can be cancelled both by 
user-level mechanism and <BR>by OS.<BR>3. Function al_dev_cancel_ioctl() calls 
to IoGetCurrentIrpStackLocation() in order <BR>to receive context and take a 
spinlock (p_context->cb_lock)<BR>4. But IoGetCurrentIrpStackLocation() as 
well further access to stack pointer<BR>should be protected !!! <BR>5. BSOD 
happened when context or IRP itself were already cancelled by concurrent 
<BR>calls to al_dev_cancel_ioctl()</FONT></DIV>
<DIV> </DIV>
<DIV><FONT size=2 face=Arial>Signed-off by: Alexander Naslednikov (xalex<SPAN 
class=805414207-08062010> at mellanox.co.il)</SPAN><BR>Index: 
B:/users/xalex/2_1_0/core/al/kernel/al_dev.c<BR>===================================================================<BR>--- 
B:/users/xalex/2_1_0/core/al/kernel/al_dev.c (revision 5929)<BR>+++ 
B:/users/xalex/2_1_0/core/al/kernel/al_dev.c (revision 5930)<BR>@@ -65,9 
+65,16 
@@<BR> __proxy_cancel_cblists(<BR>  IN  al_dev_open_context_t   *p_context 
);<BR> <BR>+CL_INLINE 
void<BR>+al_dev_cancel_ioctl_unlocked(<BR>+ IN     al_dev_open_context_t *p_context,<BR>+ IN 
OUT    cl_ioctl_handle_t  *p_ioctl 
);<BR> static 
void<BR> __construct_open_context(<BR>  IN  al_dev_open_context_t   *p_context 
)<BR>@@ -343,12 +350,19 @@<BR>  p_context->closing = 
TRUE;<BR> <BR>  /* Flush any pending IOCTLs in case user-mode 
threads died on us. */<BR>+ /* Protect IOCTL cancellation by spinlock to 
avoid race <BR>+ */<BR>+ <BR>+ cl_spinlock_acquire( 
&p_context->cb_lock );<BR>+ <BR>  if( 
p_context->h_cm_ioctl )<BR>-  al_dev_cancel_ioctl( 
p_context->h_cm_ioctl );<BR>- if( p_context->h_comp_ioctl 
)<BR>-  al_dev_cancel_ioctl( p_context->h_comp_ioctl 
);<BR>+  al_dev_cancel_ioctl_unlocked( p_context, 
&p_context->h_cm_ioctl );<BR>+ if( p_context->h_comp_ioctl ) 
<BR>+  al_dev_cancel_ioctl_unlocked( p_context, 
&p_context->h_comp_ioctl );<BR>  if( p_context->h_misc_ioctl 
)<BR>-  al_dev_cancel_ioctl( p_context->h_misc_ioctl 
);<BR>+  al_dev_cancel_ioctl_unlocked( p_context, 
&p_context->h_misc_ioctl );<BR>+ <BR>+ cl_spinlock_release ( 
&p_context->cb_lock );<BR> <BR>  while( 
p_context->ref_cnt )<BR>  {<BR>@@ -514,20 +528,31 
@@<BR> <BR>  /* Get the stack location. 
*/<BR>  p_io_stack = IoGetCurrentIrpStackLocation( h_ioctl 
);<BR>+ if (!p_io_stack) {<BR>+  AL_PRINT( TRACE_LEVEL_WARNING, 
AL_DBG_DEV, ("This IOCTL was previosly destroyed \n") 
);<BR>+  return;<BR>+ }<BR> <BR>  p_context = 
(al_dev_open_context_t 
*)p_io_stack->FileObject->FsContext;<BR>- ASSERT( p_context 
);<BR>-<BR>+ if (!p_context) {<BR>+  AL_PRINT( TRACE_LEVEL_ERROR, 
AL_DBG_ERROR, ("This IOCTL was previosly destroyed \n") 
);<BR>+  return;<BR>+ }<BR>  /* Clear the IOCTL. 
*/<BR>  cl_spinlock_acquire( &p_context->cb_lock 
);<BR>  switch( cl_ioctl_ctl_code( h_ioctl ) 
)<BR>  {<BR>  case 
UAL_GET_COMP_CB_INFO:<BR>   ph_ioctl = 
&p_context->h_comp_ioctl;<BR>+  ASSERT(ph_ioctl);<BR>   break;<BR>  case 
UAL_GET_MISC_CB_INFO:<BR>   ph_ioctl = 
&p_context->h_misc_ioctl;<BR>   break;<BR>+ case 
NULL:<BR>+  AL_PRINT( TRACE_LEVEL_WARNING, AL_DBG_DEV, ("This IOCTL 
was previosly destroyed \n") );<BR>+  cl_spinlock_release( 
&p_context->cb_lock 
);<BR>+  return;<BR>  default:<BR>   AL_PRINT( 
TRACE_LEVEL_ERROR, AL_DBG_ERROR, ("Invalid CB type\n") 
);<BR>   ph_ioctl = NULL;<BR>@@ -550,7 +575,33 
@@<BR>  AL_EXIT( AL_DBG_DEV );<BR> }<BR> <BR>+/*<BR>+ * 
Cancel any pending IOCTL calls for the specified type.<BR>+ * This routine is 
also called when closing the device.<BR>+ * The lock should already be taken by 
the caller<BR>+ */<BR>+CL_INLINE 
void<BR>+al_dev_cancel_ioctl_unlocked(<BR>+ IN     al_dev_open_context_t *p_context,<BR>+ IN 
OUT    cl_ioctl_handle_t  *p_ioctl 
)<BR>+{<BR>+ <BR>+ AL_ENTER( AL_DBG_DEV );<BR> <BR>+#pragma 
warning(push, 3)<BR>+ IoSetCancelRoutine( *p_ioctl, NULL );<BR>+#pragma 
warning(pop)<BR>+<BR>+ /* Complete the IOCTL. 
*/<BR>+ cl_ioctl_complete( *p_ioctl, CL_CANCELED, 0 
);<BR>+ proxy_context_deref( p_context );<BR>+ *p_ioctl = 
NULL;<BR>+<BR>+ AL_EXIT( AL_DBG_DEV 
);<BR>+}<BR>+<BR>+<BR>+<BR> void<BR> al_dev_cancel_io(<BR>  IN    DEVICE_OBJECT    *p_dev_obj,<BR>Index: 
B:/users/xalex/2_1_0/inc/kernel/complib/cl_ioctl_osd.h<BR>===================================================================<BR>--- 
B:/users/xalex/2_1_0/inc/kernel/complib/cl_ioctl_osd.h (revision 
5929)<BR>+++ 
B:/users/xalex/2_1_0/inc/kernel/complib/cl_ioctl_osd.h (revision 
5930)<BR>@@ -49,7 +49,9 @@<BR> #define IOCTL_CODE( type, cmd 
) \<BR>  CTL_CODE( type, (cmd & 0x0FFF), METHOD_BUFFERED, 
FILE_ANY_ACCESS)<BR> <BR>+#define BAD_IRP_STACK 
0<BR> <BR>+<BR> typedef 
PIRP cl_ioctl_handle_t;<BR> <BR> <BR>@@ -101,6 +103,10 
@@<BR>  IO_STACK_LOCATION *p_io_stack;<BR> <BR>  p_io_stack 
= IoGetCurrentIrpStackLocation( h_ioctl );<BR>+ if (!p_io_stack) 
{<BR>+  /* "This IOCTL was previosly destroyed ! 
*/<BR>+  return BAD_IRP_STACK ;<BR>+ }<BR>  return 
p_io_stack->Parameters.DeviceIoControl.IoControlCode;<BR> }<BR> <BR></FONT></DIV></BODY></HTML>