int nfs41_Session_Set(nfs41_session_t *session_data)
{
    struct gsh_buffdesc key;
    struct gsh_buffdesc val;
    struct hash_latch latch;
    hash_error_t code;
    int rc = 0;

    key.addr = session_data->session_id;
    key.len = NFS4_SESSIONID_SIZE;

    val.addr = session_data;
    val.len = sizeof(nfs41_session_t);

    /* The latch idiom isn't strictly necessary here */
    code = hashtable_getlatch(ht_session_id, &key, &val, true, &latch);
    if (code == HASHTABLE_SUCCESS) {
        hashtable_releaselatched(ht_session_id, &latch);
        goto out;
    }
    if (code == HASHTABLE_ERROR_NO_SUCH_KEY) {
        /* nfs4_op_create_session ensures refcount == 2 for new
         * session records */
        code =
            hashtable_setlatched(ht_session_id, &key, &val, &latch,
                                 false, NULL, NULL);
        if (code == HASHTABLE_SUCCESS)
            rc = 1;
    }

out:
    return rc;
}
Example #2
0
/**
 * @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;
}
Example #3
0
fsal_acl_t *nfs4_acl_new_entry(fsal_acl_data_t *acldata,
                               fsal_acl_status_t *status)
{
    fsal_acl_t *acl = NULL;
    struct gsh_buffdesc key;
    struct gsh_buffdesc value;
    int rc;
    struct hash_latch latch;

    /* Set the return default to NFS_V4_ACL_SUCCESS */
    *status = NFS_V4_ACL_SUCCESS;

    key.addr = acldata->aces;
    key.len = acldata->naces * sizeof(fsal_ace_t);

    /* Check if the entry already exists */
    rc = hashtable_getlatch(fsal_acl_hash, &key, &value, true, &latch);
    if (rc == HASHTABLE_SUCCESS) {
        /* Entry is already in the cache, do not add it */
        acl = value.addr;
        *status = NFS_V4_ACL_EXISTS;

        nfs4_ace_free(acldata->aces);
        nfs4_acl_entry_inc_ref(acl);
        hashtable_releaselatched(fsal_acl_hash, &latch);

        return acl;
    }

    /* Any other result other than no such key is an error */
    if (rc != HASHTABLE_ERROR_NO_SUCH_KEY) {
        *status = NFS_V4_ACL_INIT_ENTRY_FAILED;
        nfs4_ace_free(acldata->aces);
        return NULL;
    }

    /* Adding the entry in the cache */
    acl = nfs4_acl_alloc();
    if (pthread_rwlock_init(&(acl->lock), NULL) != 0) {
        nfs4_acl_free(acl);
        LogCrit(COMPONENT_NFS_V4_ACL,
                "New ACL RW lock init returned %d (%s)", errno,
                strerror(errno));
        *status = NFS_V4_ACL_INIT_ENTRY_FAILED;

        nfs4_ace_free(acldata->aces);
        hashtable_releaselatched(fsal_acl_hash, &latch);

        return NULL;
    }

    acl->naces = acldata->naces;
    acl->aces = acldata->aces;
    acl->ref = 1;		/* We give out one reference */

    /* Build the value */
    value.addr = acl;
    value.len = sizeof(fsal_acl_t);

    rc = hashtable_setlatched(fsal_acl_hash, &key, &value, &latch,
                              HASHTABLE_SET_HOW_SET_NO_OVERWRITE, NULL,
                              NULL);

    if (rc != HASHTABLE_SUCCESS) {
        /* Put the entry back in its pool */
        nfs4_acl_free(acl);
        LogWarn(COMPONENT_NFS_V4_ACL,
                "New ACL entry could not be added to hash, rc=%s",
                hash_table_err_to_str(rc));

        *status = NFS_V4_ACL_HASH_SET_ERROR;
        return NULL;
    }

    return acl;
}
Example #4
0
/**
 * @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;
}