static int unload_fsal(struct fsal_module *fsal_hdl) { int retval = EBUSY; /* someone still has a reference */ pthread_mutex_lock(&fsal_lock); pthread_mutex_lock(&fsal_hdl->lock); if (fsal_hdl->refs != 0 || !glist_empty(&fsal_hdl->exports)) goto err; if (fsal_hdl->dl_handle == NULL) { retval = EACCES; /* cannot unload static linked fsals */ goto err; } glist_del(&fsal_hdl->fsals); pthread_mutex_unlock(&fsal_hdl->lock); pthread_mutex_destroy(&fsal_hdl->lock); fsal_hdl->refs = 0; retval = dlclose(fsal_hdl->dl_handle); pthread_mutex_unlock(&fsal_lock); return retval; err: pthread_mutex_unlock(&fsal_hdl->lock); pthread_mutex_unlock(&fsal_lock); return retval; }
int32_t dec_session_ref(nfs41_session_t *session) { int i; int32_t refcnt = atomic_dec_int32_t(&session->refcount); if (refcnt == 0) { /* Unlink the session from the client's list of sessions */ PTHREAD_MUTEX_lock(&session->clientid_record->cid_mutex); glist_del(&session->session_link); PTHREAD_MUTEX_unlock(&session->clientid_record->cid_mutex); /* Decrement our reference to the clientid record */ dec_client_id_ref(session->clientid_record); /* Destroy this session's mutexes and condition variable */ for (i = 0; i < NFS41_NB_SLOTS; i++) PTHREAD_MUTEX_destroy(&session->slots[i].lock); PTHREAD_COND_destroy(&session->cb_cond); PTHREAD_MUTEX_destroy(&session->cb_mutex); /* Destroy the session's back channel (if any) */ if (session->flags & session_bc_up) nfs_rpc_destroy_chan(&session->cb_chan); /* Free the memory for the session */ pool_free(nfs41_session_pool, session); } return refcnt; }
fsal_status_t schedule_fsal_up_event_process(fsal_up_event_t *arg) { int rc; fsal_status_t ret = {0, 0}; /* Events which needs quick response, and locking events wich has its own queue gets processed here, rest will be queued. */ if (arg->event_type == FSAL_UP_EVENT_LOCK_GRANT || arg->event_type == FSAL_UP_EVENT_LOCK_AVAIL) { arg->event_process_func(&arg->event_data); gsh_free(arg->event_data.event_context.fsal_data.fh_desc.start); pool_free(fsal_up_event_pool, arg); return ret; } if(arg->event_type == FSAL_UP_EVENT_INVALIDATE) { arg->event_process_func(&arg->event_data); /* Step2 where we perform close; which could be expensive operation so deffer it to the separate thread. */ arg->event_process_func = dumb_fsal_up_invalidate_step2; } if(arg->event_type == FSAL_UP_EVENT_UPDATE) { /* Invalidate first without scheduling */ arg->event_process_func(&arg->event_data); if ((arg->event_data.type.update.upu_flags & FSAL_UP_NLINK) && (arg->event_data.type.update.upu_stat_buf.st_nlink == 0) ) { /* upu_flags must be set or st_nlink is unreliable. */ /* Step2 where we perform close; which could be expensive operation so defer it to the separate thread. */ arg->event_process_func = dumb_fsal_up_invalidate_step2; } else return ret; } /* Now queue them for further process. */ LogFullDebug(COMPONENT_FSAL_UP, "Schedule %p", arg); P(fsal_up_process_tcb.tcb_mutex); glist_add_tail(&fsal_up_process_queue, &arg->event_list); rc = pthread_cond_signal(&fsal_up_process_tcb.tcb_condvar); LogFullDebug(COMPONENT_FSAL_UP,"Signaling tcb_condvar"); if (rc == -1) { LogDebug(COMPONENT_FSAL_UP, "Unable to signal FSAL_UP Process Thread"); glist_del(&arg->event_list); ret.major = ERR_FSAL_FAULT; } V(fsal_up_process_tcb.tcb_mutex); return ret; }
void free_nfs4_owner(state_owner_t * owner) { if(owner->so_owner.so_nfs4_owner.so_related_owner != NULL) dec_state_owner_ref(owner->so_owner.so_nfs4_owner.so_related_owner); /* Release the saved response. */ nfs4_Compound_FreeOne(&owner->so_owner.so_nfs4_owner.so_resp); /* Remove the owner from the owners per clientid list. */ P(owner->so_owner.so_nfs4_owner.so_clientrec->cid_mutex); glist_del(&owner->so_owner.so_nfs4_owner.so_perclient); V(owner->so_owner.so_nfs4_owner.so_clientrec->cid_mutex); dec_client_id_ref(owner->so_owner.so_nfs4_owner.so_clientrec); }
void free_nfs4_owner(state_owner_t *owner) { state_nfs4_owner_t *nfs4_owner = &owner->so_owner.so_nfs4_owner; if (nfs4_owner->so_related_owner != NULL) dec_state_owner_ref(nfs4_owner->so_related_owner); /* Release the saved response. */ nfs4_Compound_FreeOne(&nfs4_owner->so_resp); /* Remove the owner from the owners per clientid list. */ PTHREAD_MUTEX_lock(&nfs4_owner->so_clientrec->cid_mutex); glist_del(&nfs4_owner->so_perclient); PTHREAD_MUTEX_unlock(&nfs4_owner->so_clientrec->cid_mutex); dec_client_id_ref(nfs4_owner->so_clientrec); }
fsal_status_t GPFSFSAL_CleanUpExportContext(fsal_export_context_t * export_context) { gpfsfsal_export_context_t *p_export_context = (gpfsfsal_export_context_t *)export_context; if(export_context == NULL) { LogCrit(COMPONENT_FSAL, "NULL mandatory argument passed to %s()", __FUNCTION__); Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_CleanUpExportContext); } if(p_export_context->mount_root_fd != 0) close(p_export_context->mount_root_fd); if(p_export_context->fe_fsal_up_ctx != NULL) { /* Start to clean up FSAL_UP stuff. There is actually more to do here...*/ glist_del(&p_export_context->fe_list); } Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_CleanUpExportContext); }
void remove_nfs4_owner(state_owner_t * powner, const char * str) { hash_buffer_t buffkey, old_key, old_value; state_nfs4_owner_name_t oname; int rc; memset(&oname, 0, sizeof(oname)); oname.son_clientid = powner->so_owner.so_nfs4_owner.so_clientid; oname.son_owner_len = powner->so_owner_len; oname.son_islock = powner->so_type == STATE_LOCK_OWNER_NFSV4; memcpy(oname.son_owner_val, powner->so_owner_val, powner->so_owner_len); buffkey.pdata = (caddr_t) &oname; buffkey.len = sizeof(*powner); rc = HashTable_DelRef(ht_nfs4_owner, &buffkey, &old_key, &old_value, Hash_dec_state_owner_ref); switch(rc) { case HASHTABLE_SUCCESS: if(powner->so_type == STATE_LOCK_OWNER_NFSV4 && powner->so_owner.so_nfs4_owner.so_related_owner != NULL) dec_state_owner_ref(powner->so_owner.so_nfs4_owner.so_related_owner); /* Release the owner_name (key) and owner (data) back to appropriate pools */ LogFullDebug(COMPONENT_STATE, "Free %s", str); nfs4_Compound_FreeOne(&powner->so_owner.so_nfs4_owner.so_resp); P(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex); glist_del(&powner->so_owner.so_nfs4_owner.so_perclient); V(powner->so_owner.so_nfs4_owner.so_pclientid->cid_mutex); dec_client_id_ref(powner->so_owner.so_nfs4_owner.so_pclientid); pool_free(state_owner_pool, old_value.pdata); pool_free(state_nfs4_owner_name_pool, old_key.pdata); break; case HASHTABLE_NOT_DELETED: /* ref count didn't end up at 0, don't free. */ LogDebug(COMPONENT_STATE, "HashTable_DelRef didn't reduce refcount to 0 for %s", str); break; default: /* some problem occurred */ LogDebug(COMPONENT_STATE, "HashTable_DelRef failed (%s) for %s", hash_table_err_to_str(rc), str); break; } }
/* This thread processes FSAL UP events. */ void *fsal_up_process_thread(void *UnUsedArg) { struct timeval now; struct timespec timeout; fsal_up_event_t * fupevent; int rc; SetNameFunction("fsal_up_process_thread"); if (mark_thread_existing(&fsal_up_process_tcb) == PAUSE_EXIT) { /* Oops, that didn't last long... exit. */ mark_thread_done(&fsal_up_process_tcb); LogDebug(COMPONENT_INIT, "FSAL_UP Process Thread: Exiting before initialization"); return NULL; } LogFullDebug(COMPONENT_INIT, "FSAL_UP Process Thread: my pthread id is %p", (caddr_t) pthread_self()); while(1) { /* Check without tcb lock*/ if ((fsal_up_process_tcb.tcb_state != STATE_AWAKE) || glist_empty(&fsal_up_process_queue)) { while(1) { P(fsal_up_process_tcb.tcb_mutex); if ((fsal_up_process_tcb.tcb_state == STATE_AWAKE) && !glist_empty(&fsal_up_process_queue)) { V(fsal_up_process_tcb.tcb_mutex); break; } switch(thread_sm_locked(&fsal_up_process_tcb)) { case THREAD_SM_RECHECK: V(fsal_up_process_tcb.tcb_mutex); continue; case THREAD_SM_BREAK: if (glist_empty(&fsal_up_process_queue)) { gettimeofday(&now, NULL); timeout.tv_sec = 10 + now.tv_sec; timeout.tv_nsec = 0; rc = pthread_cond_timedwait(&fsal_up_process_tcb.tcb_condvar, &fsal_up_process_tcb.tcb_mutex, &timeout); } V(fsal_up_process_tcb.tcb_mutex); continue; case THREAD_SM_EXIT: V(fsal_up_process_tcb.tcb_mutex); return NULL; } } } P(fsal_up_process_tcb.tcb_mutex); fupevent = glist_first_entry(&fsal_up_process_queue, fsal_up_event_t, event_list); if(fupevent != NULL) { /* Pull the event off of the list */ glist_del(&fupevent->event_list); /* Release the mutex */ V(fsal_up_process_tcb.tcb_mutex); fupevent->event_process_func(&fupevent->event_data); gsh_free(fupevent->event_data.event_context.fsal_data.fh_desc.start); pool_free(fsal_up_event_pool, fupevent); continue; } V(fsal_up_process_tcb.tcb_mutex); } tcb_remove(&fsal_up_process_tcb); }