diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c --- a/sys/dev/nvme/nvme_ctrlr.c +++ b/sys/dev/nvme/nvme_ctrlr.c @@ -1442,6 +1442,8 @@ ctrlr->enable_aborts = 0; TUNABLE_INT_FETCH("hw.nvme.enable_aborts", &ctrlr->enable_aborts); + ctrlr->alignment_splits = counter_u64_alloc(M_WAITOK); + /* Cap transfers by the maximum addressable by page-sized PRP (4KB pages -> 2MB). */ ctrlr->max_xfer_size = MIN(maxphys, (ctrlr->page_size / 8 * ctrlr->page_size)); if (nvme_ctrlr_construct_admin_qpair(ctrlr) != 0) @@ -1560,6 +1562,9 @@ ctrlr->resource_id, ctrlr->resource); nores: + if (ctrlr->alignment_splits) + counter_u64_free(ctrlr->alignment_splits); + mtx_destroy(&ctrlr->lock); } diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -428,6 +428,7 @@ if (child_bios == NULL) return (ENOMEM); + counter_u64_add(ns->ctrlr->alignment_splits, 1); for (i = 0; i < num_bios; i++) { child = child_bios[i]; err = nvme_ns_bio_process(ns, child, nvme_bio_child_done); diff --git a/sys/dev/nvme/nvme_private.h b/sys/dev/nvme/nvme_private.h --- a/sys/dev/nvme/nvme_private.h +++ b/sys/dev/nvme/nvme_private.h @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -317,6 +318,9 @@ bus_dmamap_t hmb_desc_map; struct nvme_hmb_desc *hmb_desc_vaddr; uint64_t hmb_desc_paddr; + + /* Statistics */ + counter_u64_t alignment_splits; }; #define nvme_mmio_offsetof(reg) \ diff --git a/sys/dev/nvme/nvme_sysctl.c b/sys/dev/nvme/nvme_sysctl.c --- a/sys/dev/nvme/nvme_sysctl.c +++ b/sys/dev/nvme/nvme_sysctl.c @@ -30,6 +30,7 @@ #include "opt_nvme.h" #include +#include #include #include @@ -419,4 +420,8 @@ nvme_sysctl_initialize_queue(&ctrlr->ioq[i], ctrlr_ctx, que_tree); } + + SYSCTL_ADD_COUNTER_U64(ctrlr_ctx, ctrlr_list, OID_AUTO, "alignment_splits", + CTLFLAG_RD, &ctrlr->alignment_splits, + "Number of times we split the I/O alignment for drives with preferred alignment"); }