Share via


Solicitando e concedendo oplocks

Quando o redirecionador de rede acessa arquivos em servidores remotos, ele solicita o oplock do servidor remoto. Os aplicativos cliente solicitam oplocks diretamente somente quando o bloqueio é destinado a um arquivo no servidor local.

Os Oplocks são solicitados por meio de FSCTLs. As seguintes FSCTLs são usadas para os diferentes tipos oplock, que os aplicativos de modo de usuário e os drivers de modo kernel podem emitir:

Para solicitar um oplock do Windows 7 no modo de usuário, chame DeviceIoControl:

De maneira semelhante, para solicitar oplocks do Windows 7 no modo kernel:

Para especificar qual dos quatro oplocks do Windows 7 é necessário, defina um ou mais dos seguintes sinalizadores no membro RequestedOplockLevel da estrutura REQUEST_OPLOCK_INPUT_BUFFER :

  • OPLOCK_LEVEL_CACHE_READ
  • OPLOCK_LEVEL_CACHE_HANDLE
  • OPLOCK_LEVEL_CACHE_WRITE

Para obter mais informações, consulte FSCTL_REQUEST_OPLOCK.

Se o oplock solicitado puder ser concedido, o sistema de arquivos retornará STATUS_PENDING. Por esse motivo, os oplocks nunca são concedidos para E/S síncrona. O IRP FSCTL não é concluído até que o oplock seja quebrado.

Se o oplock não puder ser concedido, o sistema de arquivos retornará um código de erro apropriado. Os códigos de erro retornados com mais frequência são STATUS_OPLOCK_NOT_GRANTED e STATUS_INVALID_PARAMETER (e seus análogos de modo de usuário equivalentes).

O oplock Filter permite que um aplicativo "faça backup" quando outros aplicativos/clientes tentarem acessar o mesmo fluxo. Esse mecanismo permite que um aplicativo acesse um fluxo sem fazer com que outros acessadores do fluxo recebam violações de compartilhamento ao tentar abrir o fluxo. Para evitar violações de compartilhamento, um procedimento especial de três etapas deve ser usado para solicitar um filtro oplock (FSCTL_REQUEST_FILTER_OPLOCK):

  1. Abra o arquivo com um acesso necessário de FILE_READ_ATTRIBUTES e um modo de compartilhamento de FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.

  2. Solicite um Oplock de filtro no identificador da etapa 1.

  3. Abra o arquivo novamente para acesso de leitura.

O identificador aberto na etapa 1 não fará com que outros aplicativos recebam violações de compartilhamento, pois está aberto apenas para acesso a atributos (FILE_READ_ATTRIBUTES) e não acesso a dados (FILE_READ_DATA). Esse identificador é adequado para solicitar o oplock de filtro, mas não para executar E/S real no fluxo de dados. O identificador aberto na etapa 3 permite que o titular do oplock execute E/S no fluxo; o oplock concedido na etapa 2 permite que o titular do oplock "saia do caminho" sem causar uma violação de compartilhamento para outro aplicativo que tenta acessar o fluxo.

O sistema de arquivos NTFS fornece uma otimização para esse procedimento por meio do sinalizador de opção FILE_RESERVE_OPFILTER create. Se esse sinalizador for especificado na etapa 1 do procedimento anterior, ele permitirá que o sistema de arquivos falhe na solicitação de criação com STATUS_OPLOCK_NOT_GRANTED se o sistema de arquivos puder determinar se a etapa 2 falhará. Se a etapa 1 for bem-sucedida, não haverá garantia de que a etapa 2 terá êxito, mesmo que FILE_RESERVE_OPFILTER tenha sido especificado para a solicitação de criação.

A tabela a seguir identifica as condições necessárias para conceder um oplock.

Tipo de solicitação Condições

Nível 1

Filtrar

Lote

Concedido somente se todas as seguintes condições forem verdadeiras:

  • A solicitação é para um determinado fluxo de um arquivo.
    • Se um diretório, STATUS_INVALID_PARAMETER será retornado.
  • O fluxo é aberto para acesso ASSÍNCROno.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED é retornado (oplocks não são concedidos para solicitações de E/S síncronas).
  • Não há transações TxF em nenhum fluxo do arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Não há outras aberturas no fluxo (mesmo pelo mesmo thread).
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.

Se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Nível 2: a solicitação de Nível 2 original é interrompida com FILE_OPLOCK_BROKEN_TO_NONE. O oplock exclusivo solicitado é concedido.

  • Nível 1, Lote, Filtro, Leitura, Identificador de Leitura, Leitura/Gravação ou Identificador de Leitura/Gravação: STATUS_OPLOCK_NOT_GRANTED é retornado.

Nível 2

Concedido somente se todas as seguintes condições forem verdadeiras:

  • A solicitação é para um determinado fluxo de um arquivo.
    • Se um diretório, STATUS_INVALID_PARAMETER será retornado.
  • O fluxo é aberto para acesso ASSÍNCROno.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED será retornado.
  • Não há transações TxF no arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Não há bloqueios de intervalo de bytes atuais no fluxo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
    • Antes do Windows 7, o sistema operacional verifica se um bloqueio de intervalo de bytes já existia no fluxo desde a última vez em que foi aberto e falha na solicitação em caso afirmativo.

Se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Nível 2 e/ou Leitura: a solicitação é concedida. Você pode ter vários oplocks de Nível 2/Leitura concedidos no mesmo fluxo ao mesmo tempo. Vários oplocks de Nível 2 (mas não Leitura) podem existir no mesmo identificador.
    • Se um oplock de leitura for solicitado em um identificador que já tenha um Oplock de leitura concedido a ele, o PRIMEIRO IRP do Oplock de Leitura será concluído com STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE antes que o segundo oplock de leitura seja concedido.
  • Nível 1, Lote, Filtro, Identificador de Leitura, Leitura/Gravação, Identificador de Leitura/Gravação: STATUS_OPLOCK_NOT_GRANTED é retornado.

Ler

Concedido somente se todas as seguintes condições forem verdadeiras:

  • A solicitação é para um determinado fluxo de um arquivo.
  • O fluxo é aberto para acesso ASSÍNCROno.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED será retornado.
  • Não há transações TxF no arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Não há bloqueios de intervalo de bytes atuais no fluxo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.

Lembre-se de que, se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Nível 2 e/ou Leitura: a solicitação é concedida. Você pode ter vários oplocks de Nível 2/Leitura concedidos no mesmo fluxo ao mesmo tempo.
    • Além disso, se um oplock existente tiver a mesma chave oplock que a nova solicitação, seu IRP será concluído com STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
  • Read-Handle e o oplock existente têm uma chave oplock diferente da nova solicitação: a solicitação é concedida. Vários oplocks de leitura e Read-Handle podem coexistir no mesmo fluxo (consulte a observação a seguir nesta tabela).
    • Caso contrário ,as chaves oplock são as mesmas) STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Nível 1, Lote, Filtro, Leitura/Gravação, Identificador de Leitura/Gravação: STATUS_OPLOCK_NOT_GRANTED é retornado.

Read-Handle

Concedido somente se todas as seguintes condições forem verdadeiras:

  • A solicitação é para um determinado fluxo de um arquivo.
  • O fluxo é aberto para acesso ASYNCHRONOUS.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED será retornado.
  • Não há transações TxF no arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Não há bloqueios de intervalo de bytes atuais no fluxo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.

Se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Leia: a solicitação é concedida.
    • Se um Oplock de Leitura existente tiver a mesma chave oplock que a nova solicitação, seu IRP será concluído com STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE. O resultado é que o oplock é atualizado de Leitura para Identificador de Leitura.
    • Qualquer oplock de leitura existente que não tenha a mesma chave oplock que a nova solicitação permanece inalterada.
  • Nível 2, Nível 1, Lote, Filtro, Leitura/Gravação, Identificador de Leitura/Gravação: STATUS_OPLOCK_NOT_GRANTED é retornado.

Leitura-Gravação

Concedido somente se todas as seguintes condições forem verdadeiras:

  • A solicitação é para um determinado fluxo de um arquivo.
    • Se um diretório, STATUS_INVALID_PARAMETER será retornado.
  • O fluxo é aberto para acesso ASYNCHRONOUS.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED será retornado.
  • Não há transações TxF no arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Se houver outras aberturas no fluxo (mesmo pelo mesmo thread), elas deverão ter a mesma chave oplock.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.

Se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Ler ou Read-Write e o oplock existente tem a mesma chave oplock que a solicitação: o IRP do oplock existente é concluído com STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE, a solicitação é concedida.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Nível 2, Nível 1, Lote, Filtro, Identificador de Leitura, Identificador de Leitura/Gravação: STATUS_OPLOCK_NOT_GRANTED é retornado.

Identificador de leitura/gravação

Concedido somente se todos os seguintes itens forem verdadeiros:

  • A solicitação é para um determinado fluxo de um arquivo.
    • Se um diretório, STATUS_INVALID_PARAMETER será retornado.
  • O fluxo é aberto para acesso ASYNCHRONOUS.
    • Se aberto para acesso SÍNCRONO, STATUS_OPLOCK_NOT_GRANTED será retornado.
  • Não há transações TxF no arquivo.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Se houver outras solicitações abertas no fluxo (mesmo pelo mesmo thread), elas deverão ter a mesma chave oplock.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.

Se o estado atual do oplock for:

  • Sem oplock: a solicitação é concedida.

  • Read, Read-Handle, Read-Write ou Read-Write-Handle e o oplock existente têm a mesma chave oplock que a solicitação: o IRP do oplock existente é concluído com STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE, a solicitação é concedida.
    • Caso contrário, STATUS_OPLOCK_NOT_GRANTED é retornado.
  • Nível 2, Nível 1, Lote, Filtro: STATUS_OPLOCK_NOT_GRANTED é retornado.

Observação

Os oplocks de Leitura e Nível 2 podem coexistir no mesmo fluxo e oplocks de leitura e Read-Handle podem coexistir, mas oplocks de Nível 2 e Read-Handle não podem coexistir.