Operazioni di interruzione
Dopo aver richiesto e concesso un oplock, il proprietario di tale oplock ha accesso al flusso in base al tipo di oplock richiesto. Se l'operazione ricevuta non è compatibile con l'oplock corrente, il sistema interrompe l'oplock.
Quando viene concesso un oplock, il sistema esegue la penna dell'IRP richiesta. Quando viene interrotto un oplock, l'IRP della richiesta di oplock penna viene completato con STATUS_SUCCESS. Per Livello 1, Batch e Filtro oplocks il membro IoStatus.Information dell'IRP è impostato per indicare il livello a cui si sta interrompendo il blocco. Questi livelli sono:
FILE_OPLOCK_BROKEN_TO_NONE: il blocco è stato interrotto e non esiste alcun blocco corrente nel flusso. L'oplock è detto che è stato "interrotto a Nessuno".
FILE_OPLOCK_BROKEN_TO_LEVEL_2: l'oplock corrente (livello 1 o Batch) è stato convertito in un blocco di livello 2. I filtri non si interrompono mai a Livello 2, vengono sempre interrotti su Nessuno.
Per gli oplock Read-Handle, Read-Write e Read-Write-Handle, il livello a cui l'oplock è descritto come combinazione di zero o più flag OPLOCK_LEVEL_CACHE_READ, OPLOCK_LEVEL_CACHE_HANDLE o OPLOCK_LEVEL_CACHE_WRITE nel membro NewOplockLevel della struttura REQUEST_OPLOCK_OUTPUT_BUFFER passata come parametro lpOutBuffer di DeviceIoControl. In modo simile, FltFsControlFile e ZwFsControlFile possono essere usati per richiedere oplock di Windows 7 dalla modalità kernel. Per altre informazioni, vedere FSCTL_REQUEST_OPLOCK.
Quando il pacchetto oplock del sistema interrompe un blocco di livello 1, Batch, Filtro, Lettura-Scrittura, Read-Write-Handle o, in determinate circostanze, un Read-Handle oplock:
- Il pacchetto oplock completa l'IRP della richiesta oplock pennata.
- L'operazione che ha causato l'interruzione di oplock viene usata.
Se l'operazione viene emessa su un handle sincrono o è una IRP_MJ_CREATE, che è sempre sincrona, il gestore di I/O causa il blocco dell'operazione, invece di restituire STATUS_PENDING, in attesa di un riconoscimento dal proprietario dell'oplock per indicare al pacchetto oplock che hanno completato l'elaborazione ed è sicuro che l'operazione penna venga eseguita. Lo scopo di questo ritardo consiste nel consentire al proprietario del blocco di inserire nuovamente il flusso in uno stato coerente prima che l'operazione corrente proceda. Il sistema attende per sempre di ricevere il riconoscimento perché non esiste alcun timeout. È quindi incumbent sul proprietario dell'oplock per riconoscere l'interruzione in modo tempestivo. L'IRP dell'operazione penna viene impostato in uno stato annullabile. Se l'applicazione o il driver che esegue l'attesa termina, il pacchetto oplock completa immediatamente l'IRP con STATUS_CANCELLED.
Un IRP_MJ_CREATE IRP può specificare l'opzione di creazione FILE_COMPLETE_IF_OPLOCKED per evitare di essere bloccata come parte del riconoscimento dell'interruzione di blocco. Questa opzione indica al pacchetto oplock di non bloccare la creazione di IRP finché non viene ricevuto il riconoscimento dell'interruzione di blocco. È invece possibile procedere con la creazione. Se una creazione riuscita genera un'interruzione di oplock, il codice restituito è STATUS_OPLOCK_BREAK_IN_PROGRESS anziché STATUS_SUCCESS. Il flag FILE_COMPLETE_IF_OPLOCKED viene in genere usato per evitare deadlock. Ad esempio, se un client possiede un oplock in un flusso e lo stesso client apre lo stesso flusso, il client blocca l'attesa di confermare l'interruzione di oplock. In questo scenario, l'uso del flag di FILE_COMPLETE_IF_OPLOCKED evita il deadlock.
Poiché il file system NTFS avvia interruzioni di oplock per gli oplock batch e filtra prima di controllare le violazioni di condivisione, è possibile che una creazione specificata FILE_COMPLETE_IF_OPLOCKED non riesca con STATUS_SHARING_VIOLATION, ma causa ancora l'interruzione di un oplock batch o filtro. In questo caso, il membro informativo della struttura IO_STATUS_BLOCK è impostato su FILE_OPBATCH_BREAK_UNDERWAY per consentire al chiamante di rilevare questo caso.
Per Read-Handle e oplock read-write-handle, l'interruzione di blocco viene avviata dopo i controlli NTFS e rileva una violazione di condivisione. Ciò consente ai titolari di questi oplock l'opportunità di chiudere i loro handle e uscire dal modo, consentendo così la possibilità di non restituire la violazione di condivisione all'utente. Evita inoltre l'interruzione incondizionato del blocco nei casi in cui l'handle che le cache di oplock non sono in conflitto con la nuova creazione.
Quando il livello 2, lettura e, in determinate circostanze, Read-Handle interruzione degli oplock, il sistema non attende un riconoscimento. Questo perché non dovrebbe essere presente alcun stato memorizzato nella cache nel flusso che deve essere ripristinato nel file prima di consentire ad altri client di accedervi.
Esistono alcune operazioni di file system che controllano lo stato di oplock corrente per determinare se il blocco deve essere interrotto. Gli articoli seguenti elencano ogni operazione e descrivono quali attivano un'interruzione di oplock, ciò che determina il livello a cui si interrompe il blocco e se è necessario un riconoscimento dell'interruzione:
Un'interruzione di un oplock di Windows 7 richiede un riconoscimento se il flag di REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED è impostato nel membro Flag della struttura REQUEST_OPLOCK_OUTPUT_BUFFER passato come parametro di output di DeviceIoControl(lpOutBuffer), FltFsControlFile(OutBuffer) o ZwFsControlFile(OutBuffer). Per altre informazioni, vedere FSCTL_REQUEST_OPLOCK.
Gli articoli elencati per operazione descrivono i dettagli di quando un'interruzione di un Read-Handle oplock genera l'in sospeso dell'operazione che ha interrotto il blocco. Ad esempio, l'articolo IRP_MJ_CREATE contiene i dettagli Read-Handle associati.