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.
Simon Wilkinson [Mon, 29 Oct 2012 19:02:03 +0000 (19:02 +0000)]
opr: Add opr_jhash_int2 function
Add a function to jhash that can be used to hash a pair of unsigned
integers (or other stuff that can cast to them) without having to build
up an array.
Simon Wilkinson [Thu, 1 Nov 2012 17:38:45 +0000 (17:38 +0000)]
tests: Fix fallout from cleanup change
The change to cleanup temporary files after tests
(0c3670914a05c7aa33f0b1239ba9cc25f430ed04) broke all attempts
to run the tests using libwrap, as it would cause libwrap to run
the binary named "MAKECHECK=1"
Move the variable defintion before the libwrap invocation to fix this.
Jeffrey Altman [Wed, 31 Oct 2012 16:04:50 +0000 (12:04 -0400)]
Windows: cm_ConnByServer increment under lock
Incrementing the cm_conn.refCount must be performed while holding
the cm_connLock in order to prevent cm_GCConnections() from
seeing an in-use object as having a zero count.
Jeffrey Altman [Wed, 31 Oct 2012 13:53:57 +0000 (09:53 -0400)]
Windows: cm_FindVolumeByName refactoring
The cm_volume allocation within cm_FindVolumeByName() was racy.
Given how locks were obtained and dropped it was possible for two
threads to both determine that a cm_volume_t object needed to be
allocated. It might even have been possible for two threads to
attempt to allocate the same object.
This refactoring ensures that if a volume cannot be found under
a read lock that a second search is performed under the write lock
in case the object had in fact been allocated during the transition.
Once it is determined that an allocation is required, the cm_volumeLock
is not dropped until the object has been built and inserted into the
name hash table. This ensures that two threads cannot attempt to
allocate a cm_volume object for the same volume group.
InterlockedIncrement is used to manage the cm_data volume count.
Jeffrey Altman [Wed, 31 Oct 2012 13:52:23 +0000 (09:52 -0400)]
Windows: use cm_GetVolume / cm_PutVolume
Instead of locally incrementing and decrementing the cm_volume
refCount field use cm_GetVolume and cm_PutVolume. Doing so makes
it easier to see if there is an imbalance.
Andrew Deason [Tue, 23 Oct 2012 20:47:06 +0000 (15:47 -0500)]
ptserver: Avoid inet_ntoa
The ptserver uses inet_ntoa in a few places, such as for calculating
host CPS. This isn't safe in pthreaded environments, so use
afs_inet_ntoa_r instead.
Simon Wilkinson [Sun, 21 Oct 2012 19:07:44 +0000 (20:07 +0100)]
Fix mutex assertion
RX mutexes have two mechanisms for asserting ownership of a mutex:
MUTEX_ISMINE, which returns true if the caller is the owner of the
mutex in question, and osirx_AssertMutex which fires an assertion if
the calling thread doesn't own a specified mutex.
Neither of these work with pthread mutexes on all platforms, and the
kernel support for MUTEX_ISMINE is dubious in places. Because in some
implementations, MUTEX_ISMINE tries to lock the mutex in question, a
failing call to MUTEX_ISMINE can lead to the process holding an
additional, unexpected, lock.
This patch reworks all of this, and uses the new opr mutex framework
so that we can do mutex assertions in userspace, too. We remove the
unsafe MUTEX_ISMINE macro, and replace it with MUTEX_ASSERT which
simply asserts if the specified mutex is not held by the current
thread. osirx_AssertMutex is removed as it is now redundant.
MUTEX_ASSERT will always work in kernel code.
For userspace, we provide opr_mutex_assert, which is implemented using
POSIX error checking mutexes. As error checking mutexes have a runtime
overhead, this is only available when configured with
--enable-debug-locks, the rest of the time calls to opr_mutex_assert are
no-ops.
Simon Wilkinson [Sun, 21 Oct 2012 20:19:40 +0000 (21:19 +0100)]
rx: Move kernel assertion macros
Move the kernel assertion macros out of rx_prototypes.h and into
rx_kernel.h. This solves an ordering problem if these macros are to
be used from src/rx/<arch>/*.h
Simon Wilkinson [Sat, 20 Oct 2012 22:14:41 +0000 (23:14 +0100)]
Add opr/lock.h and tidy locking macros
The MUTEX_* and CV_* macros leaked from RX a while ago - they mean
that most of the pthreaded tree has a dependency on RX, as well as
further confusing the difference between userspace and kernel.
Tidy all of this up so that we have opr_mutex_* and opr_cv_* macros
to handle portable locking, and use these throughout the userspace
tree. Only kernel code should now use MUTEX_* and CV_*.
Provide opr/lockstub.h as a header that can be used by non-pthreaded
code to easily stub out these functions.
Simon Wilkinson [Fri, 26 Oct 2012 14:37:52 +0000 (15:37 +0100)]
rx: Move transmit queue clearing
When the client receives a data packet from the server, it means that
the server has completed processing the client's request. This, in turn,
implies that the transmit queue can be cleared. However, we were doing
this with every incoming data packet.
Move the transmit queue clearing to the code which handles the rest of
the data packet, and make the function only run if the transmit queue
is non-empty.
Now that there's no client specific logic in the ReceiveCall section,
clean up this code to reduce duplication.
Simon Wilkinson [Fri, 26 Oct 2012 14:23:48 +0000 (15:23 +0100)]
rx: Refactor code to acknowledge a whole TX queue
We acknowledge a whole transmit queue whenever an ACKALL packet is
received, or whenever the call changes direction. As the same logic
is used in both locations, pull it out into a common helper function.
Simon Wilkinson [Fri, 26 Oct 2012 13:55:02 +0000 (14:55 +0100)]
rx: Remove duplicate out of order ACK check
Once we've moved the congestion window, there's no going back. So
any ACK packets that attempt to move the window backwards by including
a 'firstPacket' value earlier than the current window position must
be ignored.
However, we check (and ignore) these packets twice. Once in
rxi_ReceivePacket, which only checks in the client side case, and again
in rxi_ReceiveAckPacket, which has a more complete check that runs for
both client and server connections.
Remove the identical check from rxi_ReceivePacket in a continuing effort
to clean up this bit of code.
Simon Wilkinson [Fri, 26 Oct 2012 13:52:46 +0000 (14:52 +0100)]
rx: Remove duplicate security layer check
rxi_FindConnection checks that the connection it returns has a
security layer matching that of the incoming packet. Don't duplicate
this check within the rxi_ReceivePacket code.
Simon Wilkinson [Fri, 26 Oct 2012 11:21:41 +0000 (12:21 +0100)]
rx: Don't build a call to immediately abort it
If the server is over the busy threshold, then don't create a new
call structure just to be able to send an abort on that call. Instead,
use rx_SendRawAbort to send an abort packet on the appropriate channel.
Simon Wilkinson [Thu, 25 Oct 2012 12:34:33 +0000 (13:34 +0100)]
rx: Remove unreachable debug statement
ReceivePacket has a dpf which is conditional on the packet having a
zero callnumber. However, just before we reach this debug statement,
we always return if the header doesn't have a call number included.
So, the debug statement can never run. Just remove it, as it's
potentially confusing.
Jeffrey Altman [Mon, 29 Oct 2012 16:59:14 +0000 (12:59 -0400)]
Windows: Set Server Prefs recalc immediately
When processing the set server preferences pioctl call cm_RankServer()
to update the server preference value reported by "getserverprefs"
in addition to cm_ChangeRankVolume() or cm_ChangeRankCellVLServer().
Jeffrey Altman [Mon, 29 Oct 2012 14:33:18 +0000 (10:33 -0400)]
Windows: mark server reference offline for VOFFLINE
cm_Analyze() was not marking the cm_ServerRef_t reference to
a volume instance as srv_offline in response to a VOFFLINE error.
As a result the same volume instance is tried again and again.
Returning STATUS_MEDIA_WRITE_PROTECTED in preference to
STATUS_OBJECT_NAME_COLLISION when the file results in silent
failures by some applications (ie, Firefox.exe) when the
first directory in the path below the share name is the
root of a .readonly volume.
Simon Wilkinson [Thu, 25 Oct 2012 10:49:55 +0000 (11:49 +0100)]
rx: Get rid of AFS_GLOBAL_RXLOCK_KERNEL
Get rid of the AFS_GLOBAL_RXLOCK_KERNEL #define. RX used to have a
single global lock locking mode, but none of our kernel modules use
it any more. In fact, AFS_GLOBAL_RXLOCK_KERNEL is now only defined
when RX_ENABLE_LOCKS is also defined. Simplify the code by renaming
all of the occurrences of AFS_GLOBAL_RXLOCK_KERNEL as RX_ENABLE_LOCKS,
and remove any cases where we're now doing unecessary tests
Simon Wilkinson [Thu, 25 Oct 2012 10:32:03 +0000 (11:32 +0100)]
rx: Don't have 2 different protos for rxi_CheckCall
Use a single prototype for rxi_CheckCall in both the pthread and
lwp cases. Remove the #ifdef maze at the call sites, and take advantage
of the fact that MUTEX_EXIT reduces to an empty string in the lwp
case.
Simon Wilkinson [Thu, 25 Oct 2012 10:27:33 +0000 (11:27 +0100)]
rx: Don't double check conn->call
We currently have
call = conn->call[channel]
if (call) {
...
} else {
call = conn->call[channel]
if (call) {
...
}
}
As we don't drop (or acquire) any locks between the first and the
second check of call, there's no way that the result can be different
from the first time we checked. So just get rid of the uneccessary
code, and reindent the following block to match.
Simon Wilkinson [Tue, 23 Oct 2012 18:21:09 +0000 (19:21 +0100)]
rx: Move bytesSent + bytesRcvd into app only data
The call->bytesSent and call->bytesRcvd counters are only manipulated
by the application thread in running calls. Move them into the app-only
section of the call structure so this is clear.
Simon Wilkinson [Tue, 23 Oct 2012 12:35:43 +0000 (13:35 +0100)]
rx: Don't use app-thread variable in SendXmitList
The value of call->app.mode is changed by the application thread
without taking the call lock. Instead of using this variable in
SendXmitList to determine whether the queue should be flushed, add
a new flag (RX_CALL_FLUSH) to control flushing behaviour.
As call->flags is manipulated under the call lock, its value can
be safely used by SendXmitList.
Simon Wilkinson [Tue, 23 Oct 2012 11:41:07 +0000 (12:41 +0100)]
rx: Make lock-free call data explicit
For speed, the application thread accesses a number of elements of
the call structure without holding the call lock. This is safe, as
long as the application thread is the only place in which these
items of data are accessed.
Make this distinction explicit by creating a new structure to hold
all of these fields, and include this structure within the rx_call.
This turns up one place in the code (SendXmitList) which accesses an
application private piece of data in the listener and event threads.
A forthcoming patch will fix this.
Jeffrey Altman [Mon, 6 Aug 2012 16:19:26 +0000 (12:19 -0400)]
Windows: Send all \\AFS\PIPE to afsd_service
Anytime there is a pipe service request, forward it to the
afsd_service.exe and permit the service to manage the request.
The prior implementation resulted in STATUS_FILE_NOT_FOUND errors
being delivered when an unexpected service was requested.
Jeffrey Altman [Fri, 19 Oct 2012 15:26:21 +0000 (11:26 -0400)]
Windows: ObjectInfo RefCount 0 <-> 1 transitions
When the reference count transitions from 0 <-> 1 ensure that the
ObjectInfoLock is held exclusive to prevent the current thread from
altering the state while another thread is holding the ObjectInfoLock
shared in order to conditionally perform an action based upon
the the reference count being zero.
Patchset eaad522651a81f20eac4966a55a731e0e59e39dd inadvertently
introduced a deadlock with invalidation requests from the service.
It is not safe to hold the ObjectInfoLock resource across calls
to AFSCleanupFcb(). Instead of holding the lock obtain a reference
to the ObjectInformationCB.
Jeffrey Altman [Thu, 25 Oct 2012 18:33:29 +0000 (14:33 -0400)]
Windows: AFSCleanup re-organization
Reorganize the activities of the AFSCleanup() for File FCBs
so that the Fcb Resource can be dropped prior to issuing the
cleanup request to the cache manager. The cache manager can
block for a long period of time while flushing data and holding
the Fcb resource blocks all subsequent CreateFile requests.
Jeffrey Altman [Thu, 25 Oct 2012 18:31:14 +0000 (14:31 -0400)]
Windows: AFSCleanup Flush Data decision
AFSCleanup() should instruct the cache manager to flush dirty
data when the Context Control Block indicates that the handle
being closed was opened for writing and was granted appropriate
permissions. The decision to flush should not be dependent on
the open handle count because the last handle might belong to
an authentication group that does not have write permission.
Jeffrey Altman [Tue, 23 Oct 2012 00:40:21 +0000 (20:40 -0400)]
Windows: AFSMarkDirty() require ExtentsResource held
Instead of dynamically testing if the ExtentsResource is held
and if not acquire it within AFSMarkDirty(), simply require that
it be held. AFSMarkDirty() is only called from one location.
Jeffrey Altman [Tue, 23 Oct 2012 00:34:59 +0000 (20:34 -0400)]
Windows: AFSFlushExtents QueuedFlushCount leak
The FCB QueuedFlushCount was decremented in all code paths
but only incremented if the AuthGroup acquisition succeeded.
Increment the counter before the AuthGroup checks.
Jeffrey Altman [Tue, 23 Oct 2012 00:29:47 +0000 (20:29 -0400)]
Windows: RDRFunction remove DebugBreak
DebugBreak hard coded into the source tree makes debugging
other unrelated issues difficult if the code path being executed
includes them. Remove them.
Jeffrey Altman [Fri, 19 Oct 2012 13:33:18 +0000 (09:33 -0400)]
Windows: Promote DELETED from DirEntry to ObjInfo
On deletion of the DirEntry in AFSDeleteDirEntry() set the
AFS_OBJECT_FLAGS_DELETED flag on the ObjectInformation object
if and only if the AFS_DIR_ENTRY_DELETED flag was set in the
DirEntry. Setting the AFS_OBJECT_FLAGS_DELETED should not
be conditional on the ObjectInformatION ReferenceCount being
zero.
Remove the test and set of AFS_OBJECT_FLAGS_DELETED from
AFSClose() because that operation will already have been
performed in the call to AFSDeleteDirEntry() if necessary.
Jeffrey Altman [Tue, 16 Oct 2012 13:36:56 +0000 (09:36 -0400)]
Windows: Remove 'bAllocatedFcb' from AFSCreate.cpp
All functions now call AFSInitFcb() and the ObjectInfo->Fcb == NULL
test is performed internally. Therefore, it is not possible for
the caller to track whether or not an Fcb was allocated. It is
irrelevant. The Fcb will be cleaned up when the ObjectInfo is
destroyed by the PrimaryVolumeWorker thread.
Jeffrey Altman [Mon, 8 Oct 2012 03:41:32 +0000 (23:41 -0400)]
Windows: PrimaryvolumeWorker do not pause if busy fcb
The AFSPrimaryVolumeWorkerThread should not unnecessarily block
on the FCB Resource because such blockage could be the result of
of waiiting for extents to be delivered from the service. The
AFSPrimaryVolumeWorkerThread is the primary method by which
extents are released back to the service.
AFSCleanupFcb() is modified to return STATUS_RETRY if the Fcb
resource cannot be obtained without blocking.
The AFSPrimaryVolumeWorkerThread() does not call
AFSCleanupFcb() with 'ForceFlush' parameter set to TRUE and
remembers if STATUS_RETRY is returned. If any Fcb was busy,
then the worker does not wait for the 5 second timer to fire.
The FCB ExtentsRequestComplete KEVENT setting, clearing
and testing was racy. Clear the event before issuing the
request to the service and if the request fails, set it in
case two threads issued requests for the same FCB in parallel
and one fails and the other succeeds.
We must ensure that a clear does not mask the event being set
prior to the request thread returning.
Jeffrey Altman [Thu, 18 Oct 2012 13:56:12 +0000 (09:56 -0400)]
Windows: clear pending delete upon deletion
During cleanup processing if the DELETE_PENDING flag is set
the service will be told to delete the file when the handle
count reaches 1. At that point the file will be deleted
and the DELETED flag will be set on the object info object.
The DELETE_PENDING flag was not being cleared which could
lead to confusion. This patchset clears the flag after deletion.
Jeffrey Altman [Sun, 7 Oct 2012 14:23:19 +0000 (10:23 -0400)]
Windows: AFSInitFcb Check ObjectInfo->Fcb for NULL
Now that AFSInitFcb is called under the ObjectInfoLock, it is
once again safe to perform a test for ObjectInfo->Fcb != NULL
and return immediately if an Fcb is already assigned.
Jeffrey Altman [Fri, 5 Oct 2012 15:36:45 +0000 (11:36 -0400)]
Windows: Protect ObjectRefCnts with ObjectInfoLock
The ObjectInfoCB.ObjectReferenceCount is tested to determined
when it is safe to remove an FCB from the ObjectInfoCB. The
value must not be permitted to change while a removal is performed.
Protect AFSRemoveFcb() calls with exclusive holds of the
ObjectInfoCB.NonPagedInfo->ObjectInfoLock. New functions:
AFSObjectInfoIncrement()
AFSObjectInfoDecrement()
perform all increments and decrements while holding the
ObjectInfoLock in a Shared state.
Jeffrey Altman [Wed, 3 Oct 2012 01:07:21 +0000 (21:07 -0400)]
Windows: Always AFSInitFcb and AFSRemoveFcb
Instead of comparing ObjectInfo->Fcb to NULL and conditionally
calling AFSInitFcb() or AFSRemoveFcb(), always call them and use
InterlockedExchangePointer() as the test.
Jeffrey Altman [Sat, 6 Oct 2012 21:36:25 +0000 (17:36 -0400)]
Windows: AFSRequestExtentsAsync and AFSDoExtentsMapRegion
When calling AFSDoExtentsMapRegion() the FCB ExtentsResource
must be held. AFSRequestExtentsAsync() failed to hold the
ExtentsResource across the call.
The LazyWriterThread should not be recorded in the FCB. It is
possible for multiple lazy writes to occur on a file in parallel
in separate threads. The value is not used for anything in any
case. AFSCommonWrite() tests the LazyWriterThread value but only
if 'bMapped' is FALSE. Since 'bMapped' is always TRUE, the
comparison is never performed. Remove the test and the value.
Jeffrey Altman [Sun, 14 Oct 2012 19:46:06 +0000 (15:46 -0400)]
Windows: Add cm_SyncOp to cm_ReadMountPoint()
Add a cm_SyncOp(CM_SCACHESYNC_FETCHDATA) call to cm_ReadMountPoint()
to prevent multiple FetchData RPCs being issued for the same
mount point at the same time.
In AFSInitFcb() assign pFcb->ObjectInformation before the
InterlockedExchangePointer call and not afterwards. Assigning
it afterwards leaves a small race where the ObjectInformation
value will be invalid.
Jeffrey Altman [Wed, 17 Oct 2012 00:26:43 +0000 (20:26 -0400)]
Windows: OpenTargetDirectory AFSInitFcb Reparse Test
In AFSOpenTargetDirectory the test to determine if AFSInitFcb
allocated a FCB or returned an existing one (STATUS_REPARSE)
was reversed. If AFSInitFcb was called and AFSOpenTargetDirectory
eventually failed, an in use FCB would be freed.