/* * LOCK: Try to create a lock * * Programmer Harassment Alert * * When given a blocking lock request in a sync RPC call, the HPUX lockd * will faithfully return LCK_BLOCKED but never cares to notify us when * the lock could be granted. This way, our local process could hang * around forever waiting for the callback. * * Solution A: Implement busy-waiting * Solution B: Use the async version of the call (NLM_LOCK_{MSG,RES}) * * For now I am implementing solution A, because I hate the idea of * re-implementing lockd for a third time in two months. The async * calls shouldn't be too hard to do, however. * * This is one of the lovely things about standards in the NFS area: * they're so soft and squishy you can't really blame HP for doing this. */ static int nlmclnt_lock(struct nlm_rqst *req, struct file_lock *fl) { struct nlm_host *host = req->a_host; struct nlm_res *resp = &req->a_res; int status; if (!host->h_monitored && nsm_monitor(host) < 0) { printk(KERN_NOTICE "lockd: failed to monitor %s\n", host->h_name); return -ENOLCK; } while (1) { if ((status = nlmclnt_call(req, NLMPROC_LOCK)) >= 0) { if (resp->status != NLM_LCK_BLOCKED) break; status = nlmclnt_block(host, fl, &resp->status); } if (status < 0) return status; } if (resp->status == NLM_LCK_GRANTED) { fl->fl_u.nfs_fl.state = host->h_state; fl->fl_u.nfs_fl.flags |= NFS_LCK_GRANTED; } return nlm_stat_to_errno(resp->status); }
/* * Obtain client and file from arguments */ static u32 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; u32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) return nlm_lck_denied_nolocks; /* Obtain handle for client host */ if (rqstp->rq_client == NULL) { printk(KERN_NOTICE "lockd: unauthenticated request from (%08x:%d)\n", ntohl(rqstp->rq_addr.sin_addr.s_addr), ntohs(rqstp->rq_addr.sin_port)); return nlm_lck_denied_nolocks; } /* Obtain host handle */ if (!(host = nlmsvc_lookup_host(rqstp)) || (argp->monitor && !host->h_monitored && nsm_monitor(host) < 0)) goto no_locks; *hostp = host; /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) goto no_locks; *filp = file; /* Set up the missing parts of the file_lock structure */ lock->fl.fl_file = &file->f_file; lock->fl.fl_owner = (fl_owner_t) host; } return 0; no_locks: if (host) nlm_release_host(host); if (error) return error; return nlm_lck_denied_nolocks; }
/* * Obtain client and file from arguments */ static __be32 nlm4svc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; __be32 error = 0; /* nfsd callbacks must have been installed for this procedure */ if (!nlmsvc_ops) return nlm_lck_denied_nolocks; /* Obtain host handle */ if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) || (argp->monitor && nsm_monitor(host) < 0)) goto no_locks; *hostp = host; /* Obtain file pointer. Not used by FREE_ALL call. */ if (filp != NULL) { if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) goto no_locks; *filp = file; /* Set up the missing parts of the file_lock structure */ lock->fl.fl_file = file->f_file; lock->fl.fl_owner = (fl_owner_t) host; lock->fl.fl_lmops = &nlmsvc_lock_operations; } return 0; no_locks: if (host) nlm_release_host(host); if (error) return error; return nlm_lck_denied_nolocks; }
static __be32 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, struct nlm_host **hostp, struct nlm_file **filp) { struct nlm_host *host = NULL; struct nlm_file *file = NULL; struct nlm_lock *lock = &argp->lock; __be32 error = 0; if (!nlmsvc_ops) return nlm_lck_denied_nolocks; if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) || (argp->monitor && nsm_monitor(host) < 0)) goto no_locks; *hostp = host; if (filp != NULL) { error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); if (error != 0) goto no_locks; *filp = file; lock->fl.fl_file = file->f_file; lock->fl.fl_owner = (fl_owner_t) host; lock->fl.fl_lmops = &nlmsvc_lock_operations; } return 0; no_locks: nlmsvc_release_host(host); if (error) return error; return nlm_lck_denied_nolocks; }
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; }
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT * xprt, char * caller_name) { state_nsm_client_t key; state_nsm_client_t * pclient; char sock_name[SOCK_NAME_MAX]; 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)); if(nfs_param.core_param.nsm_use_caller_name) { key.ssc_nlm_caller_name_len = strlen(caller_name); if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN) { return NULL; } key.ssc_nlm_caller_name = caller_name; } else if(xprt == NULL) { int rc = ipstring_to_sockaddr(caller_name, &key.ssc_client_addr); if(rc != 0) { LogEvent(COMPONENT_STATE, "Error %s, converting caller_name %s to an ipaddress", gai_strerror(rc), caller_name); return NULL; } key.ssc_nlm_caller_name_len = strlen(caller_name); if(key.ssc_nlm_caller_name_len > LM_MAXSTRLEN) { return NULL; } key.ssc_nlm_caller_name = caller_name; } else { key.ssc_nlm_caller_name = sock_name; if(copy_xprt_addr(&key.ssc_client_addr, xprt) == 0) { LogCrit(COMPONENT_STATE, "Error converting caller_name %s to an ipaddress", caller_name); return NULL; } if(sprint_sockip(&key.ssc_client_addr, key.ssc_nlm_caller_name, sizeof(sock_name)) == 0) { LogCrit(COMPONENT_STATE, "Error converting caller_name %s to an ipaddress", caller_name); return NULL; } key.ssc_nlm_caller_name_len = strlen(key.ssc_nlm_caller_name); } if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.pdata = &key; buffkey.len = sizeof(key); rc = HashTable_GetLatch(ht_nsm_client, &buffkey, &buffval, TRUE, &latch); /* If we found it, return it */ if(rc == HASHTABLE_SUCCESS) { pclient = buffval.pdata; /* Return the found NSM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nsm_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_nsm_client_ref(pclient); HashTable_ReleaseLatched(ht_nsm_client, &latch); if(care == CARE_MONITOR && !nsm_monitor(pclient)) { dec_nsm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if(rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nsm_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 NSM Client */ if(isFullDebug(COMPONENT_STATE)) { display_nsm_client(&key, str); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } HashTable_ReleaseLatched(ht_nsm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if(pclient == NULL) { display_nsm_client(&key, str); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1) { /* Mutex initialization failed, free the created client */ display_nsm_client(&key, str); LogCrit(COMPONENT_STATE, "Could not init mutex for {%s}", str); gsh_free(pclient); return NULL; } pclient->ssc_nlm_caller_name = gsh_strdup(key.ssc_nlm_caller_name); if(pclient->ssc_nlm_caller_name == NULL) { /* Discard the created client */ free_nsm_client(pclient); return NULL; } init_glist(&pclient->ssc_lock_list); init_glist(&pclient->ssc_share_list); pclient->ssc_refcount = 1; if(isFullDebug(COMPONENT_STATE)) { display_nsm_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_nsm_client, &buffval, &buffval, &latch, FALSE, NULL, NULL); /* An error occurred, return NULL */ if(rc != HASHTABLE_SUCCESS) { display_nsm_client(pclient, str); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); free_nsm_client(pclient); return NULL; } if(care != CARE_MONITOR || nsm_monitor(pclient)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nsm_client_ref(pclient); return NULL; }
state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT * xprt, const char * caller_name) { state_nsm_client_t *pkey, *pclient; if(caller_name == NULL) return NULL; pkey = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pkey == NULL) return NULL; memset(pkey, 0, sizeof(*pkey)); pkey->ssc_refcount = 1; if(nfs_param.core_param.nsm_use_caller_name) { pkey->ssc_nlm_caller_name_len = strlen(caller_name); if(pkey->ssc_nlm_caller_name_len > LM_MAXSTRLEN) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } pkey->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1); if(pkey->ssc_nlm_caller_name == NULL) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } memcpy(pkey->ssc_nlm_caller_name, caller_name, pkey->ssc_nlm_caller_name_len); pkey->ssc_nlm_caller_name[pkey->ssc_nlm_caller_name_len] = '\0'; } else { pkey->ssc_nlm_caller_name_len = SOCK_NAME_MAX; pkey->ssc_nlm_caller_name = Mem_Alloc(SOCK_NAME_MAX); if(pkey->ssc_nlm_caller_name == NULL) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } if(copy_xprt_addr(&pkey->ssc_client_addr, xprt) == 0) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } if(sprint_sockip(&pkey->ssc_client_addr, pkey->ssc_nlm_caller_name, SOCK_NAME_MAX) == 0) { /* Discard the key we created */ free_nsm_client(pkey); return NULL; } pkey->ssc_nlm_caller_name_len = strlen(pkey->ssc_nlm_caller_name); } if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pkey, str); LogFullDebug(COMPONENT_STATE, "Find NSM Client pkey {%s}", str); } /* If we found it, return it, if we don't care, return NULL */ if(nsm_client_Get_Pointer(pkey, &pclient) == 1 || care == CARE_NOT) { /* Discard the key we created and return the found NSM Client */ free_nsm_client(pkey); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found NSM Client {%s}", str); } if(care == CARE_MONITOR) if(!nsm_monitor(pclient)) { dec_nsm_client_ref(pclient); return NULL; } return pclient; } pclient = (state_nsm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pclient == NULL) { free_nsm_client(pkey); return NULL; } /* Copy everything over */ *pclient = *pkey; pclient->ssc_nlm_caller_name = Mem_Alloc(pkey->ssc_nlm_caller_name_len + 1); if(pclient->ssc_nlm_caller_name == NULL) { /* Discard the key and created client */ free_nsm_client(pkey); free_nsm_client(pclient); return NULL; } memcpy(pclient->ssc_nlm_caller_name, pkey->ssc_nlm_caller_name, pclient->ssc_nlm_caller_name_len); pclient->ssc_nlm_caller_name[pclient->ssc_nlm_caller_name_len] = '\0'; init_glist(&pclient->ssc_lock_list); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New NSM Client {%s}", str); } if(pthread_mutex_init(&pclient->ssc_mutex, NULL) == -1) { /* Mutex initialization failed, free the key and created client */ free_nsm_client(pkey); free_nsm_client(pclient); return NULL; } if(nsm_client_Set(pkey, pclient) == 1) { if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nsm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Set NSM Client {%s}", str); } if(care != CARE_MONITOR || nsm_monitor(pclient)) return pclient; dec_nsm_client_ref(pclient); return NULL; } free_nsm_client(pkey); free_nsm_client(pclient); return NULL; }
state_nlm_client_t *get_nlm_client(care_t care, SVCXPRT * xprt, state_nsm_client_t * pnsm_client, const char * caller_name) { state_nlm_client_t *pkey, *pclient; if(caller_name == NULL) return NULL; pkey = (state_nlm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pkey == NULL) return NULL; memset(pkey, 0, sizeof(*pkey)); pkey->slc_refcount = 1; pkey->slc_nsm_client = pnsm_client; pkey->slc_nlm_caller_name_len = strlen(caller_name); pkey->slc_client_type = get_xprt_type(xprt); if(pkey->slc_nlm_caller_name_len > LM_MAXSTRLEN) { /* Discard the key we created */ Mem_Free(pkey); return NULL; } memcpy(pkey->slc_nlm_caller_name, caller_name, pkey->slc_nlm_caller_name_len); pkey->slc_nlm_caller_name[pkey->slc_nlm_caller_name_len] = '\0'; if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_client(pkey, str); LogFullDebug(COMPONENT_STATE, "Find NLM Client pkey {%s}", str); } /* If we found it, return it, if we don't care, return NULL */ if(nlm_client_Get_Pointer(pkey, &pclient) == 1 || care == CARE_NOT) { /* Discard the key we created and return the found NLM Client */ Mem_Free(pkey); if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Found NLM Client {%s}", str); } if(care == CARE_MONITOR) if(!nsm_monitor(pnsm_client)) { dec_nlm_client_ref(pclient); return NULL; } return pclient; } pclient = (state_nlm_client_t *)Mem_Alloc(sizeof(*pkey)); if(pclient == NULL) { Mem_Free(pkey); return NULL; } /* Copy everything over */ *pclient = *pkey; if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "New NLM Client {%s}", str); } if(pthread_mutex_init(&pclient->slc_mutex, NULL) == -1) { /* Mutex initialization failed, free the key and created owner */ Mem_Free(pkey); Mem_Free(pclient); return NULL; } /* Ref count the NSM Client as being used by this NLM Client */ inc_nsm_client_ref(pnsm_client); if(nlm_client_Set(pkey, pclient) == 1) { if(isFullDebug(COMPONENT_STATE)) { char str[HASHTABLE_DISPLAY_STRLEN]; display_nlm_client(pclient, str); LogFullDebug(COMPONENT_STATE, "Set NLM Client {%s}", str); } if(care != CARE_MONITOR || nsm_monitor(pnsm_client)) return pclient; dec_nlm_client_ref(pclient); return NULL; } dec_nsm_client_ref(pnsm_client); Mem_Free(pkey); Mem_Free(pclient); return NULL; }
/** * @brief Get an NSM client * * @param[in] care Care status * @param[in] xprt RPC transport * @param[in] caller_name Caller name * * @return NSM client or NULL. */ state_nsm_client_t *get_nsm_client(care_t care, SVCXPRT *xprt, char *caller_name) { state_nsm_client_t key; state_nsm_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; if (caller_name == NULL) return NULL; memset(&key, 0, sizeof(key)); if (nfs_param.core_param.nsm_use_caller_name) { key.ssc_nlm_caller_name_len = strlen(caller_name); if (key.ssc_nlm_caller_name_len > LM_MAXSTRLEN) return NULL; key.ssc_nlm_caller_name = caller_name; } else if (op_ctx->client == NULL) { LogCrit(COMPONENT_STATE, "No gsh_client for caller_name %s", caller_name); return NULL; } else { key.ssc_nlm_caller_name = op_ctx->client->hostaddr_str; key.ssc_nlm_caller_name_len = strlen(key.ssc_nlm_caller_name); key.ssc_client = op_ctx->client; } if (isFullDebug(COMPONENT_STATE)) { display_nsm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Find {%s}", str); } buffkey.addr = &key; buffkey.len = sizeof(key); rc = hashtable_getlatch(ht_nsm_client, &buffkey, &buffval, true, &latch); /* If we found it, return it */ if (rc == HASHTABLE_SUCCESS) { pclient = buffval.addr; /* Return the found NSM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nsm_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_nsm_client_ref(pclient); hashtable_releaselatched(ht_nsm_client, &latch); if (care == CARE_MONITOR && !nsm_monitor(pclient)) { dec_nsm_client_ref(pclient); pclient = NULL; } return pclient; } /* An error occurred, return NULL */ if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) { display_nsm_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 NSM Client */ if (isFullDebug(COMPONENT_STATE)) { display_nsm_client(&dspbuf, &key); LogFullDebug(COMPONENT_STATE, "Ignoring {%s}", str); } hashtable_releaselatched(ht_nsm_client, &latch); return NULL; } pclient = gsh_malloc(sizeof(*pclient)); if (pclient == NULL) { display_nsm_client(&dspbuf, &key); LogCrit(COMPONENT_STATE, "No memory for {%s}", str); return NULL; } /* Copy everything over */ memcpy(pclient, &key, sizeof(key)); PTHREAD_MUTEX_init(&pclient->ssc_mutex, NULL); pclient->ssc_nlm_caller_name = gsh_strdup(key.ssc_nlm_caller_name); if (pclient->ssc_nlm_caller_name == NULL) { /* Discard the created client */ PTHREAD_MUTEX_destroy(&pclient->ssc_mutex); free_nsm_client(pclient); return NULL; } glist_init(&pclient->ssc_lock_list); glist_init(&pclient->ssc_share_list); pclient->ssc_refcount = 1; if (op_ctx->client != NULL) { pclient->ssc_client = op_ctx->client; inc_gsh_client_refcount(op_ctx->client); } if (isFullDebug(COMPONENT_STATE)) { display_nsm_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_nsm_client, &buffval, &buffval, &latch, false, NULL, NULL); /* An error occurred, return NULL */ if (rc != HASHTABLE_SUCCESS) { display_nsm_client(&dspbuf, pclient); LogCrit(COMPONENT_STATE, "Error %s, inserting {%s}", hash_table_err_to_str(rc), str); PTHREAD_MUTEX_destroy(&pclient->ssc_mutex); free_nsm_client(pclient); return NULL; } if (care != CARE_MONITOR || nsm_monitor(pclient)) return pclient; /* Failed to monitor, release client reference * and almost certainly remove it from the hash table. */ dec_nsm_client_ref(pclient); return NULL; }
/** * @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; }