blob: 9b1f2acfa695b561b8027dda014728421a935a27 [file] [log] [blame]
/*
*
*
* Copyright CEA/DAM/DIF (2008)
* contributeur : Philippe DENIEL philippe.deniel@cea.fr
* Thomas LEIBOVICI thomas.leibovici@cea.fr
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*
* ---------------------------------------
*/
/**
* @defgroup SAL State abstraction layer
* @{
*/
/**
* @file sal_functions.h
* @brief Routines in the state abstraction layer
* @note not called by other header files.
*/
#ifndef SAL_FUNCTIONS_H
#define SAL_FUNCTIONS_H
#include <stdint.h>
#include "sal_data.h"
#include "fsal.h"
/**
* @brief Divisions in state and clientid tables.
*/
#define PRIME_STATE 17
/*****************************************************************************
*
* Misc functions
*
*****************************************************************************/
const char *state_err_str(state_status_t err);
state_status_t state_error_convert(fsal_status_t fsal_status);
nfsstat4 nfs4_Errno_state(state_status_t error);
nfsstat3 nfs3_Errno_state(state_status_t error);
const char *state_owner_type_to_str(state_owner_type_t type);
bool different_owners(state_owner_t *owner1, state_owner_t *owner2);
int display_owner(struct display_buffer *dspbuf, state_owner_t *owner);
void inc_state_owner_ref(state_owner_t *owner);
void dec_state_owner_ref(state_owner_t *owner);
void free_state_owner(state_owner_t *owner);
#define LogStateOwner(note, owner) \
do { \
if (isFullDebug(COMPONENT_STATE)) { \
char str[LOG_BUFF_LEN]; \
struct display_buffer dspbuf = { \
sizeof(str), str, str}; \
display_owner(&dspbuf, owner); \
LogFullDebug(COMPONENT_STATE, "%s%s", note, str); \
} \
} while (0)
state_owner_t *get_state_owner(care_t care, state_owner_t *pkey,
state_owner_init_t init_owner, bool_t *isnew);
void state_wipe_file(struct fsal_obj_handle *obj);
#ifdef DEBUG_SAL
void dump_all_owners(void);
#endif
void state_release_export(struct gsh_export *exp);
bool state_unlock_err_ok(state_status_t status);
/**
* @brief Initialize a state handle
*
* @param[in,out] ostate State handle to initialize
* @param[in] type Type of handle
* @param[in] obj Object owning handle
* @return Return description
*/
static inline void state_hdl_init(struct state_hdl *ostate,
object_file_type_t type,
struct fsal_obj_handle *obj)
{
memset(ostate, 0, sizeof(*ostate));
PTHREAD_RWLOCK_init(&ostate->state_lock, NULL);
switch (type) {
case REGULAR_FILE:
glist_init(&ostate->file.list_of_states);
glist_init(&ostate->file.layoutrecall_list);
glist_init(&ostate->file.lock_list);
glist_init(&ostate->file.nlm_share_list);
ostate->file.obj = obj;
break;
case DIRECTORY:
glist_init(&ostate->dir.export_roots);
break;
default:
break;
}
}
/*****************************************************************************
*
* 9P State functions
*
*****************************************************************************/
#ifdef _USE_9P
int compare_9p_owner(state_owner_t *owner1, state_owner_t *owner2);
int compare_9p_owner_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
int display_9p_owner(struct display_buffer *dspbuf, state_owner_t *owner);
int display_9p_owner_key(struct gsh_buffdesc *buff, char *str);
int display_9p_owner_val(struct gsh_buffdesc *buff, char *str);
uint32_t _9p_owner_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t _9p_owner_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
state_owner_t *get_9p_owner(struct sockaddr_storage *client_addr,
uint32_t proc_id);
int Init_9p_hash(void);
#endif
/******************************************************************************
*
* NLM Owner functions
*
******************************************************************************/
void free_nsm_client(state_nsm_client_t *client);
/* These refcount functions must not be called holding the ssc_mutex */
void inc_nsm_client_ref(state_nsm_client_t *client);
void dec_nsm_client_ref(state_nsm_client_t *client);
int display_nsm_client(struct display_buffer *dspbuf, state_nsm_client_t *key);
int display_nsm_client_key(struct gsh_buffdesc *buff, char *str);
int compare_nsm_client(state_nsm_client_t *client1,
state_nsm_client_t *client2);
int compare_nsm_client_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint32_t nsm_client_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t nsm_client_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT *xprt,
char *caller_name);
void inc_nlm_client_ref(state_nlm_client_t *client);
void dec_nlm_client_ref(state_nlm_client_t *client);
int display_nlm_client_val(struct gsh_buffdesc *buff, char *str);
int display_nlm_client_key(struct gsh_buffdesc *buff, char *str);
int compare_nlm_client(state_nlm_client_t *client1,
state_nlm_client_t *client2);
int compare_nlm_client_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint32_t nlm_client_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t nlm_client_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT *xprt,
state_nsm_client_t *nsm_client,
char *caller_name);
void free_nlm_owner(state_owner_t *powner);
int display_nlm_owner(struct display_buffer *dspbuf, state_owner_t *owner);
int display_nlm_owner_val(struct gsh_buffdesc *buff, char *str);
int display_nlm_owner_key(struct gsh_buffdesc *buff, char *str);
int compare_nlm_owner(state_owner_t *owner1, state_owner_t *owner2);
int compare_nlm_owner_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint32_t nlm_owner_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t nlm_owner_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
state_owner_t *get_nlm_owner(care_t care, state_nlm_client_t *client,
netobj *oh, uint32_t svid);
int Init_nlm_hash(void);
/******************************************************************************
*
* NLM State functions
*
******************************************************************************/
int display_nlm_state(struct display_buffer *dspbuf, state_t *key);
int compare_nlm_state(state_t *state1, state_t *state2);
int Init_nlm_state_hash(void);
void dec_nlm_state_ref(state_t *state);
int get_nlm_state(enum state_type state_type,
struct fsal_obj_handle *state_obj,
state_owner_t *state_owner,
bool nsm_state_applies,
uint32_t nsm_state,
state_t **pstate);
/******************************************************************************
*
* NFS4 Client ID functions
*
******************************************************************************/
nfsstat4 clientid_error_to_nfsstat(clientid_status_t err);
static inline
nfsstat4 clientid_error_to_nfsstat_no_expire(clientid_status_t err)
{
nfsstat4 rc = clientid_error_to_nfsstat(err);
if (rc == NFS4ERR_EXPIRED)
rc = NFS4ERR_STALE_CLIENTID;
return rc;
}
const char *clientid_error_to_str(clientid_status_t err);
int nfs_Init_client_id(void);
clientid_status_t nfs_client_id_get_unconfirmed(clientid4 clientid,
nfs_client_id_t **pclient_rec);
clientid_status_t nfs_client_id_get_confirmed(clientid4 clientid,
nfs_client_id_t **client_rec);
nfs_client_id_t *create_client_id(clientid4 clientid,
nfs_client_record_t *client_record,
nfs_client_cred_t *credential,
uint32_t minorversion);
clientid_status_t nfs_client_id_insert(nfs_client_id_t *clientid);
int remove_confirmed_client_id(nfs_client_id_t *clientid);
int remove_unconfirmed_client_id(nfs_client_id_t *clientid);
clientid_status_t nfs_client_id_confirm(nfs_client_id_t *clientid,
log_components_t component);
bool clientid_has_state(nfs_client_id_t *clientid);
bool nfs_client_id_expire(nfs_client_id_t *clientid, bool make_stale);
#define DISPLAY_CLIENTID_SIZE 36
int display_clientid(struct display_buffer *dspbuf, clientid4 clientid);
clientid4 new_clientid(void);
void new_clientid_verifier(char *verf);
int display_client_id_key(struct gsh_buffdesc *buff, char *str);
int display_client_id_val(struct gsh_buffdesc *buff, char *str);
int compare_client_id(struct gsh_buffdesc *buff1, struct gsh_buffdesc *buff2);
uint64_t client_id_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint32_t client_id_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
int display_client_id_rec(struct display_buffer *dspbuf,
nfs_client_id_t *clientid);
#define CLIENTNAME_BUFSIZE (NFS4_OPAQUE_LIMIT * 2 + 1)
int display_clientid_name(struct display_buffer *dspbuf,
nfs_client_id_t *clientid);
void free_client_id(nfs_client_id_t *clientid);
void
nfs41_foreach_client_callback(bool(*cb) (nfs_client_id_t *cl, void *state),
void *state);
bool client_id_has_state(nfs_client_id_t *clientid);
int32_t inc_client_id_ref(nfs_client_id_t *clientid);
int32_t dec_client_id_ref(nfs_client_id_t *clientid);
int display_client_record(struct display_buffer *dspbuf,
nfs_client_record_t *record);
void free_client_record(nfs_client_record_t *record);
int32_t inc_client_record_ref(nfs_client_record_t *record);
int32_t dec_client_record_ref(nfs_client_record_t *record);
int display_client_record_key(struct gsh_buffdesc *buff, char *str);
int display_client_record_val(struct gsh_buffdesc *buff, char *str);
int compare_client_record(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint64_t client_record_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint32_t client_record_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
nfs_client_record_t *get_client_record(const char *const value,
const size_t len,
const uint32_t pnfs_flags,
const uint32_t server_addr);
/******************************************************************************
*
* NFS4.1 Session ID functions
*
******************************************************************************/
int display_session_id(struct display_buffer *dspbuf, char *session_id);
int display_session(struct display_buffer *dspbuf, nfs41_session_t *session);
int32_t inc_session_ref(nfs41_session_t *session);
int32_t dec_session_ref(nfs41_session_t *session);
int display_session_id_key(struct gsh_buffdesc *buff, char *str);
int display_session_id_val(struct gsh_buffdesc *buff, char *str);
int compare_session_id(struct gsh_buffdesc *buff1, struct gsh_buffdesc *buff2);
uint32_t session_id_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t session_id_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
int nfs41_Init_session_id(void);
int nfs41_Session_Set(nfs41_session_t *session_data);
int nfs41_Session_Get_Pointer(char sessionid[NFS4_SESSIONID_SIZE],
nfs41_session_t **session_data);
int nfs41_Session_Del(char sessionid[NFS4_SESSIONID_SIZE]);
void nfs41_Build_sessionid(clientid4 *clientid, char *sessionid);
void nfs41_Session_PrintAll(void);
/******************************************************************************
*
* NFSv4 Stateid functions
*
******************************************************************************/
#define DISPLAY_STATEID_OTHER_SIZE (DISPLAY_CLIENTID_SIZE + 72)
int display_stateid_other(struct display_buffer *dspbuf, char *other);
int display_stateid(struct display_buffer *dspbuf, state_t *state);
/* 17 is 7 for " seqid=" and 10 for MAX_UINT32 digits */
#define DISPLAY_STATEID4_SIZE (DISPLAY_STATEID_OTHER_SIZE + 17)
int display_stateid4(struct display_buffer *dspbuf, stateid4 *stateid);
void nfs4_BuildStateId_Other(nfs_client_id_t *clientid, char *other);
#define STATEID_NO_SPECIAL 0 /*< No special stateids */
#define STATEID_SPECIAL_ALL_0 2 /*< Allow anonymous */
#define STATEID_SPECIAL_ALL_1 4 /*< Allow read-bypass */
#define STATEID_SPECIAL_CURRENT 8 /*< Allow current */
#define STATEID_SPECIAL_FREE 0x100 /*< Check for FREE_STATEID */
#define STATEID_SPECIAL_FOR_FREE (STATEID_SPECIAL_CURRENT | \
STATEID_SPECIAL_FREE)
/* The following flag tells nfs4_Check_Stateid this is a close call
* and to ignore stateid that have valid clientid portion, but the
* counter portion doesn't reference a currently open file.
*/
#define STATEID_SPECIAL_CLOSE_40 0x40
#define STATEID_SPECIAL_CLOSE_41 0x80
#define STATEID_SPECIAL_ANY 0x3F
#define STATEID_SPECIAL_FOR_LOCK (STATEID_SPECIAL_CURRENT)
#define STATEID_SPECIAL_FOR_CLOSE_40 (STATEID_SPECIAL_CLOSE_40)
#define STATEID_SPECIAL_FOR_CLOSE_41 (STATEID_SPECIAL_CLOSE_41 | \
STATEID_SPECIAL_CURRENT)
nfsstat4 nfs4_Check_Stateid(stateid4 *stateid, struct fsal_obj_handle *fsal_obj,
state_t **state, compound_data_t *data, int flags,
seqid4 owner_seqid, bool check_seqid,
const char *tag);
void update_stateid(state_t *state, stateid4 *stateid, compound_data_t *data,
const char *tag);
int nfs4_Init_state_id(void);
/**
* @brief Take a reference on state_t
*
* @param[in] state The state_t to ref
*/
static inline void inc_state_t_ref(struct state_t *state)
{
(void) atomic_inc_int32_t(&state->state_refcount);
}
void dec_nfs4_state_ref(struct state_t *state);
/**
* @brief Relinquish a reference on any State
*
* @param[in] state The NLM State to release
*/
static inline void dec_state_t_ref(struct state_t *state)
{
#ifdef _USE_NLM
if (state->state_type == STATE_TYPE_NLM_LOCK ||
state->state_type == STATE_TYPE_NLM_SHARE)
dec_nlm_state_ref(state);
else
#endif /* _USE_NLM */
dec_nfs4_state_ref(state);
}
int nfs4_State_Set(state_t *state_data);
struct state_t *nfs4_State_Get_Pointer(char *other);
bool nfs4_State_Del(state_t *state);
void nfs_State_PrintAll(void);
struct state_t *nfs4_State_Get_Obj(struct fsal_obj_handle *obj,
state_owner_t *owner);
int display_state_id_val(struct gsh_buffdesc *buff, char *str);
int display_state_id_key(struct gsh_buffdesc *buff, char *str);
uint32_t state_id_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t state_id_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
/******************************************************************************
*
* NFSv4 Lease functions
*
******************************************************************************/
int reserve_lease(nfs_client_id_t *clientid);
void update_lease(nfs_client_id_t *clientid);
bool valid_lease(nfs_client_id_t *clientid);
/******************************************************************************
*
* NFSv4 Owner functions
*
******************************************************************************/
void uncache_nfs4_owner(struct state_nfs4_owner_t *nfs4_owner);
void free_nfs4_owner(state_owner_t *owner);
int display_nfs4_owner(struct display_buffer *dspbuf, state_owner_t *owner);
int display_nfs4_owner_val(struct gsh_buffdesc *buff, char *str);
int display_nfs4_owner_key(struct gsh_buffdesc *buff, char *str);
int compare_nfs4_owner(state_owner_t *owner1, state_owner_t *owner2);
int compare_nfs4_owner_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint32_t nfs4_owner_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t nfs4_owner_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
/**
* @brief Convert an open_owner to an owner name
*
* @param[in] nfsowner Open owner as specified in NFS
* @param[out] name_owner Name used as key in owner table
*/
static inline void convert_nfs4_open_owner(open_owner4 *nfsowner,
state_nfs4_owner_name_t *name_owner)
{
name_owner->son_owner_len = nfsowner->owner.owner_len;
name_owner->son_owner_val = nfsowner->owner.owner_val;
}
/**
* @brief Convert a lock_owner to an owner name
*
* @param[in] nfsowner Open owner as specified in NFS
* @param[out] name_owner Name used as key in owner table
*/
static inline void convert_nfs4_lock_owner(lock_owner4 *nfsowner,
state_nfs4_owner_name_t *name_owner)
{
name_owner->son_owner_len = nfsowner->owner.owner_len;
name_owner->son_owner_val = nfsowner->owner.owner_val;
}
void nfs4_owner_PrintAll(void);
state_owner_t *create_nfs4_owner(state_nfs4_owner_name_t *name,
nfs_client_id_t *clientid,
state_owner_type_t type,
state_owner_t *related_owner,
unsigned int init_seqid, bool_t *pisnew,
care_t care);
int Init_nfs4_owner(void);
void Process_nfs4_conflict(/* NFS v4 Lock4denied structure to fill in */
LOCK4denied * denied,
/* owner that holds conflicting lock */
state_owner_t *holder,
/* description of conflicting lock */
fsal_lock_param_t *conflict);
void Release_nfs4_denied(LOCK4denied *denied);
void Copy_nfs4_denied(LOCK4denied *denied_dst, LOCK4denied *denied_src);
void Copy_nfs4_state_req(state_owner_t *owner, seqid4 seqid, nfs_argop4 *args,
struct fsal_obj_handle *obj, nfs_resop4 *resp,
const char *tag);
bool Check_nfs4_seqid(state_owner_t *owner, seqid4 seqid, nfs_argop4 *args,
struct fsal_obj_handle *obj, nfs_resop4 *resp,
const char *tag);
/**
* @brief Determine if an NFS v4 owner has state associated with it
*
* Note that this function is racy and is only suitable for calling
* from places that should not have other activity pending against
* the owner. Currently it is only called from setclientid which should
* be fine.
*
* @param[in] owner The owner of interest
*
* @retval true if the owner has state
*/
static inline bool owner_has_state(state_owner_t *owner)
{
bool live_state;
struct state_nfs4_owner_t *nfs4_owner = &owner->so_owner.so_nfs4_owner;
/* If the owner is on the cached owners list, there can't be
* active state.
*/
if (atomic_fetch_time_t(&nfs4_owner->cache_expire) != 0)
return false;
PTHREAD_MUTEX_lock(&owner->so_mutex);
live_state = !glist_empty(&nfs4_owner->so_state_list);
PTHREAD_MUTEX_unlock(&owner->so_mutex);
return live_state;
}
/******************************************************************************
*
* Lock functions
*
******************************************************************************/
static inline int display_lock_cookie(struct display_buffer *dspbuf,
struct gsh_buffdesc *buff)
{
return display_opaque_value(dspbuf, buff->addr, buff->len);
}
int display_lock_cookie_key(struct gsh_buffdesc *buff, char *str);
int display_lock_cookie_val(struct gsh_buffdesc *buff, char *str);
int compare_lock_cookie_key(struct gsh_buffdesc *buff1,
struct gsh_buffdesc *buff2);
uint32_t lock_cookie_value_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
uint64_t lock_cookie_rbt_hash_func(hash_parameter_t *hparam,
struct gsh_buffdesc *key);
state_status_t state_lock_init(void);
void log_lock(log_components_t component,
log_levels_t debug,
const char *reason,
struct fsal_obj_handle *obj,
state_owner_t *owner,
fsal_lock_param_t *lock,
char *file,
int line,
char *function);
#define LogLock(component, debug, reason, obj, owner, lock) \
log_lock(component, debug, reason, obj, owner, lock, \
(char *) __FILE__, __LINE__, (char *) __func__)
void dump_all_locks(const char *label);
state_status_t state_add_grant_cookie(struct fsal_obj_handle *obj,
void *cookie, int cookie_size,
state_lock_entry_t *lock_entry,
state_cookie_entry_t **cookie_entry);
state_status_t state_find_grant(void *cookie, int cookie_size,
state_cookie_entry_t **cookie_entry);
void state_complete_grant(state_cookie_entry_t *cookie_entry);
state_status_t state_cancel_grant(state_cookie_entry_t *cookie_entry);
state_status_t state_release_grant(state_cookie_entry_t *cookie_entry);
state_status_t state_test(struct fsal_obj_handle *obj,
state_t *state,
state_owner_t *owner,
fsal_lock_param_t *lock,
/* owner that holds conflicting lock */
state_owner_t **holder,
/* description of conflicting lock */
fsal_lock_param_t *conflict);
state_status_t state_lock(struct fsal_obj_handle *obj,
state_owner_t *owner,
state_t *state, state_blocking_t blocking,
state_block_data_t *block_data,
fsal_lock_param_t *lock,
/* owner that holds conflicting lock */
state_owner_t **holder,
/* description of conflicting lock */
fsal_lock_param_t *conflict);
state_status_t state_unlock(struct fsal_obj_handle *obj,
state_t *state,
state_owner_t *owner,
bool state_applies,
int32_t nsm_state,
fsal_lock_param_t *lock);
state_status_t state_cancel(struct fsal_obj_handle *obj,
state_owner_t *owner, fsal_lock_param_t *lock);
state_status_t state_nlm_notify(state_nsm_client_t *nsmclient,
bool state_applies,
int32_t state);
void state_nfs4_owner_unlock_all(state_owner_t *owner);
void state_export_unlock_all(void);
bool state_lock_wipe(struct state_hdl *hstate);
void cancel_all_nlm_blocked(void);
static inline void *convert_lock_owner(struct fsal_export *fsal_export,
state_owner_t *owner)
{
return fsal_export->exp_ops.fs_supports(fsal_export,
fso_lock_support_owner)
? owner : NULL;
}
/******************************************************************************
*
* NFSv4 State Management functions
*
******************************************************************************/
state_status_t state_add_impl(struct fsal_obj_handle *obj,
enum state_type state_type,
union state_data *state_data,
state_owner_t *owner_input, state_t **state,
struct state_refer *refer);
state_status_t state_add(struct fsal_obj_handle *obj,
enum state_type state_type,
union state_data *state_data,
state_owner_t *owner_input,
state_t **state, struct state_refer *refer);
state_status_t state_set(state_t *state);
void state_del_locked(state_t *state);
void state_del(state_t *state);
static inline struct fsal_obj_handle *get_state_obj_ref(state_t *state)
{
struct fsal_obj_handle *obj = NULL;
fsal_status_t fsal_status;
struct gsh_buffdesc fh_desc;
struct gsh_export *save_exp = op_ctx->ctx_export;
struct fsal_export *save_fsal = op_ctx->fsal_export;
if (state->state_export == NULL)
return NULL;
/* Need to look up in the correct export */
op_ctx->ctx_export = state->state_export;
op_ctx->fsal_export = state->state_export->fsal_export;
fh_desc.addr = state->state_obj.digest;
fh_desc.len = state->state_obj.len;
fsal_status =
state->state_export->fsal_export->exp_ops.create_handle(
state->state_export->fsal_export, &fh_desc, &obj, NULL);
op_ctx->ctx_export = save_exp;
op_ctx->fsal_export = save_fsal;
if (FSAL_IS_ERROR(fsal_status))
return NULL;
return obj;
}
static inline struct gsh_export *get_state_export_ref(state_t *state)
{
struct gsh_export *export = NULL;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_export != NULL &&
export_ready(state->state_export)) {
get_gsh_export_ref(state->state_export);
export = state->state_export;
}
PTHREAD_MUTEX_unlock(&state->state_mutex);
return export;
}
static inline bool state_same_export(state_t *state, struct gsh_export *export)
{
bool same = false;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_export != NULL)
same = state->state_export == export;
PTHREAD_MUTEX_unlock(&state->state_mutex);
return same;
}
static inline uint16_t state_export_id(state_t *state)
{
uint16_t export_id = UINT16_MAX;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_export != NULL)
export_id = state->state_export->export_id;
PTHREAD_MUTEX_unlock(&state->state_mutex);
return export_id;
}
static inline state_owner_t *get_state_owner_ref(state_t *state)
{
state_owner_t *owner = NULL;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_owner != NULL) {
owner = state->state_owner;
inc_state_owner_ref(owner);
}
PTHREAD_MUTEX_unlock(&state->state_mutex);
return owner;
}
static inline bool state_owner_confirmed(state_t *state)
{
bool confirmed = false;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_owner != NULL) {
confirmed =
state->state_owner->so_owner.so_nfs4_owner.so_confirmed;
}
PTHREAD_MUTEX_unlock(&state->state_mutex);
return confirmed;
}
static inline bool state_same_owner(state_t *state, state_owner_t *owner)
{
bool same = false;
PTHREAD_MUTEX_lock(&state->state_mutex);
if (state->state_owner != NULL)
same = state->state_owner == owner;
PTHREAD_MUTEX_unlock(&state->state_mutex);
return same;
}
bool get_state_obj_export_owner_refs(state_t *state,
struct fsal_obj_handle **obj,
struct gsh_export **export,
state_owner_t **owner);
void state_nfs4_state_wipe(struct state_hdl *ostate);
enum nfsstat4 release_lock_owner(state_owner_t *owner);
void release_openstate(state_owner_t *owner);
void state_export_release_nfs4_state(void);
void revoke_owner_delegs(state_owner_t *client_owner);
#ifdef DEBUG_SAL
void dump_all_states(void);
#endif
/******************************************************************************
*
* Delegations functions
*
******************************************************************************/
state_status_t acquire_lease_lock(struct state_hdl *ostate,
state_owner_t *owner,
state_t *state);
state_status_t release_lease_lock(struct fsal_obj_handle *obj, state_t *state);
bool init_deleg_heuristics(struct fsal_obj_handle *obj);
bool deleg_supported(struct fsal_obj_handle *obj,
struct fsal_export *fsal_export,
struct export_perms *export_perms, uint32_t share_access);
bool can_we_grant_deleg(struct state_hdl *ostate, state_t *open_state);
bool should_we_grant_deleg(struct state_hdl *ostate, nfs_client_id_t *client,
state_t *open_state, OPEN4args *args,
state_owner_t *owner, bool *prerecall);
void init_new_deleg_state(union state_data *deleg_state,
open_delegation_type4 sd_type,
nfs_client_id_t *clientid);
void deleg_heuristics_recall(struct fsal_obj_handle *obj,
state_owner_t *owner,
struct state_t *deleg);
void get_deleg_perm(nfsace4 *permissions, open_delegation_type4 type);
void update_delegation_stats(struct state_hdl *ostate,
state_owner_t *owner,
struct state_t *deleg);
state_status_t delegrecall_impl(struct fsal_obj_handle *obj);
nfsstat4 deleg_revoke(struct fsal_obj_handle *obj, struct state_t *deleg_state);
void state_deleg_revoke(struct fsal_obj_handle *obj, state_t *state);
bool state_deleg_conflict(struct fsal_obj_handle *obj, bool write);
/******************************************************************************
*
* Layout functions
*
******************************************************************************/
state_status_t state_add_segment(state_t *state, struct pnfs_segment *segment,
void *fsal_data, bool return_on_close);
state_status_t state_delete_segment(state_layout_segment_t *segment);
state_status_t state_lookup_layout_state(struct fsal_obj_handle *obj,
state_owner_t *owner,
layouttype4 type, state_t **state);
void revoke_owner_layouts(state_owner_t *client_owner);
/******************************************************************************
*
* Share functions
*
******************************************************************************/
#define OPEN4_SHARE_ACCESS_NONE 0
state_status_t state_share_add(struct fsal_obj_handle *obj,
state_owner_t *owner,
/* state that holds share bits to be added */
state_t *state, bool reclaim);
state_status_t state_share_remove(struct fsal_obj_handle *obj,
state_owner_t *owner,
/* state that holds share bits to be removed
*/
state_t *state);
state_status_t state_share_upgrade(struct fsal_obj_handle *obj,
/* new share bits */
union state_data *state_data,
state_owner_t *owner,
/* state that holds current share bits */
state_t *state, bool reclaim);
state_status_t state_share_downgrade(struct fsal_obj_handle *obj,
/* new share bits */
union state_data *state_data,
state_owner_t *owner,
/* state that holds current share bits */
state_t *state);
state_status_t state_share_set_prev(state_t *state,
union state_data *state_data);
enum share_bypass_modes {
SHARE_BYPASS_NONE,
SHARE_BYPASS_READ,
SHARE_BYPASS_V3_WRITE
};
state_status_t state_share_check_conflict(struct state_hdl *ostate,
int share_acccess,
int share_deny,
enum share_bypass_modes bypass);
bool state_open_deleg_conflict(struct state_hdl *ostate,
const state_t *open_state);
state_status_t state_share_anonymous_io_start(struct fsal_obj_handle *obj,
int share_access,
enum share_bypass_modes bypass);
void state_share_anonymous_io_done(struct fsal_obj_handle *obj,
int share_access);
state_status_t state_nlm_share(struct fsal_obj_handle *obj,
int share_access,
int share_deny,
state_owner_t *owner,
state_t *state,
bool reclaim);
state_status_t state_nlm_unshare(struct fsal_obj_handle *obj,
int share_access,
int share_deny,
state_owner_t *owner,
state_t *state);
void state_share_wipe(struct state_hdl *ostate);
void state_export_unshare_all(void);
/******************************************************************************
*
* Async functions
*
******************************************************************************/
/* Schedule Async Work */
state_status_t state_async_schedule(state_async_queue_t *arg);
/* Schedule lock notifications */
state_status_t state_block_schedule(state_block_data_t *block);
/* Signal Async Work */
void signal_async_work(void);
state_status_t state_async_init(void);
state_status_t state_async_shutdown(void);
void grant_blocked_lock_upcall(struct fsal_obj_handle *obj, void *owner,
fsal_lock_param_t *lock);
void available_blocked_lock_upcall(struct fsal_obj_handle *obj, void *owner,
fsal_lock_param_t *lock);
void process_blocked_lock_upcall(state_block_data_t *block_data);
void blocked_lock_polling(struct fridgethr_context *ctx);
/******************************************************************************
*
* NFSv4 Recovery functions
*
******************************************************************************/
void nfs4_start_grace(nfs_grace_start_t *gsp);
int nfs_in_grace(void);
void nfs4_create_clid_name(nfs_client_record_t *, nfs_client_id_t *,
struct svc_req *);
void nfs4_add_clid(nfs_client_id_t *);
void nfs4_rm_clid(const char *, char *, int);
void nfs4_chk_clid(nfs_client_id_t *);
void nfs4_load_recov_clids(nfs_grace_start_t *gsp);
void nfs4_clean_old_recov_dir(char *);
void nfs4_create_recov_dir(void);
void nfs4_record_revoke(nfs_client_id_t *, nfs_fh4 *);
bool nfs4_check_deleg_reclaim(nfs_client_id_t *, nfs_fh4 *);
#endif /* SAL_FUNCTIONS_H */
/** @} */