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

nvme/pcie: Add statistics per poll group



Check if qpair has a poll group during the connect process,
use poll group's statistics or allocate own structure per
qpair. That is done due to not all applications use poll
groups and we want to avoid "if (qpair->group)"
conditions in data path.

Admin qpair always allocates its own statistics
structure but the statistics are not reported
since this qpair is not attached to a poll group.

Statistics are reported by spdk_nvme_perf tool
if --transport-stats and in bdev_nvme_transport_statistics
RPC method.

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


Community-CI: Broadcom CI
Community-CI: Mellanox Build Bot
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
parent 5c33437b
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -3036,6 +3036,16 @@ Example response:
				  "recv_sq_doorbell_updates": 348445
				}
			  ]
			},
			{
			  "trname": "PCIE",
			  "polls": 435419831,
			  "idle_polls": 434901004,
			  "completions": 1485543,
			  "cq_doorbell_updates": 518827,
			  "queued_requests": 0,
			  "submitted_requests": 1485543,
			  "sq_doobell_updates": 516081
			}
		  ]
		},
@@ -3068,6 +3078,16 @@ Example response:
				  "recv_sq_doorbell_updates": 357956
				}
			  ]
			},
			{
			  "trname": "PCIE",
			  "polls": 429044294,
			  "idle_polls": 428525658,
			  "completions": 1478730,
			  "cq_doorbell_updates": 518636,
			  "queued_requests": 0,
			  "submitted_requests": 1478730,
			  "sq_doobell_updates": 511658
			}
		  ]
		}
+20 −0
Original line number Diff line number Diff line
@@ -1044,6 +1044,23 @@ nvme_dump_rdma_statistics(struct spdk_nvme_transport_poll_group_stat *stat)
	}
}

static void
nvme_dump_pcie_statistics(struct spdk_nvme_transport_poll_group_stat *stat)
{
	struct spdk_nvme_pcie_stat *pcie_stat;

	pcie_stat = &stat->pcie;

	printf("PCIE transport:\n");
	printf("\tpolls: %"PRIu64"\n", pcie_stat->polls);
	printf("\tidle_polls: %"PRIu64"\n", pcie_stat->idle_polls);
	printf("\tcompletions: %"PRIu64"\n", pcie_stat->completions);
	printf("\tcq_doorbell_updates: %"PRIu64"\n", pcie_stat->cq_doorbell_updates);
	printf("\tsubmitted_requests: %"PRIu64"\n", pcie_stat->submitted_requests);
	printf("\tsq_doobell_updates: %"PRIu64"\n", pcie_stat->sq_doobell_updates);
	printf("\tqueued_requests: %"PRIu64"\n", pcie_stat->queued_requests);
}

static void
nvme_dump_transport_stats(uint32_t lcore, struct ns_worker_ctx *ns_ctx)
{
@@ -1071,6 +1088,9 @@ nvme_dump_transport_stats(uint32_t lcore, struct ns_worker_ctx *ns_ctx)
		case SPDK_NVME_TRANSPORT_RDMA:
			nvme_dump_rdma_statistics(stat->transport_stat[i]);
			break;
		case SPDK_NVME_TRANSPORT_PCIE:
			nvme_dump_pcie_statistics(stat->transport_stat[i]);
			break;
		default:
			fprintf(stderr, "Unknown transport statistics %d %s\n", stat->transport_stat[i]->trtype,
				spdk_nvme_transport_id_trtype_str(stat->transport_stat[i]->trtype));
+11 −0
Original line number Diff line number Diff line
@@ -462,6 +462,16 @@ struct spdk_nvme_rdma_device_stat {
	uint64_t recv_doorbell_updates;
};

struct spdk_nvme_pcie_stat {
	uint64_t polls;
	uint64_t idle_polls;
	uint64_t completions;
	uint64_t cq_doorbell_updates;
	uint64_t submitted_requests;
	uint64_t queued_requests;
	uint64_t sq_doobell_updates;
};

struct spdk_nvme_transport_poll_group_stat {
	spdk_nvme_transport_type_t trtype;
	union {
@@ -469,6 +479,7 @@ struct spdk_nvme_transport_poll_group_stat {
			uint32_t num_devices;
			struct spdk_nvme_rdma_device_stat *device_stats;
		} rdma;
		struct spdk_nvme_pcie_stat pcie;
	};
};

+38 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
 *
 *   Copyright (c) Intel Corporation. All rights reserved.
 *   Copyright (c) 2017, IBM Corporation. All rights reserved.
 *   Copyright (c) 2019, 2020 Mellanox Technologies LTD. All rights reserved.
 *   Copyright (c) 2019-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
@@ -1218,11 +1218,13 @@ nvme_pcie_qpair_submit_request(struct spdk_nvme_qpair *qpair, struct nvme_reques
	tr = TAILQ_FIRST(&pqpair->free_tr);

	if (tr == NULL) {
		pqpair->stat->queued_requests++;
		/* Inform the upper layer to try again later. */
		rc = -EAGAIN;
		goto exit;
	}

	pqpair->stat->submitted_requests++;
	TAILQ_REMOVE(&pqpair->free_tr, tr, tq_list); /* remove tr from free_tr */
	TAILQ_INSERT_TAIL(&pqpair->outstanding_tr, tr, tq_list);
	tr->req = req;
@@ -1276,6 +1278,39 @@ spdk_nvme_pcie_set_hotplug_filter(spdk_nvme_pcie_hotplug_filter_cb filter_cb)
	g_hotplug_filter_cb = filter_cb;
}

static int
nvme_pcie_poll_group_get_stats(struct spdk_nvme_transport_poll_group *tgroup,
			       struct spdk_nvme_transport_poll_group_stat **_stats)
{
	struct nvme_pcie_poll_group *group;
	struct spdk_nvme_transport_poll_group_stat *stats;

	if (tgroup == NULL || _stats == NULL) {
		SPDK_ERRLOG("Invalid stats or group pointer\n");
		return -EINVAL;
	}

	group = SPDK_CONTAINEROF(tgroup, struct nvme_pcie_poll_group, group);
	stats = calloc(1, sizeof(*stats));
	if (!stats) {
		SPDK_ERRLOG("Can't allocate memory for RDMA stats\n");
		return -ENOMEM;
	}
	stats->trtype = SPDK_NVME_TRANSPORT_PCIE;
	memcpy(&stats->pcie, &group->stats, sizeof(group->stats));

	*_stats = stats;

	return 0;
}

static void
nvme_pcie_poll_group_free_stats(struct spdk_nvme_transport_poll_group *tgroup,
				struct spdk_nvme_transport_poll_group_stat *stats)
{
	free(stats);
}

static struct spdk_pci_id nvme_pci_driver_id[] = {
	{
		.class_id = SPDK_PCI_CLASS_NVME,
@@ -1329,6 +1364,8 @@ const struct spdk_nvme_transport_ops pcie_ops = {
	.poll_group_remove = nvme_pcie_poll_group_remove,
	.poll_group_process_completions = nvme_pcie_poll_group_process_completions,
	.poll_group_destroy = nvme_pcie_poll_group_destroy,
	.poll_group_get_stats = nvme_pcie_poll_group_get_stats,
	.poll_group_free_stats = nvme_pcie_poll_group_free_stats
};

SPDK_NVME_TRANSPORT_REGISTER(pcie, &pcie_ops);
+42 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@
 *   BSD LICENSE
 *
 *   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
@@ -271,6 +272,13 @@ nvme_pcie_ctrlr_construct_admin_qpair(struct spdk_nvme_ctrlr *ctrlr, uint16_t nu
		return rc;
	}

	pqpair->stat = spdk_zmalloc(sizeof(*pqpair->stat), 64, NULL, SPDK_ENV_SOCKET_ID_ANY,
				    SPDK_MALLOC_SHARE);
	if (!pqpair->stat) {
		SPDK_ERRLOG("Failed to allocate admin qpair statistics\n");
		return -ENOMEM;
	}

	return nvme_pcie_qpair_construct(ctrlr->adminq, NULL);
}

@@ -444,6 +452,24 @@ _nvme_pcie_ctrlr_create_io_qpair(struct spdk_nvme_ctrlr *ctrlr, struct spdk_nvme
		return -ENOMEM;
	}

	/* Statistics may already be allocated in the case of controller reset */
	if (!pqpair->stat) {
		if (qpair->poll_group) {
			struct nvme_pcie_poll_group *group = SPDK_CONTAINEROF(qpair->poll_group,
							     struct nvme_pcie_poll_group, group);

			pqpair->stat = &group->stats;
			pqpair->shared_stats = true;
		} else {
			pqpair->stat = calloc(1, sizeof(*pqpair->stat));
			if (!pqpair->stat) {
				SPDK_ERRLOG("Failed to allocate qpair statistics\n");
				free(status);
				return -ENOMEM;
			}
		}
	}

	rc = nvme_pcie_ctrlr_cmd_create_io_cq(ctrlr, qpair, nvme_completion_poll_cb, status);
	if (rc != 0) {
		free(status);
@@ -781,6 +807,8 @@ nvme_pcie_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_
		max_completions = pqpair->max_completions_cap;
	}

	pqpair->stat->polls++;

	while (1) {
		cpl = &pqpair->cpl[pqpair->cq_head];

@@ -838,7 +866,10 @@ nvme_pcie_qpair_process_completions(struct spdk_nvme_qpair *qpair, uint32_t max_
	}

	if (num_completions > 0) {
		pqpair->stat->completions += num_completions;
		nvme_pcie_qpair_ring_cq_doorbell(qpair);
	} else {
		pqpair->stat->idle_polls++;
	}

	if (pqpair->flags.delay_cmd_submit) {
@@ -891,6 +922,17 @@ nvme_pcie_qpair_destroy(struct spdk_nvme_qpair *qpair)

	nvme_qpair_deinit(qpair);

	if (!pqpair->shared_stats) {
		if (qpair->id) {
			free(pqpair->stat);
		} else {
			/* statistics of admin qpair are allocates from huge pages because
			 * admin qpair is shared for multi-process */
			spdk_free(pqpair->stat);
		}

	}

	spdk_free(pqpair);

	return 0;
Loading