Ejemplo n.º 1
0
/**
 * @brief Retrieves a full fsal_handle from a NFS3 digest.
 *
 * @param[in]  nfs23_digest The NFS3 handle digest
 * @param[out] fsal_handle  The fsal handle to be retrieved
 *
 * @note The caller must provide storage for nfs_fh4_val.
 *
 * @retval HANDLEMAP_SUCCESS if the handle is available
 * @retval HANDLEMAP_STALE if the disgest is unknown or the handle has been deleted
 */
int HandleMap_GetFH(const nfs23_map_handle_t *nfs23_digest,
		    struct gsh_buffdesc *fsal_handle)
{

	int rc;
	struct gsh_buffdesc buffkey;
	struct gsh_buffdesc buffval;
	digest_pool_entry_t digest;
	struct hash_latch hl;

	digest.nfs23_digest = *nfs23_digest;

	buffkey.addr = (caddr_t) &digest;
	buffkey.len = sizeof(digest_pool_entry_t);

	rc = hashtable_getlatch(handle_map_hash, &buffkey, &buffval, 0, &hl);

	if (rc == HASHTABLE_SUCCESS) {
		handle_pool_entry_t *h = (handle_pool_entry_t *) buffval.addr;
		if (h->fh_len < fsal_handle->len) {
			fsal_handle->len = h->fh_len;
			memcpy(fsal_handle->addr, h->fh_data, h->fh_len);
			rc = HANDLEMAP_SUCCESS;
		} else {
			rc = HANDLEMAP_INTERNAL_ERROR;
		}
		hashtable_releaselatched(handle_map_hash, &hl);
		return rc;
	}

	if (rc == HASHTABLE_ERROR_NO_SUCH_KEY)
		hashtable_releaselatched(handle_map_hash, &hl);
	return HANDLEMAP_STALE;
}				/* HandleMap_GetFH */
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
int nfs41_Session_Get_Pointer(char sessionid[NFS4_SESSIONID_SIZE],
                              nfs41_session_t **session_data)
{
    struct gsh_buffdesc key;
    struct gsh_buffdesc val;
    struct hash_latch latch;
    char str[LOG_BUFF_LEN];
    struct display_buffer dspbuf = {sizeof(str), str, str};
    bool str_valid = false;
    hash_error_t code;

    if (isFullDebug(COMPONENT_SESSIONS)) {
        display_session_id(&dspbuf, sessionid);
        LogFullDebug(COMPONENT_SESSIONS, "Get Session %s", str);
        str_valid = true;
    }

    key.addr = sessionid;
    key.len = NFS4_SESSIONID_SIZE;

    code = hashtable_getlatch(ht_session_id, &key, &val, false, &latch);
    if (code != HASHTABLE_SUCCESS) {
        hashtable_releaselatched(ht_session_id, &latch);
        if (str_valid)
            LogFullDebug(COMPONENT_SESSIONS,
                         "Session %s Not Found", str);
        return 0;
    }

    *session_data = val.addr;
    inc_session_ref(*session_data);	/* XXX more locks? */

    hashtable_releaselatched(ht_session_id, &latch);

    if (str_valid)
        LogFullDebug(COMPONENT_SESSIONS, "Session %s Found", str);

    return 1;
}
Ejemplo n.º 4
0
void nfs4_acl_release_entry(fsal_acl_t *acl, fsal_acl_status_t *status)
{
    struct gsh_buffdesc key, old_key;
    struct gsh_buffdesc old_value;
    int rc;
    struct hash_latch latch;

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

    if (!acl)
        return;

    PTHREAD_RWLOCK_wrlock(&acl->lock);
    if (acl->ref > 1) {
        nfs4_acl_entry_dec_ref(acl);
        PTHREAD_RWLOCK_unlock(&acl->lock);
        return;
    } else
        LogDebug(COMPONENT_NFS_V4_ACL, "Free ACL %p", acl);

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

    PTHREAD_RWLOCK_unlock(&acl->lock);

    /* Get the hash table entry and hold latch */
    rc = hashtable_getlatch(fsal_acl_hash, &key, &old_value, true, &latch);

    switch (rc) {
    case HASHTABLE_ERROR_NO_SUCH_KEY:
        hashtable_releaselatched(fsal_acl_hash, &latch);
        return;

    case HASHTABLE_SUCCESS:
        PTHREAD_RWLOCK_wrlock(&acl->lock);
        nfs4_acl_entry_dec_ref(acl);
        if (acl->ref != 0) {
            /* Did not actually release last reference */
            hashtable_releaselatched(fsal_acl_hash, &latch);
            PTHREAD_RWLOCK_unlock(&acl->lock);
            return;
        }

        /* use the key to delete the entry */
        hashtable_deletelatched(fsal_acl_hash, &key, &latch,
                                &old_key, &old_value);

        /* Release the latch */
        hashtable_releaselatched(fsal_acl_hash, &latch);
        break;

    default:
        LogCrit(COMPONENT_NFS_V4_ACL,
                "ACL entry could not be deleted, status=%s",
                hash_table_err_to_str(rc));
        return;
    }

    /* Sanity check: old_value.addr is expected to be equal to acl,
     * and is released later in this function */
    assert(old_value.addr == acl);

    PTHREAD_RWLOCK_unlock(&acl->lock);

    /* Release acl */
    nfs4_acl_free(acl);
}
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/**
 * @brief Relinquish a reference on an NSM client
 *
 * @param[in] client The client to release
 */
void dec_nsm_client_ref(state_nsm_client_t *client)
{
	char str[LOG_BUFF_LEN];
	struct display_buffer dspbuf = {sizeof(str), str, str};
	bool str_valid = false;
	struct hash_latch latch;
	hash_error_t rc;
	struct gsh_buffdesc buffkey;
	struct gsh_buffdesc old_value;
	struct gsh_buffdesc old_key;
	int32_t refcount;

	if (isDebug(COMPONENT_STATE)) {
		display_nsm_client(&dspbuf, client);
		str_valid = true;
	}

	refcount = atomic_dec_int32_t(&client->ssc_refcount);

	if (refcount > 0) {
		if (str_valid)
			LogFullDebug(COMPONENT_STATE,
				     "Decrement refcount now=%" PRId32 " {%s}",
				     refcount, str);

		return;
	}

	if (str_valid)
		LogFullDebug(COMPONENT_STATE, "Try to remove {%s}", str);

	buffkey.addr = client;
	buffkey.len = sizeof(*client);

	/* Get the hash table entry and hold latch */
	rc = hashtable_getlatch(ht_nsm_client, &buffkey, &old_value, true,
				&latch);

	if (rc != HASHTABLE_SUCCESS) {
		if (rc == HASHTABLE_ERROR_NO_SUCH_KEY)
			hashtable_releaselatched(ht_nsm_client, &latch);

		if (!str_valid)
			display_nsm_client(&dspbuf, client);

		LogCrit(COMPONENT_STATE, "Error %s, could not find {%s}",
			hash_table_err_to_str(rc), str);

		return;
	}

	refcount = atomic_fetch_int32_t(&client->ssc_refcount);

	if (refcount > 0) {
		if (str_valid)
			LogDebug(COMPONENT_STATE,
				 "Did not release refcount now=%"PRId32" {%s}",
				 refcount, str);

		hashtable_releaselatched(ht_nsm_client, &latch);

		return;
	}

	/* use the key to delete the entry */
	rc = hashtable_deletelatched(ht_nsm_client, &buffkey, &latch, &old_key,
				     &old_value);

	if (rc != HASHTABLE_SUCCESS) {
		if (rc == HASHTABLE_ERROR_NO_SUCH_KEY)
			hashtable_releaselatched(ht_nsm_client, &latch);

		if (!str_valid)
			display_nsm_client(&dspbuf, client);

		LogCrit(COMPONENT_STATE, "Error %s, could not remove {%s}",
			hash_table_err_to_str(rc), str);

		return;
	}

	LogFullDebug(COMPONENT_STATE, "Free {%s}", str);

	nsm_unmonitor(old_value.addr);
	free_nsm_client(old_value.addr);
}
Ejemplo n.º 8
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;
}