if we're recovering a lock stateid for a LOCK operation, and the file has no outstanding locks, we won't be able to recover a lock stateid. resend the LOCK with an open stateid instead
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
if we see NFS4ERR_NO_GRACE from recovery operations, it means we lost our state due to a lease expiration rather than a server reboot. in this case, it's possible that conflicting locks were granted to other clients, so we have to try normal OPEN/LOCK operations to recover our state. because they're sent during recovery, nfs41_open() and nfs41_lock() take a new 'bool_t try_recovery' argument so we can avoid recursion
if these operations fail due to conflicting locks, we have no choice but to return errors to the application. using a stateid that was revoked due to lease expiration results in NFS4ERR_EXPIRED, and we map this error to ERROR_FILE_INVALID: The volume for a file has been externally altered so that the opened file is no longer valid.
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
nfs41_open_state maintains a list of outstanding byte-range locks by calling open_lock_add() and open_lock_remove() in lock.c
during client state recovery, after reclaiming each OPEN stateid, send LOCK requests with reclaim=TRUE for each lock it owns, and update the open's lock stateid with the result
added 'bool_t reclaim' argument to nfs41_lock(); when set, compound_encode_send_decode() is called with try_recovery=FALSE to avoid recursive recovery
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
avoid the recursive case where state recovery operations (OPEN for reclaim and RECLAIM_COMPLETE) return BADSESSION, which kicks off another round of recovery
added a 'bool_t try_recovery' argument to compound_encode_send_decode() in place of its unused 'bufsize_in' and 'bufsize_out'. when try_recovery=FALSE, return BADSESSION/STALE_CLIENTID errors instead of attempting recovery. nfs41_open_reclaim(), nfs41_reclaim_complete(), and nfs41_destroy_session() now pass try_recovery=FALSE
during state recovery, we can now check the return values of nfs41_open_reclaim() and nfs41_reclaim_complete() for BADSESSION, and use a goto to restart session recovery
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
moved recovery-related fields into struct nfs41_client.recovery. now uses a com
bination of CRITICAL_SECTION and CONDITION_VARIABLE for use with SleepConditionV
ariableCS()
renamed check_renew_in_progress() to recovery_start_or_wait(), and fixed the loc
king so that we atomically check/set in_recovery
when recovery is finished (including error conditions), call recovery_finish() t
o reset the recovery status and wake any waiting threads
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
consider an operation that takes a stateid, and results in a BADSESSION error due to server reboot. we'll recover the client and session, and send OPENs to reclaim all of the client's state. but after recovery, we'll resend the original operation with the original stateid, and this will result in a STALE_STATEID error
we handle this by making use of the information in stateid_arg. if we determine that stateid_arg.stateid is different from the nfs41_open_state's stateid, we copy the new stateid into stateid_arg.stateid and retry
note that if another thread is in recovery, it hasn't finished reclaiming its open state yet; so we wait on recovery to finish before comparing the stateids
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
after the client and session have been recovered, loop through the client's list of open state, calling nfs41_open_reclaim() and updating the stateid on success
nfs41_open_state saves the share_access and share_deny fields from the initial open, for use with nfs41_open_reclaim()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>