of oplocks and locks

below you'll find a sample understanding what oplocks are and how they are handled by SMB over the network. the client machines at 192.168.1.200 and 192.168.1.250 are Windows XP SP2 clients and the fileserver is a Windows Server 2003 SP2.

I've used a very simple application on both clients to demonstrate a simple concept, an application locking a file and not sharing. the code that runs on both client machines is below:

HANDLE hFile;
printf("press Enter to create file handle..\n");
getchar();

hFile = CreateFile(L" \\\\192.168.1.100\\share\\foo.bar ",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

printf("CreateFile returns with %d\n", GetLastError());

printf("file created.. press Enter to exit..\n");
getchar();

return 0;

 

the noteworthy thing here is parameter 3, by providing this with a 0 im telling the OS that I'd like that file to be opened but I will not share it with anyone. If I get access to it, it's mine only..

32 17.535497 192.168.1.200 192.168.1.100 SMB SMB:C; Tree Connect Andx, Path = \\192.168.1.100\SHARE , Service = ?????

33 17.535969 192.168.1.100 192.168.1.200 SMB SMB:R; Tree Connect Andx, Service = A:

34 17.536613 192.168.1.200 192.168.1.100 SMB SMB:C; Nt Create Andx, FileName = \foo.bar

.....(below is part of packet 34, how the createfile is sent over the network to the fileserver by smb..)

    - ShareAccess ShareAccess: 0x00000000
      Read: (...............................0) Read NOT Allowed
Write: (..............................0.) Write NOT Allowed
Delete: (.............................0..) Delete NOT Allowed

Rsvd: (00000000000000000000000000000...) Reserved(Must be zero)

....
 
35 17.536838 192.168.1.100 192.168.1.200 SMB SMB:R; Nt Create Andx, FID = 0x4007 (\foo.bar@#34)

then the client at 192.168.1.250 tries to access the same file..

63 28.574906 192.168.1.250 192.168.1.100 SMB SMB:C; Tree Connect Andx, Path = \\192.168.1.100\SHARE , Service = ?????

**

64 28.575080 192.168.1.100 192.168.1.250 SMB SMB:R; Tree Connect Andx, Service = A:

65 28.575562 192.168.1.250 192.168.1.100 SMB SMB:C; Nt Create Andx, FileName = \foo.bar

the same application is being used so the same share access settings are sent to the server. now the server checks with the previous lock owner...

66 28.575674 192.168.1.100 192.168.1.200 SMB SMB:C; Locking Andx, FID = 0x4007 (\foo.bar@#34)

67 28.576314 192.168.1.200 192.168.1.100 SMB SMB:C; Locking Andx, FID = 0x4007 (\foo.bar@#34)

it's basically asking the previous owner of the lock if it can release it gracefully. the client says no

71 29.573853 192.168.1.100 192.168.1.250 SMB SMB:R; Nt Create Andx - NT Status: System - Error, Code = (67) STATUS_SHARING_VIOLATION

the second machine receives a STATUS_SHARING_VIOLATION and the file cannot be opened. This is what happens when oplocks are enabled. now check below. this new trace is from an instance where both clients are not using oplocks. you can do this on 2K and later by adding a new dword OplocksDisabled under services\mrxsmb..

25 2.766744 192.168.1.200 192.168.1.100 SMB SMB:C; Tree Connect Andx, Path = \\192.168.1.100\SHARE , Service = ?????

**

26 2.767213 192.168.1.100 192.168.1.200 SMB SMB:R; Tree Connect Andx, Service = A:

27 2.767977 192.168.1.200 192.168.1.100 SMB SMB:C; Nt Create Andx, FileName = \foo.bar

28 2.768163 192.168.1.100 192.168.1.200 SMB SMB:R; Nt Create Andx, FID = 0x400F (\foo.bar@#27)

....
64 15.419357 192.168.1.250 192.168.1.100 SMB SMB:C; Nt Create Andx, FileName = \foo.bar

66 16.419300 192.168.1.100 192.168.1.250 SMB SMB:R; Nt Create Andx - NT Status: System - Error, Code = (67) STATUS_SHARING_VIOLATION

 

the server responds immediately after it receives the request to create a handle on the file. this file is open as share nothing by a previous client and that client has not requested any oplocks on the file. the server in the first instance where oplocks are in effect, asks the client first because it thinks the client may release it, and it doesnt want the first client to lose any data in any scenario because the first client may be opportunistically caching local in memory information and we do not want to mess around with data integrity.

 

the second instance where oplocks are not there, the server responds to the second opener immediately as it knows the first client is not caching anything and uses the open file object on the server side and information on this object to immediately deny the second open request.