Derrick Brashear [Mon, 19 Nov 2012 20:54:35 +0000 (15:54 -0500)]
macos: decode mountain lion panics
security hardening in the mountain lion kernel
screws up our decoder. apple doesn't bother to document
what to do, but after some head smashing, here we are.
AFSLocateNameEntry() can return STATUS_REPARSE in addition to
NTSTATUS failure codes. As in the case of an NTSTATUS code other
than STATUS_OBJECT_NAME_NOT_FOUND, the reference counts are decremented in
AFSLocateNameEntry() if STATUS_REPARSE is returned.
Jeffrey Altman [Sat, 1 Dec 2012 12:54:59 +0000 (07:54 -0500)]
Windows: Decr. used buf count flush and deleted files
When flushing the cache (fs flush*) or when deleting files or
when a file server reported error indicates that the buffer is
bad, decrement the used cache count so "fs getcacheparms" now
indicates a floating value based upon the number of buffers
containing potentially valid data.
Jeffrey Altman [Sat, 1 Dec 2012 12:30:57 +0000 (07:30 -0500)]
Windows: Restore "fs getcacheparms" used space
buf_Init() adds all of the available buffers to the free queue
at startup and cm_data.buf_freeCount tracks the number of items
in the free queue. So it cannot be used as a method of reporting
how much of the cache space has been used. Add a new buf_usedCount
parameter to the cm_memmap data to track the number of cache blocks
that have been used up to the total number of allocated blocks.
buf_usedCount can then be used in cm_IoctlGetCacheParms to restore
the original behavior.
Jeffrey Altman [Thu, 29 Nov 2012 08:14:42 +0000 (03:14 -0500)]
Windows: QFileInfo only Verify Entry when necessary
During a QueryFileInformation request only call AFSVerifyEntry()
when the AFS_OBJECT_FLAGS_VERIFY flag is set on the ObjectInformationCB.
The AFS_OBJECT_FLAGS_VERIFY flag is set in response to an invalidation
event from the cache manager. Let the cache manager decide when our
data is no longer consistent with the file server.
Jeffrey Altman [Thu, 29 Nov 2012 08:13:11 +0000 (03:13 -0500)]
Windows: Dir Enum only validate when necessary
During a directory enumeration, do not call AFSValidateEntry()
for every DirectoryCB. Instead only do so when the
AFS_OBJECT_FLAGS_VERIFY is set on the ObjectInformationCB.
Fcb->Specific.File.ExtentsCount cannot be used directly
in the for loop conditional because each call to AFSFreeExtent()
decrements the value. Instead, save the original value to
'lFcbExtentCount' and use that in the loop conditional.
Jeffrey Altman [Thu, 29 Nov 2012 08:00:48 +0000 (03:00 -0500)]
Windows: AFSCleanup calls AFSDeleteFcbExtents
When the hard link count of the file drops to zero, call
AFSDeleteFcbExtents() instead of AFSTearDownFcbExtents()
because the file has been deleted and the extents have been
implicitly released.
Jeffrey Altman [Thu, 29 Nov 2012 07:58:46 +0000 (02:58 -0500)]
Windows: AFSDeleteFcbExtents()
Similar to AFSTearDownFcbExtents() but does not release the
extents to afsd_service.exe. It is intended for use when the
FCB's extents are implicitly released as the result of file
deletion.
Jeffrey Altman [Wed, 28 Nov 2012 07:48:48 +0000 (02:48 -0500)]
Windows: Fcb sectionObjectResource
Add a SectionObjectResource to the AFS_FCB structure. This lock
replaces the Fcb.Resource in protecting the SectionObjectPointers.
The new resource is being added to assist in avoiding deadlocks
caused by Trend Micro and perhaps other AV products when
CcPurgeCacheSection() is called while holding the Fcb.Resource
which is required in AFSProcessOpen().
Jeffrey Altman [Tue, 27 Nov 2012 19:26:21 +0000 (14:26 -0500)]
Windows: Implement dynamic cell detection for RDR
RDR_EvaluateNodeByName knew how to parse \\afs\foo#bar\ notation
but couldn't perform a lookup for a cell that wasn't already
in the root directory. Add support for autorecognition.
Revert commit cecd99abd3837ef820d78fb15e450c8688b0f39b. Failing
to garbage collect the FCB from the ObjectInformationCB at the
earliest opportunity opens the door to a deadlock with Trend Micro's
anti-virus driver. Trend Micro attempts to make a copy of the
file data each time a CcPurgeCacheSection() is performed on the
FCB. If during AFSValidateEntry or AFSVerifyEntry a DirectoryCB->
ObjectInformationCB->FCB is discovered which has a non-NULL
SectionObjectPointers.DataSectionObject and the data version in
the DirEnumEntryCB differs from the ObjectInformationCB, a
CcPurgeCacheSection() call is performed while holding the
FCB->NPFcb->Resource exclusively. Trend Micro will deadlock the
thread making the CcPurgeCacheSection() call when it attempts
to open the file in one of its worker threads.
Jeffrey Altman [Sun, 25 Nov 2012 01:10:49 +0000 (20:10 -0500)]
rx: set abort client_initiated flag to match direction
In a recent incident involving packet reflection back to the
file server, aborts were being sent by the file server in response
to a server sent packet. The aborts sent in response also failed
to set the CLIENT_INITIATED flag in the header which permitted the
the actual client to confuse the Abort as applying to its client
initiated connection.
in rxi_SendRawAbort, set the CLIENT_INITIATED flag to the opposite
of the packet the abort is being sent in response to.
Simon Wilkinson [Sun, 4 Nov 2012 17:06:41 +0000 (17:06 +0000)]
rx: Make rxevent_Put NULL the event ptr being put
Change rxevent_Put so that it takes a pointer to the event being
put, and NULLs that pointer. This removes a lot of duplicate code
in callers, as well as making it harder to reuse a discarded event.
Simon Wilkinson [Thu, 22 Nov 2012 08:41:51 +0000 (08:41 +0000)]
rx: Return success value when cancelling an event
When cancelling an event that holds reference counts, we need
to know whether the attempt to cancel the event was successful
or not, otherwise references can be double put when the
cancellation races with the event firing. Take the follwing
Holding obj->lock doesn't control whether the event is fired or
not. Only putting the reference if the event being fired matches
that in obj doesn't help - it just leaks a reference in a different
race.
So, make rxevent_Cancel return true if it did actually cancel the
event, and false if the event has already been fired. This means
that Thread A can become
MUTEX_ENTER(&obj->lock);
if (rxevent_Cancel(&obj->event)
obj_put(&obj->refcnt);
MUTEX_EXIT(&obj->lock)
In the example above, rxevent_Cancel would return false.
Simon Wilkinson [Sat, 3 Nov 2012 23:15:50 +0000 (23:15 +0000)]
rx: Don't treat calls specially in event package
Many different structures can be passed to the rxevent package as
data. Don't give calls special treatment by making rxevent aware of
how to release their reference counts when an event is cancelled.
Update all of the callers of rxevent_Cancel to use the new arguments,
and where they were cancelling functions with calls as parameters add
the appropriate CALL_RELE directives. In many cases, this has led to
new helper functions to cancel particular call-based events.
Simon Wilkinson [Thu, 1 Nov 2012 17:44:07 +0000 (17:44 +0000)]
rx: Remove unused origPeer parameter to FindPeer
rxi_FindPeer took an 'origPeer' parameter, which was originally
there as an optimisation to decrement a reference count when replacing
a peer on a connection structure. However, we don't do that any more,
and the origPeer parameter is never used.
Simon Wilkinson [Fri, 9 Nov 2012 23:20:42 +0000 (23:20 +0000)]
rx: CheckBusy doesn't drop conn_call_lock
As rxi_CheckBusy doesn't drop the conn_call_lock when it checks for
busy call slots, it doesn't need to deal with someone replacing a
call behind its back.
Jeffrey Altman [Mon, 26 Nov 2012 16:25:43 +0000 (11:25 -0500)]
Windows: RefCounts, Asserts, and Trace Logging
Rename DirectoryCB.OpenReferenceCount to DirOpenReferenceCount
to distinguish it from the FCB.OpenReferenceCount. This makes
it easier to search for instances within an editor or debugger.
Ensure that all InterlockedIncrement and InterlockedDecrement
calls on a reference count field assign their value to a local
'lCount' variable. Ensure that 'lCount' is used within any
trace log messages and conditionals.
Add ASSERT( lCount >= 0) after all reference count decrements
in order to catch underflows.
Change conditionals from (RefCount == 0) to (RefCount <= 0) so
that object destruction can occur when there has been an underflow.
This is important in release builds for which ASSERT() is a no-op.
Jeffrey Altman [Mon, 26 Nov 2012 16:16:56 +0000 (11:16 -0500)]
Windows: AFSClose File FCB/CCB cleanup before DirCB
Move the processing of FCB and CCB cleanup ahead of the
DirectoryCB cleanup. It is not safe to dereference the
Ccb->DirectoryCB until after the CCB has been destroyed.
Jeffrey Altman [Sun, 25 Nov 2012 23:13:53 +0000 (18:13 -0500)]
Windows: AFSDeleteObjectInfo not on volume roots
The VolumeCB embeds an ObjectInformationCB structure which must
not be freed by calling AFSDeleteObjectInfo(). Add an assert
in the checked build and return without destroying the object
in the free build.
Jeffrey Altman [Mon, 26 Nov 2012 06:18:19 +0000 (01:18 -0500)]
Windows: AFSLocateNameEntry move InsertNextEntry
In AFSLocateNameEntry, move the InsertNextEntry to name array
call from before the directory entry DirOpenReferenceCount is
incremented to afterwards. This permits InsertNextEntry() to
consistently assert based upon the DirOpenReferenceCount value.
Jeffrey Altman [Sun, 25 Nov 2012 23:06:17 +0000 (18:06 -0500)]
Windows: AFSInvalidateCache volume refcounts
AFSInvalidateCache failed to release the volume reference count
when FileId is the volume root. In the non-root case it released
it too early permitting a race with AFSPrimaryVolumeWorkerThread
calling AFSRemoveVolume().
Jeffrey Altman [Sat, 24 Nov 2012 19:36:46 +0000 (14:36 -0500)]
Windows: Fail RX_INVALID_OPERATION errors
RX_INVALID_OPERATION errors were not resulting in an eventual
failure and the RPC was being repeated indefinitely. There were
three subtle problems:
1. RX_INVALID_OPERATION was being processed by cm_Analyze()
resulting in a retry in all cases. Even those where no
connp was passed in as NULL. connp == NULL implies that
no server could be obtained so the RPC was not issued on
this pass. As a result there should be no retry.
2. RX_INVALID_OPERATION was mapped to CM_ERROR_UNKNOWN which
is not an error that is reported to the AFS redirector.
3. RDR_BkgFetch was setting CM_REQ_NORETRY and permitting
the retries to be handled by the cm_daemon threads. However,
CM_ERROR_UNKNOWN was not treated as a fatal error by cm_Daemon.
Address the failures in the following ways:
A. cm_Analyze no longer retries calls which did not take place.
B. Create a new CM_ERROR_INVAL_NET_RESP error for RX_INVALID_OPERATION
which is translated to the Win32 STATUS_INVALID_NETWORK_RESPONSE
error. This is now returned to the AFS redirector and treated
as a fatal error.
C. RDR_BkgFetch no longer queues tasks to cm_Daemon with the
CM_REQ_NORETRY flag set.
Andrew Deason [Wed, 28 Nov 2012 23:22:21 +0000 (17:22 -0600)]
vol: Let non-usable volumes attach for non-DAFS
Before DAFS, volumes that were not inService/blessed were not
accessible by normal clients, but were still allowed to attach. That
is, access to clients was prevented at VGetVolume-time, rather than at
attach-time. Commit 939382c5 tried to short-circuit this by detecting
this volume state at attach-time. However, volume utilities (e.g.
volserver) can give us back a volume over FSSYNC when they are done
with the volume, and for non-DAFS, we then try to attach the volume.
So, with 939382c5 that attachment will fail when volserver gives us
back a volume that is not inService/blessed (which can happen for some
normal volume operations).
This situation is not terrible, since either way the volume is not
usable by clients (since the volume didn't attach), and the volume is
still usable by volserver (since volserver is allowed to check out
nonexistent volumes). But it is a deviation from pre-DAFS behavior and
it can result in confusing error messages, so revert the 939382c5
behavior for non-DAFS.
For DAFS, this behavior is fine, since the fileserver does not attach
a volume unless it is trying to service a client request. So, leave it
for DAFS.
Simon Wilkinson [Fri, 9 Nov 2012 23:11:16 +0000 (23:11 +0000)]
rx: Add a no-op afs_kcondvar_t for LWP
Remove the need to protect afs_kcondvar_t with RX_ENABLE_LOCKS, by
typedefing it as an int in rx_lwp.c. This is identical to what we
already do with afs_kmutex_t, and should let us get rid of some more
preprocessor spaghetti.
Andrew Deason [Wed, 14 Nov 2012 00:27:11 +0000 (18:27 -0600)]
afs: Handle VNOSERVICE as a timeout
For whatever reason, the fileserver uses VNOSERVICE to indicate that
an Rx call was killed due to an idledead timeout. It is not used for
any volume errors, so treat it like the idle dead error codes.
Jeffrey Altman [Tue, 27 Nov 2012 05:16:58 +0000 (00:16 -0500)]
Windows: cm_LookupInternal obtain type of target
cm_LookupInternal needs to return the target of a mount point
if the matching directory entry is a mount point. Therefore, if
the target type is unknown the status information must be queried.
Jeffrey Altman [Tue, 27 Nov 2012 05:08:30 +0000 (00:08 -0500)]
Windows: cm_GetNewSCache init mpDV to BAD
when allocatiing a new cm_scache_t object the mpDataVersion
field must be initialized to CM_SCACHE_BAD_VERSION. Zero is
a valid data version for a mount point or symlink.
Andrew Deason [Wed, 14 Nov 2012 00:15:21 +0000 (18:15 -0600)]
afs: Slight restructuring in afs_Analyze
We test for acode < 0 && acode != VRESTARTING, but then immediately
test for specific values for acode. Move this conditional down, and
remove a level of indentation for the next couple of acode checks.
This commit should introduce no functional change.
Andrew Deason [Wed, 14 Nov 2012 04:46:34 +0000 (22:46 -0600)]
rx: Generate BUSY packets for error call channels
Currently, if a call is error'd out but still active, we won't
generate BUSY packets if another call comes in on the same channel.
This is because we bail out earlier, here, before we get to the BUSY
processing.
The comments suggest that this is for if we enter an error state while
waiting for TQ to clear. So, only do this if our error has changed.
Jeffrey Altman [Mon, 26 Nov 2012 04:56:47 +0000 (23:56 -0500)]
Windows: Panic if RDR_Initialize SERVICE_DISABLED
If RDR_Initialize() fails with ERROR_SERVICE_DISABLED it means that
the AFSRedir.sys driver loaded but the AFSRedirLib.sys driver library
cannot be loaded. In this situation neither the RDR nor SMB interfaces
can successfully be used. Panic!
In the network provider, GetResourceInformation was logging the
input resource path after the afs redirector chopped it up. Log
it before the DeviceIoControl call.
Andrew Deason [Wed, 21 Nov 2012 16:39:51 +0000 (10:39 -0600)]
LINUX: Dir follow_link should set LAST_BIND
For our faux-symlink directory follow_link operation, we leave the
given nameidata struct with an invalid 'last' component. That is,
nd->last is not changed or set to anything meaningful.
Usually the callers of our follow_link op do not care about the last
component of the nameidata. However, at least one caller does: the
caller near the do_link label in open_namei(). This is called during
processing for O_CREAT operations on symlinks, and since our
directories look like symlinks, it gets called. It tries to use
nd->last to look up the last component of the dereferenced path (so it
can try to create it, as necessary), but since our nd->last is not
set, this will not work.
Specifically, our nd->last.name is not pointing into the names cache,
so the subsequent putname/__putname on it will corrupt the names
cache. However, even if this were not a problem, the actual contents
of the last component do not seem meaningful so this would probably
result in incorrect behavior anyway.
To avoid all of this, set nd->last_type to LAST_BIND, so any callers
know that the last component of the given nd is not valid, and we are
pointing directly to the target component with a dentry.
Do not call afs_MarinerLog when afs_mariner is not set
When mariner log is not set up (afs_mariner=0), do not call afs_MarinerLog,
otherwise a osi_NetSend() to hostaddress=0 is tried, which will give you
ICMP messages in the socket error queue.
Do not call afs_AddMarinerName, when afs_mariner is not set.
Jeffrey Altman [Sat, 17 Nov 2012 05:43:00 +0000 (00:43 -0500)]
Windows: Add Hard Link support to Service
Implement Hard Link support to the redirector interface in the
service. It is implemented to support hard links across directories
even though AFS does not currently support it. cm_Link() will
check before issuing an RPC to the file server. ReplaceIfExists
functionality is implemented by cm_Unlink() followed by cm_Link()
if required.
Jeffrey Altman [Sat, 17 Nov 2012 03:27:02 +0000 (22:27 -0500)]
Windows: Add Hard Link support to AFS Redirector
Both Windows and AFS support the notion of hard links to files.
Add an implementation to the AFS redirector. The body of the
functionality and the IOCTL to the service permits the specification
of hard links to files across directory boundaries. There is a
restriction within AFSSetFileLinkInfo() which prevents cross-directory
requests. However, this can be taken out if AFS ever permits them.
Decrement object information link counts on directory entry
deletions. Do not delete object information context blocks if the
link count is greater than 0. Increment link counts when hard
links are added.
A subsequent patchset will implement the afsd_service support.
Jeffrey Altman [Thu, 22 Nov 2012 16:52:11 +0000 (11:52 -0500)]
Windows: Trend Micro QueryDirectory deadlock
Trend Micro will deadlock both itself and the AFS redirector by
calling a worker thread to generate a temporary file name during
an active FindFirst Directory Query. The Trend Micro worker will
also attempt to enumerate the directory. If the directory contains
an entry for which the data version as reported by the service is
different than the data version in the ObjectInformationCB a deadlock
will occur on the matching FileCB Resource.
To avoid this deadlock, prevent AFSValidateEntry from purging or
updating the ObjectInformationCB and FileObject information when
called from AFSQueryDirectory.
Change-Id: I8f2f7136796759eb91dadfea34a89513c1a1fff4
Reviewed-on: http://gerrit.openafs.org/8492 Reviewed-by: Peter Scott <pscott@kerneldrivers.com> Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com> Tested-by: Jeffrey Altman <jaltman@your-file-system.com>
Jeffrey Altman [Mon, 19 Nov 2012 20:30:09 +0000 (15:30 -0500)]
Windows: AFSSetRenameInfo always set pRenameInfo
Make it easier to debug AFSSetRenameInfo by setting pRenameInfo
so that the FILE_RENAME_INFORMATION structure is visible within
the debugger on all code paths.
Jeffrey Altman [Fri, 16 Nov 2012 04:13:17 +0000 (23:13 -0500)]
Windows: SetFileRenameInfo Improve Error Handling
If a Target FileObject is not provided by the IOManager and
a Target RootDirectory Handle is provided something has gone
wrong. Return STATUS_INVALID_PARAMETER to indicate the
invalid state.
If the target directory is not specified by FileObject and a full
target path is provided return STATUS_NOT_SAME_DEVICE to force
an object Move instead of Rename.
Jeffrey Altman [Wed, 21 Nov 2012 23:08:35 +0000 (18:08 -0500)]
Windows: smb_ReceiveTran2QFileInfo Pioctl support
Similar to the QueryPathInfo support for _._AFS_IOCTL_._ the
QueryFileInfo interface must respond to pioctl queries. When
GetFileAttributes() on XP is called from the afslogon.dll the
QFileInfo path is used instead of the QPathInfo path.
Jeffrey Altman [Wed, 21 Nov 2012 23:03:10 +0000 (18:03 -0500)]
Windows: afslogon do not specify smbName for tokens
The smbName was added to the Windows ktc_SetTokens() interface
to provide a mechanism for passing the Windows account name
that the tokens should be associated with via Integrated Logon.
This was only required when the Authentication Provider did not
impersonate the user context prior to calling ktc_SetTokens().
Now that impersonation is used, the ktc_SetTokens() call will
do the right thing without the smbName. In fact, when impersonation
is used setting the smbName does the wrong thing by specifying
the AFS_PIOCTL_LOGON flag which is only valid if the SYSTEM account
is issuing the ktc_SetToken() call.
Jeffrey Altman [Tue, 20 Nov 2012 06:23:08 +0000 (01:23 -0500)]
Windows: QuerySecurity deny access to SACL
The SACL requires System Access Level. Requests for SACL by
end user applications must be denied. Permit access to Owner,
Group, DACL and Label but not SACL.
This change permits executables to be initiated from drive
letter mappings.
Jeffrey Altman [Mon, 19 Nov 2012 20:06:47 +0000 (15:06 -0500)]
Windows: Fix Redir link counting
Each object in AFS has a link count which tracks the number of
directory entries that refer to the FileId. In the redirector
there is one ObjectInformationCB per FileId and one AFSDirectoryCB
for each directory entry. When a directory entry is deleted perhaps
by delete on close it is important to ensure that the matching
ObjectInformationCB is not deleted unless the Link count drops to 0.
Jeffrey Altman [Sun, 18 Nov 2012 02:44:52 +0000 (21:44 -0500)]
Windows: buf_CleanLocked protect against NULL bp->userp
The cm_buf_t.userp field should never be NULL if the CM_BUF_DIRTY
flag is set but apparently it sometimes is. cm_BufWrite() requires
that the userp parameter be non-NULL. Otherwise, an assertion fails
and afsd_service.exe panics. If bp->userp is NULL, use cm_rootUserp.
The worst that will happen is the write will fail due to an access
denied error.
Jeffrey Altman [Sun, 18 Nov 2012 02:39:50 +0000 (21:39 -0500)]
Windows: do not adjust deleted scache LRU ordering
Instead of moving deleted scache objects so that they are next
in line to be recycled, do not move them at all. Making them
next to be recycled results in the CM_SCACHEFLAG_DELETED flag
value being lost.
Jeffrey Altman [Sun, 18 Nov 2012 02:32:44 +0000 (21:32 -0500)]
Windows: buf_CleanLocked validate cm_scache_t
If the cm_scache_t object is not passed in by the caller ensure
that the cm_scache_t has a valid callback. If the cm_scache_t
has the CM_SCACHEFLAG_DELETED flag set, clear the dirty flag on
the cm_buf_t and do not bother contacting the file server.
Simon Wilkinson [Wed, 21 Nov 2012 16:46:29 +0000 (16:46 +0000)]
opr: Don't confuse isLast and isEnd
opr_queue_IsEnd's implementation was incorrect - it would return
true when the element was the last item in the list, not when it
was the end of the list (equal to the head record)
Correct the implementation of isEnd, and add an implementation for
isLast.
This fixes a bug in RX, wher we would never notice that the last
packet in the transmit queue was acknowledged, because the loop that
iterates over the queue uses isEnd to detect when its work is done.
Andrew Deason [Thu, 15 Nov 2012 00:29:35 +0000 (18:29 -0600)]
afs: Do not skip flushing pages for dv-0 files
If the dv for a file is 0, we know the file is empty. Currently we
skip flushing pages for such files, presumably the idea being there is
no data in the file, so there should be no pages to flush.
However, Linux seems to keep empty pages around for empty files. So, a
future read can result in the application reading a page full of
zeroes, unless we flush the page here. While this has only been found
to happen on Linux 2.6.22 and later (and distribution-specific
backports, like RHEL 2.6.18-128), other platforms could in theory also
choose to do this. It would be difficult to find out when another
platform started to behave like this, so just remove this skip for
everyone so we never have to deal with this again.
Replace this code with a comment with a quick explanation, in case
anyone tries to add a similar optimization here in the future.
Marc Dionne [Thu, 15 Nov 2012 22:49:53 +0000 (17:49 -0500)]
Linux 3.7: remove use of param.h and ioctl.h
Header files param.h and ioctl.h have moved as part of the userspace
API restructuring of header files. Nothing in those files is
currently needed by the source, so just drop the includes.
Marc Dionne [Thu, 15 Nov 2012 03:12:13 +0000 (22:12 -0500)]
Linux: change test for new putname API
Replace the existing test with a more robust one that checks for
the existence of the new filename structure. Since older kernels
are expected to fail this test, we'll get the correct result even
if there is unrelated failure, for instance a missing/different
header file.
Jeffrey Altman [Wed, 14 Nov 2012 12:02:01 +0000 (07:02 -0500)]
Windows: Hold ProcessTreeLock across AFSValidateProcessEntry
AFSValidateProcessEntry() is called from AFSProcessCreate() which
holds the ProcessTree.TreeLock exclusive across the call and from
AFSCreate() and AFSRetrieveAuthGroup() where it is not held at all.
Add a parameter to AFSValidateProcessEntry() that indicates whether
or not the ProcessTree.TreeLock is held. If it is held, it must be
held exclusive. If it is not held, the lock must be acquired within
AFSValidateProcessEntry() and it must be held for the entire lifetime
of the pParentProcessCB reference. Failure to hold the TreeLock
for the lifetime of the reference permits a race with AFSProcessDestroy()
that can result in the parent ProcessCB being destroyed while its
Resource is held.
Jeffrey Altman [Tue, 13 Nov 2012 22:59:06 +0000 (17:59 -0500)]
Windows: Do not reset cm_buf.offset on error
When an error occurs the cm_buf_t is not removed from the
hash tables. Since the scacheHashTable hash is built from
the fid and the offset it is not safe to reset the offset field.
Resetting the offset field results in an assertion failure
during buffer recycling.
Andrew Deason [Thu, 1 Nov 2012 21:46:13 +0000 (16:46 -0500)]
afs: Add some comments on GetValidDSlot panics
A couple of call sites for afs_GetValidDSlot currently panic if an
error is returned, but no explanation is given. Add a few comments
helping explain why there is a panic there, instead of graceful error
handling.
Andrew Deason [Thu, 1 Nov 2012 21:33:31 +0000 (16:33 -0500)]
afs_FreeDiscardedDCache: Avoid assert on error
Currently afs_FreeDiscardedDCache will assert if it cannot read in any
discarded dcache entry to free. Return an error instead of asserting,
so the caller can figure out what to do about the error.
Adjust the callers to handle the error, or panic.
afs_MaybeFreeDiscardedDCache still just panics anyway, as making it
handle the error gracefully is beyond the scope of this commit, and is
work for another day.
This changes afs_FreeDiscardedDCache to return an int.
Andrew Deason [Thu, 1 Nov 2012 20:43:09 +0000 (15:43 -0500)]
afs: Handle afs_AllocDCache errors
Do not panic if afs_AllocDCache encounters an error and returns NULL.
Instead, go into the normal retry loop that occurs if we couldn't free
up any more free/discard dcache entries.
Andrew Deason [Thu, 1 Nov 2012 20:32:31 +0000 (15:32 -0500)]
afs_AllocDCache: return NULL instead of panic
Currently afs_AllocDCache will panic if we cannot get a valid dcache
from the free/discard lists. Instead, return NULL, so the caller can
decide how to handle the error.
Currently the caller will just panic anyway, but that will be
addressed in a future commit.
Andrew Deason [Thu, 1 Nov 2012 18:41:06 +0000 (13:41 -0500)]
afs: Traverse discard/free dslot list if errors
Currently, when we pull a dslot off of the discard or free list, we
just try to get the first entry from the list, and panic if we cannot
get it. Instead, traverse through the whole list, trying to find an
entry we can successfully get. This introduces the helper function
afs_GetDSlotFromList to do this traversal.
This does not yet address the case where we cannot get any entry on
the relevant list.
Andrew Deason [Thu, 1 Nov 2012 16:51:42 +0000 (11:51 -0500)]
afs: Handle easy GetValidDSlot errors
Many callers of GetValidDSlot currently assume they will always get
back a valid dcache, and will panic on getting NULL. However, for many
of these callers, handling the NULL case is quite easy, since the
failure to get a dcache can just result in an error directly, or
obtaining the dcache is best-effort or just an optimization.
This commit just handles the "easy" cases; some other callers require
more complex handling.
Andrew Deason [Wed, 31 Oct 2012 20:55:35 +0000 (15:55 -0500)]
afs: Never use GetNewDSlot after init
Currently there are two ways to get a dcache via a slot number:
afs_GetNewDSot and afs_GetValidDSlot. afs_GetValidDSlot assumes that
the given slot number refers to a dcache entry that is valid on disk;
with afs_GetNewDSlot, the given slot may not be valid, and if it is
not, an empty 'template' dcache is returned.
afs_GetNewDSlot is useful for initializing cache files, since if a
given dcache slot exists on disk and contains valid data, we use the
dcache like normal. If it does not already exist or does not contain
valid data, we fill in the missing data after afs_GetNewDSlot returns.
However, for all other uses, afs_GetNewDSlot is incorrect, and causes
various serious problems. After we have initialized our dcache
entries, any attempt to read a dcache by slot number should succeed,
since the number of dcache entries never changes after we are started,
and we initialized all of them during client startup.
Some code outside of afs_InitCacheFile was still using
afs_GetNewDSlot; code that reads in a dslot from the free or discard
list. In these cases, if there is any error reading the dcache slot
from disk, we will be given a dcache that has some of its fields not
filled in properly. Notably, we assume that the entry is not on the
global hash table (we set tdc->f.fid.Fid.Volume to 0), and the
tdc->f.inode field is not initialized at all, leaving it set to
whatever was in memory for that tdc before we tried to read the slot
from disk.
This can cause cache corruption, since tdc->f.inode can point to the
inoder for a different existing cache file, so writing to that dcache
modifies the data for another cached file.
To avoid this, modify the non-afs_InitCacheFile callers of
afs_GetNewDSlot to avoid afs_GetNewDSlot. Since these callers read
from the free/discard list, the contents of the dcache entries are not
valid (the cell, volume, dv, etc are not valid), though they must
exist on disk (we have a valid inode number for them). So, create a
new function, afs_GetUnusedDSlot, to get a dcache that must exist on
disk, but does not represent any valid data. Use this for callers that
must get a dslot from the free/discard list.
Add some comments to try and help explain what is going on.
Jeffrey Altman [Mon, 12 Nov 2012 03:00:07 +0000 (22:00 -0500)]
afsio: process windows file paths consistently
Windows file paths can use either '\' or '/' as a path
separator. libafscp on the other hand requires '/' and argv[0]
will always use '\'.
Introduce a new function ConvertAFSPath() which converts the
input path to '/' and converts \\afs to /afs. A future commit
should access the registry and make use of the NetbiosName and
MountRoot values to perform the conversion correctly.
Andrew Deason [Tue, 30 Oct 2012 18:30:27 +0000 (13:30 -0500)]
afs: Pass rx connection to print_internet_address
Make print_internet_address take an rx_connection, so it can print out
more information based on rx info. Currently it does not use the
connection; this commit is just for adding the connection to the
interface, and adjusting all of the callers to cope. There should be
no behavior change.
Michael Meffie [Tue, 30 Oct 2012 14:41:12 +0000 (10:41 -0400)]
fix stale volume info from vos examine (non-dafs)
A volume examine on a non-dafs volume server/fileserver can show old
information, including old volume update time, for up to about 20
minutes. The non-dafs volume server reads the volume information
from the volume headers, which are updated by the fileserver only
periodically to avoid excessive i/o.
Before dafs, when the volume server performed a volume examine, the
volume server would send a fssync command to the fileserver with the
request FSYNC_NEEDVOLUME and mode V_READONLY. The fileserver writes
the current memory contents to disk on this fssync command. The
volume server would then attach the volume, reading the current
volume data.
The dafs volume/fileserver avoids this extra i/o by using a new set
of fssync commands to retrieve the volume information from the
fileserver. However, the non-dafs volume server does not use the new
fssync commands and reads the volume headers from disk.
Revert the volume attachment processing for the non-dafs volume
server to request the volume with the V_READONLY mode. This causes
the fileserver to update the volume headers, allowing the volume
server to read the up to date volume header data.
Sadly, this adds another dafs ifdef to the already twisty maze of
passages that all look alike.
This changes the volserver to use the V_READONLY attachment mode
only for the case of getting a single volume, as that what was
done in 1.4.x.
Michael Meffie [Tue, 30 Oct 2012 14:22:40 +0000 (10:22 -0400)]
vol: allow non-dafs volume utils to attach with V_READONLY again
Allow non-fileserver, non-dafs, programs to attach volumes with the
V_READONLY mode again. This was lost during the code changes for
dafs.
The caller sends a fssync request to the fileserver, which updates the
on-disk contents of the volume headers, before the caller reads the
volume headers, allowing the caller to have the most recent info about
the volume. The fileserver still has the volume in use.
Later in the attachment process, the inUse check is skipped for the case
of a non-fileserver process which is attaching the volume using the
V_READONLY mode, otherwise the attachment would incorrectly mark the
volume as needing to be salvaged.
Note: The mode checks in VMustCheckOutVolume() are correct. We must
checkout the volume when attaching with the V_READONLY mode. This
fix updates the VShouldCheckInUse(), in which an additional
exception was added to cover the case for V_READONLY mode from a non-
fileserver process.
Note: A check is added in the dafs version of attach to avoid overwriting the
inUse field when a volume utility is attaching a volume in V_READONLY mode.
Currently, V_READONLY is not used by dafs, but this was done to avoid future
errors.
Jeffrey Altman [Thu, 8 Nov 2012 16:29:20 +0000 (11:29 -0500)]
Windows: Treat invalid AFSFetchStatus as VBUSY
Modify cm_Analyze() to accept an AFSFetchStatus parameter which
when set is verified for validity. If the status info is invalid,
then consider the response equivalent to VBUSY and attempt to
query an alternate file server (if any.) Log the invalid status
info to the Windows Application Event Log as a Warning.
When cm_Analyze() is processing the response of an RPC that returns
multiple AFSFetchStatus structures, pass in the one that corresponds
with the source object.
Jeffrey Altman [Thu, 8 Nov 2012 05:24:14 +0000 (00:24 -0500)]
Windows: cm_MergeStatus now returns an error code
cm_MergeStatus() can fail if the AFSFetchStatus InterfaceVersion
field does not have the value 0x1 as that is the only version that
is defined by the protocol. The return code will be CM_ERROR_INVAL.
cm_MergeStatus() returns 0 on success.
Andrew Deason [Wed, 31 Oct 2012 20:04:55 +0000 (15:04 -0500)]
afs: Make last_error always useful
Currently we record last_error as the last getuerror() we got when
failing to read in a slot in UFSGetDSlot. For kernels that do not have
getuerror(), this variable is currently useless, and we do not record
anywhere what the last error received was (besides logging it via
afs_warn).
So, for non-uerror, just record what 'code' we got, so we at least
have something.
Andrew Deason [Thu, 8 Nov 2012 00:46:24 +0000 (18:46 -0600)]
rx: Fix non-TSFPQ rxi_FreePackets
Actually count the number of packets we're given, so we don't bail out
early because num_pkts is 0. Without this, we effectively do not free
most packets for non-pthreads Rx, so e.g. the unix kernel module will
leak memory quite quickly and be very slow.
Jeffrey Altman [Tue, 6 Nov 2012 11:39:39 +0000 (06:39 -0500)]
Windows: call MIDL_user_allocate instead of calloc
In the RPC service routines do not call calloc() directly.
All memory will be deallocated by a call to MIDL_user_free()
so use MIDL_user_allocate() to perform the allocation.
Modify MIDL_user_allocate() to call calloc() instead of malloc()
to ensure that the memory is initialized to NUL bytes.
Ben Kaduk [Wed, 7 Nov 2012 15:08:33 +0000 (10:08 -0500)]
Catch up to FreeBSD non-MPSAFE deorbit
All filesystems must have their own locking now.
We have been MPSAFE for quite some time, but the preprocessor macro
"MPSAFE" has been removed and we must catch up in order to compile.
The MNTK_MPSAFE macro has not yet been removed, but it is toothless
now, so we can preemptively stop using it.
Jeffrey Altman [Thu, 1 Nov 2012 00:59:30 +0000 (20:59 -0400)]
Windows: Use MountRoot for Absolute Symlinks
Replace the absolute symlink processing in AFSLocateName().
Implement AFSIsAbsoluteAFSName() to test whether or not the
path is in fact an absolute /afs path by comparing the input
string to the registry MountRoot value which specifies the
case sensitive root path for all absolute symlinks stored
in the AFS cell.
If a symlink target path begins with a directory separator
and is not an absolute afs path name, return an error.
Construct the substitution string using the target path
without the MountRoot prefix.
Add functionality to AFSRedir.sys to read the MountRoot
from the registry and pass it on to AFSRedirLib.sys.