Commit e9669376 authored by Alexey Marchuk's avatar Alexey Marchuk Committed by Jim Harris
Browse files

nvme: Add functions to get/free poll group statistics



These are interface functions that can be used by
an application e.g. spdk_nvme_perf or bdev_nvme
library. The next patches will add usage of these
functions.

Change-Id: I33b88e0e713c2ea5967f9241885e3257c5070577
Signed-off-by: default avatarAlexey Marchuk <alexeymar@mellanox.com>
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/6300


Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 3fcda8e7
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -69,6 +69,9 @@ independent SPDK processes are running on one node. The filter function can
then be implemented in these processes to decide which SSDs to probe based on
the new SSD's PCI address.

New functions `spdk_nvme_poll_group_get_stats` and `spdk_nvme_poll_group_free_stats`
added. These functions allow to get transport statistics per NVME poll group.

### nvmf

Removed the `spdk_nvmf_tgt_listen` and `spdk_nvmf_subsystem_add_ns` API.
+27 −0
Original line number Diff line number Diff line
@@ -472,6 +472,11 @@ struct spdk_nvme_transport_poll_group_stat {
	};
};

struct spdk_nvme_poll_group_stat {
	uint32_t num_transports;
	struct spdk_nvme_transport_poll_group_stat **transport_stat;
};

/*
 * Controller support flags
 *
@@ -2337,6 +2342,28 @@ int64_t spdk_nvme_poll_group_process_completions(struct spdk_nvme_poll_group *gr
 */
void *spdk_nvme_poll_group_get_ctx(struct spdk_nvme_poll_group *group);

/**
 * Retrieves transport statistics for the given poll group.
 *
 * Note: the structure returned by this function should later be freed with
 * @b spdk_nvme_poll_group_free_stats function
 *
 * \param group Pointer to NVME poll group
 * \param stats Double pointer to statistics to be filled by this function
 * \return 0 on success or negated errno on failure
 */
int spdk_nvme_poll_group_get_stats(struct spdk_nvme_poll_group *group,
				   struct spdk_nvme_poll_group_stat **stats);

/**
 * Frees poll group statistics retrieved using @b spdk_nvme_poll_group_get_stats function
 *
 * @param group Pointer to a poll group
 * @param stat Pointer to statistics to be released
 */
void spdk_nvme_poll_group_free_stats(struct spdk_nvme_poll_group *group,
				     struct spdk_nvme_poll_group_stat *stat);

/**
 * Get the identify namespace data as defined by the NVMe specification.
 *
+2 −0
Original line number Diff line number Diff line
@@ -1339,6 +1339,8 @@ int nvme_transport_poll_group_get_stats(struct spdk_nvme_transport_poll_group *t
					struct spdk_nvme_transport_poll_group_stat **stats);
void nvme_transport_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgroup,
		struct spdk_nvme_transport_poll_group_stat *stats);
enum spdk_nvme_transport_type nvme_transport_get_trtype(const struct spdk_nvme_transport
		*transport);
/*
 * Below ref related functions must be called with the global
 *  driver lock held for the multi-process condition.
+79 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 *
 *   Copyright (c) Intel Corporation.
 *   All rights reserved.
 *   Copyright (c) 2021 Mellanox Technologies LTD. All rights reserved.
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
@@ -192,3 +193,81 @@ spdk_nvme_poll_group_destroy(struct spdk_nvme_poll_group *group)

	return 0;
}

int
spdk_nvme_poll_group_get_stats(struct spdk_nvme_poll_group *group,
			       struct spdk_nvme_poll_group_stat **stats)
{
	struct spdk_nvme_transport_poll_group *tgroup;
	struct spdk_nvme_poll_group_stat *result;
	uint32_t transports_count = 0;
	/* Not all transports used by this poll group may support statistics reporting */
	uint32_t reported_stats_count = 0;
	int rc;

	assert(group);
	assert(stats);

	result = calloc(1, sizeof(*result));
	if (!result) {
		SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
		return -ENOMEM;
	}

	STAILQ_FOREACH(tgroup, &group->tgroups, link) {
		transports_count++;
	}

	result->transport_stat = calloc(transports_count, sizeof(*result->transport_stat));
	if (!result->transport_stat) {
		SPDK_ERRLOG("Failed to allocate memory for poll group statistics\n");
		free(result);
		return -ENOMEM;
	}

	STAILQ_FOREACH(tgroup, &group->tgroups, link) {
		rc = nvme_transport_poll_group_get_stats(tgroup, &result->transport_stat[reported_stats_count]);
		if (rc == 0) {
			reported_stats_count++;
		}
	}

	if (reported_stats_count == 0) {
		free(result->transport_stat);
		free(result);
		SPDK_DEBUGLOG(nvme, "No transport statistics available\n");
		return -ENOTSUP;
	}

	result->num_transports = reported_stats_count;
	*stats = result;

	return 0;
}

void
spdk_nvme_poll_group_free_stats(struct spdk_nvme_poll_group *group,
				struct spdk_nvme_poll_group_stat *stat)
{
	struct spdk_nvme_transport_poll_group *tgroup;
	uint32_t i;
	uint32_t freed_stats __attribute__((unused)) = 0;

	assert(group);
	assert(stat);

	for (i = 0; i < stat->num_transports; i++) {
		STAILQ_FOREACH(tgroup, &group->tgroups, link) {
			if (nvme_transport_get_trtype(tgroup->transport) == stat->transport_stat[i]->trtype) {
				nvme_transport_poll_group_free_stats(tgroup, stat->transport_stat[i]);
				freed_stats++;
				break;
			}
		}
	}

	assert(freed_stats == stat->num_transports);

	free(stat->transport_stat);
	free(stat);
}
+5 −0
Original line number Diff line number Diff line
@@ -619,3 +619,8 @@ nvme_transport_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgro
		tgroup->transport->ops.poll_group_free_stats(tgroup, stats);
	}
}

enum spdk_nvme_transport_type nvme_transport_get_trtype(const struct spdk_nvme_transport *transport)
{
	return transport->ops.type;
}
Loading