Reorganize the locking for cm_BeginDirOp and cm_EndDirOp.
There are a number of locations where locks are obtained, dropped, and
reobtained. This reorganization attempts to accomplish several things:
(1) be optimistic for the most common case so it will be fast
(2) add consistency checks after each location where locks are dropped
and re-obtained. If we lose a race in cm_BeginDirOp and the bplus
tree is out of date, retry until we get to a consistent state
that we can use.
(3) Ensure that all operations take place with the correct locks.
rename findNode to leafNode in bplus_Lookup
replace all OutputDebugString calls with osi_LogX calls
modify bestMatch to special case the return values for leaf nodes.
If an entry is above or below the values available in the leaf node
return BTLOWER or BTUPPER instead of BTERROR.
In insert and delete operations check for BTLOWER/BTUPPER and isleaf,
if true convert to either slot 0 or Max and perform the insertion.
This produces easier to read code when performing lookups.
Add additional validation and error handling code after each call to
getSlot(). If an invalid slot is returned, return NONODE. If the
invalid slot is returned when extracting a data node, invalidate the
tree.
Modify compareKeys() to always perform a case-insensitive comparison
and only perform a case sensistive comparison if the case-insensitive
one matches. This ensures the ordering is consistently reported.
Add lock assertions to ensure that all calls are being performed with
the correct locks being held. There have been some crash reports that
provide stack data that does not appear to be possible unless there is
a race. However, there are no obvious locations where the race is
taking place and the test suite indicates that all of the correct locks
are being held. We shall see what happens in the field.
For consistency replace all calls to findKey in which the range is
(1,numentries) with calls to getSlot().
Optimize the depth search loop by testing the slot value in the for
statement instead of forcing the loop to be broken later.
Microsoft provided a dump showing cm_data.aclLRUEndp == NULL in
GetFreeACLEnt(). Couldn't find any reason why that would be true.
However, there is extraneous code that manipulates the value of
aclLRUEndp when it should be left to osi_QRemoveHT() to update
the pointer values.
Also add an additional explicit test for aclLRUEndp == NULL in
GetFreeACLEnt().
At somepoint windows installer broke the use of the 'file' RegistrySearch
type. Instead of returning the full file name path we are only getting
the directory. Switch to using the 'raw' type since we know we aren't
prefixing the file name with a hash.
The cmd.exe "del" command operates by opening a file and then setting
the file disposition to delete on close followed by closing the file.
When the filename is a symlink, the smb_fid_t scp refers to the final
destination object and not the symlink. In smb_CloseFid() the correct
object would be removed from the directory by name, but the wrong cm_scache_t
would be marked deleted. This would result in subsequent references to
the target file being considered invalid.
Fix it by looking up the cm_scache_t of the symlink prior to performing
the deletion.
Add registry value "OfflineReadOnlyIsValid" option. When set to non-zero
value, an offline or down read only volume will be treated as if it has
a valid callback even if it doesn't.
cm_ParseIoctlPath() moves the ioctlp->inDatap past the ioctl path
to the next data value if there is one. Make sure we move the pointer
before we alter the contents of the buffer. Otherwise, the caller
uses the wrong string for its next data blob.