Oplocks unterbrechen
Nachdem ein Oplockangefordert und gewährt wurde, hat der Besitzer dieses Oplocks Zugriff auf den Stream, basierend auf dem Typ des Oplocks, der angefragt wurde. Wenn der empfangene Vorgang nicht mit dem aktuellen Oplock kompatibel ist, unterbricht das System den Oplock.
Wenn ein Oplock gewährt wird, stellt das System den anfragenden IRP zurück. Wenn eine Sperre aufgehoben wird, wird der IRP der angehängten Oplock-Anfrage mit STATUS_SUCCESS abgeschlossen. Für Oplocks der Stufen 1, Batch und Filter wird das IoStatus.Information Mitglied des IRP festgelegt, um die Stufe anzugeben, auf der der Oplock unterbrochen wird. Zu diesen Ebenen gehören folgende:
FILE_OPLOCK_BROKEN_TO_NONE: Der Oplock wurde unterbrochen und es gibt keinen aktuellen Oplock auf dem Stream. Das Oplock wird als "broken to None" bezeichnet.
FILE_OPLOCK_BROKEN_TO_LEVEL_2: Der aktuelle Oplock (Level 1 oder Batch) wurde in einen Level 2 Oplock umgewandelt. Filter-Oplocks unterbrechen niemals nach Level 2, sondern immer nach None.
Bei Read-Handle-, Read-Write- und Read-Write-Handle-Oplocks wird die Ebene, auf die der Oplock umgestellt wird, durch eine Kombination von null oder mehr der Flags OPLOCK_LEVEL_CACHE_READ beschrieben, OPLOCK_LEVEL_CACHE_HANDLE oder OPLOCK_LEVEL_CACHE_WRITE im NewOplockLevel-Mitglied der REQUEST_OPLOCK_OUTPUT_BUFFER-Struktur, die als lpOutBuffer-Parameter von DeviceIoControl übergeben wird. Auf ähnliche Weise können FltFsControlFile und ZwFsControlFile verwendet werden, um Windows 7 Oplocks vom Kernel-Modus aus anzufordern. Weitere Informationen finden Sie unter FSCTL_REQUEST_OPLOCK.
Wenn das Oplock-Paket des Systems einen Level 1, Batch, Filter, Read-Write, Read-Write-Handle oder unter bestimmten Umständen einen Read-Handle-Oplock aufhebt:
- Das Oplock-Paket schließt die angehängte Oplock-Anfrage IRP ab.
- Der Vorgang, der die Unterbrechung des Oplocks verursacht hat, wird selbst unterbrochen.
Der E/A-Manager bewirkt, dass der Vorgang blockiert wird, anstatt STATUS_PENDING zurückzugeben, wenn der Vorgang:
- auf ein synchrones Handle ausgegeben wird.
- ein IRP_MJ_CREATE ist, der immer synchron ist.
Der E/A-Manager wartet auf eine Bestätigung des Besitzers des Oplocks, um dem Paket mitzuteilen, dass die Verarbeitung des Oplocks abgeschlossen ist und der unterbrochene Vorgang fortgesetzt werden kann. Diese Verzögerung ermöglicht es Oplock-Besitzenden, den Stream wieder in einen konsistenten Zustand zu versetzen, bevor der aktuelle Vorgang fortgesetzt wird. Das System würde ewig auf die Bestätigung warten, da es keine Zeitüberschreitung gibt. Es obliegt daher dem Besitzer des Oplocks, die Unterbrechung rechtzeitig zu quittieren. Der IRP des angehaltenen Vorgangs wird in einen abbrechbaren Status festgelegt. Wenn die Anwendung oder der Treiber, die bzw. der das Warten durchführt, abbricht, schließt das oplock-Paket den IRP sofort mit STATUS_CANCELLED ab.
Ein IRP_MJ_CREATE IRP kann die Option FILE_COMPLETE_IF_OPLOCKED erstellen angeben, um zu vermeiden, dass er als Element der Oplock-Break-Bestätigung blockiert wird. Diese Option weist das Paket oplock an, den IRP zum Erstellen nicht zu blockieren, bis die Oplock-Break-Bestätigung eingegangen ist. Stattdessen wird zugelassen, dass das Erstellen fortgesetzt wird. Wenn ein erfolgreiches Erstellen zu einem Oplock-Break führt, lautet der Code STATUS_OPLOCK_BREAK_IN_PROGRESS und nicht STATUS_SUCCESS. Das Flag FILE_COMPLETE_IF_OPLOCKED wird normalerweise verwendet, um Deadlocks zu vermeiden. Wenn zum Beispiel ein Client einen Oplock auf einen Stream besitzt und derselbe Client später denselben Stream öffnet, würde der Client blockieren, während er darauf wartet, dass er selbst den Oplock-Break bestätigt. In diesem Szenario wird der Deadlock durch die Verwendung des Flags FILE_COMPLETE_IF_OPLOCKED vermieden.
Das NTFS-Dateisystem leitet Oplock-Unterbrechungen für Batch- und Filter-Oplocks ein, bevor es auf Freigabeverletzungen prüft. Es ist daher möglich, dass ein Erstellen, bei dem FILE_COMPLETE_IF_OPLOCKED angegeben wurde, mit STATUS_SHARING_VIOLATION fehlschlägt, aber dennoch einen Batch- oder Filter-Oplock unterbricht. In diesem Fall wird das Mitglied der Struktur IO_STATUS_BLOCK auf FILE_OPBATCH_BREAK_UNDERWAY festgelegt, um dem Aufrufer die Möglichkeit zu bieten, diesen Fall zu erkennen.
Bei Read-Handle- und Read-Write-Handle-Oplocks wird die Oplock-Unterbrechung eingeleitet, nachdem NTFS auf eine Verletzung der gemeinsamen Nutzung geprüft und diese festgestellt hat. Diese Sequenz gibt den Oplock-Inhabern die Möglichkeit, ihre Handles zu schließen und aus dem Weg zu gehen. Dies bietet die Möglichkeit, die Freigabeverletzung nicht an den Benutzer zurückzugeben. Außerdem wird vermieden, dass das Oplock in Fällen, in denen das Handle, das das Oplock zwischenspeichert, nicht mit dem neu erstellten in Konflikt steht, unbedingt unterbrochen wird.
Wenn Level 2, Read und unter bestimmten Umständen auch Read-Handle-Oplocks unterbrochen werden, wartet das System nicht auf eine Bestätigung. Der Grund dafür ist, dass es keinen zwischengespeicherten Status im Stream geben sollte, der in der Datei wiederhergestellt werden muss, bevor anderen Clients der Zugriff darauf gewährt wird.
Es gibt bestimmte Vorgänge im Dateisystem, die den aktuellen Status des Oplocks überprüfen, um festzustellen, ob der Oplock aufgelöst werden muss. Die folgenden vorgangsspezifischen Artikel beschreiben, was einen Oplock-Break auslöst, was den Grad des Oplock-Breaks bestimmt und ob eine Quittierung des Breaks erforderlich ist:
- IRP_MJ_CREATE
- IRP_MJ_READ
- IRP_MJ_WRITE
- IRP_MJ_CLEANUP
- IRP_MJ_LOCK_CONTROL
- IRP_MJ_SET_INFORMATION
- IRP_MJ_FILE_SYSTEM_CONTROL
- FS_FILTER_ACQUIRE_FOR_SECTION_SYNCHRONIZATION
Eine Unterbrechung eines Windows 7 Oplocks erfordert eine Bestätigung, wenn das Flag REQUEST_OPLOCK_OUTPUT_FLAG_ACK_REQUIRED im Mitglied Flags der Struktur REQUEST_OPLOCK_OUTPUT_BUFFER festgelegt ist, die als Ausgabeparameter von DeviceIoControl(lpOutBuffer) übergeben wird, FltFsControlFile(OutBuffer), oder ZwFsControlFile(OutBuffer) übergeben wird. Weitere Informationen finden Sie unter FSCTL_REQUEST_OPLOCK.
Die aufgeführten Artikel zu den einzelnen Operationen beschreiben die Details, wenn eine Unterbrechung eines Read-Handle-Oplocks dazu führt, dass der Vorgang, der den Oplock unterbrochen hat, ansteht. Zum Beispiel enthält der Artikel IRP_MJ_CREATE die zugehörigen Read-Handle-Details.