Hallo, dies ist ein Test.
PWD: /www/data-lst1/unixsoft/unixsoft/kaempfer/.public_html
Running in File Mode
Relative path: ./../../../../../../usr/include/nfs/nfs4.h
Real path: /usr/include/nfs/nfs4.h
Zurück
/* * Copyright (c) 2003, 2023, Oracle and/or its affiliates. */ #ifndef _NFS4_H #define _NFS4_H #include <sys/types.h> #include <sys/vnode.h> #include <sys/fem.h> #include <sys/acl.h> #include <sys/list.h> #include <rpc/rpc.h> #include <nfs/nfs_srv_inst.h> #include <nfs/nfs.h> #include <sys/uuid.h> #ifdef _KERNEL #include <nfs/nfs4_kprot.h> #include <sys/nvpair.h> #include <nfs/nfs4_fsh.h> #include <sys/disp.h> #include <nfs/lm_intsysid.h> #else #include <rpcsvc/nfs4_prot.h> #endif #ifdef __cplusplus extern "C" { #endif #include <nfs/nfs4_attr.h> #define NFS4_MAX_UTF8STRING 65536 #define NFS4_MAX_PATHNAME4 65536 #define NFS4_MAX_SECOID4 65536 #ifdef _KERNEL /* only 24 bits of start time are used in state IDs */ #define RFS4_ID_TIME(vip) (0xFFFFFF & vip->r4_start_time) typedef struct nfs4_fhandle { int fh_len; char fh_buf[NFS4_FHSIZE]; } nfs4_fhandle_t; extern bool_t nfs40_badop_tab[NFS4_NUM_OPS]; extern bool_t nfs41_badop_tab[NFS4_NUM_OPS]; /* * Set the fattr4_change variable using a time struct. Note that change * is 64 bits, but timestruc_t is 128 bits in a 64-bit kernel. */ #define NFS4_SET_FATTR4_CHANGE(change, ts) \ { \ change = (ts).tv_sec; \ change <<= 32; \ change |= (uint32_t)((ts).tv_nsec); \ } /* * This set of typedefs and interfaces represent the core or base set * of functionality that backs the NFSv4 server's state related data * structures. Since the NFSv4 server needs inter-RPC state to be * available that is unrelated to the filesystem (in other words, * soft-state), this functionality is needed to maintain that and is * written to be somewhat flexible to adapt to the various types of * data structures contained within the server. * * The basic structure at this level is that the server maintains a * global "database" which consists of a set of tables. Each table * contains a set of like data structures. Each table is indexed by * at least one hash function and in most cases two hashes. Each * table's characteristics is set when it is created at runtime via * rfs4_table_create(). All table creation and related functions are * located in nfs4_state.c. The generic database functionality is * located in nfs4_db.c. */ typedef struct rfs4_dbe rfs4_dbe_t; /* basic opaque db entry */ typedef struct rfs4_table rfs4_table_t; /* basic table type */ typedef struct rfs4_index rfs4_index_t; /* index */ typedef struct rfs4_database rfs4_database_t; /* and database */ typedef struct { /* opaque entry type for later use */ rfs4_dbe_t *dbe; } *rfs4_entry_t; /* database, table, index creation entry points */ extern rfs4_database_t *rfs4_database_create(rfs4_context_t *, char *, uint32_t); extern void rfs4_database_shutdown(rfs4_database_t *); extern void rfs4_database_destroy(rfs4_database_t *); extern rfs4_context_t *rfs4_database_ctx(rfs4_database_t *); extern void rfs4_table_cache_create(rfs_inst_t *); extern rfs4_table_t *rfs4_table_create(rfs4_database_t *, char *, time_t, uint32_t, bool_t (*create)(rfs4_entry_t, void *), void (*destroy)(rfs4_entry_t), bool_t (*expiry)(rfs4_entry_t), bool_t (*inactive)(rfs4_entry_t), void (*get_dbeid)(void *, id_t *), uint32_t, uint32_t, uint32_t, id_t, kmem_cache_t *, char *); extern void rfs4_table_destroy(rfs4_database_t *, rfs4_table_t *); extern id_t rfs4_table_id_alloc(rfs4_table_t *, void *); extern rfs4_index_t *rfs4_index_create(rfs4_table_t *, char *, uint32_t (*hash)(void *), bool_t (compare)(rfs4_entry_t, void *), void *(*mkkey)(rfs4_entry_t), bool_t); extern void rfs4_index_destroy(rfs4_index_t *); /* table accessors */ extern uint32_t rfs4_table_hwmark(rfs4_table_t *); extern uint32_t rfs4_table_maxentries(rfs4_table_t *); extern uint32_t rfs4_db_cs_threshold(void); extern uint32_t rfs4_cs_sysidmax(void); /* Type used to direct rfs4_dbsearch() in what types of records to inspect */ typedef enum {RFS4_DBS_VALID, RFS4_DBS_INVALID} rfs4_dbsearch_type_t; /* search and db entry manipulation entry points */ extern rfs4_entry_t rfs4_dbsearch(rfs4_index_t *, void *, bool_t *, void *, rfs4_dbsearch_type_t); extern rfs4_entry_t rfs4_dbsearch_id(rfs4_index_t *, void *, bool_t *, void *, rfs4_dbsearch_type_t, id_t); extern void rfs4_dbe_lock(rfs4_dbe_t *); extern int rfs4_dbe_trylock(rfs4_dbe_t *); extern void rfs4_dbe_unlock(rfs4_dbe_t *); extern clock_t rfs4_dbe_twait(rfs4_dbe_t *, clock_t); extern void rfs4_dbe_cv_broadcast(rfs4_dbe_t *); extern void rfs4_dbe_hold(rfs4_dbe_t *); extern uint32_t rfs4_dbe_test_hold(rfs4_dbe_t *); extern void rfs4_dbe_rele_nolock(rfs4_dbe_t *); extern void rfs4_dbe_rele(rfs4_dbe_t *); extern void rfs4_dbe_destroy(rfs4_dbe_t *); extern bool_t rfs4_dbe_rele_nouse(rfs4_dbe_t *); extern uint32_t rfs4_dbe_refcnt(rfs4_dbe_t *); extern id_t rfs4_dbe_getid(rfs4_dbe_t *); extern void rfs4_dbe_invalidate(rfs4_dbe_t *); extern void rfs4_dbe_markpurge(rfs4_dbe_t *); extern bool_t rfs4_dbe_is_invalid(rfs4_dbe_t *); extern time_t rfs4_dbe_get_timerele(rfs4_dbe_t *); extern void rfs4_dbe_hide(rfs4_dbe_t *); extern void rfs4_dbe_unhide(rfs4_dbe_t *); extern uint32_t rfs4_dbe_num_entries(rfs4_dbe_t *); extern uint32_t rfs4_dbe_hwmark(rfs4_dbe_t *); extern bool_t rfs4_dbe_islocked(rfs4_dbe_t *); extern void rfs4_dbe_walk(rfs4_table_t *, void (*callout)(rfs4_entry_t, void *), void *); extern migerr_t rfs4_dbe_walk_mig(rfs_inst_t *, rfs4_table_t *, void (*callout)(rfs4_entry_t, void *), void *); extern boolean_t rfs4_cpr_callb(void *, int); extern void rfs4_fse_db_create(rfs4_context_t *); extern rfs_inst_t *rfs4_dbe_rip(rfs4_dbe_t *); extern rfs4_context_t *rfs4_dbe_ctx(rfs4_dbe_t *); extern void rfs4_dbe_reaper(void); rfs4_context_t *rfs4_context_create(rfs_inst_t *, fsh_entry_t *, nfs4_minor_t); rfs4_context_t *rfs4_context_create_weak(rfs_inst_t *, fsh_entry_t *, nfs4_minor_t); void rfs4_context_hold(rfs4_context_t *); void rfs4_context_rele(rfs4_context_t *); void rfs4_context_weakhold(rfs4_context_t *); void rfs4_context_weakrele(rfs4_context_t *); nfs_lease4 rfs4_get_lease_time(rfs_inst_t *); nfs_lease4 rfs4_get_hard_lease_limit(rfs_inst_t *); /* * Minimal server stable storage. * * Currently the NFSv4 server will only save the client * ID (the long version) so that it will be able to * grant possible reclaim requests during the infamous * grace_period. */ #define RFS4_SS_DIRSIZE 64 * 1024 #define NFS4_SS_VERSION 1 /* handy pathname structure */ typedef struct ss_pn { char *leaf; char pn[MAXPATHLEN]; } rfs4_ss_pn_t; /* * The server will build this link list on startup. It represents the * clients that have had valid state on the server in a prior instance. * */ typedef struct rfs4_oldstate { avl_node_t ros_node; rfs4_ss_pn_t *ros_ss_pn; nfs_client_id4 ros_cl_id4; } rfs4_oldstate_t; /* * This union overlays the server's internal structure of a * client ID with the protocol's data type, a clientid4. */ typedef union { struct { uint32_t start_time:28; uint32_t mc_nodeid:4; uint32_t cl_nodeid:8; uint32_t c_id:24; } impl_id; clientid4 id4; } clientid_t; /* * NB: The meta-cluster node ID is 12 bits in length. It would be nice to * have it as one, 12-bit long bit field. However, when the stateid was * formed that way, it worked fine for a 64-bit kernel, but not for a 32-bit * kernel. If 32-bit kernel support is dropped, it may be worth changing * the structure to remove this complexity. */ typedef struct { uint32_t chgseq; /* State changes / protocol's seqid */ uint32_t boottime:24; /* boot time */ uint32_t type:4; /* stateid_type_t as define below */ uint32_t mcid:4; /* meta-cluster nodeid is 12 bits */ uint32_t clnodeid:8; /* mcid cont or cluster server nodeid */ uint32_t ident:24; /* 2^24-1 openowner x fhs */ pid_t pid; /* pid of corresponding lock owner */ } v40_bits_t; typedef struct { uint32_t chgseq; /* State changes / protocol's seqid */ uint32_t type:4; /* stateid_type_t as define below */ uint32_t ident:28; /* 2^28-1 openowner x fhs */ fsid_t fsid; /* fsid */ } v41_bits_t; /* * This union is used to overlay the server's internal treatment of * the protocols stateid4 datatype. Therefore, "bits" must not exceed * the size of stateid4 and more importantly should match the size of * stateid4. The chgseq field must the first entry since it overlays * stateid4.seqid. * */ typedef union { stateid4 stateid; v40_bits_t v40_bits; v41_bits_t v41_bits; struct { uint32_t chgseq; /* common to 4.0 and 4.1 bits */ char stuff[12]; } bits; } stateid_t; /* * Note that the way the type field above is defined, this enum must * not have more than 16 members. */ typedef enum stateid_type { NFS4_SIDT_OPENID, NFS4_SIDT_LOCKID, NFS4_SIDT_DELEGID, NFS4_SIDT_NLMLOCK, NFS4_SIDT_INVAL = 16 } stateid_type_t; extern stateid4 special0; extern stateid4 special1; extern stateid4 invalid_special_stateid; extern stateid4 current_stateid; #define STATEID4_OTHER_LEN 12 #define STATEID4_OTHER_HEX_LEN (STATEID4_OTHER_LEN * 2 + 1) #define NFS4_ISSPECIAL(id) \ (stateid4_cmp((id), &special0) || stateid4_cmp((id), &special1)) #define NFS4_ISINVALIDSPECIAL(id) \ (stateid4_cmp((id), &invalid_special_stateid)) #define NFS4_ISCURRENT_STATEID(id) (stateid4_cmp((id), ¤t_stateid)) #define STATEID_CK_LEASE 0x00000001 #define STATEID_CK_CONFIRM 0x00000002 #define STATEID_CK_CLOSED 0x00000004 #define STATEID_CK_REPLAY 0x00000008 #define STATEID_CK_SEQ 0x00000010 #define STATEID_CK_ALL ( \ STATEID_CK_LEASE | \ STATEID_CK_CONFIRM | \ STATEID_CK_CLOSED | \ STATEID_CK_REPLAY | \ STATEID_CK_SEQ) /* * Set of RPC credentials used for a particular operation. * Used for operations like SETCLIENTID_CONFIRM where the * credentials needs to match those used at SETCLIENTID. */ typedef void *cred_set_t; /* For now XXX */ typedef struct { cred_t *cp_cr; int cp_aflavor; int cp_secmod; caddr_t cp_princ; } cred_princ_t; /* * "wait" struct for use in the open open and lock owner state * structures to provide serialization between server threads that are * handling requests for the same open owner or lock stateid. This * way only one thread will be updating things like sequence ids, * replay cache and stateid at a time. */ typedef struct rfs4_state_wait { uint32_t sw_active; uint32_t sw_wait_count; kmutex_t sw_cv_lock[1]; kcondvar_t sw_cv[1]; } rfs4_state_wait_t; extern void rfs4_sw_enter(rfs4_state_wait_t *); extern void rfs4_sw_exit(rfs4_state_wait_t *); /* * This enum and the following rfs40_cbinfo_t struct are used to * maintain information about the callback path used from the server * to client for operations like CB_GETATTR and CB_RECALL. The * rfs40_cbinfo_t struct is meant to be encompassed in the client * struct and managed within that structure's locking scheme. * * The various states of the callback path are used by the server to * determine if delegations should initially be provided to a client * and then later on if connectivity has been lost and delegations * should be revoked. */ /* * CB_NOCHANGE - Special value used for interfaces within the delegation * code to signify that "no change" has occurred to the * callback path * CB_UNINIT - No callback info provided by the client * CB_NONE - Callback info provided but CB_NULL call * has yet to be attempted * CB_OK - Callback path tested with CB_NULL with success * CB_INPROG - Callback path currently being tested with CB_NULL * CB_FAILED - Callback path was == CB_OK but has failed * with timeout/rpc error * CB_BAD - Callback info provided but CB_NULL failed */ typedef enum { CB_NOCHANGE = 0, CB_UNINIT = 1, CB_NONE = 2, CB_OK = 3, CB_INPROG = 4, CB_FAILED = 5, CB_BAD = 6 } rfs4_cbstate_t; #define RFS4_CBCH_MAX 10 /* size callback client handle cache */ /* * Callback info for a client. * Client only provides: cb_client4 and cb_ident * The rest of the information is used to track callback path status * and usage. * * cb_state - used as comments for the rfs4_cbstate_t enum indicate * cb_notified_of_cb_path_down - if the callback path was once CB_OK and * has hence CB_FAILED, the client needs to be notified via RENEW. * cb_timefailed - current time when cb_state transitioned from * CB_OK -> CB_FAILED. Meant for observability. When did that happen? * cb_chc_free/cb_chc - cache of client handles for the callback path * cb_ident - SETCLIENTID provided callback_ident value * callback - SETCLIENTID provided cb_client4 value * cb_refcnt - current number of users of this structure's content * protected by cb_lock * cb_badbehavior - how many times did a client do something we didn't like? * cb_lock - lock for contents of cbinfo * cb_cv - used to allow threads to wait on CB_NULL completion * cb_nullcaller - is there a thread currently taking care of * new callback information? * cb_cv_nullcaller - used by the thread doing CB_NULL to wait on * threads that may be using client handles of the current * client handle cache. * newer - new callback info provided by a client and awaiting * CB_NULL testing and move to regular cbinfo. */ typedef struct { rfs4_cbstate_t cb_state; unsigned cb_notified_of_cb_path_down:1; time_t cb_timefailed; int cb_chc_free; CLIENT *cb_chc[RFS4_CBCH_MAX]; uint32_t cb_ident; cb_client4 cb_callback; uint32_t cb_refcnt; uint32_t cb_badbehavior; kmutex_t cb_lock[1]; kcondvar_t cb_cv[1]; bool_t cb_nullcaller; kcondvar_t cb_cv_nullcaller[1]; struct { bool_t cb_update; verifier4 cb_verifier; bool_t cb_new; bool_t cb_confirmed; uint32_t cb_ident; cb_client4 cb_callback; } cb_newer; } rfs40_cbinfo_t; /* * grace period state: in grace or not */ typedef enum {IN_GRACE, NOT_IN_GRACE} grace_state_t; /* * rfs4_grace_t groups clients subject to the same grace period. * There's a single grace period per minor version of a server instance. */ typedef struct rfs4_grace { krwlock_t rg_rwlock; krwlock_t rg_oldstate_rwlock; clock_t rg_start_tick; avl_tree_t rg_oldstate_tree; int rg_cl_to_recov; unsigned rg_grace_new:1; unsigned rg_completed:1; unsigned rg_completed_early:1; hrtime_t rg_created_time; hrtime_t rg_started_time; hrtime_t rg_completed_time; } rfs4_grace_t; typedef enum rfs4_grace_why { RFS4_NOT_IN_GRACE = 0, RFS4_GRACE_INST, RFS4_GRACE_NLM, RFS4_GRACE_FSE } rfs4_grace_why_t; /* * DSS: distributed stable storage */ typedef struct rfs4_dss_path { list_node_t ds_node; char *ds_path; } rfs4_dss_path_t; /* * NFSv4.1: slot support (nfs41_slrc) */ /* se_state values */ #define NFS41_SLOT_INUSE 0x00000001 /* allocated; callers needing */ /* it may wait via se_wait */ #define NFS41_SLOT_CACHED 0x00000002 /* slot holds cached result */ #define NFS41_SLOT_ERROR 0x00000004 /* last op on slot failed */ #define NFS41_SLOT_RECALLED 0x00000008 /* slot was in recall race */ #define NFS41_SLOT_NEEDS_RESYNC 0x00000010 /* slot needs to be resynced */ #define NFS41_SLOT_LORP 0x00000020 /* slot reserved for lorp */ #define SLOT_HOLD(sltp) atomic_add_32(&(sltp)->se_refcnt, 1) /* Slot entry structure */ typedef struct slot_ent { avl_node_t se_node; /* avl tree linkage */ uint32_t se_sltno; /* slot number */ uint32_t se_state; /* slot state bits, see above */ sequenceid4 se_seqid; /* current or last sequence ID */ COMPOUND4res_srv se_buf; /* Buf for slot and replays */ cred_t *se_cred; /* current or last cred used */ stateid_type_t se_rs_type; /* saved stateid type */ void *se_rs_data; /* saved stateid data */ kmutex_t se_lock; /* slot entry lock */ uint32_t se_refcnt; /* slot ref count (no lock needed) */ kcondvar_t se_wait; /* cv for slot wait sync */ } slot_ent_t; /* Slot table */ typedef struct nfs41_slot_table { uint32_t st_highest; /* highest slotid */ uint32_t st_target_highest; /* target highest slotid */ uint32_t st_fslots; /* number of available slots */ uint32_t st_maxslot; /* max slotid in use */ uint32_t st_errslots; /* number of error slots */ avl_tree_t *st_sltab; /* tree of slot_ent pointers */ kmutex_t st_lock; /* slot table lock */ kcondvar_t st_wait; /* cv for free slot wait sync */ int st_flags; /* slot table flags, below */ void (*st_cleanup)(slot_ent_t *); /* cleanup function */ uint32_t st_max_allowed; /* max slot used for creation */ uint32_t st_bm_words; /* slot number bitmap size */ ulong_t *st_bitmap; /* slot number bitmap array */ } nfs41_slot_table_t; typedef enum { SLT_NOSLEEP = 0, SLT_SLEEP = 1 } slt_wait_t; /* defines for st_flags */ #define ST_MAXSLOT_VALID 1 #define ST_OPEN 2 #define NFS41_MAX_BC_SLOTS 50 /* should match RDMA_BUFS_CB_RQST */ #define RFS41_MAX_FORE 4096 #define RFS41_MAX_BACK NFS41_MAX_BC_SLOTS #define NFS41_MAX_FORE 1000 #define NFS41_MAX_BACK NFS41_MAX_BC_SLOTS /* internal values of delegation, pgr saves this type */ typedef enum rfs4_deleg_type { RFS4_DELEG_NONE = 0, RFS4_DELEG_READ = 1, RFS4_DELEG_WRITE = 2 } rfs4_deleg_type_t; /* * NFSv4.1 Sessions */ typedef struct rfs41_csr { /* contrived create_session result */ sequenceid4 cs_exseqid; /* EXCHANGE_ID seq id */ sequenceid4 cs_seqid; /* CREATE_SESSION seq id */ nfsstat4 cs_status; /* CREATE_SESSION status */ CREATE_SESSION4resok cs_res; /* cached results if NFS4_OK */ } rfs41_csr_t; typedef enum { CB_PING_INIT = 0, CB_PING_OK = 1, CB_PING_NEEDED = 2, CB_PING_INPROG = 3, CB_PING_FAILED = 4 } cb_ping_state_t; typedef struct { state_protect_how4 sp_type; } rfs41_sprot_t; /* * The server maintains a set of state on a per client basis that * matches that of the protocol requirements. A client's state is * rooted with the rfs4_client_t struct of which there is one per * client and is created when SETCLIENTID/SETCLIENTID_CONFIRM are * received. From there, the server then creates rfs4_openowner_t * structs for each new open owner from that client and are initiated * at OPEN/OPEN_CONFIRM (when the open owner is new to the server). * At OPEN, at least two other structures are created, and potentially a * third. rfs4_state_t is created to track the association between an * open owner and a particular file. An rfs4_file_t struct may be * created (if the file is not already open) at OPEN as well. The * rfs4_file_t struct is the only one that is per server and not per * client. The rfs4_deleg_state_t struct is created in the * instance that the server is going to provide a delegation for the * file being OPENed. Finally, the rfs4_lockowner_t is created at the * first use of a lock owner at the server and is a result of the LOCK * operation. The rfs4_lo_state_t struct is then created to represent * the relation between the lock owner and the file. * */ /* * The following ascii art represents each of these data structs and * their references to each other. Note: "<-(x)->" represents the * doubly link lists. * * ____________________ * | | * | rfs4_client_t | * ->| (1) |<- * / |____________________| \ * / ^ \ * / | \ * ____________________ ____________________ ____________________ * | | | | | | * | rfs4_lockowner_t | | rfs4_openowner_t | | rfs4_deleg_state_t | * | | | (3) <-(1)-> | | <-(2)-> | * |____________________| |____________________| |____________________| * ^ ^ | * | | V * ____________________ ____________________ ____________________ * | | | | | | * | rfs4_lo_state_t |->| rfs4_state_t |->| rfs4_file_t | * | <-(4)-> | | (4) <-(3)-> | | (2) | * |____________________| |____________________| |____________________| */ /* * Each of these data types are kept in a separate rfs4_table_t and is * actually encapsulated within a rfs4_dbe_t struct. The various * tables and their construction is done in nfs4_state.c but * documented here to completeness. * * Table Data struct stored Indexed by * ----- ------------------ ---------- * rfs4_client_tab rfs4_client_t nfs_client_id4 * clientid4 * * rfs4_openowner_tab rfs4_openowner_t open_owner4 * * rfs4_state_tab rfs4_state_t open_owner4 | file * stateid * * rfs4_lo_state_tab rfs4_lo_state_t lockowner | stateid * lock_stateid * * rfs4_lockowner_tab rfs4_lockowner_t lockowner * pid * * rfs4_file_tab rfs4_file_t filehandle * * rfs4_deleg_state_tab rfs4_deleg_state_t clientid4 | file * deleg_stateid */ /* * Although the client struct is the root of all client * state, it is possible for multiple rfs4_client_t objects to * exist for a particular client. * The client_master struct organizes the set of client structs * for a particular client. * * rcm_dbe - encapsulation struct * rcm_oid_len - size in bytes of client owner identifier * rcm_oid_val - client owner identifier * rcm_clientcreatelock - used to serialize creation of rfs4_client_ts * rcm_clientlistlock - protects rcm_clientlist * rcm_clientlist - list of rfs4_client_ts for a client owner identifier * * The rcm_clientcreatelock is used to ensure correct behavior * when the server is presented with multiple identical client owner * ids at the same time. This can happen when two clients happen to * use the same client owner identifier, when a single client is performing * recovery, or when the server is under attack from a rogue client. * Since this is an unusual condition, the lock is used to serialize * rfs4_client_t creation with a per client granularity. * * The rcm_clientlist is used to hold the set of rfs4_client_ts for a * particular client owner identifier. The list is used instead of * state database queries since the state database has limited functionality * for returning sets of data. */ typedef struct rfs4_client_master { rfs4_dbe_t *rcm_dbe; uint_t rcm_oid_len; char *rcm_oid_val; krwlock_t rcm_clientcreatelock; krwlock_t rcm_clientlistlock; list_t rcm_clientlist; } rfs4_client_master_t; /* * The client struct, it is the root of all state for a particular * client. The client is identified by the nfs_client_id4 via * SETCLIENTID and the server returns the clientid4 as short hand reference */ /* * Client struct - as mentioned above it is the root of all state for * a single client as identified by the client supplied nfs_client_id4 * * dbe - encapsulation struct * clientid - server assigned short hand reference to client * nfs_client - client supplied identifier for itself * confirm_verf - the value provided to the client for SETCLIENTID_CONFIRM * confirmed - does this client need to be SETCLIENTID_CONFIRMed? * * unlksys_completed - has an F_UNLKSYS been done for this client which * says that the use of cleanlocks() on individual files * is not required? * can_reclaim - indicates if client is allowed to reclaim after server * start-up (client had previous state at server) * ss_remove - indicates that the rfs4_client_destroy function should * clean up stable storage file. * forced_expire - set if the sysadmin has used clear_locks for this client. * tsm_hydrated - set if client migrated from another server * deleg_revoked - how many delegations have been revoked for this client? * * cp_confirmed - this refers to a confirmed client struct that has * the same nfs_client_id4 as this client struct. When/if this client * struct is confirmed via SETCLINETID_CONFIRM, the previously * * last_access - used to determine if the client has let its lease expire * cbinfo - struct containing all callback related information * cr_set - credentials used for the SETCLIENTID/SETCLIENTID_CONFIRM pair * sysidt - the lock manager sysid allocated for this client's file locks * openownerlist - root of openowners list associated with this client * deleg_list - list of delegations for this client * ss_pn - Pathname to the stable storage file. * addr - Clients network address. * grace - pointer to the currently associated grace instance */ typedef struct rfs4_client { rfs4_dbe_t *rc_dbe; clientid4 rc_clientid; nfs_client_id4 rc_nfs_client; verifier4 rc_confirm_verf; unsigned rc_confirmed:1; unsigned rc_unlksys_completed:1; unsigned rc_can_reclaim:1; unsigned rc_ss_remove:1; unsigned rc_forced_expire:1; unsigned rc_tsm_hydrated:1; unsigned rc_reclaim_completed:1; unsigned rc_stale_ent:1; uint_t rc_deleg_revoked; hrtime_t rc_last_access; /* NFS stores seconds, not ns */ rfs40_cbinfo_t rc_cbinfo40; cred_set_t rc_cr_set; lm_intsysid_t rc_sysidt; rfs4_client_master_t *rc_client_master; list_node_t rc_node; list_t rc_openownerlist; rfs4_ss_pn_t *rc_ss_pn; struct sockaddr_storage rc_addr; list_t rc_lemo_list; list_t rc_deleg_list; rfs4_grace_t *rc_grace; cred_princ_t *rc_cr_princ; uint_t rc_migrated; rfs41_csr_t rc_contrived; rfs41_sprot_t rc_state_prot; int rc_clid_scope; nfs_impl_id4 rc_client_impl_id; uint_t rc_bc_cnt; char rc_tofab_id[UUID_PRINTABLE_STRING_LENGTH]; char rc_mig_id[UUID_PRINTABLE_STRING_LENGTH]; } rfs4_client_t; typedef struct rfs4_client_dbdata { rfs4_client_master_t *rcd_clientmaster; clientid4 rcd_clientid; verifier4 rcd_verifier; uint_t rcd_id_len; char *rcd_id_val; struct sockaddr *rcd_cl_addr; int rcd_migrated; int rcd_created; char rcd_tofab_id[UUID_PRINTABLE_STRING_LENGTH]; char rcd_mig_id[UUID_PRINTABLE_STRING_LENGTH]; } rfs4_client_dbdata_t; /* * ClntIP struct - holds the diagnosis about whether the client * cannot support referrals. Set to true for old Solaris clients. */ typedef struct rfs4_clntip { rfs4_dbe_t *ri_dbe; struct sockaddr_storage ri_addr; unsigned ri_no_referrals:1; } rfs4_clntip_t; typedef struct rfs4_lemo_entry { list_node_t rle_ln; fsid_t rle_fsid; hrtime_t rle_time_seen; } rfs4_lemo_entry_t; /* * The openowner contains the client supplied open_owner4 as well as * the matching sequence id and is used to track the client's usage of * the open_owner4. Note that a reply is saved here as well for * processing of retransmissions. * * dbe - encapsulation struct * client - reference to rfs4_client_t for this openowner * owner - actual client supplied open_owner4 * need_confirm - does this openowner need to be OPEN_CONFIRMed * postpone_confirm - set if error received on first use of open_owner * open_seqid - what is the next open_seqid expected for this openowner * sw - used to serialize access to the open_seqid/reply handling * cr_set - credential used for the OPEN * statelist - root of state struct list associated with this openowner * node - node for client struct list of openowners * reply_fh - open replay processing needs the filehandle so that it is * able to reset the current filehandle for appropriate compound * processing and reply. * reply - last reply sent in relation to this openowner */ typedef struct rfs4_openowner { rfs4_dbe_t *ro_dbe; rfs4_client_t *ro_client; open_owner4 ro_owner; unsigned ro_need_confirm:1; unsigned ro_postpone_confirm:1; seqid4 ro_open_seqid; rfs4_state_wait_t ro_sw; cred_set_t ro_cr_set; list_t ro_statelist; list_node_t ro_node; nfs_fh4 ro_reply_fh; nfs_resop4 ro_reply; char ro_mig_id[UUID_PRINTABLE_STRING_LENGTH]; } rfs4_openowner_t; /* * This state struct represents the association between an openowner * and a file that has been OPENed by that openowner. * * dbe - encapsulation struct * stateid - server provided stateid * owner - reference back to the openowner for this state * finfo - reference to the open file for this state * open_access - how did the openowner OPEN the file (access) * open_deny - how did the openowner OPEN the file (deny) * share_access - what share reservation is on the file (access) * share_deny - what share reservation is on the file (deny) * closed - has this file been closed? * lostatelist - root of list of lo_state associated with this state/file * node - node for state struct list of states * destroy_node - list of state that are ready to be rele() / destroyed */ typedef struct rfs4_state { rfs4_dbe_t *rs_dbe; stateid_t rs_stateid; rfs4_openowner_t *rs_owner; struct rfs4_file *rs_finfo; uint32_t rs_open_access; uint32_t rs_open_deny; uint32_t rs_share_access; uint32_t rs_share_deny; unsigned rs_closed:1; uint32_t rs_tsm_idreuse; id_t rs_tsm_dbeid; list_t rs_lostatelist; list_node_t rs_node; list_node_t rs_destroy_node; } rfs4_state_t; /* * Lockowner - track the lockowner and its related info * * dbe - encapsulation struct * client - reference to the client * owner - lockowner supplied by the client * pid - local identifier used for file locking */ typedef struct rfs4_lockowner { rfs4_dbe_t *rl_dbe; rfs4_client_t *rl_client; lock_owner4 rl_owner; pid_t rl_pid; } rfs4_lockowner_t; /* * Lockowner_state associated with a state struct and lockowner * * dbe - encapsulation struct * state - reference back to state struct for open file * lockid - stateid for this lockowner/state * locker - reference to lockowner * seqid - sequence id for this lockowner/state * locks_cleaned - have all locks been released for this lockowner/file? * lock_completed - successful LOCK with lockowner/file? * sw - used to serialize update seqid/reply/stateid handling * node - node for state struct list of lo_states * destroy_node - list of lo_state that are ready to be destroyed * reply - last reply sent in relation to this lockowner/state * * NOTE: the embedded pid in 'rls_lockid' can not be used to search * for the lock_owner of this lock if this lock state was migrated * from another system as part of a filesystem migration. This pid * and the rl_pid do not match. * See comment in rfs4_hydrate_mig_lo_state() for additional details. */ typedef struct rfs4_lo_state { rfs4_dbe_t *rls_dbe; rfs4_state_t *rls_state; stateid_t rls_lockid; uint32_t rls_tsm_idreuse; id_t rls_tsm_dbeid; rfs4_lockowner_t *rls_locker; seqid4 rls_seqid; unsigned rls_locks_cleaned:1; unsigned rls_lock_completed:1; rfs4_state_wait_t rls_sw; list_node_t rls_node; list_node_t rls_destroy_node; nfs_resop4 rls_reply; } rfs4_lo_state_t; /* * Delegation state - per client * * dbe - encapsulation struct * dtype - type of delegation (NONE, READ, WRITE) * delegid - stateid for this delegation * time_granted - time this delegation was assigned to client * time_recalled - time when the server started recall process * time_revoked - if revoked, time that the revoke occurred * finfo - reference to the file associated with this delegation * client - reference to client for which this delegation is associated * node - list of delegations for the file (WRITE == 1, READ == ) * clientnode - list of delegations for the client */ typedef struct rfs4_deleg_state { rfs4_dbe_t *rds_dbe; rfs4_deleg_type_t rds_dtype; stateid_t rds_delegid; time_t rds_time_granted; time_t rds_time_recalled; time_t rds_time_revoked; uint32_t rds_tsm_idreuse; id_t rds_tsm_dbeid; struct rfs4_file *rds_finfo; rfs4_client_t *rds_client; list_node_t rds_node; list_node_t rds_clientnode; uint32_t rds_slot_inuse; sessionid4 rds_slot_sessid; sequenceid4 rds_slot_seqid; uint32_t rds_slot_no; } rfs4_deleg_state_t; /* * Delegation info associated with the file * * dtype - type of delegation for file (NONE, READ, WRITE) * time_returned - time that last delegation was returned for file * time_recalled - time that recall sequence started * time_lastgrant - time that last delegation was provided to a client * time_lastwrite - time of last write to use the delegation stateid * time_rm_delayed - time of last remove/rename which was DELAYed * rdgrants - how many read delegations have been provided for this file * wrgrants - how many write delegations provided (can only be one) * recall_count - how many recall threads are outstanding * recall_lock - lock to protect contents of this struct * recall_cv - condition var for the "parent" thread to wait upon * deleg_change_grant - value for change attribute at time of write grant * deleg_change - most recent value of change obtained from client * deleg_change_ts - time of last deleg_change update * ever_recalled - has this particular delegation ever been recalled? * hold_grant - file deletion is impending, don't grant a delegation * conflicted_client - clientid of the client that caused a CB_RECALL * to occur. This is used for delegation policy (should a delegation * be granted shortly after it has been returned?) * rd_recall_in_progress - recall is already in progress */ typedef struct rfs4_dinfo { rfs4_deleg_type_t rd_dtype; time_t rd_time_returned; time_t rd_time_recalled; time_t rd_time_lastgrant; time_t rd_time_lastwrite; time_t rd_time_rm_delayed; uint32_t rd_rdgrants; uint32_t rd_wrgrants; int32_t rd_recall_count; kmutex_t rd_recall_lock[1]; kcondvar_t rd_recall_cv[1]; bool_t rd_ever_recalled; uint32_t rd_hold_grant; clientid4 rd_conflicted_client; bool_t rd_recall_in_progress; } rfs4_dinfo_t; /* * File * * dbe - encapsulation struct * vp - vnode for the file that is open or has a delegation * filehandle - the filehandle generated by the server for this file * delegstatelist - root of delegation list for this file * dinfo - see struct definition above * share_deny - union of all deny modes on file * share_access - union of all access modes on file * access_read - count of read access * access_write - count of write access * deny_read - count of deny reads * deny_write - count of deny writes * file_rwlock - lock for serializing the removal of a file while * the state structures are active within the server * * The only requirement for locking file_rwlock is that the * caller have a reference to the containing rfs4_file. The dbe * lock may or may not be held for lock/unlock of file_rwlock. * As mentioned above, the file_rwlock is used for serialization * of file removal and more specifically reference to the held * vnode (e.g. vp). */ typedef struct rfs4_file { rfs4_dbe_t *rf_dbe; vnode_t *rf_vp; nfs_fh4 rf_filehandle; list_t rf_delegstatelist; rfs4_dinfo_t rf_dinfo; uint32_t rf_share_deny; uint32_t rf_share_access; uint32_t rf_access_read; uint32_t rf_access_write; uint32_t rf_deny_read; uint32_t rf_deny_write; krwlock_t rf_file_rwlock; } rfs4_file_t; /* * NFSv4.1 Sessions (cont'd) * * rfs41_session_t rfs4_client_t * +-------------+ +--------------------+ * | sn_sessid | | clientid | * | sn_clnt * -|---------->| : | * | | +--------------------+ * | sn_replay* -|---------> +--------------------------------+ * | . | | st_currw | * | : | | st_fslots | * +-------------+ | st_sltab (slot_ent_t) | * | +----------------------------+| * | | status, slot, seqid, resp *||------><Res> * | +----------------------------+| * | | status, slot, seqid, resp *|| * | +----------------------------+| * | | status, slot, seqid, resp *|| * | +----------------------------+| * | . | * | : | * +--------------------------------+ * nfs41_slot_table_t */ typedef struct { nfsstat4 cs_error; rfs4_client_t *cs_client; struct svc_req *cs_req; CREATE_SESSION4args cs_aotw; } session41_create_t; typedef struct rfs41_sec_data { list_node_t rsp_node; sec_data_t *rsp_sec_data; cred_t *rsp_cred; } rfs41_sec_data_t; typedef struct rfs41_bc_client { uint32_t bcc_version; uint32_t bcc_program; CLIENT *bcc_clnt; } rfs41_bc_client_t; typedef struct rfs41_session { rfs4_dbe_t *sn_dbe; sessionid4 sn_sessid; /* session id */ rfs4_client_t *sn_clnt; /* back ptr to client state */ channel_attrs4 sn_fore_attrs; /* fore channel attributes */ nfs41_slot_table_t *sn_replay; /* slot replay cache */ int sn_csflags; /* create_session only flags */ channel_attrs4 sn_bc_attrs; /* back channel attributes */ uint32_t sn_bc_conn_count; uint32_t sn_bc_check_inprog; time_t sn_bc_check_tod; int32_t sn_bc_penalty; uint32_t sn_bc_fault; nfs41_slot_table_t *sn_bc_stok; krwlock_t sn_bc_rwlock; uint32_t sn_bc_sec_version; list_t sn_bc_sec_data_list; uint32_t sn_bc_program; int sn_bc_ch_free; rfs41_bc_client_t *sn_bc_clnt[RFS4_CBCH_MAX]; int sn_bc_xp_type; /* backchannel xprt type */ } rfs41_session_t; /* forward declaration */ struct rfs4_compound_state; extern rfs4_grace_why_t rfs4_in_grace(rfs4_client_t *, rfs4_context_t *); extern rfs4_grace_why_t rfs4_in_grace_gip(rfs4_grace_t *, rfs4_context_t *); extern char *rfs4_grace_why_to_str(rfs4_grace_why_t); extern void rfs4_fse_grace_start(rfs4_context_t *); extern rfs4_context_t *rfs4_fse_ctx(fsh_entry_t *, nfs4_minor_t); extern void rfs4_grace_create(rfs4_context_t *); extern void rfs4_grace_destroy_all(rfs4_context_t *); extern void rfs4_clnt_grace_assign(rfs4_client_t *, rfs4_grace_t *); extern rfs4_grace_t *rfs4_clnt_grace(rfs4_client_t *); extern int rfs4_clnt_in_grace(rfs4_client_t *); extern int rfs4_grace_in(rfs4_context_t *, rfs4_grace_t *); extern void rfs4_grace_disable(rfs4_context_t *, rfs4_grace_t *); extern void rfs4_inst_grace_disable(rfs4_context_t *, rfs4x_inst_t *); extern int rfs4_inst_exited_grace(rfs4_context_t *); extern int rfs4_grace_new(rfs4_grace_t *); extern void rfs4_grace_start(rfs4_grace_t *, rfs4_context_t *); extern void rfs4_grace_reset(rfs_inst_t *); extern grace_state_t rfs4_inst_grace_start_all(rfs4_context_t *); extern int rfs4_ss_oldstate(rfs4_context_t *, rfs4_grace_t *, char *, char *); extern int rfs4_dss_readstate(rfs4_context_t *, int, char **); extern void rfs4_dss_clear_oldstate(rfs4_context_t *, rfs4_grace_t *, int, boolean_t); extern void rfs4_grace_instance_addpaths(rfs4_context_t *, int, char **); extern boolean_t rfs4_own_dsspath(char *, uint32_t); extern void rfs4_dss_freepaths(char **, int); extern void mc_verftree_cleanup(rfs4x_inst_t *); extern void rfs4_clnt_grace_remove(rfs4_client_t *); extern void rfs4_destroy_oldstate(rfs4_context_t *, rfs4_grace_t *, rfs4_oldstate_t *, int); extern cred_t *rfs4_cs_setcred(struct rfs4_compound_state *, struct svc_req *, cred_t *, boolean_t); extern int rfs4_inst_lease_to_recover(rfs4_context_t *); /* * rfs4_deleg_policy is used to signify the server's global delegation * policy. The default is to NEVER delegate files and the * administrator must configure the server to enable delegations. * * The disable/enable delegation functions are used to eliminate a * race with exclusive creates. */ typedef enum { SRV_NEVER_DELEGATE = 0, SRV_NORMAL_DELEGATE = 1 } srv_deleg_policy_t; extern void rfs4_disable_delegation(rfs4_context_t *); extern void rfs4_enable_delegation(rfs4_context_t *); typedef struct rfs4_deleg_context { uint32_t rdc_access; uint32_t rdc_deny; uint32_t rdc_want; uint32_t rdc_want_when; rfs4_deleg_type_t rdc_dtype; why_no_delegation4 rdc_whynone; uint_t rdc_invalid:1; uint_t rdc_claimprev:1; uint_t rdc_claimdelcur:1; uint_t rdc_recall:1; uint_t rdc_nodeleg:1; } rfs4_deleg_context_t; void rfs4_deleg_context_setup(uint32_t, uint32_t, rfs4_deleg_context_t *); /* * Various interfaces to manipulate the state structures introduced * above */ extern void rfs4_clean_state_exi(struct exportinfo *); extern void rfs4_clean_state_fse(rfs4_context_t *, fsh_entry_t *); extern void rfs4_invalidate_tsm_client(rfs4_entry_t, void *); extern void rfs4_invalidate_mig_client(rfs4_entry_t, void *); extern void rfs4_free_reply(nfs_resop4 *); extern void rfs4_copy_reply(nfs_resop4 *, nfs_resop4 *); extern rfs4_client_master_t *rfs4_findclientmaster(rfs4_context_t *, char *, uint_t, bool_t *); /* rfs4_client_t handling */ extern rfs4_client_t *rfs4_createclient(rfs4_context_t *, rfs4_client_dbdata_t *); extern rfs4_client_t *rfs4_findclient(rfs4_context_t *, clientid4, bool_t); extern void rfs4_client_hold(rfs4_client_t *); extern void rfs4_client_rele(rfs4_client_t *); extern void rfs4_client_close(rfs4_client_t *); extern int rfs4_client_statecheck(rfs4_client_t *); extern bool_t rfs4_update_lease(rfs4_client_t *); extern void rfs4_invalidate_lease(rfs4_client_t *); extern void rfs4_invalidate_lease_nolock(rfs4_client_t *); extern bool_t rfs4_update_lease_locked(rfs4_client_t *); extern bool_t rfs4_is_lease_expired(rfs4_client_t *); extern bool_t rfs4_is_lease_expired_nolock(rfs4_client_t *); extern bool_t rfs4_is_hard_lease_expired(rfs4_client_t *); extern bool_t rfs4_lease_moved(rfs4_client_t *, struct rfs4_compound_state *); extern rfs4_lemo_entry_t *rfs4_lemo_insert(rfs4_client_t *, fsid_t); extern void rfs4_lemo_remove(rfs4_client_t *, rfs4_lemo_entry_t *); extern bool_t rfs4_clear_lease_moved(rfs4_client_t *, fsid_t); extern nfsstat4 rfs4_check_clientid(rfs4_context_t *, clientid4 *, int); extern void rfs4_ss_chkclid(rfs4_client_t *); extern void rfs4_free_cred_princ_impl(cred_princ_t *); extern void rfs4_free_cred_princ(rfs4_client_t *); extern void rfs4_client_verifier_next(verifier4 *); extern bool_t rfs4_client_is_invalid(rfs4_client_t *, bool_t); extern boolean_t rfs4_is_client_lease_expired(void *); extern boolean_t rfs4_is_lockowner_lease_expired(pid_t, lm_intsysid_t); /* rfs4_clntip_t handling */ extern rfs4_clntip_t *rfs4_find_clntip(rfs4_context_t *, struct sockaddr *, bool_t *); extern void rfs4_invalidate_clntip(rfs4_context_t *, struct sockaddr *); /* rfs41_session_t handling */ extern rfs41_session_t *rfs41_findsession_by_id(rfs4_context_t *, sessionid4); extern rfs41_session_t *rfs41_findsession_by_clid(rfs4_context_t *, clientid4); extern rfs41_session_t *rfs41_findsession_with_bc(rfs4_context_t *, clientid4, bool_t); extern rfs41_session_t *rfs41_createsession(rfs4_context_t *, session41_create_t *); extern nfsstat4 rfs41_destroysession(rfs41_session_t *); extern void rfs41_session_hold(rfs41_session_t *); extern void rfs41_session_rele(rfs41_session_t *); extern void rfs41_clean_up_sessions(rfs4_context_t *, rfs4_client_t *); extern void rfs41_session_penalty(rfs41_session_t *, int); /* rfs4_openowner_t handling */ extern rfs4_openowner_t *rfs4_findopenowner(rfs4_context_t *, open_owner4 *, bool_t *, seqid4); extern void rfs4_update_open_sequence(rfs4_openowner_t *); extern void rfs4_update_open_resp(rfs4_openowner_t *, nfs_resop4 *, nfs_fh4 *); extern void rfs4_openowner_rele(rfs4_openowner_t *); extern void rfs4_free_opens(rfs4_openowner_t *, bool_t, bool_t); /* rfs4_lockowner_t handling */ extern rfs4_lockowner_t *rfs4_findlockowner(rfs4_context_t *, lock_owner4 *, bool_t *); extern rfs4_lockowner_t *rfs4_findlockowner_by_pid(rfs4_context_t *, pid_t); extern void rfs4_lockowner_rele(rfs4_lockowner_t *); /* rfs4_state_t handling */ extern rfs4_state_t *rfs4_findstate(rfs4_context_t *, stateid_t *, rfs4_dbsearch_type_t, bool_t); extern rfs4_state_t *rfs4_findstate_by_owner_file(rfs4_context_t *, rfs4_openowner_t *, rfs4_file_t *, bool_t *); extern void rfs4_state_rele(rfs4_state_t *); extern void rfs4_state_close(rfs4_state_t *, bool_t, bool_t, cred_t *); extern void rfs4_release_share_lock_state(rfs4_state_t *, cred_t *, bool_t, bool_t); extern void rfs4_close_all_state(rfs4_context_t *, rfs4_file_t *); extern void rfs4_state_rele_nounlock(rfs4_state_t *); extern bool_t rfs4_state_is_inactive(rfs4_entry_t); /* rfs4_lo_state_t handling */ extern rfs4_lo_state_t *rfs4_findlo_state_by_owner(rfs4_context_t *, rfs4_lockowner_t *, rfs4_state_t *, bool_t *); extern rfs4_lo_state_t *rfs4_findlo_state(rfs4_context_t *, stateid_t *, bool_t); extern void rfs4_lo_state_rele(rfs4_lo_state_t *, bool_t); extern void rfs4_update_lock_sequence(rfs4_lo_state_t *); extern void rfs4_update_lock_resp(rfs4_lo_state_t *, nfs_resop4 *); extern bool_t rfs4_lo_state_is_inactive(rfs4_entry_t); /* rfs4_file_t handling */ extern rfs4_file_t *rfs4_findfile(rfs4_context_t *, vnode_t *, nfs_fh4 *, bool_t *); extern rfs4_file_t *rfs4_findfile_withlock(rfs4_context_t *, vnode_t *, nfs_fh4 *, bool_t *); extern void rfs4_file_rele(rfs4_file_t *); /* General collection of "get state" functions */ typedef enum {RFS4_BADSTATE_NONE, RFS4_BADSTATE_FOREIGN} rfs4_badstate_cause_t; extern nfsstat4 rfs4_get_state(struct rfs4_compound_state *, stateid4 *, rfs4_state_t **, rfs4_dbsearch_type_t, rfs4_badstate_cause_t *); extern nfsstat4 rfs4_get_deleg_state(struct rfs4_compound_state *, stateid4 *, rfs4_deleg_state_t **); extern nfsstat4 rfs4_get_lo_state(struct rfs4_compound_state *, stateid4 *, rfs4_lo_state_t **, bool_t); extern nfsstat4 rfs4_check_stateid(int, struct rfs4_compound_state *, vnode_t *, stateid4 *, bool_t, bool_t *, caller_context_t *); extern int rfs4_check_stateid_seqid(struct rfs4_compound_state *, rfs4_state_t *, stateid4 *); extern nfsstat4 rfs4_do_check_stateid_seqid( struct rfs4_compound_state *, rfs4_state_t *, stateid_t *, stateid4 *, uint32_t, int *); extern int rfs4_check_lo_stateid_seqid( struct rfs4_compound_state *, rfs4_lo_state_t *, stateid4 *); extern id_t rfs4_dbeid_stateid(stateid_t, nfs4_minor_t); extern nfsstat4 rfs4_get_all_state(struct rfs4_compound_state *, stateid4 *, rfs4_state_t **, rfs4_deleg_state_t **, rfs4_lo_state_t **); extern nfsstat4 rfs4_process_stateid_arg(struct rfs4_compound_state *, stateid4 *, stateid4 *); extern void rfs4_format_stateid(stateid4 *, char *); extern bool_t rfs4_expired_client(rfs4_client_t *, bool_t); extern bool_t rfs4_deleg_state_is_inactive(rfs4_entry_t); /* return values for rfs4_check_stateid_seqid() */ #define NFS4_CHECK_STATEID_OKAY 1 #define NFS4_CHECK_STATEID_OLD 2 #define NFS4_CHECK_STATEID_BAD 3 #define NFS4_CHECK_STATEID_EXPIRED 4 #define NFS4_CHECK_STATEID_REPLAY 5 #define NFS4_CHECK_STATEID_CLOSED 6 #define NFS4_CHECK_STATEID_UNCONFIRMED 7 /* time that server is willing to briefly wait for a delegreturn */ #define NFS4_DELEGATION_CONFLICT_DELAY (hz/10) /* * Interfaces for handling of callback's client handle cache and * callback interfaces themselves. */ extern void rfs40_cbinfo_free(rfs40_cbinfo_t *); extern void rfs40_client_setcb(rfs4_client_t *, cb_client4 *, uint32_t); extern void rfs40_deleg_cb_check(rfs4_client_t *); extern nfsstat4 rfs4_vop_getattr(vnode_t *, vattr_t *, int, cred_t *); /* rfs4_deleg_state_t handling and other delegation interfaces */ extern rfs4_deleg_state_t *rfs4_finddeleg(rfs4_context_t *, rfs4_state_t *, bool_t *); extern rfs4_deleg_state_t *rfs4_finddelegstate(rfs4_context_t *, stateid_t *); extern bool_t rfs4_check_recall(rfs4_state_t *, uint32_t); extern void rfs4_recall_deleg(rfs4_file_t *, bool_t, rfs4_client_t *); extern void rfs4_recall_delay(rfs4_file_t *); extern rfs4_deleg_state_t *rfs4_grant_delegation(rfs4_context_t *, rfs4_deleg_context_t *, rfs4_state_t *); extern void rfs4_set_deleg_response(rfs4_deleg_state_t *, open_delegation4 *, nfsace4 *, rfs4_deleg_context_t *); extern void rfs4_return_deleg(rfs4_deleg_state_t *, bool_t); extern bool_t rfs4_is_deleg(rfs4_state_t *); extern void rfs4_deleg_state_rele(rfs4_deleg_state_t *); extern bool_t rfs4_check_delegated_byfp(int, rfs4_file_t *, bool_t, bool_t, bool_t, clientid4 *, bool_t *); extern void rfs4_clear_dont_grant(rfs4_file_t *); extern void rfs40_cb_recall(rfs4_deleg_state_t *, int); extern void rfs41_cb_recall(rfs4_deleg_state_t *, int); extern void rfs41_rs_record(slot_ent_t *, stateid_type_t, void *, rfs41_session_t *); extern void rfs41_rs_erase(slot_ent_t *, void *); extern void rfs41_slot_cleanup(slot_ent_t *); /* * nfs4 monitored operations. */ extern int deleg_rd_open(femarg_t *, int, cred_t *, caller_context_t *); extern int deleg_wr_open(femarg_t *, int, cred_t *, caller_context_t *); extern int deleg_wr_read(femarg_t *, uio_t *, int, cred_t *, caller_context_t *); extern int deleg_rd_write(femarg_t *, uio_t *, int, cred_t *, caller_context_t *); extern int deleg_wr_write(femarg_t *, uio_t *, int, cred_t *, caller_context_t *); extern int deleg_rd_setattr(femarg_t *, vattr_t *, int, cred_t *, caller_context_t *); extern int deleg_wr_setattr(femarg_t *, vattr_t *, int, cred_t *, caller_context_t *); extern int deleg_rd_rwlock(femarg_t *, int, caller_context_t *); extern int deleg_wr_rwlock(femarg_t *, int, caller_context_t *); extern int deleg_rd_space(femarg_t *, int, flock64_t *, int, offset_t, cred_t *, caller_context_t *); extern int deleg_wr_space(femarg_t *, int, flock64_t *, int, offset_t, cred_t *, caller_context_t *); extern int deleg_rd_setsecattr(femarg_t *, vsecattr_t *, int, cred_t *, caller_context_t *); extern int deleg_wr_setsecattr(femarg_t *, vsecattr_t *, int, cred_t *, caller_context_t *); extern int deleg_rd_vnevent(femarg_t *, vnevent_t, vnode_t *, char *, caller_context_t *); extern int deleg_wr_vnevent(femarg_t *, vnevent_t, vnode_t *, char *, caller_context_t *); extern void rfs4_mon_hold(void *); extern void rfs4_mon_rele(void *); extern int rfs4_share(rfs4_state_t *, uint32_t, uint32_t); extern int rfs4_unshare(rfs4_state_t *); extern void rfs4_set_deleg_policy(rfs_inst_t *, srv_deleg_policy_t); extern void rfs41_bc_check_start(rfs41_session_t *); extern void rfs41_bc_check(rfs41_session_t *); extern bool_t rfs4_dbe_is_memory_low(rfs4_client_t *, rfs4_table_t *); #ifdef DEBUG #define NFS4_DEBUG(var, args) if (var) cmn_err args extern int rfs4_debug; extern int nfs4_client_attr_debug; extern int nfs4_client_state_debug; extern int nfs4_client_shadow_debug; extern int nfs4_client_lock_debug; extern int nfs4_client_lease_debug; extern int nfs4_client_lease_l4time_debug; extern int nfs4_seqid_sync; extern int nfs4_client_map_debug; extern int nfs4_client_inactive_debug; extern int nfs4_client_recov_debug; extern int nfs4_client_failover_debug; extern int nfs4_client_call_debug; extern int nfs4_client_foo_debug; extern int nfs4_client_zone_debug; extern int nfs4_lost_rqst_debug; extern int nfs4_open_stream_debug; extern int nfs4_open_owner_debug; extern int nfs4_client_open_dg; extern int nfs4_utf8_debug; void rfs4_dbe_debug(rfs4_dbe_t *e); #ifdef NFS4_DEBUG_MUTEX void nfs4_debug_mutex_enter(kmutex_t *, char *, int); void nfs4_debug_mutex_exit(kmutex_t *, char *, int); /* CSTYLED */ #define mutex_enter(m) nfs4_debug_mutex_enter((m), __FILE__, __LINE__) /* CSTYLED */ #define mutex_exit(m) nfs4_debug_mutex_exit((m), __FILE__, __LINE__) #endif /* NFS4_DEBUG_MUTEX */ #else /* ! DEBUG */ #define NFS4_DEBUG(var, args) #endif /* DEBUG */ /* * could test volatile fh in DEBUG kernels here */ #ifdef NOTYET #define VOLATILE_FH_TEST struct nfs_fh4_fmt { fhandle4_t fh4_i; uint32_t fh4_flag; uint32_t fh4_volatile_id; }; #else /* NOTYET */ struct nfs_fh4_fmt { fhandle4_t fh4_i; uint32_t fh4_flag; }; #endif /* NOTYET */ #define FH4_NAMEDATTR 1 #define FH4_ATTRDIR 2 #define fh4_fsid fh4_i.fhx_fsid #define fh4_len fh4_i.fhx_len /* fid length */ #define fh4_data fh4_i.fhx_data /* fid bytes */ #define fh4_xlen fh4_i.fhx_xlen #define fh4_xdata fh4_i.fhx_xdata typedef struct nfs_fh4_fmt nfs_fh4_fmt_t; extern nfs_fh4_fmt_t *fh4_to_fmt4(nfs_fh4 *); #define get_fh4_flag(fh4p, flag) ((fh4_to_fmt4(fh4p)->fh4_flag) & (flag)) #define set_fh4_flag(fh4p, flag) ((fh4_to_fmt4(fh4p)->fh4_flag) |= (flag)) #define clr_fh4_flag(fh4p, flag) ((fh4_to_fmt4(fh4p)->fh4_flag) &= ~(flag)) #define NFS_FH4_LEN sizeof (nfs_fh4_fmt_t) /* * A few definitions of repeatedly used constructs for nfsv4 */ #define UTF8STRING_FREE(str) \ kmem_free((str).utf8string_val, (str).utf8string_len); \ (str).utf8string_val = NULL; \ (str).utf8string_len = 0; /* * NFS4_VOLATILE_FH yields non-zero if the filesystem uses non-persistent * filehandles. */ #define NFS4_VOLATILE_FH(mi) \ ((mi)->mi_fh_expire_type & \ (FH4_VOLATILE_ANY | FH4_VOL_MIGRATION | FH4_VOL_RENAME)) /* * NFS_IS_DOTNAME checks if the name given represents a dot or dotdot entry */ #define NFS_IS_DOTNAME(name) \ (((name)[0] == '.') && \ (((name)[1] == '\0') || (((name)[1] == '.') && ((name)[2] == '\0')))) /* * Define the number of bits in a bitmap word (uint32) */ #define NFS4_BITMAP4_BITSPERWORD (sizeof (uint32_t) * 8) /* * Define the value for the access field of the rfs4_compound_state structure * based on the result of nfsauth access checking. */ #define CS_ACCESS_OK 0x1 #define CS_ACCESS_DENIED 0x2 #define CS_ACCESS_LIMITED 0x4 /* * CS_ACCESS_CHECKREQ triggers the additional client access list checks * for pseudofs which only allow clients to only see/access pseudonodes which * lead to shares that the client is allowed to access. It is set when * a) show_mountinfo=none * b) additional client access list checks are applicable to calling rfs4 op * (putfh, lookup, readdir, etc) */ #define CS_ACCESS_CHECKREQ 0x8 /* namespace visibility check requested */ /* * callback compound state in nfsv4 client */ typedef struct compound_state { nfs4_minor_t cs_mvers; bool_t cs_cont; nfsstat4 *cs_statusp; } compound_state_t; struct rfs_disp; /* * compound state in nfsv4 server */ typedef struct rfs4_compound_state { struct exportinfo *cs_exi; struct exportinfo *cs_saved_exi; /* export struct for saved_vp */ rfs4_context_t *cs_ctx; /* 40/41 context */ rfs_inst_t *cs_rip; cred_t *cs_basecr; /* UNIX cred: only RPC request */ caddr_t cs_principal; int cs_nfsflavor; cred_t *cs_cr; /* UNIX cred: RPC request and */ /* target export */ uint_t cs_access; /* access perm on vp per request */ vnode_t *cs_vp; /* modified by PUTFH, and by ops that */ /* input to GETFH */ bool_t cs_mandlock; /* Is mandatory locking in effect */ /* for vp */ bool_t cs_got_fs_loca; /* compound has gotten fs_locations */ bool_t cs_lease_moved; /* state check saw LEASE_MOVED */ uint32_t cs_pri; /* default priority or from OISP hint */ vnode_t *cs_saved_vp; /* modified by SAVEFH, copied to */ /* vp by RESTOREFH */ nfs_fh4 cs_fh; /* ditto. valid only if vp != NULL */ nfs_fh4 cs_saved_fh; /* ditto. valid only if */ /* saved_vp != NULL */ struct svc_req *cs_req; char cs_fhbuf[NFS4_FHSIZE]; clientid4 cs_clientid; /* short for client id from RENEW */ bool_t cs_renew_seen; struct rfs_disp *cs_dispbuf; rfs41_session_t *cs_sp; rfs4_client_t *cs_cp; slot_ent_t *cs_slotp; sequenceid4 cs_seqid; bool_t cs_curstateid_valid; stateid4 cs_curstateid; stateid4 cs_saved_curstateid; bool_t cs_saved_curstateid_valid; int cs_sequenced; int cs_cachethis; size_t cs_rqst_sz; size_t cs_resp_sz; uint_t cs_args_index; uint_t cs_num_ops; uint_t cs_curop; int cs_skip_idmap; /* idmapping enabled? */ void *cs_oisp_ioattrp; /* OISP hints */ rpc_drc_cookie_t cs_dupreq_cookie; } rfs4_compound_state_t; /* * Conversion commands for nfsv4 server attr checking */ enum nfs4_attr_cmd { NFS4ATTR_SUPPORTED = 0, /* check which attrs supported */ NFS4ATTR_GETIT = 1, /* getattr - sys to fattr4 (r) */ NFS4ATTR_SETIT = 2, /* setattr - fattr4 to sys (w) */ NFS4ATTR_VERIT = 3, /* verify - fattr4 to sys (r) */ NFS4ATTR_FREEIT = 4 /* free any alloc'd space for attr */ }; typedef enum nfs4_attr_cmd nfs4_attr_cmd_t; /* * The functions for getting attributes can return: * 0 - OK * >0 - Protocol error * -1 - Error can be ignored if rdattr_error is set * -2 - Error can silently be ignored */ #define NFS4_ATTR_ERR_RDATTR_OKAY -1 #define NFS4_ATTR_ERR_SILENT_IGNORE -2 struct nfs4_svgetit_arg { nfs4_attr_cmd_t op; /* getit or setit */ rfs4_compound_state_t *cs; struct statvfs64 *sbp; uint_t flag; /* VOP_GETATTR/VOP_SETATTR flag */ uint_t xattr; /* object is xattr */ bool_t rdattr_error_req; /* if readdir & client wants */ /* rdattr_error */ nfsstat4 rdattr_error; /* used for per-entry status */ /* (if rdattr_err) */ bool_t is_referral; /* because sometimes we tell lies */ bool_t mntdfid_set; fattr4_mounted_on_fileid mounted_on_fileid; /* readdir op can always return */ /* d_ino from server fs dirent */ /* for mounted_on_fileid attr. */ /* This field holds d_ino so */ /* srv attr conv code can avoid */ /* doing an untraverse. */ vattr_t vap[1]; }; struct nfs4_ntov_map { attrmap4 fbit; /* FATTR4_XXX_MASKY */ uint_t vbit; /* AT_XXX */ bool_t vfsstat; bool_t mandatory; /* attribute mandatory to implement? */ uint_t nval; int xdr_size; /* Size of XDR'd attr */ xdrproc_t xfunc; int (*sv_getit)(nfs4_attr_cmd_t, struct nfs4_svgetit_arg *, union nfs4_attr_u *); /* subroutine for getting attr. */ char *prtstr; /* string attr for printing */ }; struct nfs4attr_to_vattr { vnode_t *vp; vattr_t *vap; nfs_fh4 *fhp; nfsstat4 rdattr_error; uint32_t flag; fattr4_change change; fattr4_fsid srv_fsid; fattr4_mounted_on_fileid mntd_fid; }; typedef struct nfs4attr_to_vattr ntov4_t; /* * nfs4attr_to_vattr flags */ #define NTOV_FHP_VALID 0x01 #define NTOV_RDATTR_ERROR_VALID 0x02 #define NTOV_CHANGE_VALID 0x04 #define NTOV_SUPP_VALID 0x08 #define NTOV_SRV_FSID_VALID 0x10 #define NTOV_MOUNTED_ON_FILEID_VALID 0x20 #define FATTR4_MANDATTR_MASK ( \ FATTR4_SUPPORTED_ATTRS_MASK | \ FATTR4_TYPE_MASK | \ FATTR4_FH_EXPIRE_TYPE_MASK | \ FATTR4_CHANGE_MASK | \ FATTR4_SIZE_MASK | \ FATTR4_LINK_SUPPORT_MASK | \ FATTR4_SYMLINK_SUPPORT_MASK | \ FATTR4_NAMED_ATTR_MASK | \ FATTR4_FSID_MASK | \ FATTR4_UNIQUE_HANDLES_MASK | \ FATTR4_LEASE_TIME_MASK | \ FATTR4_RDATTR_ERROR_MASK | \ FATTR4_FILEHANDLE_MASK) struct nfs4attr_to_osattr { void *attrconv_arg; uint_t mask; }; struct mntinfo4; /* * lkp4_attr_setup lists the different options for attributes when calling * nfs4lookup_setup - either no attributes (just lookups - e.g., secinfo), * one component only (normal component lookup), get attributes for the * last component (e.g., mount), attributes for each component (e.g., * failovers later), just the filehandle for the last component (e.g., * volatile filehandle recovery), or stuff that needs OPENATTR (e.g. * looking up a named attribute or it's hidden directory). */ enum lkp4_attr_setup { LKP4_NO_ATTRIBUTES = 0, /* no attrs or filehandles */ LKP4_ALL_ATTRIBUTES = 3, /* multi-comp: attrs for all comps */ LKP4_LAST_NAMED_ATTR = 5, /* multi-comp: named attr & attrdir */ LKP4_LAST_ATTRDIR = 6, /* multi-comp: just attrdir */ LKP4_ALL_ATTR_SECINFO = 7 /* multi-comp: attrs for all comp and */ /* secinfo for last comp */ }; typedef enum lkp4_attr_setup lkp4_attr_setup_t; #define NFS4_FATTR4_FINISH -1 /* fattr4 index indicating finish */ typedef int (*nfs4attr_to_os_t)(int, union nfs4_attr_u *, struct nfs4attr_to_osattr *); /* * The nfs4_error_t is the basic structure to return error values * from rfs4call. It encapsulates the unix errno * value, the nfsstat4 value and the rpc status value into a single * structure. * * If error is set, then stat is ignored and rpc_status may be * set if the error occurred as the result of a CLNT_CALL. If * stat is set, then rpc request succeeded, error and * rpc_status are set to 0 and stat contains the result of * operation, NFS4_OK or one of the NFS4ERR_* values. * * Functions which want to generate errors independently from * rfs4call should set error to the desired errno value and * set stat and rpc_status to 0. nfs4_error_init() is a * convenient function to do this. * * The field needs_recovery is used to carry information to the * caller that a recoverable issue should be handled; this is * also used to short-circuit work and bubble up the information. */ typedef struct { int error; nfsstat4 stat; enum clnt_stat rpc_status; int needs_recovery; } nfs4_error_t; #define NFS4_ERROR_ZINIT { 0, NFS4_OK, RPC_SUCCESS, 0 } /* * Shared functions */ extern void nfs_fh4_copy(nfs_fh4 *, nfs_fh4 *); extern void nfs4_fattr4_free(fattr4 *); extern int nfs4_getattr_otw(vnode_t *, nfs4_ga_res_t *, cred_t *, int); extern int nfs4cmpfh(const nfs_fh4 *, const nfs_fh4 *); extern int nfs4cmpfhandle(nfs4_fhandle_t *, nfs4_fhandle_t *); extern int nfs4getattr(vnode_t *, struct vattr *, cred_t *); extern int nfs4_waitfor_purge_complete(vnode_t *); extern int nfs4_validate_caches(vnode_t *, cred_t *); extern int nfs4init(int, char *); extern void nfs4fini(void); extern int nfs4_vfsinit(void); extern void nfs4_vfsfini(void); extern void nfs4_vnops_init(void); extern void nfs4_vnops_fini(void); extern void nfs_idmap_init(void); extern void nfs_idmap_flush(int); extern void nfs_idmap_fini(void); extern int nfs4_rnode_init(void); extern int nfs4_rnode_fini(void); extern int nfs4_shadow_init(void); extern int nfs4_shadow_fini(void); extern int nfs4_acache_init(void); extern int nfs4_acache_fini(void); extern int nfs4_subr_init(void); extern int nfs4_subr_fini(void); extern void nfs4_acl_init(void); extern void nfs4_acl_free_cache(vsecattr_t *); extern int geterrno4(nfsstat4); extern nfsstat4 puterrno4(int, nfs_opnum4); extern int nfs4_need_to_bump_seqid(COMPOUND4res_clnt *); extern char *nfs4_op_to_str(nfs_opnum4); extern int nfs4tsize(void); extern int checkauth4(rfs4_compound_state_t *, struct svc_req *); extern nfsstat4 call_checkauth4(rfs4_compound_state_t *, struct svc_req *); extern int is_exported_sec(int, struct exportinfo *); extern void nfs4_vmask_to_nmask(uint_t, attrmap4 *, nfs4_minor_t); extern void nfs4_vmask_to_nmask_set(uint_t, attrmap4 *); extern int nfs_idmap_str_uid(utf8string *, uid_t *, bool_t, int); extern int nfs_idmap_str_gid(utf8string *, gid_t *, bool_t, int); extern int nfs_idmap_uid_str(uid_t, utf8string *, bool_t, int); extern int nfs_idmap_gid_str(gid_t, utf8string *, bool_t, int); extern int nfs4_time_ntov(nfstime4 *, timestruc_t *); extern int nfs4_time_vton(timestruc_t *, nfstime4 *); extern char *utf8_to_str(utf8string *, uint_t *, char *); extern char *utf8_to_fn(utf8string *, uint_t *, char *); extern utf8string *str_to_utf8(char *, utf8string *); extern void utf8_free(utf8string *); extern utf8string *utf8_copy(utf8string *, utf8string *); extern int utf8_compare(const utf8string *, const utf8string *); extern int utf8_dir_verify(utf8string *); extern char *utf8_strchr(utf8string *, const char); extern int ln_ace4_cmp(nfsace4 *, nfsace4 *, int); extern int vs_aent_to_ace4(vsecattr_t *, vsecattr_t *, int, int, int); extern int vs_ace4_to_aent(vsecattr_t *, vsecattr_t *, uid_t, gid_t, int, int, int); extern int vs_ace4_to_acet(vsecattr_t *, vsecattr_t *, uid_t, gid_t, int, int); extern int vs_acet_to_ace4(vsecattr_t *, vsecattr_t *, int, int); extern void vs_acet_destroy(vsecattr_t *); extern void vs_ace4_destroy(vsecattr_t *); extern void vs_aent_destroy(vsecattr_t *); extern int vn_find_nfs_record(vnode_t *, nvlist_t **, char **, char **); extern int vn_is_nfs_reparse(vnode_t *, cred_t *, fsh_entry_t *); extern fs_locations4 *fetch_referral(rfs_inst_t *, vnode_t *, cred_t *, fsh_entry_t *, int *); extern fs_locations4 *fetch_replicas(rfs_inst_t *, vfs_t *, cred_t *); extern int vfs_replica_parse(vfs_t *, nvlist_t *); extern int stateid4_cmp(stateid4 *, stateid4 *); extern int netbuf_cmp(struct netbuf *, struct netbuf *); extern vtype_t nf4_to_vt[]; extern struct nfs4_ntov_map nfs4_ntov_map[]; extern uint_t nfs4_ntov_map_size; extern struct nfs4_ntov_map nfs40_ntov_map[]; extern struct nfs4_ntov_map nfs41_ntov_map[]; extern void rfs4_attr_init(rfs_inst_t *); extern void rfs4_ntov_init(void); extern struct vfsops *nfs4_vfsops; extern struct vnodeops *nfs4_vnodeops; extern const struct fs_operation_def nfs4_vnodeops_template[]; extern vnodeops_t *nfs4_trigger_vnodeops; extern const struct fs_operation_def nfs4_trigger_vnodeops_template[]; extern uint_t nfs4_tsize(struct knetconfig *); extern uint_t rfs4_tsize(struct svc_req *); extern bool_t xdr_inline_decode_nfs_fh4(uint32_t *, nfs_fh4_fmt_t *, uint32_t); extern bool_t xdr_inline_encode_nfs_fh4(uint32_t **, uint32_t *, nfs_fh4_fmt_t *); struct nfs4clrst_args; extern void (*rfs4_client_clrst)(struct nfs4clrst_args *); extern void rfs4_clear_client_state(struct nfs4clrst_args *); extern rfs4_cbstate_t rfs40_cb_check(rfs4_client_t *); extern rfs4_cbstate_t rfs41_cb_check(rfs4_client_t *); extern stateid4 clnt_special0; extern stateid4 clnt_special1; extern stateid4 clnt_current_stateid; #define CLNT_ISSPECIAL(id) (stateid4_cmp(id, &clnt_special0) || \ stateid4_cmp(id, &clnt_special1)) extern boolean_t nfs_filename_is_silly(char *); extern void nfs_record_silly_file(rfs_inst_t *, char *, char *, char *, vnode_t *); extern void nfs_remove_silly_file(rfs_inst_t *, char *, char *, vnode_t *); extern void nfs_get_fsroot(vnode_t *, vnode_t **); /* * The NFS Version 4 service procedures. */ extern int rfs4_compound(rfs4_compound_state_t *); extern void rfs4_compound_free(COMPOUND4res_srv *); extern void rfs4_global_init(void); extern void rfs4_global_fini(void); extern void rfs4_srvrinit(rfs_inst_t *); extern void rfs4_srvrfini(rfs_inst_t *); extern void rfs4_state_init(rfs4_context_t *); extern void rfs4_state_fini(rfs4_context_t *); extern void rfs4_state_cpr_enable(rfs_inst_t *); extern void rfs4_state_cpr_disable(rfs_inst_t *); /* NFSv4.1: slot support */ struct nfs4_session; extern int slot_alloc(nfs41_slot_table_t *, slt_wait_t, slot_ent_t **); extern int slot_alloc_error(nfs41_slot_table_t *, slot_ent_t **); extern void slot_free(nfs41_slot_table_t *, slot_ent_t *); extern int slot_race(nfs41_slot_table_t *, uint32_t, sequenceid4); extern nfs41_slot_table_t *slot_table_create(uint32_t); extern void slot_table_destroy(nfs41_slot_table_t *); extern int slot_table_close(nfs41_slot_table_t *); extern void slot_table_resize(nfs41_slot_table_t *, uint32_t, uint32_t); extern void slot_table_size_inuse(nfs41_slot_table_t *, uint32_t); extern void slot_table_cleanup(nfs41_slot_table_t *); extern nfsstat4 slot_find(nfs41_slot_table_t *, uint32_t, sequenceid4, int, slot_ent_t **); extern void slot_incr_seq(slot_ent_t *, int); extern slot_ent_t *slot_get(nfs41_slot_table_t *, uint32_t); extern void slot_rele(nfs41_slot_table_t *, slot_ent_t *); #endif #ifdef __cplusplus } #endif #endif /* _NFS4_H */