void make_nlm_special_owner(state_nlm_client_t * pclient, state_owner_t * pnlm_owner) { if(pnlm_owner == NULL) return; memset(pnlm_owner, 0, sizeof(*pnlm_owner)); inc_nlm_client_ref(pclient); pnlm_owner->so_type = STATE_LOCK_OWNER_NLM; pnlm_owner->so_refcount = 1; pnlm_owner->so_owner.so_nlm_owner.so_client = pclient; pnlm_owner->so_owner_len = -1; }
state_status_t nlm_granted_callback(cache_entry_t * pentry, state_lock_entry_t * lock_entry, state_status_t * pstatus) { fsal_op_context_t fsal_context, *pcontext = &fsal_context; state_block_data_t * block_data = lock_entry->sle_block_data; state_nlm_block_data_t * nlm_block_data = &block_data->sbd_block_data.sbd_nlm_block_data; state_cookie_entry_t * cookie_entry = NULL; state_async_queue_t * arg; nlm4_testargs * inarg; state_nlm_owner_t * nlm_grant_owner = &lock_entry->sle_owner->so_owner.so_nlm_owner; state_nlm_client_t * nlm_grant_client = nlm_grant_owner->so_client; granted_cookie_t nlm_grant_cookie; state_status_t dummy_status; if(nlm_block_data_to_fsal_context(block_data, &fsal_context) != TRUE) { *pstatus = STATE_INCONSISTENT_ENTRY; return *pstatus; } arg = gsh_malloc(sizeof(*arg)); if(arg == NULL) { /* If we fail allocation the best is to delete the block entry * so that client can try again and get the lock. May be * by then we are able to allocate objects */ *pstatus = STATE_MALLOC_ERROR; return *pstatus; } memset(arg, 0, sizeof(*arg)); /* Get a cookie to use for this grant */ next_granted_cookie(&nlm_grant_cookie); /* Add a cookie to the blocked lock pending grant. * It will also request lock from FSAL. * Could return STATE_LOCK_BLOCKED because FSAL would have had to block. */ if(state_add_grant_cookie(pentry, pcontext, &nlm_grant_cookie, sizeof(nlm_grant_cookie), lock_entry, &cookie_entry, pstatus) != STATE_SUCCESS) { free_grant_arg(arg); return *pstatus; } /* Fill in the arguments for the NLMPROC4_GRANTED_MSG call */ inc_nlm_client_ref(nlm_grant_client); arg->state_async_func = nlm4_send_grant_msg; arg->state_async_data.state_nlm_async_data.nlm_async_host = nlm_grant_client; arg->state_async_data.state_nlm_async_data.nlm_async_key = cookie_entry; inarg = &arg->state_async_data.state_nlm_async_data.nlm_async_args.nlm_async_grant; if(!copy_netobj(&inarg->alock.fh, &nlm_block_data->sbd_nlm_fh)) goto grant_fail_malloc; if(!fill_netobj(&inarg->alock.oh, lock_entry->sle_owner->so_owner_val, lock_entry->sle_owner->so_owner_len)) goto grant_fail_malloc; if(!fill_netobj(&inarg->cookie, (char *) &nlm_grant_cookie, sizeof(nlm_grant_cookie))) goto grant_fail_malloc; inarg->alock.caller_name = gsh_strdup(nlm_grant_client->slc_nlm_caller_name); if(!inarg->alock.caller_name) goto grant_fail_malloc; inarg->exclusive = lock_entry->sle_lock.lock_type == FSAL_LOCK_W; inarg->alock.svid = nlm_grant_owner->so_nlm_svid; inarg->alock.l_offset = lock_entry->sle_lock.lock_start; inarg->alock.l_len = lock_entry->sle_lock.lock_length; if(isDebug(COMPONENT_NLM)) { char buffer[1024]; netobj_to_string(&inarg->cookie, buffer, sizeof(buffer)); LogDebug(COMPONENT_NLM, "Sending GRANTED for arg=%p svid=%d start=%llx len=%llx cookie=%s", arg, inarg->alock.svid, (unsigned long long) inarg->alock.l_offset, (unsigned long long) inarg->alock.l_len, buffer); } /* Now try to schedule NLMPROC4_GRANTED_MSG call */ *pstatus = state_async_schedule(arg); if(*pstatus != STATE_SUCCESS) goto grant_fail; return *pstatus; grant_fail_malloc: *pstatus = STATE_MALLOC_ERROR; grant_fail: /* Something went wrong after we added a grant cookie, need to clean up */ dec_nlm_client_ref(nlm_grant_client); /* Clean up NLMPROC4_GRANTED_MSG arguments */ free_grant_arg(arg); /* Cancel the pending grant to release the cookie */ if(state_cancel_grant(pcontext, cookie_entry, &dummy_status) != STATE_SUCCESS) { /* Not much we can do other than log that something bad happened. */ LogCrit(COMPONENT_NLM, "Unable to clean up GRANTED lock after error"); } return *pstatus; }
state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT * xprt, state_nsm_client_t * pnsm_client, char * caller_name) { state_nlm_client_t key; state_nlm_client_t * pclient; char str[HASHTABLE_DISPLAY_STRLEN]; struct hash_latch latch; hash_error_t rc; hash_buffer_t buffkey; hash_buffer_t buffval; if(caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); key.slc_nsm_client = pnsm_client; key.slc_nlm_caller_name_len = strlen(caller_name); key.slc_client_type = svc_get_xprt_type(xprt); if(key.slc_nlm_caller_name_len > LM_MAXSTRLEN) return NULL; key.slc_nlm_caller_name = caller_name; if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.pdata = &key; buffkey.len = sizeof(key); rc = HashTable_GetLatch(ht_nlm_client, &buffkey, &buffval, TRUE, &latch); /* If we found it, return it */ if(rc == HASHTABLE_SUCCESS) { pclient = buffval.pdata; /* Return the found NLM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } /* Increment refcount under hash latch. * This prevents dec ref from removing this entry from hash if a race * occurs. */ inc_nlm_client_ref(pclient); HashTable_ReleaseLatched(ht_nlm_client, &latch); if(care == CARE_MONITOR && !nsm_monitor(pnsm_client)) { dec_nlm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if(rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nlm_client(&key, str); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return NULL; } /* Not found, but we don't care, return NULL */ if(care == CARE_NOT) { /* Return the found NLM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } HashTable_ReleaseLatched(ht_nlm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if(pclient == NULL) { display_nlm_client(&key, str); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name); /* Take a reference to the NSM Client */ inc_nsm_client_ref(pnsm_client); if(pclient->slc_nlm_caller_name == NULL) { /* Discard the created client */ free_nlm_client(pclient); return NULL; } pclient->slc_refcount = 1; if(isFullDebug(COMPONENT_STATE)) { display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } buffkey.pdata = pclient; buffkey.len = sizeof(*pclient); buffval.pdata = pclient; buffval.len = sizeof(*pclient); rc = HashTable_SetLatched(ht_nlm_client, &buffval, &buffval, &latch, FALSE, NULL, NULL); /* An error occurred, return NULL */ if(rc != HASHTABLE_SUCCESS) { display_nlm_client(pclient, str); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nlm_client(pclient); return NULL; } if(care != CARE_MONITOR || nsm_monitor(pnsm_client)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nlm_client_ref(pclient); return NULL; }
static void init_nlm_owner(state_owner_t * powner) { inc_nlm_client_ref(powner->so_owner.so_nlm_owner.so_client); init_glist(&powner->so_owner.so_nlm_owner.so_nlm_shares); }
state_owner_t *get_nlm_owner(care_t care, state_nlm_client_t * pclient, netobj * oh, uint32_t svid) { state_owner_t * pkey, *powner; if(pclient == NULL || oh == NULL || oh->n_len > MAX_NETOBJ_SZ) return NULL; pkey = (state_owner_t *)Mem_Alloc(sizeof(*pkey)); if(pkey == NULL) return NULL; memset(pkey, 0, sizeof(*pkey)); pkey->so_type = STATE_LOCK_OWNER_NLM; pkey->so_refcount = 1; pkey->so_owner.so_nlm_owner.so_client = pclient; pkey->so_owner.so_nlm_owner.so_nlm_svid = svid; pkey->so_owner_len = oh->n_len; memcpy(pkey->so_owner_val, oh->n_bytes, oh->n_len); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_owner(pkey, str); LogFullDebug(COMPONENT_STATE, "Find NLM Owner KEY {%s}", str); } /* If we found it, return it, if we don't care, return NULL */ if(nlm_owner_Get_Pointer(pkey, &powner) == 1 || care == CARE_NOT) { /* Discard the key we created and return the found NLM Owner */ Mem_Free(pkey); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_owner(powner, str); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } return powner; } powner = (state_owner_t *)Mem_Alloc(sizeof(*pkey)); if(powner == NULL) { Mem_Free(pkey); return NULL; } /* Copy everything over */ *powner = *pkey; init_glist(&powner->so_lock_list); if(pthread_mutex_init(&powner->so_mutex, NULL) == -1) { /* Mutex initialization failed, free the key and created owner */ Mem_Free(pkey); Mem_Free(powner); return NULL; } if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_owner(powner, str); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } /* Ref count the client as being used by this owner */ inc_nlm_client_ref(pclient); if(nlm_owner_Set(pkey, powner) == 1) { if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_owner(powner, str); LogFullDebug(COMPONENT_STATE, "Set NLM Owner {%s}", str); } return powner; } dec_nlm_client_ref(pclient); Mem_Free(pkey); Mem_Free(powner); return NULL; }
/** * @brief Initialize an NLM owner object * * @param[in] owner Stored owner */ static void init_nlm_owner(state_owner_t *owner) { inc_nlm_client_ref(owner->so_owner.so_nlm_owner.so_client); glist_init(&owner->so_owner.so_nlm_owner.so_nlm_shares); }
/** * @brief Get an NLM client * * @param[in] care Care status * @param[in] xprt RPC transport * @param[in] nsm_client Related NSM client * @param[in] caller_name Caller name * * @return NLM client or NULL. */ state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT *xprt, state_nsm_client_t *nsm_client, char *caller_name) { state_nlm_client_t key; state_nlm_client_t *pclient; char str[LOG_BUFF_LEN]; struct display_buffer dspbuf = {sizeof(str), str, str}; struct hash_latch latch; hash_error_t rc; struct gsh_buffdesc buffkey; struct gsh_buffdesc buffval; struct sockaddr_storage local_addr; socklen_t addr_len; if (caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); key.slc_nsm_client = nsm_client; key.slc_nlm_caller_name_len = strlen(caller_name); key.slc_client_type = svc_get_xprt_type(xprt); addr_len = sizeof(local_addr); if (getsockname(xprt->xp_fd, (struct sockaddr *)&local_addr, &addr_len) == -1) { LogEvent(COMPONENT_CLIENTID, "Failed to get local addr."); } else { memcpy(&(key.slc_server_addr), &local_addr, sizeof(struct sockaddr_storage)); } if (key.slc_nlm_caller_name_len > LM_MAXSTRLEN) return NULL; key.slc_nlm_caller_name = caller_name; if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.addr = &key; buffkey.len = sizeof(key); rc = hashtable_getlatch(ht_nlm_client, &buffkey, &buffval, true, &latch); /* If we found it, return it */ if (rc == HASHTABLE_SUCCESS) { pclient = buffval.addr; /* Return the found NLM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, pclient); LogFullDebug(COMPONENT_STATE, "Found {%s}", str); } /* Increment refcount under hash latch. * This prevents dec ref from removing this entry from hash * if a race occurs. */ inc_nlm_client_ref(pclient); hashtable_releaselatched(ht_nlm_client, &latch); if (care == CARE_MONITOR && !nsm_monitor(nsm_client)) { dec_nlm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nlm_client(&dspbuf, &key); LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}", hash_table_err_to_str(rc), str); return NULL; } /* Not found, but we don't care, return NULL */ if (care == CARE_NOT) { /* Return the found NLM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } hashtable_releaselatched(ht_nlm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if (pclient == NULL) { display_nlm_client(&dspbuf, &key); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); pclient->slc_nlm_caller_name = gsh_strdup(key.slc_nlm_caller_name); /* Take a reference to the NSM Client */ inc_nsm_client_ref(nsm_client); if (pclient->slc_nlm_caller_name == NULL) { /* Discard the created client */ free_nlm_client(pclient); return NULL; } pclient->slc_refcount = 1; if (isFullDebug(COMPONENT_STATE)) { display_nlm_client(&dspbuf, pclient); LogFullDebug(COMPONENT_STATE, "New {%s}", str); } buffkey.addr = pclient; buffkey.len = sizeof(*pclient); buffval.addr = pclient; buffval.len = sizeof(*pclient); rc = hashtable_setlatched(ht_nlm_client, &buffval, &buffval, &latch, false, NULL, NULL); /* An error occurred, return NULL */ if (rc != HASHTABLE_SUCCESS) { display_nlm_client(&dspbuf, pclient); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nlm_client(pclient); return NULL; } if (care != CARE_MONITOR || nsm_monitor(nsm_client)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nlm_client_ref(pclient); return NULL; }