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: Alexey 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: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com> Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
This commit is contained in:
parent
5c33437b99
commit
558be98fd3
@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
@ -120,6 +121,7 @@ SPDK_STATIC_ASSERT((offsetof(struct nvme_tracker, meta_sgl) & 7) == 0, "SGL must
|
||||
|
||||
struct nvme_pcie_poll_group {
|
||||
struct spdk_nvme_transport_poll_group group;
|
||||
struct spdk_nvme_pcie_stat stats;
|
||||
};
|
||||
|
||||
/* PCIe transport extensions for spdk_nvme_qpair */
|
||||
@ -142,6 +144,8 @@ struct nvme_pcie_qpair {
|
||||
/* Array of trackers indexed by command ID. */
|
||||
struct nvme_tracker *tr;
|
||||
|
||||
struct spdk_nvme_pcie_stat *stat;
|
||||
|
||||
uint16_t num_entries;
|
||||
|
||||
uint8_t retry_count;
|
||||
@ -185,6 +189,7 @@ struct nvme_pcie_qpair {
|
||||
*/
|
||||
|
||||
bool sq_in_cmb;
|
||||
bool shared_stats;
|
||||
|
||||
uint64_t cmd_bus_addr;
|
||||
uint64_t cpl_bus_addr;
|
||||
@ -260,6 +265,7 @@ nvme_pcie_qpair_ring_sq_doorbell(struct spdk_nvme_qpair *qpair)
|
||||
|
||||
if (spdk_likely(need_mmio)) {
|
||||
spdk_wmb();
|
||||
pqpair->stat->sq_doobell_updates++;
|
||||
g_thread_mmio_ctrlr = pctrlr;
|
||||
spdk_mmio_write_4(pqpair->sq_tdbl, pqpair->sq_tail);
|
||||
g_thread_mmio_ctrlr = NULL;
|
||||
@ -281,6 +287,7 @@ nvme_pcie_qpair_ring_cq_doorbell(struct spdk_nvme_qpair *qpair)
|
||||
}
|
||||
|
||||
if (spdk_likely(need_mmio)) {
|
||||
pqpair->stat->cq_doorbell_updates++;
|
||||
g_thread_mmio_ctrlr = pctrlr;
|
||||
spdk_mmio_write_4(pqpair->cq_hdbl, pqpair->cq_head);
|
||||
g_thread_mmio_ctrlr = NULL;
|
||||
|
@ -973,6 +973,19 @@ rpc_bdev_nvme_rdma_stats(struct spdk_json_write_ctx *w,
|
||||
spdk_json_write_array_end(w);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_nvme_pcie_stats(struct spdk_json_write_ctx *w,
|
||||
struct spdk_nvme_transport_poll_group_stat *stat)
|
||||
{
|
||||
spdk_json_write_named_uint64(w, "polls", stat->pcie.polls);
|
||||
spdk_json_write_named_uint64(w, "idle_polls", stat->pcie.idle_polls);
|
||||
spdk_json_write_named_uint64(w, "completions", stat->pcie.completions);
|
||||
spdk_json_write_named_uint64(w, "cq_doorbell_updates", stat->pcie.cq_doorbell_updates);
|
||||
spdk_json_write_named_uint64(w, "queued_requests", stat->pcie.queued_requests);
|
||||
spdk_json_write_named_uint64(w, "submitted_requests", stat->pcie.submitted_requests);
|
||||
spdk_json_write_named_uint64(w, "sq_doobell_updates", stat->pcie.sq_doobell_updates);
|
||||
}
|
||||
|
||||
static void
|
||||
rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i)
|
||||
{
|
||||
@ -1009,6 +1022,9 @@ rpc_bdev_nvme_stats_per_channel(struct spdk_io_channel_iter *i)
|
||||
case SPDK_NVME_TRANSPORT_RDMA:
|
||||
rpc_bdev_nvme_rdma_stats(ctx->w, tr_stat);
|
||||
break;
|
||||
case SPDK_NVME_TRANSPORT_PCIE:
|
||||
rpc_bdev_nvme_pcie_stats(ctx->w, tr_stat);
|
||||
break;
|
||||
default:
|
||||
SPDK_WARNLOG("Can't handle trtype %d %s\n", tr_stat->trtype,
|
||||
spdk_nvme_transport_id_trtype_str(tr_stat->trtype));
|
||||
|
@ -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
|
||||
@ -79,6 +80,9 @@ DEFINE_STUB(spdk_pci_register_error_handler, int, (spdk_pci_error_handler sighan
|
||||
0);
|
||||
DEFINE_STUB_V(spdk_pci_unregister_error_handler, (spdk_pci_error_handler sighandler));
|
||||
|
||||
DEFINE_STUB(nvme_transport_get_name, const char *, (const struct spdk_nvme_transport *transport),
|
||||
NULL);
|
||||
|
||||
SPDK_LOG_REGISTER_COMPONENT(nvme)
|
||||
|
||||
struct nvme_driver *g_spdk_nvme_driver = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user