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