void dec_nlm_client_ref_locked(state_nlm_client_t *pclient) { bool_t remove = FALSE; char str[HASHTABLE_DISPLAY_STRLEN]; if(isFullDebug(COMPONENT_STATE)) display_nlm_client(pclient, str); if(pclient->slc_refcount > 1) { pclient->slc_refcount--; LogFullDebug(COMPONENT_STATE, "Decrement refcount NLM Client {%s}", str); } else remove = TRUE; V(pclient->slc_mutex); if(remove) { hash_buffer_t buffkey, old_key, old_value; buffkey.pdata = (caddr_t) pclient; buffkey.len = sizeof(*pclient); switch(HashTable_DelRef(ht_nlm_client, &buffkey, &old_key, &old_value, Hash_dec_nlm_client_ref)) { case HASHTABLE_SUCCESS: LogFullDebug(COMPONENT_STATE, "Free NLM Client {%s} size %llx", str, (unsigned long long) old_value.len); if(pclient->slc_callback_clnt != NULL) Clnt_destroy(pclient->slc_callback_clnt); dec_nsm_client_ref(pclient->slc_nsm_client); if(isFullDebug(COMPONENT_MEMLEAKS)) { memset(old_key.pdata, 0, old_key.len); memset(old_value.pdata, 0, old_value.len); } Mem_Free(old_key.pdata); Mem_Free(old_value.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 NLM Client {%s}", str); break; default: /* some problem occurred */ LogDebug(COMPONENT_STATE, "HashTable_DelRef failed for NLM Client {%s}", str); break; } } }
/* Client routine to send the asynchrnous response, key is used to wait for a response */ int nlm_send_async(int proc, state_nlm_client_t * host, void * inarg, void * key) { struct timeval tout = { 0, 10 }; int retval, retry; struct timeval start, now; struct timespec timeout; for(retry = 1; retry <= MAX_ASYNC_RETRY; retry++) { if(host->slc_callback_clnt == NULL) { LogFullDebug(COMPONENT_NLM, "Clnt_create %s", host->slc_nsm_client->ssc_nlm_caller_name); host->slc_callback_clnt = Clnt_create(host->slc_nsm_client->ssc_nlm_caller_name, NLMPROG, NLM4_VERS, (char *)xprt_type_to_str(host->slc_client_type)); if(host->slc_callback_clnt == NULL) { LogMajor(COMPONENT_NLM, "Cannot create NLM async %s connection to client %s", xprt_type_to_str(host->slc_client_type), host->slc_nsm_client->ssc_nlm_caller_name); return -1; } } pthread_mutex_lock(&nlm_async_resp_mutex); resp_key = key; pthread_mutex_unlock(&nlm_async_resp_mutex); LogFullDebug(COMPONENT_NLM, "About to make clnt_call"); retval = clnt_call(host->slc_callback_clnt, proc, nlm_reply_proc[proc], inarg, (xdrproc_t) xdr_void, NULL, tout); LogFullDebug(COMPONENT_NLM, "Done with clnt_call"); if(retval == RPC_TIMEDOUT || retval == RPC_SUCCESS) { retval = RPC_SUCCESS; break; } LogDebug(COMPONENT_NLM, "NLM async Client procedure call %d failed with return code %d %s", proc, retval, clnt_sperror(host->slc_callback_clnt, "")); Clnt_destroy(host->slc_callback_clnt); host->slc_callback_clnt = NULL; if(retry == MAX_ASYNC_RETRY) { LogMajor(COMPONENT_NLM, "NLM async Client exceeded retry count %d", MAX_ASYNC_RETRY); pthread_mutex_lock(&nlm_async_resp_mutex); resp_key = NULL; pthread_mutex_unlock(&nlm_async_resp_mutex); return retval; } } pthread_mutex_lock(&nlm_async_resp_mutex); if(resp_key != NULL) { /* Wait for 5 seconds or a signal */ gettimeofday(&start, NULL); gettimeofday(&now, NULL); timeout.tv_sec = 5 + start.tv_sec; timeout.tv_nsec = 0; LogFullDebug(COMPONENT_NLM, "About to wait for signal for key %p", resp_key); while(resp_key != NULL && now.tv_sec < (start.tv_sec + 5)) { int rc = pthread_cond_timedwait(&nlm_async_resp_cond, &nlm_async_resp_mutex, &timeout); LogFullDebug(COMPONENT_NLM, "pthread_cond_timedwait returned %d", rc); gettimeofday(&now, NULL); } LogFullDebug(COMPONENT_NLM, "Done waiting"); } pthread_mutex_unlock(&nlm_async_resp_mutex); return retval; }