1*f5f0964cSRobert Mustacchi /*
2*f5f0964cSRobert Mustacchi * This file and its contents are supplied under the terms of the
3*f5f0964cSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*f5f0964cSRobert Mustacchi * You may only use this file in accordance with the terms of version
5*f5f0964cSRobert Mustacchi * 1.0 of the CDDL.
6*f5f0964cSRobert Mustacchi *
7*f5f0964cSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*f5f0964cSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*f5f0964cSRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*f5f0964cSRobert Mustacchi */
11*f5f0964cSRobert Mustacchi
12*f5f0964cSRobert Mustacchi /*
13*f5f0964cSRobert Mustacchi * Copyright 2025 Oxide Computer Company
14*f5f0964cSRobert Mustacchi */
15*f5f0964cSRobert Mustacchi
16*f5f0964cSRobert Mustacchi /*
17*f5f0964cSRobert Mustacchi * This program is used to check everything about a device before we continue
18*f5f0964cSRobert Mustacchi * execution.
19*f5f0964cSRobert Mustacchi *
20*f5f0964cSRobert Mustacchi * 1) We will check that there are no blkdev attached namespaces. That is it is
21*f5f0964cSRobert Mustacchi * up to the user of this program to ensure that this is already the case. This
22*f5f0964cSRobert Mustacchi * helps make sure that we don't end up in an awkward spot with tests that issue
23*f5f0964cSRobert Mustacchi * blkdev detaches and related.
24*f5f0964cSRobert Mustacchi *
25*f5f0964cSRobert Mustacchi * 2) We will verify that the device supports namespace management and format
26*f5f0964cSRobert Mustacchi * commands. All of our destructive tests require this.
27*f5f0964cSRobert Mustacchi *
28*f5f0964cSRobert Mustacchi * 3) After doing this, we will confirm with the user that this is explicitly
29*f5f0964cSRobert Mustacchi * what they asked for!
30*f5f0964cSRobert Mustacchi */
31*f5f0964cSRobert Mustacchi
32*f5f0964cSRobert Mustacchi #include <err.h>
33*f5f0964cSRobert Mustacchi #include <string.h>
34*f5f0964cSRobert Mustacchi #include <pcidb.h>
35*f5f0964cSRobert Mustacchi #include "libnvme_test_common.h"
36*f5f0964cSRobert Mustacchi
37*f5f0964cSRobert Mustacchi static bool
check_blkdev_cb(nvme_ctrl_t * ctrl,const nvme_ns_disc_t * disc,void * arg)38*f5f0964cSRobert Mustacchi check_blkdev_cb(nvme_ctrl_t *ctrl, const nvme_ns_disc_t *disc, void *arg)
39*f5f0964cSRobert Mustacchi {
40*f5f0964cSRobert Mustacchi if (nvme_ns_disc_level(disc) < NVME_NS_DISC_F_BLKDEV) {
41*f5f0964cSRobert Mustacchi return (true);
42*f5f0964cSRobert Mustacchi }
43*f5f0964cSRobert Mustacchi
44*f5f0964cSRobert Mustacchi (void) fprintf(stderr, "\nDevice not suitable: Encountered blkdev "
45*f5f0964cSRobert Mustacchi "on namespace %u\n", nvme_ns_disc_nsid(disc));
46*f5f0964cSRobert Mustacchi
47*f5f0964cSRobert Mustacchi (void) fprintf(stderr, "\nThis test will erase all data found on the "
48*f5f0964cSRobert Mustacchi "requested device! To\nindicate that you intend to use this device "
49*f5f0964cSRobert Mustacchi "for destructive testing,\nyou must manually detach blkdev from "
50*f5f0964cSRobert Mustacchi "all namespaces on this device!\n\nALL DATA ON THIS DEVICE WILL BE "
51*f5f0964cSRobert Mustacchi "LOST!\n");
52*f5f0964cSRobert Mustacchi exit(EXIT_FAILURE);
53*f5f0964cSRobert Mustacchi }
54*f5f0964cSRobert Mustacchi
55*f5f0964cSRobert Mustacchi static void
check_feats(nvme_ctrl_info_t * info)56*f5f0964cSRobert Mustacchi check_feats(nvme_ctrl_info_t *info)
57*f5f0964cSRobert Mustacchi {
58*f5f0964cSRobert Mustacchi const nvme_version_t *vers = nvme_ctrl_info_version(info);
59*f5f0964cSRobert Mustacchi const nvme_identify_ctrl_t *id = nvme_ctrl_info_identify(info);
60*f5f0964cSRobert Mustacchi
61*f5f0964cSRobert Mustacchi (void) printf("NVMe Version: %u.%u\n", vers->v_major, vers->v_minor);
62*f5f0964cSRobert Mustacchi
63*f5f0964cSRobert Mustacchi if (!NVME_VERSION_ATLEAST(vers, 1, 2)) {
64*f5f0964cSRobert Mustacchi (void) fprintf(stderr, "\nDevice not suitable: device revision "
65*f5f0964cSRobert Mustacchi "must be at least NVMe 1.2\nto support NVMe namespace "
66*f5f0964cSRobert Mustacchi "management! Namespace management is required for "
67*f5f0964cSRobert Mustacchi "destructive tests!");
68*f5f0964cSRobert Mustacchi exit(EXIT_FAILURE);
69*f5f0964cSRobert Mustacchi }
70*f5f0964cSRobert Mustacchi
71*f5f0964cSRobert Mustacchi (void) printf("Format NVM: %s\n", id->id_oacs.oa_format != 0 ?
72*f5f0964cSRobert Mustacchi "supported" : "unsupported");
73*f5f0964cSRobert Mustacchi (void) printf("Namespace Management: %s\n", id->id_oacs.oa_nsmgmt ?
74*f5f0964cSRobert Mustacchi "supported" : "unsupported");
75*f5f0964cSRobert Mustacchi
76*f5f0964cSRobert Mustacchi if (id->id_oacs.oa_format == 0 || id->id_oacs.oa_nsmgmt == 0) {
77*f5f0964cSRobert Mustacchi (void) fprintf(stderr, "\nDevice not suitable: missing "
78*f5f0964cSRobert Mustacchi "required command set support!\nPlease pick another "
79*f5f0964cSRobert Mustacchi "device.\n");
80*f5f0964cSRobert Mustacchi exit(EXIT_FAILURE);
81*f5f0964cSRobert Mustacchi }
82*f5f0964cSRobert Mustacchi
83*f5f0964cSRobert Mustacchi (void) printf("Namespace Count: %u\n", id->id_nn);
84*f5f0964cSRobert Mustacchi if (id->id_nn <= 1) {
85*f5f0964cSRobert Mustacchi (void) fprintf(stderr, "\nDevice not suitable: at least "
86*f5f0964cSRobert Mustacchi "two namespaces required!\nPlease pick another "
87*f5f0964cSRobert Mustacchi "device.\n");
88*f5f0964cSRobert Mustacchi exit(EXIT_FAILURE);
89*f5f0964cSRobert Mustacchi }
90*f5f0964cSRobert Mustacchi }
91*f5f0964cSRobert Mustacchi
92*f5f0964cSRobert Mustacchi int
main(void)93*f5f0964cSRobert Mustacchi main(void)
94*f5f0964cSRobert Mustacchi {
95*f5f0964cSRobert Mustacchi nvme_t *nvme;
96*f5f0964cSRobert Mustacchi nvme_ctrl_t *ctrl;
97*f5f0964cSRobert Mustacchi nvme_ctrl_info_t *info;
98*f5f0964cSRobert Mustacchi pcidb_hdl_t *pcidb;
99*f5f0964cSRobert Mustacchi pcidb_vendor_t *vendor;
100*f5f0964cSRobert Mustacchi char buf[64];
101*f5f0964cSRobert Mustacchi
102*f5f0964cSRobert Mustacchi if ((pcidb = pcidb_open(PCIDB_VERSION)) == NULL) {
103*f5f0964cSRobert Mustacchi err(EXIT_FAILURE, "failed to initialize PCI DB handle");
104*f5f0964cSRobert Mustacchi }
105*f5f0964cSRobert Mustacchi
106*f5f0964cSRobert Mustacchi libnvme_test_init(&nvme, &ctrl);
107*f5f0964cSRobert Mustacchi if (!nvme_ctrl_info_snap(ctrl, &info)) {
108*f5f0964cSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to get controller "
109*f5f0964cSRobert Mustacchi "information snapshot");
110*f5f0964cSRobert Mustacchi }
111*f5f0964cSRobert Mustacchi
112*f5f0964cSRobert Mustacchi (void) printf("Checking NVMe device %s for destructive test "
113*f5f0964cSRobert Mustacchi "suitability\n", getenv(NVME_TEST_DEV_ENVVAR));
114*f5f0964cSRobert Mustacchi vendor = pcidb_lookup_vendor(pcidb, nvme_ctrl_info_vendor(info));
115*f5f0964cSRobert Mustacchi if (vendor != NULL) {
116*f5f0964cSRobert Mustacchi (void) printf("Vendor: %s (0x%x)\n", pcidb_vendor_name(vendor),
117*f5f0964cSRobert Mustacchi nvme_ctrl_info_vendor(info));
118*f5f0964cSRobert Mustacchi } else {
119*f5f0964cSRobert Mustacchi (void) printf("Vendor ID: 0x%x\n", nvme_ctrl_info_vendor(info));
120*f5f0964cSRobert Mustacchi }
121*f5f0964cSRobert Mustacchi (void) printf("Model: %s\n", nvme_ctrl_info_model(info));
122*f5f0964cSRobert Mustacchi (void) printf("Serial: %s\n", nvme_ctrl_info_serial(info));
123*f5f0964cSRobert Mustacchi (void) printf("Firmware Revision: %s\n", nvme_ctrl_info_fwrev(info));
124*f5f0964cSRobert Mustacchi
125*f5f0964cSRobert Mustacchi if (!nvme_ctrl_lock(ctrl, NVME_LOCK_L_WRITE, NVME_LOCK_F_DONT_BLOCK)) {
126*f5f0964cSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to obtain write lock");
127*f5f0964cSRobert Mustacchi }
128*f5f0964cSRobert Mustacchi
129*f5f0964cSRobert Mustacchi if (!nvme_ns_discover(ctrl, NVME_NS_DISC_F_ALL, check_blkdev_cb,
130*f5f0964cSRobert Mustacchi NULL)) {
131*f5f0964cSRobert Mustacchi libnvme_test_ctrl_fatal(ctrl, "failed to discover namespaces");
132*f5f0964cSRobert Mustacchi }
133*f5f0964cSRobert Mustacchi
134*f5f0964cSRobert Mustacchi check_feats(info);
135*f5f0964cSRobert Mustacchi
136*f5f0964cSRobert Mustacchi (void) printf("\nALL DATA ON THE ABOVE DEVICE WILL BE LOST!!\n");
137*f5f0964cSRobert Mustacchi (void) printf("Continue [yes/No]: ");
138*f5f0964cSRobert Mustacchi (void) fflush(stdout);
139*f5f0964cSRobert Mustacchi if (fgets(buf, sizeof (buf), stdin) == NULL) {
140*f5f0964cSRobert Mustacchi errx(EXIT_FAILURE, "aborting: failed to read from stdin\n");
141*f5f0964cSRobert Mustacchi }
142*f5f0964cSRobert Mustacchi
143*f5f0964cSRobert Mustacchi if (strcmp(buf, "yes\n") != 0) {
144*f5f0964cSRobert Mustacchi (void) printf("Aborting on user request\n");
145*f5f0964cSRobert Mustacchi exit(EXIT_FAILURE);
146*f5f0964cSRobert Mustacchi }
147*f5f0964cSRobert Mustacchi
148*f5f0964cSRobert Mustacchi nvme_ctrl_info_free(info);
149*f5f0964cSRobert Mustacchi nvme_ctrl_fini(ctrl);
150*f5f0964cSRobert Mustacchi nvme_fini(nvme);
151*f5f0964cSRobert Mustacchi return (EXIT_SUCCESS);
152*f5f0964cSRobert Mustacchi }
153