Oplock 부여

Oplock은 FSCTL을 통해 요청됩니다. 다음 목록에서는 다양한 oplock 유형(사용자 모드 애플리케이션 및 커널 모드 드라이버에서 발급할 수 있는)에 대한 FSCTL을 보여 줍니다.

  • FSCTL_REQUEST_OPLOCK_LEVEL_1
  • FSCTL_REQUEST_OPLOCK_LEVEL_2
  • FSCTL_REQUEST_BATCH_OPLOCK
  • FSCTL_REQUEST_FILTER_OPLOCK
  • FSCTL_REQUEST_OPLOCK

목록의 처음 4개 FSCTL은 레거시 oplock을 요청하는 데 사용됩니다. 마지막 FSCTL은 deviceIoControllpInBuffer 매개 변수로 전달된 REQUEST_OPLOCK_INPUT_BUFFER 구조체의 Flags 멤버에 지정된 REQUEST_OPLOCK_INPUT_FLAG_REQUEST 플래그를 사용하여 Windows 7개의 oplock을 요청하는 데 사용됩니다. 비슷한 방식으로 ZwFsControlFile을 사용하여 커널 모드에서 Windows 7개의 oplock을 요청할 수 있습니다. 파일 시스템 미니 필터는 FltAllocateCallbackDataFltPerformAsynchronousIo를 사용하여 Windows 7 oplock을 요청해야 합니다. 필요한 4개의 Windows 7개의 oplock 중 하나 이상의 플래그가 OPLOCK_LEVEL_CACHE_READ, OPLOCK_LEVEL_CACHE_HANDLE 또는 OPLOCK_LEVEL_CACHE_WRITE REQUEST_OPLOCK_INPUT_BUFFER 구조체의 RequestedOplockLevel 멤버에 설정됩니다. 자세한 내용은 FSCTL_REQUEST_OPLOCK 참조하세요.

oplock에 대한 요청이 수행되고 oplock을 부여할 수 있는 경우 파일 시스템은 STATUS_PENDING 반환합니다(이 때문에 동기 I/O에 대해 oplock이 부여되지 않음). FSCTL IRP는 oplock이 손상될 때까지 완료되지 않습니다. oplock을 부여할 수 없는 경우 적절한 오류 코드가 반환됩니다. 가장 일반적으로 반환되는 오류 코드는 STATUS_OPLOCK_NOT_GRANTED 및 STATUS_INVALID_PARAMETER(및 이와 동등한 사용자 모드 아날로그)입니다.

앞에서 설명한 것처럼 Filter oplock을 사용하면 다른 애플리케이션/클라이언트가 동일한 스트림에 액세스하려고 할 때 애플리케이션이 "백아웃"할 수 있습니다. 이 메커니즘을 사용하면 스트림을 열려고 할 때 다른 스트림 접근자가 공유 위반을 수신하지 않고도 애플리케이션이 스트림에 액세스할 수 있습니다. 위반을 공유하지 않도록 하려면 특수한 3단계 프로시저를 사용하여 필터 oplock(FSCTL_REQUEST_FILTER_OPLOCK)을 요청해야 합니다.

  1. FILE_READ_ATTRIBUTES 필요한 액세스 권한과 공유 모드의 FILE_SHARE_READ | 파일을 엽니다. FILE_SHARE_WRITE | FILE_SHARE_DELETE.

  2. 1단계에서 핸들에 필터 oplock을 요청합니다.

  3. 읽기 액세스를 위해 파일을 다시 엽니다.

1단계에서 열린 핸들은 데이터 액세스(FILE_READ_DATA)가 아닌 특성 액세스(FILE_READ_ATTRIBUTES)에 대해서만 열려 있으므로 다른 애플리케이션에서 공유 위반을 수신하지 않습니다. 이 핸들은 필터 oplock을 요청하는 데 적합하지만 데이터 스트림에서 실제 I/O를 수행하는 데는 적합하지 않습니다. 3단계에서 열린 핸들을 사용하면 oplock의 소유자가 스트림에서 I/O를 수행할 수 있으며, 2단계에서 부여된 oplock을 사용하면 oplock 소유자가 스트림에 액세스하려는 다른 애플리케이션에 대한 공유 위반을 일으키지 않고도 "방해가 될 수 있습니다".

NTFS 파일 시스템은 FILE_RESERVE_OPFILTER 만들기 옵션 플래그를 통해 이 절차에 대한 최적화를 제공합니다. 이전 절차의 1단계에서 이 플래그를 지정하면 파일 시스템에서 2단계가 실패할 것이라고 판단할 수 있는 경우 파일 시스템에서 STATUS_OPLOCK_NOT_GRANTED 사용하여 만들기 요청에 실패할 수 있습니다. 1단계가 성공하면 만들기 요청에 대해 FILE_RESERVE_OPFILTER 지정되었더라도 2단계가 성공한다는 보장은 없습니다.

다음 표에서는 oplock을 부여하는 데 필요한 조건을 식별합니다.

요청 유형 조건

수준 1

Assert

Batch

다음 조건이 모두 충족되는 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
    • 디렉터리인 경우 STATUS_INVALID_PARAMETER 반환됩니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열린 경우 STATUS_OPLOCK_NOT_GRANTED 반환됩니다(동기 I/O 요청에 대해 oplock이 부여되지 않음).
  • 파일의 스트림에는 TxF 트랜잭션이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 다른 열기가 없습니다(동일한 스레드에서도).
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 수준 2: 원래 수준 2 요청이 FILE_OPLOCK_BROKEN_TO_NONE 손상되었습니다. 그런 다음 요청된 배타적 oplock이 부여됩니다.

  • 수준 1, 일괄 처리, 필터, 읽기, 읽기 핸들, 읽기-쓰기 또는 읽기-쓰기 핸들: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

수준 2

다음 조건이 모두 충족되는 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
    • 디렉터리인 경우 STATUS_INVALID_PARAMETER 반환됩니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열리면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 파일에 TxF 트랜잭션이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 현재 바이트 범위 잠금이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
    • Windows 7 이전에 운영 체제는 마지막으로 열린 이후 스트림에 바이트 범위 잠금이 있는지 확인하고, 그렇다면 요청에 실패합니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 수준 2 및/또는 읽기: 요청이 부여됩니다. 동일한 스트림에 여러 수준 2/읽기 oplock을 동시에 부여할 수 있습니다. 여러 수준 2(읽기 아님) oplock은 동일한 핸들에도 존재할 수 있습니다.
    • 이미 읽기 oplock이 부여된 핸들에서 읽기 oplock이 요청되면 두 번째 읽기 oplock이 부여되기 전에 첫 번째 읽기 oplock의 IRP가 STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE 완료됩니다.
  • 수준 1, 일괄 처리, 필터, 읽기 핸들, 읽기-쓰기, 읽기-쓰기 핸들: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

읽기

다음 조건이 모두 충족되는 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열리면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 파일에 TxF 트랜잭션이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 현재 바이트 범위 잠금이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 수준 2 및/또는 읽기: 요청이 부여됩니다. 동일한 스트림에 여러 수준 2/읽기 oplock을 동시에 부여할 수 있습니다.
    • 또한 기존 oplock에 새 요청과 동일한 oplock 키가 있는 경우 해당 IRP는 STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE 함께 완료됩니다.
  • Read-Handle 기존 oplock에는 새 요청과 다른 oplock 키가 있습니다. 요청이 부여됩니다. 여러 읽기 및 Read-Handle oplock이 동일한 스트림에 공존할 수 있습니다(이 표 다음 참고 사항 참조).
    • 그렇지 않으면(oplock 키는 동일) STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 수준 1, 일괄 처리, 필터, 읽기-쓰기, 읽기-쓰기 핸들: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

Read-Handle

다음 조건이 모두 충족되는 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열리면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 파일에 TxF 트랜잭션이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 현재 바이트 범위 잠금이 없습니다.
    • 다른 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 읽기: 요청이 부여됩니다.
    • 기존 읽기 oplock에 새 요청과 동일한 oplock 키가 있는 경우 해당 IRP는 STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE 완료됩니다. 즉, oplock이 읽기에서 읽기 핸들로 업그레이드됩니다.
    • 새 요청과 동일한 oplock 키가 없는 기존 읽기 oplock은 변경되지 않은 상태로 유지됩니다.
  • 수준 2, 수준 1, 일괄 처리, 필터, 읽기-쓰기, 읽기-쓰기 핸들: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

Read-Write

다음 조건이 모두 충족되는 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
    • 디렉터리인 경우 STATUS_INVALID_PARAMETER 반환됩니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 파일에 TxF 트랜잭션이 없습니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 다른 열기가 있는 경우(동일한 스레드에서도) 동일한 oplock 키가 있어야 합니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 읽기 또는 Read-Write 기존 oplock에는 요청과 동일한 oplock 키가 있습니다. 기존 oplock의 IRP는 STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE 완료되고 요청이 부여됩니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 수준 2, 수준 1, 일괄 처리, 필터, 읽기 핸들, 읽기-쓰기 핸들: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

읽기-쓰기-핸들

다음이 모두 true인 경우에만 허용됩니다.

  • 요청은 지정된 파일 스트림에 대한 것입니다.
    • 디렉터리인 경우 STATUS_INVALID_PARAMETER 반환됩니다.
  • ASYNCHRONOUS 액세스를 위해 스트림이 열립니다.
    • SYNCHRONOUS 액세스를 위해 열면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 파일에 TxF 트랜잭션이 없습니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 스트림에 열려 있는 다른 요청이 있는 경우(동일한 스레드에서도) 동일한 oplock 키가 있어야 합니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

현재 oplock 상태가 다음과 같은 경우 주의해야 합니다.

  • Oplock 없음: 요청이 부여됩니다.

  • 읽기, 읽기-핸들, 읽기-쓰기 또는 읽기-쓰기 핸들 및 기존 oplock은 요청과 동일한 oplock 키를 가집니다. 기존 oplock의 IRP는 STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE 완료되고 요청이 부여됩니다.
    • 그렇지 않으면 STATUS_OPLOCK_NOT_GRANTED 반환됩니다.
  • 수준 2, 수준 1, 일괄 처리, 필터: STATUS_OPLOCK_NOT_GRANTED 반환됩니다.

참고

읽기 및 수준 2 oplock은 동일한 스트림에서 공존할 수 있으며 읽기 및 Read-Handle oplock은 공존할 수 있지만 수준 2 및 Read-Handle oplock은 공존할 수 없습니다.