Condividi tramite


Richiesta e concessione di oplock

Quando il reindirizzamento di rete accede ai file nei server remoti, richiede il blocco dal server remoto. Le applicazioni client richiedono direttamente oplock solo quando il blocco è destinato a un file nel server locale.

Gli oplock vengono richiesti tramite LETLS. Per i diversi tipi di oplock vengono usati i seguenti tipi di oplock, che possono essere usata sia le applicazioni in modalità utente che i driver in modalità kernel:

Per richiedere un oplock di Windows 7 in modalità utente, chiamare DeviceIoControl:

In modo simile, per richiedere oplock di Windows 7 in modalità kernel:

Per specificare quale dei quattro oplock di Windows 7 è necessario, impostare uno o più dei flag seguenti nel membro RequestedOplockLevel della struttura REQUEST_OPLOCK_INPUT_BUFFER :

  • OPLOCK_LEVEL_CACHE_READ
  • OPLOCK_LEVEL_CACHE_HANDLE
  • OPLOCK_LEVEL_CACHE_WRITE

Per altre informazioni, vedere FSCTL_REQUEST_OPLOCK.

Se è possibile concedere l'oplock richiesto, il file system restituisce STATUS_PENDING. Per questo motivo, gli oplock non vengono mai concessi per I/O sincroni. L'IRP FSCTL non viene completato fino a quando il blocco non viene interrotto.

Se non è possibile concedere il blocco, il file system restituisce un codice di errore appropriato. I codici di errore restituiti più comunemente sono STATUS_OPLOCK_NOT_GRANTED e STATUS_INVALID_PARAMETER (e i relativi analogici in modalità utente equivalenti).

Il blocco filtro consente a un'applicazione di eseguire il "backout" quando altre applicazioni/client tentano di accedere allo stesso flusso. Questo meccanismo consente a un'applicazione di accedere a un flusso senza causare altre funzioni di accesso del flusso per ricevere violazioni di condivisione quando si tenta di aprire il flusso. Per evitare violazioni di condivisione, è consigliabile usare una procedura speciale in tre passaggi per richiedere un blocco di filtri (FSCTL_REQUEST_FILTER_OPLOCK):

  1. Aprire il file con un accesso obbligatorio di FILE_READ_ATTRIBUTES e una modalità di condivisione di FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.

  2. Richiedere un blocco di filtro nell'handle dal passaggio 1.

  3. Aprire di nuovo il file per l'accesso in lettura.

L'handle aperto nel passaggio 1 non causerà la ricezione di violazioni di condivisione da parte di altre applicazioni, poiché è aperta solo per l'accesso agli attributi (FILE_READ_ATTRIBUTES) e non l'accesso ai dati (FILE_READ_DATA). Questo handle è adatto per richiedere l'oplock Filtro, ma non per eseguire operazioni di I/O effettive nel flusso di dati. L'handle aperto nel passaggio 3 consente al titolare del blocco di eseguire operazioni di I/O nel flusso; il blocco concesso nel passaggio 2 consente al titolare del blocco di "uscire dal modo" senza causare una violazione di condivisione a un'altra applicazione che tenta di accedere al flusso.

Il file system NTFS fornisce un'ottimizzazione per questa procedura tramite il flag di opzione di creazione FILE_RESERVE_OPFILTER. Se questo flag viene specificato nel passaggio 1 della procedura precedente, consente al file system di non riuscire la richiesta di creazione con STATUS_OPLOCK_NOT_GRANTED se il file system può determinare che il passaggio 2 avrà esito negativo. Se il passaggio 1 ha esito positivo, non è garantito che il passaggio 2 abbia esito positivo, anche se FILE_RESERVE_OPFILTER è stato specificato per la richiesta di creazione.

La tabella seguente identifica le condizioni necessarie per concedere un oplock.

Tipo di richiesta Condizioni

Livello 1

Filtra

Batch

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
    • Se viene restituita una directory, STATUS_INVALID_PARAMETER.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONO, viene restituito STATUS_OPLOCK_NOT_GRANTED (i blocchi non vengono concessi per le richieste di I/O sincrone).
  • Non sono presenti transazioni TxF in alcun flusso del file.
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti altre finestre sul flusso (anche per lo stesso thread).
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.

Se lo stato di oplock corrente è:

  • Nessun blocco: la richiesta viene concessa.

  • Livello 2: la richiesta di livello 2 originale viene interrotta con FILE_OPLOCK_BROKEN_TO_NONE. Viene quindi concesso l'oplock esclusivo richiesto.

  • Livello 1, Batch, Filter, Read, Read-Handle, Read-Write o Read-Write-Handle: viene restituito STATUS_OPLOCK_NOT_GRANTED.

Livello 2

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
    • Se viene restituita una directory, STATUS_INVALID_PARAMETER.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONO, viene restituito STATUS_OPLOCK_NOT_GRANTED.
  • Nel file non sono presenti transazioni TxF.
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti blocchi di intervallo byte correnti nel flusso.
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.
    • Prima di Windows 7, il sistema operativo verifica se esiste un blocco intervallo di byte nel flusso dall'ultima apertura e non riesce la richiesta in caso affermativo.

Se lo stato di oplock corrente è:

  • Nessun blocco: la richiesta viene concessa.

  • Livello 2 e/o Lettura: viene concessa la richiesta. È possibile disporre di più oplock di livello 2/lettura concessi allo stesso flusso contemporaneamente. Più operazioni di livello 2 (ma non di lettura) possono esistere anche nello stesso handle.
    • Se viene richiesto un oplock di lettura in un handle che dispone già di un blocco di lettura concesso a esso, il primo IRP di lettura viene completato con STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE prima che venga concesso il secondo blocco di lettura.
  • Livello 1, Batch, Filtro, Read-Handle, Read-Write, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED viene restituito.

Lettura

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONO, viene restituito STATUS_OPLOCK_NOT_GRANTED.
  • Nel file non sono presenti transazioni TxF.
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti blocchi di intervallo byte correnti nel flusso.
    • Viene restituito un altro STATUS_OPLOCK_NOT_GRANTED.

Tenere presente che se lo stato di oplock corrente è:

  • Nessun blocco: la richiesta viene concessa.

  • Livello 2 e/o Lettura: viene concessa la richiesta. È possibile disporre di più oplock di livello 2/lettura concessi allo stesso flusso contemporaneamente.
    • Inoltre, se un oplock esistente ha la stessa chiave di oplock della nuova richiesta, il relativo IRP viene completato con STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE.
  • Read-Handle e l'oplock esistente hanno una chiave di oplock diversa dalla nuova richiesta: la richiesta viene concessa. Più operazioni di lettura e Read-Handle oplock possono coesistere nello stesso flusso (vedere la nota seguente questa tabella).
    • Else (le chiavi oplock sono uguali) STATUS_OPLOCK_NOT_GRANTED viene restituito.
  • Livello 1, Batch, Filtro, Lettura-Scrittura, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED viene restituito.

Read-Handle

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONOUS, viene restituito STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti transazioni TxF nel file.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.
  • Non sono presenti blocchi di intervallo di byte correnti nel flusso.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.

Se lo stato di oplock corrente è:

  • Nessun oplock: la richiesta viene concessa.

  • Lettura: la richiesta viene concessa.
    • Se un oplock di lettura esistente ha la stessa chiave oplock della nuova richiesta, il relativo IRP viene completato con STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE. Il risultato è che l'oplock viene aggiornato da Read a Read-Handle.
    • Qualsiasi oplock di lettura esistente che non ha la stessa chiave oplock della nuova richiesta rimane invariata.
  • Livello 2, Livello 1, Batch, Filtro, Lettura-Scrittura, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED viene restituito.

Read-Write

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
    • Se viene restituita una directory, STATUS_INVALID_PARAMETER.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONOUS, viene restituito STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti transazioni TxF nel file.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.
  • Se nel flusso sono presenti altri elementi aperti (anche dallo stesso thread), devono avere la stessa chiave di oplock.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.

Se lo stato di oplock corrente è:

  • Nessun oplock: la richiesta viene concessa.

  • Lettura o Read-Write e l'oplock esistente ha la stessa chiave oplock della richiesta: l'IRP dell'oplock esistente viene completato con STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE, viene concessa la richiesta.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.
  • Livello 2, Livello 1, Batch, Filtro, Read-Handle, Read-Write-Handle: STATUS_OPLOCK_NOT_GRANTED viene restituito.

Read-Write-Handle

Concesso solo se tutte le condizioni seguenti sono vere:

  • La richiesta è per un determinato flusso di un file.
    • Se viene restituita una directory, STATUS_INVALID_PARAMETER.
  • Il flusso viene aperto per l'accesso ASINCRONO.
    • Se aperto per l'accesso SINCRONOUS, viene restituito STATUS_OPLOCK_NOT_GRANTED.
  • Non sono presenti transazioni TxF nel file.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.
  • Se nel flusso sono presenti altre richieste aperte (anche dallo stesso thread) devono avere la stessa chiave di oplock.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.

Se lo stato di oplock corrente è:

  • Nessun oplock: la richiesta viene concessa.

  • Read, Read-Handle, Read-Write o Read-Write-Handle e l'oplock esistente ha la stessa chiave oplock della richiesta: l'IRP esistente viene completato con STATUS_OPLOCK_SWITCHED_TO_NEW_HANDLE, viene concessa la richiesta.
    • Viene restituito STATUS_OPLOCK_NOT_GRANTED else.
  • Livello 2, Livello 1, Batch, Filtro: STATUS_OPLOCK_NOT_GRANTED viene restituito.

Nota

Gli oplock di lettura e di livello 2 possono coesistere nello stesso flusso e read e Read-Handle oplock possono coesistere, ma i oplock di livello 2 e Read-Handle non possono coesistere.