struct NFS41_V_NET_ROOT_EXTENSION now stores only the FILE_FS_ATTRIBUTE_INFORMATION (without the extra buffer space for a name). on QueryVolumeInfo() for FileFsAttributeInformation on the root directory, the FILE_FS_ATTRIBUTE_INFORMATION is copied into the output buffer, and the name is added there. QueryVolumeInfo() only makes upcalls when FileFsAttributeInformation queries are not for the root directory
new function is_root_directory() uses the logic from Set/GetReparsePoint() to determine whether it's operating on the root directory
moved logic from volume.c:handle_volume_attributes() to superblock.c:nfs41_superblock_fs_attributes(). the mount downcall copies the FILE_FS_ATTRIBUTE_INFORMATION buffer down to the driver. the driver reads this buffer directly into VNetRootContext->FsAttrs
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
adds a new function nfs41_superblock_getattr(), which adds an OPENATTR call with createdir=0 after the GETATTR to check for named attribute support. OPENATTR will either return ERR_NOTSUPP if not supported, or OK/ERR_NOENT depending on whether named attributes are present on the given file. we can't query for the 'named_attr' attribute, because it only tells us whether the given file contains named attributes
if named attributes are supported on a superblock, it will return FILE_SUPPORTS_EXTENDED_ATTRIBUTES for associated volume queries
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
on creation of a new superblock, construct a bitmap for the default attribute mask to be used for GETATTR and READDIR requests on that filesystem. mask out any unsupported attributes, and store the bitmap in the field nfs41_superblock.default_getattr
replaced function init_getattr_request() with nfs41_superblock_getattr_mask(), which returns a copy of superblock->default_getattr
removed the locking in nfs41_superblock_supported_attrs() and nfs41_superblock_supported_attrs_exclcreat(), as the supported_attrs and suppattr_exclcreat fields are read-only after the superblock is first initialized. also factored out their common code into a bitmap_intersect() function in util.h
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
when we receive a delegation recall, we need to make a downcall
to the kernel and change a buffering/caching policy on this file.
on each open and close we pass an srv_open pointer to the nfsd to
keep in case it receives a cb_recall. we store srv_open in the
delegation state if we got a delegation.
iozone tests were failing intermittently against emc-2 due to out-of-order LAYOUTCOMMITs that both specified new_last_offset
nfs41_open_state now maintains a cached value of the last_offset, and avoids sending it with LAYOUTCOMMIT unless the new last_offset is greater than the cached offset. this cached value is initialized on open/delegation, and updated on setattr for size
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>
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_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>
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>
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>
if we receive an rpc_autherr, just recreate a new rpc client as well
as the rpc auth structure. as it ties into the recovery and handles
that only one thread recovers and reestablishes the rpc auth context.
in theory, reestablishing rpc client does not necessitate new rpc auth
context. we really need to restablish one only if we get rpc autherr. however,
it simplifies the code not to introduce a different synchronization
mechanism for rpc auth in addition to the rpc one.
nfs41_cb_session stores the last cb_compound reply (whether or not cachethis was set) to handle retry attempts, along with the cb_compound arguments for improved NFS4ERR_SEQ_FALSE_RETRY detection
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
on a successful LAYOUTGET, file_layout_fetch() calls layout_update() to copy the first layout segment returned and update the layout stateid
on a successful LAYOUTRETURN, file_layout_return() frees the layout segment and updates/clears the stateid
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
moved state data (stateid, flags, locks, and reference counts) out of struct pnfs_layout, which should represent a layout segment returned by LAYOUTGET
struct pnfs_layout_state now holds this state, along with a pointer to a single pnfs_file_layout
struct pnfs_file_layout_list is now a list of pnfs_layout_states, and was renamed to pnfs_layout_list
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>
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>
operations that require a stateid now take stateid_arg for recovery information. these operations include close, setattr, lock/unlock, layoutget, and read/write (including pnfs)
nfs41_open_stateid_arg() locks nfs41_open_state and copies its stateid into a stateid_arg
nfs41_lock_stateid_arg() locks nfs41_open_state.last_lock and copies its stateid into a stateid_arg; if there is no lock state, it falls back to nfs41_open_stateid_arg()
pnfs_read/write() now take nfs41_open_state so they can generate stateid_args
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>
open state is added to the client's list on a successful call to nfs41_open(), and removed from the list on nfs41_close() regardless of success
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
very similar to the issue with nfs41_open_state, an abandoned upcall could outlive its mount. to prevent their nfs41_root from being freed, upcalls need to hold a reference until they're finished. this also keeps all of its clients/sessions/rpc connections alive
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
fixes a memory leak that occurs when a readdir loop doesn't complete, since the cookie was only freed on the last readdir upcall. by storing the cookie with nfs41_open_state, we can avoid passing the cookie to the driver and back, and not worry about having to free it separately
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
in handle_mount(), the call to nfs41_lookup() requires a mutable nfs41_abs_path because it can change on referrals, so make a copy for it
removed unused fields in struct nfs41_root and related arguments to nfs41_root_create()
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
because we no longer have to convert strings from unicode, we can avoid copying them out of the upcall buffer
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>