Saturday, March 27, 2010

Understanding oplock and avoid sharing violation

Opportunistic locking (oplock) is a cache coherence protocol. General relations between Local FSD(file system driver), Server FSD, user and filter driver can be described in the picture below :oplock
In this sharing we are going to disscus the problem that oplock wants to solve, FILE_COMPLETE_IF_OPLOCKED flag, and different types of oplock.

Filter oplock was introduced on Windows 2000, it was design to solve sharing violatoin issue. For example, we have a kernel driver that will access \systemroot\OplockTest with only share access FILE_SHARE_READ. Now if we use notepad to modify the file at the same time, a sharing violation will occure :
ShareViolation
With filter oplock, kernel driver will be notified if a sharing violation is happenning. After driver acknowledge oplock break, notepad will be able to modify the file without sharing violation. User is totally unware all of these events.
Acknowledge Oplock Break
Although we give a kernel mode example here, we can use filter oplock in user mode. Simply replace the function with Win32 API and use DeviceIoCtl to send FSCTL_REQUEST_FILTER_OPLOCK request.
status = ZwCreateEvent(&EventHandle,
                       EVENT_ALL_ACCESS,
                       0,
                       NotificationEvent,FALSE);
  if (NT_SUCCESS(status))
  {
      
      InitializeObjectAttributes(&oa,
      MagicFilePath,
      OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
      0,0);
      
      //notice here, AP will get sharing violation 
      //if they try to modify 
      //"\\SystemRoot\\OplockTest", 
      //with oplock we can avoid sharing violation.   
      status = ZwCreateFile(&MagicFileHandle,
          GENERIC_READ,
          &oa,
          &iosb,
          0,
          0,
          FILE_SHARE_READ,  
          FILE_OPEN_IF,
          FILE_NON_DIRECTORY_FILE,0,0);
 
      if (NT_SUCCESS(status))
      {
          status = ZwFsControlFile(MagicFileHandle,
                          EventHandle,
                          NULL,
                          NULL,
                          &iosb,
                          FSCTL_REQUEST_FILTER_OPLOCK,
                          0,
                          0,
                          0,
                          0);
          //
          //STATUS_PENDING means we got oplock, 
          //
          if (status == STATUS_PENDING)
          {
          //
          //Event will be signalled when the sharing 
          //violation happen. Polling the oplock event to 
          //see if the oplock has broken. You can 
          //wait for the event in a different thread.
          //
              LARGE_INTEGER  Timeout;
              Timeout.QuadPart = (LONGLONG)-10000000;
              while(TRUE)
              {
 
                  status = ZwWaitForSingleObject(
                                          EventHandle,
                                          false,
                                          &Timeout);
                  if (!NT_SUCCESS(status))
                  {
                      //
                      //error happened
                      //
                      goto CleanupAndExit;
                  } 
                  else if(status == STATUS_TIMEOUT)
                  {
                      //
                      //  Perform major task here.  
                      //
 
                      KdPrint(("access file...\n",
                               status));
                      continue;
                  }
                  else
                  {
                      //
                      //Some operation is waiting 
                      //quickly finish up and get out. 
                      //
              KdPrint(("ackonwledge oplock break \n",
              status));
                      goto CleanupAndExit;
                  }
              }
          }
      }        
  }
  
eanupAndExit:
  
  if (MagicFileHandle)
  {
  //
  //close handle will relinquishes oplock (acknowledge 
  //the oplock break) Until acknowledge oplock break 
  //AP thread will <<<<<HANG>>>>> if AP doesn't specify 
  //FILE_COMPLETE_IF_OPLOCKED in CreateFile
  //
      ZwClose(MagicFileHandle);
      MagicFileHandle = 0;
  }

1 comment:

  1. Your website is very beautiful or Articles. I love it thank you for sharing for everyone. File System Filter Driver Programming

    ReplyDelete