I am happy to say that I deal with oplock issues very rarely. The one problem with this is that I forget the subtleties of oplocks without fail. This is meant to be a cheat sheet for myself, in a public place so that others might possibly benefit.
The Basics – What no STATUS_SHARING_VIOLATION?
Since this is public, it would be rude to continue without a basic idea of what oplocks are.
Originally, oplocks were designed as way to increase performance over the network. For example, if you know that nobody is modifying a file on a network share, you can cache your a local copy of the file for as long as you want. A lot of the Microsoft docs still talk about oplocks in this way.
In “recent” years (since Windows 7), oplocks are used quite extensively even on local file systems to prevent sharing violations. The search indexer is a good example of this. On XP, if indexer was indexing a file and you tried to open the file for write, you’d likely get back STATUS_SHARING_VIOLATION. On Windows 7+, the search indexer takes an oplock on the file; when you open the file for write, the indexer gets notified and it can close its handle which allows your create to succeed.
First of all, there are enough (8!) different kinds of oplocks at this point so it makes sense to have a cheat sheet. In practice, some are duplicates. From https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/overview :
A Level 2 (or shared) oplock indicates that there are multiple readers of a stream and no writers. This supports client read caching. [Same as R]
A Level 1 (or exclusive) oplock allows a client to open a stream for exclusive access and allows the client to perform arbitrary buffering. This supports client read caching and write caching. [Same as RW]
A Batch oplock (also exclusive) allows a client to keep a stream open on the server even though the local accessor on the client machine has closed the stream. This supports scenarios where the client needs to repeatedly open and close the same file, such as during batch script execution. This supports client read caching, write caching, and handle caching. [Same as RWH]
A Filter oplock (also exclusive) allows applications and file system filters (including minifilters), which open and read stream data, a way to “back out” when other applications, clients, or both try to access the same stream. This supports client read caching and write caching.
Windows 7 oplocks:
- A Read (R) oplock (shared) indicates that there are multiple readers of a stream and no writers. This supports client read caching. [Same as Level 2]
- A Read-Handle (RH) oplock (shared) indicates that there are multiple readers of a stream, no writers, and that a client can keep a stream open on the server even though the local accessor on the client machine has closed the stream. This supports client read caching and handle caching.
- A Read-Write (RW) oplock (exclusive) allows a client to open a stream for exclusive access and allows the client to perform arbitrary buffering. This supports client read caching and write caching. [Same as level 1]
A Read-Write-Handle (RWH) oplock (exclusive) allows a client to keep a stream open on the server even though the local accessor on the client machine has closed the stream. This supports client read caching, write caching, and handle caching. [Same as Batch]
Breaking an Oplock
Once one has an oplock, there are a number of file operations that will cause the oplock to be broken (or reduced). Best to just head to https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/breaking-oplocks for that level of detail, but in general, the following operations can affect an oplock:
- Bye range locks
Additionally some file info classes and FSCTLs can lead to oplock breaks.
Oplock-Related Flags in Zw\Flt\IoCreateFile and the Like
When an oplock is broken, the default behavior is to pend the breaking thread until the oplock break has been acknowledged by the owner, or the owner closes the file, or a configurable timeout occurs.
Over the years, some additional flags have been added to CREATE to make this process a little less deadlock-prone.
If FILE_COMPLETE_IF_OPLOCKED is passed into CREATE, the oplock break is still sent but control returns to the caller with STATUS_OPLOCK_BREAK_IN_PROGRESS. There’s no guarantee as to when the acknowledgement will be processed and so the caller must use some asynchronous mechanism to proceed. More info here: http://www.kasardia.com/some-thoughts-on-oplocks/
This is also a way to detect if a file is oplocked in some cases, though the act of checking can trigger a break. In this scenario, one could just close the HANDLE and be done with it if STATUS_OPLOCK_BREAK_IN_PROGRESS is returned.
FILE_OPEN_REQUIRING_OPLOCK is an atomic way to open a file and grab an oplock at the same time. You’re supposed to then request the oplock so you get told about oplock breaks, but it’s not required. From https://docs.microsoft.com/en-us/windows/desktop/api/winternl/nf-winternl-ntcreatefile :
An application that uses this flag must request an oplock after this call succeeds, or all subsequent attempts to open the file will be blocked without the benefit of normal oplock processing. Similarly, if this call succeeds but the subsequent oplock request fails, an application that uses this flag must close its handle after it detects that the oplock request has failed.
If the file is already oplocked, the operation will fail with STATUS_CANNOT_BREAK_OPLOCK and the original oplock remains intact. However, there is some subtlety here:
- FILE_OPEN_REQUIRING_OPLOCK represents a RH oplock in Wondows 8+ and an RWH oplock in Windows 7.This means that on Windows 8+, the CREATE will still succeed if someone else has an R or RH oplock. As such, this is not a good way to determine if a file has read oplocks on it, but you could infer that someone has W, WH, or presumably filter oplocks.
- Given the previous point, the quote above is not accurate. Not “all subsequent attempts to open the file’ will be blocked. Just ones that conflict with RH oplocks.
Available on Windows 7+.
Nothing to add for now. I don’t see filter oplocks very much, perhaps because they lack the fine grained control of the Windows 7 oplocks.
As usual, Zezula’s FileTest tool is the easiest way to test oplock behavior. You can find it here: http://www.zezula.net/en/fstools/filetest.html
In Windows 8+, the !fltkd.oplock extension in WinDBG can be used to figure out who owns an oplock.
I was surprised to see that even Wikileaks has a page on oplocks: https://wikileaks.org/ciav7p1/cms/page_38633506.html