every upcall (except few) pass session and open_state pointer, so
add that to marshal_nfs41_header() in the driver. remove passing
of session and open_state elsewhere in marshal functions.
in the deamon, upcall.c now reads and stores pointers to session
and open_state in nfs41_upcall datastructure instead of having
each individual upcall store their own pointers. setattrl
and readdir args keeping pointer because the rest of the code
uses them a lot.
in upcall_parse() up refcounts on session and open_state if
valid handles were passed in. down refcounts upcall_cleanup() as
before. but need to be careful with count value for mount and open
upcalls. we need to take an extra ref because upcall_cleanup() now
will always decrement it.
reformated some of the old functions.
finalized mapping functions for windows to nfs4 access mask bits.
satisfying nfs41_acl_query for dacl.
when doing setacl and creating "who" field of the format user@nfs4domain,
use dns domain name of the windows client machine
instead of passing sids for the owner and group, create a security
descriptor and pass that back. this way we can add all the security
information that was queried in the daemon and pass a fully formed
security descriptor back to the kernel.
notice: irp_mj_query_security provides a pointer to the buffer that
suppose to hold the security descriptor. that memory is valid only
in the context of the process doing the security irp. we can't use
this pointer in then upcall entry and try to write the security
descriptor directly there as we process the downcall. that leads
to kernel oops.
thus we have to first allocate memory to hold the security descriptor
then copy bytes passed to us from the daemon. then do another copy
with the context of the security irp.
this commit does NOT have correct windows to nfs4 acl mappings but
rather has the wrapper functions defined for mapping them.
cthon tests still work with these mappings.
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>
acls are lists of arbitrary length, so xdr_array() is used to allocate the array
during decode. because this memory is allocated by the tirpc library, it needs
to be freed there as well; added function nfsacl41_free() to do this with XDR_F
REE
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
Basic handling of owner and group security query (no dacl).
Added new upcall for NFS41_ACL_QUERY (driver and daemon code).
Daemon, upon getting NFS41_ACL_QUERY first places a getattr that has
owner, group attribute request. We currently don't cache them!!!
Then, we parse nfs4name format (ie user@domain or group@domain)
into user and domain. We currently ignore domain part!!!
Then, we assume that whatever we are mapping is "known" locally
(ie LookupAccountName() api which retrieves a SID for a given name).
Mapping from name to SID can only be done in the userland. We then
copy the bytes via the upcall pipe to the kernel. If the received
user or group cant be mapped via LookupAccoundName(), we create a
well known null SID as the reply.
Kernel creates a security descriptor in the absolute-format and adds
owner and group sids to it. Important: RtlSetOwner/Group functions only
work with absolute-format security descriptor, however the reply to the
user needs to be in the self-relative format.
The way security query works is that it passes us a buffer to be filled
with the security context. However the user doesn't know how big the
buffer should be so, the user is allowed to pass a null buffer and have
the kernel return how much memory is needed. This leads to 2 security
queries => 2 NFS41_ACL_QUERY upcalls => 2 getattr rpcs... It should be
improved.
TODO:
- need to add caching of owner/group attributes for a file?
- need to add calls to LDAP for more general mapping?
- need to cache reply of the ACL if supplied length is 0?
adding a check to see if the destination filename is currently opened by
looking through the list of open states stored for a given client.
fail rename with ERROR_FILE_EXISTS if we find an open.
exclusive locks are no longer held over LAYOUTGET, LAYOUTRETURN, or GETDEVICEINFO rpcs. this prevents a deadlock when CB_LAYOUTRECALL needs an exclusive lock while another operation is on the wire
introduced a 'pending' condition variable to protect access to state->layout while the layout's lock is not held
updated file_layout_recall() to compare the stateid sequence numbers to determine if the server has processed an outstanding LAYOUTGET or LAYOUTRETURN, where we're required to reply with NFS4ERR_DELAY
LAYOUTGET, LAYOUTRETURN, and GETDEVICEINFO can now be sent with try_recovery=TRUE because they no longer hold an exclusive lock. this makes it possible for recover_client_state() to recall all of the client's layouts without deadlocking
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
nfs41_lock_stateid_arg() is now called only once in handle_read()/handle_write(), and pnfs_read()/pnfs_write() no longer depend on nfs41_open_state
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>
LAYOUTGET xdr now supports decoding of multiple layout segments, which are returned in a list with pnfs_layoutget_res_ok
LAYOUTRETURN no longer operates on an existing pnfs_file_layout. it now takes a copy of the layout stateid, and returns the new stateid with pnfs_layoutreturn_res
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>
we already drop the lock between sending and receiving the rpc packets. now making it so that receive doesn't block for too long (ie 100ms) before unlocking the socket. this is needed for the callback. original rpc is sent and it triggers a callback from the server. we fork another thread to handle it, ie it needs to send a deleg_return rpc. if original rpc gets control and blocks on trying to receive its reply, it'll timeout and original rpc will return an error. instead we need to not block for long and allow the deleg_return to go thru so that the server can reply successfully to the original rpc.
added pnfs_layout.open_count to count open references, and only return the layout when pnfs_open_state_close() takes the open_count to 0
use InterlockedIncrement/Decrement to avoid an exclusive lock on the layout
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>
we were checking for error result of send_null but not setting
status, then going to "out_unlock" and since status is NO_ERROR
trying to send bind_conn_to_session
instead of ignoring errors from proc_cb_compound_args(), return NFS4ERR_BADXDR. note that we still need to allocate the cb_compound_res structure to return this error
added null checks to the end of handle_cb_compound(); if the cb_compound_res allocation fails, we'd crash trying to access res->status and res->resarray_count
also fixed some indenting
Signed-off-by: Casey Bodley <cbodley@citi.umich.edu>