when marshalling of the open downcall or allocating buffer for the downcall
fails, upcall.status gets set but we still need to cancel the open we
just did. instead check for non-allocated open state as evidence that
handle_open() failed and we don't need to cancel vs the other failure.
windows api frequently sends a query security with a buffer len of 0
to figure out how big of buffer is needed for a security descriptor.
we send a getattr for acl attribute on the 1st irp, then cache the
returned security descriptor in fobx. on the 2nd query, if the buffer
is cached and it's not "stale", we return that buffer.
to prevent delegations from claiming all available slots in the attribute cache, nfs41_name_cache_insert() now returns ERROR_TOO_MANY_OPEN_FILES when the number of delegated entries reaches 50% of the cache capacity. see comment 'delegations and cache feedback' in name_cache.c for details
when nfs41_open() sees this error from nfs41_name_cache_insert(), it calls new function nfs41_client_delegation_return_lru() to return the least-recently-used delegation and, if successful, loops back to nfs41_name_cache_insert(). nfs41_client_delegation_return_lru() returns NFS4ERR_BADHANDLE if all delegations are currently in use (associated with an existing open), in which case nfs41_open() returns the newly-granted delegation
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
on opens that grant a delegation, return the delegation immediately if attribute cache insertion fails
nfs41_name_cache_insert() now returns success in the 'out_err_deleg' case, where name cache insertion failed but attr cache insertion was successful
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
once the attribute cache fills up with delegated entries, attr_cache_find_or_create() will start returning ERROR_OUTOFMEMORY. this is a problem for nfs41_name_cache_insert(), because name_cache_find_or_create() will succeed and then name_cache_entry_update() will fail. this leaves behind a name cache entry with attributes=NULL, which is treated like a negative entry and causes later lookups to fail with ERROR_FILE_NOT_FOUND
added a call to name_cache_entry_invalidate() to clean up this entry if name_cache_entry_update() fails
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
use GetTickCount64() for EXCHANGE_ID's client verifier instead of time(). the higher resolution helps prevent conflicting verifiers
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added 2011 year to the copyright line
added authors info to the license
added UofM license to libtirpc files that we modified
(but i probably missed some)
new flags for nfs41_lock_state: exclusive, delegated, and id
on lock, open_lock_delegate() attempts to register a delegated lock instead of sending a LOCK request to the server
on unlock, open_unlock_delegate() removes/frees delegated locks instead of sending a LOCKU request
on delegreturn, delegation_flush_locks() sends LOCK requests for all delegated locks before returning a delegation
on recovery, recover_locks() avoids lock state recovery for delegated locks
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
for delegations without an associated open, try the optional WANT_DELEGATION operation with CLAIM_PREVIOUS before falling back to OPEN/CLAIM_PREVIOUS. the advantage of WANT_DELEGATION is that it doesn't generate an open stateid, so we don't need the corresponding CLOSE as in recover_delegation_open(). if WANT_DELEGATION fails with NFS4ERR_NOTSUPP, don't try it again during that round of state recovery
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
10.2.1. Delegation Recovery (re: client restart/lease expiration)
A server MAY support claim types of CLAIM_DELEGATE_PREV and CLAIM_DELEG_PREV_FH, and if it does, it MUST NOT remove delegations upon a CREATE_SESSION that confirm a client ID created by EXCHANGE_ID. Instead, the server MUST, for a period of time no less than that of the value of the lease_time attribute, maintain the client's delegations to allow time for the client to send CLAIM_DELEGATE_PREV and/or CLAIM_DELEG_PREV_FH requests. The server that supports CLAIM_DELEGATE_PREV and/or CLAIM_DELEG_PREV_FH MUST support the DELEGPURGE operation.
if there's a delegation to reclaim, recover_open_no_grace() now tries CLAIM_DELEGATE_PREV (supported by emc server, but not linux) before falling back to CLAIM_NULL
nfs41_client_delegation_recovery() sends DELEGPURGE to indicate that we're finished reclaiming delegations
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
while the server is required to grant us delegations we reclaim through CLAIM_PREVIOUS, it may set the flag recalled=TRUE if it's not ready to grant the delegation. the client is then responsible for flushing modified state to the server and returning the delegation
new function nfs41_client_delegation_recovery() cleans up after delegation recovery by a) returning any delegations flagged as recalled, and b) 'forgetting' any delegations that we failed to reclaim. this function is called under the client's state recovery lock, directly after open and delegation state is recovered
added 'try_recovery' argument to delegation_return(), allowing it to be called during client state recovery. split out the code that removes the delegation from the client and its opens into delegation_remove(), which is what nfs41_client_delegation_recovery() uses to 'forget' a delegation
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
delegation stateid arguments to DELEGRETURN and OPEN are now stateid_arg, for use with recover_stateid_delegation(). added a nfs41_delegation_state pointer to stateid_arg, for when a delegation stateid is used in the absence of nfs41_open_state (DELEGRETURN, SETATTR)
recovery during a call to nfs41_delegation_to_open() requires special attention; recover_stateid_delegation() has to handle the case where recover_open() already reclaimed the open stateid. it does this by returning BAD_STATEID instead of retrying the OPEN (which would generate yet another open stateid)
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
recover_client_state() flags all delegations as revoked before starting open state recovery. if recover_open() finds that its delegation is revoked, it attempts to recover it using CLAIM_PREVIOUS. if its delegation has already been reclaimed by another open, it can skip reclaiming the open stateid (provided it has no byte-range locks to reclaim). after all opens have been reclaimed, any delegations still marked 'revoked' are passed to recover_delegation(). recover_delegation() also uses CLAIM_PREVIOUS (or CLAIM_NULL outside of the grace period) to reclaim the delegation, but has to throw away the open stateid with CLOSE
added a try_recovery argument to nfs41_delegreturn() and nfs41_delegation_granted(), so it can be called by recover_open() if OPEN grants an unexpected open
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
nfs41_recover_client_state() remembers whether it's seen NFS4ERR_NO_GRACE, and will avoid sending RECLAIM_COMPLETE and the recovery versions of OPEN and LOCK
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
moved recovery of lock stateids from recover_open() to new function recover_locks()
split nfs41_recover_stateid() into recover_stateid_open() and recover_stateid_lock()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
nfs41_open() in open.c is no longer used for recovery, so made static and renamed to do_open(). renamed nfs41_rpc_open() back to nfs41_open()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
recovery.h exposes the following functions for nfs41_compound.c:
nfs41_recovery_start_or_wait()
nfs41_recovery_finish()
nfs41_recover_client_state()
nfs41_recover_stateid()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
previously we'd query owner and group file attributes on all getattrs and
storing that in nfs41_file_info structure which was caused a problem for
readdirs.
prevent an OPEN with OPEN4_CREATE from breaking a write delegation by sending a SETATTR instead
moved static function remove_unsupported_attrs() from setattr.c to nfs41_superblock_supported_attrs() in nfs41_superblock.c, now used by both setattr.c and delegation.c
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
new function nfs41_delegation_return() for synchronous delegation return. uses a condition variable to wait if another thread is already returning the delegation
if nfs41_delegate_open() would conflict with a delegation, return it before sending the OPEN
return the delegation before sending LINK, RENAME, REMOVE, and SETATTR
all of this functionality is dependent on the preprocessor define DELEGATION_RETURN_ON_CONFLICT (on by default). if not defined, nfs41_delegation_return() is a noop
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when a delegation is granted by OPEN, its delegation type is passed to nfs41_name_cache_insert(). as long as the delegation is held, its name_cache_entry is kept out of the cache.exp_entries list to prevent it from expiring. an extra reference is held on the attr_cache_entry as well, so it sticks around even if the name_cache_entry is removed (a parent expires, for example). new function nfs41_name_cache_delegreturn() adds the name_cache_entry back to the list, and releases the extra attr_cache_entry reference
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
combined nfs41_lock_stateid_arg() into nfs41_open_stateid_arg(). if a delegation is present, use the delegation stateid before looking at lock/open stateids. if a delegation recall is in progress, wait on its condition variable before falling back to the open stateid
made nfs41_lock_stateid_arg() static to lock.c because of its special semantics; open_to_lock_owner4 for LOCK won't accept a delegation stateid, so nfs41_delegation_to_open() is called to convert it
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
moved thread creation from callback_server.c to nfs41_delegation_recall() in delegation.c
nfs41_delegation_recall() first searches for the delegation, and returns NFS4ERR_BADHANDLE if not found. otherwise, it spawns a thread to handle the recall and returns NFS4_OK
delegation_return() calls nfs41_delegation_to_open() for each nfs41_open_state associated with the delegation
nfs41_delegation_to_open() sends OPEN with CLAIM_DELEGATE_CUR to reclaim an open stateid, and uses a condition variable in nfs41_open_state to prevent multiple threads from attempting reclaim
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
added delegation.c and .h
nfs41_client stores a list of nfs41_delegation_state
new function nfs41_delegate_open() to look for a compatible delegation before calling nfs41_open()
if nfs41_open() is granted a delegation, call nfs41_delegation_granted() to register it with the client
client calls nfs41_client_delegation_free() on unmount to free list of delegations
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
combined nfs41_open() and nfs41_open_reclaim() into nfs41_rpc_open() by factoring out the open_claim4 argument. new function nfs41_open() in open.c deals with the nfs41_open_state, adding it to the client's list, and handles any delegations granted
added xdr for OPEN CLAIM types CLAIM_DELEGATE_CUR, CLAIM_DELEG_CUR_FH, CLAIM_DELEGATE_PREV, CLAIM_DELEG_PREV_FH (the _FH types are new to 4.1, and not supported by linux server)
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
in create_session we were sending auth_none as available security types
for the callback channel. Adding auth_sys to the list. No enforcement of
these creds happens.
this function was called before writes and was setting time and size
attributes of the file. we were translating it into a setattr. reads
were also followed by a setattr of timestamp (unnecessarily)
instead of updating the attribute cache with the values given to SETATTR, add a GETATTR to the compound; this will capture changes to time_modify and change that the client could otherwise miss, and get the server's value of timestamps sent with SET_TO_SERVER_TIME4
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
removed issue for nfs_mount.exe not listing mounted drives
modified issue for renaming on top of an open file (now returns an error)
added issue suggesting DisableDfs
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
handling receiving WRONGSEC error in compound_encode_decode function by
sending either SECINFO or SECINFO_NONAME op to find out available
security flavors from the server. then try to establish new security
context given the ordered list returned by the server.
Not handling if parent directory doesn't permit a security flavor of
its child directory. Example "/" exported with only auth_sys and
"/sec" exported with only "gss".
proposes an alternate solution for attempts to set file size without an open sta
teid. instead of acquiring one by sending OPEN, fail the request with ACCESS_DE
NIED
according the MS File System Algorithms documentation for setting FileAllocation
Information and FileEndOfFileInformation [http://msdn.microsoft.com/en-us/librar
y/ff469355%28v=PROT.10%29.aspx]:
"If Open.GrantedAccess does not contain FILE_WRITE_DATA, the operation MUST be f
ailed with STATUS_ACCESS_DENIED"
-removes open_owner_id, access_mask, access_mode from setattr upcall arguments
-moves map_access_2_allowdeny() back to open.c as a static function, since handl
e_setattr() was its only other call site