Condividi tramite


Interruzione di oplock

Dopo che un di oplockviene richiesto e concesso, 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 sospende l'IRP richiedente. Quando un oplock viene interrotto, la richiesta IRP dell'oplock in attesa viene completata con STATUS_SUCCESS. Per il livello 1, Batch e Filtro oplock, il membro IoStatus.Information di IRP è impostato per indicare il livello a cui l'oplock si sta degradando. Questi livelli sono:

  • FILE_OPLOCK_BROKEN_TO_NONE: l'oplock è stato interrotto e non è presente alcun oplock corrente nel flusso di dati. Si dice che l'oplock sia "rotto e impostato su Nessuno".

  • FILE_OPLOCK_BROKEN_TO_LEVEL_2: l'oplock corrente (livello 1 o batch) è stato convertito in un oplock di livello 2. Gli oplock di filtro non passano mai al livello 2, ma passano sempre a Nessuno.

Per gli oplock Read-Handle, Read-Write e Read-Write-Handle, il livello a cui l'oplock si interrompe viene descritto come una 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 oplock di livello 1, Batch, Filter, lettura/scrittura, lettura/scrittura-handle o, in determinate circostanze, un oplock Read-Handle:

  • Il pacchetto oplock completa l'IRP della richiesta oplock in sospeso.
  • L'operazione che ha causato l'interruzione di oplock viene sospesa.

Il gestore I/O fa sì che l'operazione venga bloccata, anziché restituire STATUS_PENDING, se l'operazione:

  • Viene emesso su un handle sincrono.
  • Si tratta di un IRP_MJ_CREATE, che è sempre sincrono.

Il gestore di I/O attende un riconoscimento dal proprietario dell'oplock per indicare al pacchetto oplock che ha terminato l'elaborazione ed è sicuro che l'operazione pended proceda. Questo ritardo consente al proprietario di oplock di riportare 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. Spetta quindi al proprietario dell'oplock riconoscere l'interruzione in modo tempestivo. L'IRP dell'operazione in sospeso 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 oplock. Questa opzione indica al pacchetto oplock di non bloccare l'IRP di creazione fino a quando non viene ricevuto il riconoscimento dell'interruzione oplock. Al contrario, è consentito procedere con la creazione. Se una creazione andata a buon fine provoca un'interruzione di blocco, 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 è proprietario di un oplock su un flusso e lo stesso client in un secondo momento apre lo stesso flusso, il client rimane bloccato in attesa di riconoscere l'interruzione di oplock. In questo scenario, l'uso del flag FILE_COMPLETE_IF_OPLOCKED evita il deadlock.

Il file system NTFS avvia interruzioni di oplock per gli oplock batch e filtra prima di verificare la presenza di violazioni di condivisione. È quindi possibile che un'operazione di creazione che ha specificato FILE_COMPLETE_IF_OPLOCKED non riesca con STATUS_SHARING_VIOLATION, ma causi ancora un'interruzione di un blocco di operazioni 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 Read-Write-Handle oplocks, l'interruzione dell'oplock viene avviata dopo che NTFS ha effettuato i controlli e ha rilevato una violazione di condivisione. Questa sequenza offre ai titolari di oplock l'opportunità di chiudere i loro handle e farsi da parte, consentendo così di evitare di restituire all'utente l'errore di violazione della condivisione. Evita inoltre l'interruzione incondizionata dell'oplock nei casi in cui l'handle che le cache oplock non è in conflitto con la nuova istanza di creazione.

Quando gli oplock di livello 2, di lettura e, in determinate circostanze, Read-Handle si rompono, il sistema non attende una conferma. Il motivo è che non deve essere presente alcuno stato memorizzato nella cache nel flusso che deve essere ripristinato nel file prima di consentire ad altri client di accedervi.

Esistono alcune operazioni del file system che controllano lo stato di oplock corrente per determinare se l'oplock deve essere interrotto. Gli articoli specifici dell'operazione seguenti descrivono cosa attiva un'interruzione di oplock, cosa determina il livello a cui si interrompe l'oplock e se è necessario un riconoscimento dell'interruzione:

Un'interruzione di un oplock di Windows 7 richiede un riconoscimento se il flag REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED è impostato nel membro Flags 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 oplock Read-Handle comporta la sospensione dell'operazione che ha causato l'interruzione dell'oplock. Ad esempio, l'articolo IRP_MJ_CREATE contiene i dettagli Read-Handle associati.