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>
to determine that the daemon has restarted -- rather that daemon is receiving upcalls from the kernel that were processed by the old instance of the daemon -- add a version to the upcall mechanism.
when daemon starts up it generates a version number (just a timestamp). it passes this value to the driver on start up via "start_ioctl" downcall. the driver saves that value in its device extensions. it uses that value in the mount and shtudown upcalls.
when daemon replies to the mount command it again sends its version as a part of the reply. this reply is stored in driver;s netroot extensions. the driver uses netroot's value in each upcall to the daemon.
if the daemon receives an upcall for an operation where the included version does not equal to the its current version, it fails the upcall (error_code=116).
a restart of the daemon would change driver's device extension value which the driver will then use in the new mount upcalls that would establish new sessions. then the correct daemon version would be returned as a part of the mount downcalled and saved in the netroot.
struct idmap_context contains configuration data (struct idmap_config), a cache for users, and a cache for groups. idmap_context is declared in idmap.c, and only available as an opaque pointer (nfs41_idmapper) elsewhere. similarly, Winldap.h is only included by idmap.c, and not needed elsewhere
nfs41_idmap_create() allocates the idmap_context, loads the configuration from file, and calls ldap_init(). it does not call ldap_connect(); we'll still be able to start the daemon if ldap isn't configured, or the ldap server is down. calling ldap_connect() is optional, as any ldap operation that requires a connection will establish it internally. this behavior, along with the LDAP_OPT_AUTO_RECONNECT option (defaults to on), means that we shouldn't have to maintain a separate connection for each thread
nfs41_idmap_*() functions return windows errors codes. LDAP_RETCODEs are mapped to windows errors with LdapMapErrorToWin32()
the user and group caches share a common generic interface in struct idmap_cache, which uses a linked list for storage, and protects access with a SRWLOCK. expiration of cache entries can be adjusted by the config option 'cache_ttl'
struct config_option g_options[] is a table of available config options and their default values. this patch adds a 'ms-nfs41-idmap.conf' file with all possible options set to default values, and commented out. the daemon expects to find this file under c:\etc\, and won't start if it can't be opened or parsed
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
IOCTL_NFS41_DELCONN had a check for RxDeviceObject->NumberOfActiveFcbs before calling nfs41_DeleteConnection(). this prevents us from unmounting even if the netroot has no open files, and is redundant because nfs41_FinalizeNetRoot() already has the necessary check for NetRoot->NumberOfFcbs/SrvOpens
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>
added call to upcall_cleanup() after both upcall_marshall() and upcall_cancel()
individual upcall operations define their nfs41_upcall_op structs locally, instead of putting tons of function prototypes in upcall.c
made the upcall_marshall() function optional; most marshall functions are noops
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>
if the thread placing an upcall was woken up from the sleep, but have not been picked up by the daemon thread from the upcall queue, we would just cancel the upcall. thus nfsd would never see it. however, it was causing leaks in the open state. we would allocate open state but matching close would never make it to the daemon.
instead, always place an upcall to the daemon, but mark it that nobody is waiting for it if the requesting thread gets interrupted and goes away.
while following symlinks on open, after we break from the loop we need to respect that nfs41_lookup could have returned some kind of error value. thus only return error_reparse if nfs41_lookup returned success or file_not_found error.
similarly in after calling nfs41_symlink_follow() only set the reparse_error if function was successful.