xref: /illumos-gate/usr/src/test/nvme-tests/tests/libnvme/check-destruct.c (revision f5f0964ce91892f7482efc86903b0ec7c7b6ba66)
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