xref: /illumos-gate/usr/src/cmd/nvmeadm/nvmeadm_ofmt.c (revision d17be682a2c70b4505d43c830bbd2603da11918d)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2021 Oxide Computer Company
14  * Copyright 2022 Tintri by DDN, Inc. All rights reserved.
15  */
16 
17 /*
18  * nvmeadm output formatting for ofmt based rendering
19  */
20 
21 #include <strings.h>
22 
23 #include "nvmeadm.h"
24 
25 typedef enum nvme_list_ofmt_field {
26 	NVME_LIST_MODEL,
27 	NVME_LIST_SERIAL,
28 	NVME_LIST_FWREV,
29 	NVME_LIST_VERSION,
30 	NVME_LIST_SIZE,
31 	NVME_LIST_CAPACITY,
32 	NVME_LIST_USED,
33 	NVME_LIST_INSTANCE,
34 	NVME_LIST_NAMESPACE,
35 	NVME_LIST_DISK,
36 	NVME_LIST_UNALLOC,
37 } nvme_list_ofmt_field_t;
38 
39 static boolean_t
40 nvme_list_common_ofmt_cb(ofmt_arg_t *ofmt_arg, char *buf, uint_t buflen)
41 {
42 	const nvme_process_arg_t *npa = ofmt_arg->ofmt_cbarg;
43 	int nvmelen;
44 	size_t ret;
45 
46 	switch (ofmt_arg->ofmt_id) {
47 	case NVME_LIST_MODEL:
48 		nvmelen = nvme_strlen(npa->npa_idctl->id_model,
49 		    sizeof (npa->npa_idctl->id_model));
50 		if (nvmelen <= 0 || nvmelen > buflen) {
51 			return (B_FALSE);
52 		}
53 		(void) memcpy(buf, npa->npa_idctl->id_model, nvmelen);
54 		buf[nvmelen] = '\0';
55 		ret = nvmelen;
56 		break;
57 	case NVME_LIST_SERIAL:
58 		nvmelen = nvme_strlen(npa->npa_idctl->id_serial,
59 		    sizeof (npa->npa_idctl->id_serial));
60 		if (nvmelen <= 0 || nvmelen >= buflen) {
61 			return (B_FALSE);
62 		}
63 		(void) memcpy(buf, npa->npa_idctl->id_serial, nvmelen);
64 		buf[nvmelen] = '\0';
65 		ret = nvmelen;
66 		break;
67 	case NVME_LIST_FWREV:
68 		nvmelen = nvme_strlen(npa->npa_idctl->id_fwrev,
69 		    sizeof (npa->npa_idctl->id_fwrev));
70 		if (nvmelen <= 0 || nvmelen >= buflen) {
71 			return (B_FALSE);
72 		}
73 		(void) memcpy(buf, npa->npa_idctl->id_fwrev, nvmelen);
74 		buf[nvmelen] = '\0';
75 		ret = nvmelen;
76 		break;
77 	case NVME_LIST_VERSION:
78 		ret = snprintf(buf, buflen, "%u.%u", npa->npa_version->v_major,
79 		    npa->npa_version->v_minor);
80 		break;
81 	case NVME_LIST_INSTANCE:
82 		ret = strlcat(buf, npa->npa_name, buflen);
83 		break;
84 	default:
85 		abort();
86 	}
87 	if (ret >= buflen) {
88 		return (B_FALSE);
89 	}
90 	return (B_TRUE);
91 }
92 
93 static boolean_t
94 nvme_list_ctrl_ofmt_cb(ofmt_arg_t *ofmt_arg, char *buf, uint_t buflen)
95 {
96 	const nvme_process_arg_t *npa = ofmt_arg->ofmt_cbarg;
97 	size_t ret;
98 
99 	switch (ofmt_arg->ofmt_id) {
100 	case NVME_LIST_CAPACITY:
101 		ret = nvme_snprint_uint128(buf, buflen,
102 		    npa->npa_idctl->ap_tnvmcap, 0, 0);
103 		break;
104 	case NVME_LIST_UNALLOC:
105 		ret = nvme_snprint_uint128(buf, buflen,
106 		    npa->npa_idctl->ap_unvmcap, 0, 0);
107 		break;
108 	default:
109 		abort();
110 	}
111 
112 	if (ret >= buflen) {
113 		return (B_FALSE);
114 	}
115 	return (B_TRUE);
116 }
117 
118 static boolean_t
119 nvme_list_nsid_ofmt_cb(ofmt_arg_t *ofmt_arg, char *buf, uint_t buflen)
120 {
121 	const nvme_process_arg_t *npa = ofmt_arg->ofmt_cbarg;
122 	nvme_idns_lbaf_t *lbaf;
123 	uint_t blksize;
124 	uint64_t val;
125 	size_t ret;
126 
127 	lbaf = &npa->npa_idns->id_lbaf[npa->npa_idns->id_flbas.lba_format];
128 	blksize = 1 << lbaf->lbaf_lbads;
129 
130 	switch (ofmt_arg->ofmt_id) {
131 	case NVME_LIST_NAMESPACE:
132 		ret = strlcat(buf, di_minor_name(npa->npa_minor), buflen);
133 		break;
134 	case NVME_LIST_DISK:
135 		if (npa->npa_dsk != NULL) {
136 			ret = strlcat(buf, npa->npa_dsk, buflen);
137 		} else {
138 			ret = strlcat(buf, "--", buflen);
139 		}
140 		break;
141 	case NVME_LIST_SIZE:
142 		val = npa->npa_idns->id_nsize * blksize;
143 		ret = snprintf(buf, buflen, "%" PRIu64, val);
144 		break;
145 	case NVME_LIST_CAPACITY:
146 		val = npa->npa_idns->id_ncap * blksize;
147 		ret = snprintf(buf, buflen, "%" PRIu64, val);
148 		break;
149 	case NVME_LIST_USED:
150 		val = npa->npa_idns->id_nuse * blksize;
151 		ret = snprintf(buf, buflen, "%" PRIu64, val);
152 		break;
153 	default:
154 		abort();
155 	}
156 
157 	if (ret >= buflen) {
158 		return (B_FALSE);
159 	}
160 	return (B_TRUE);
161 }
162 
163 const ofmt_field_t nvme_list_ctrl_ofmt[] = {
164 	{ "MODEL", 30, NVME_LIST_MODEL, nvme_list_common_ofmt_cb },
165 	{ "SERIAL", 30, NVME_LIST_SERIAL, nvme_list_common_ofmt_cb },
166 	{ "FWREV", 10, NVME_LIST_FWREV, nvme_list_common_ofmt_cb },
167 	{ "VERSION", 10, NVME_LIST_VERSION, nvme_list_common_ofmt_cb },
168 	{ "CAPACITY", 15, NVME_LIST_CAPACITY, nvme_list_ctrl_ofmt_cb },
169 	{ "INSTANCE", 10, NVME_LIST_INSTANCE, nvme_list_common_ofmt_cb },
170 	{ "UNALLOCATED", 15, NVME_LIST_UNALLOC, nvme_list_ctrl_ofmt_cb },
171 	{ NULL, 0, 0, NULL }
172 };
173 
174 const ofmt_field_t nvme_list_nsid_ofmt[] = {
175 	{ "MODEL", 30, NVME_LIST_MODEL, nvme_list_common_ofmt_cb },
176 	{ "SERIAL", 30, NVME_LIST_SERIAL, nvme_list_common_ofmt_cb },
177 	{ "FWREV", 10, NVME_LIST_FWREV, nvme_list_common_ofmt_cb },
178 	{ "VERSION", 10, NVME_LIST_VERSION, nvme_list_common_ofmt_cb },
179 	{ "SIZE", 15, NVME_LIST_SIZE, nvme_list_nsid_ofmt_cb },
180 	{ "CAPACITY", 15, NVME_LIST_CAPACITY, nvme_list_nsid_ofmt_cb },
181 	{ "USED", 15, NVME_LIST_USED, nvme_list_nsid_ofmt_cb },
182 	{ "INSTANCE", 10, NVME_LIST_INSTANCE, nvme_list_common_ofmt_cb },
183 	{ "NAMESPACE", 10, NVME_LIST_NAMESPACE, nvme_list_nsid_ofmt_cb },
184 	{ "DISK", 15, NVME_LIST_DISK, nvme_list_nsid_ofmt_cb },
185 	{ NULL, 0, 0, NULL }
186 };
187