ses_enclosure.c revision 6316:40d5384cc8b2
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22/* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27#pragma ident "%Z%%M% %I% %E% SMI" 28 29#include <scsi/libses.h> 30#include "ses_impl.h" 31 32int 33enc_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl) 34{ 35 int nverr; 36 37 if (tp != NULL) 38 SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION, 39 tp, tip->sthi_text_len); 40 41 return (0); 42} 43 44static int 45enc_eid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 46{ 47 int nverr; 48 49 SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_subenclosure_id); 50 51 return (0); 52} 53 54static int 55enc_espid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 56{ 57 int nverr; 58 59 SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_rel_esp_id); 60 61 return (0); 62} 63 64static int 65enc_nesp(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 66{ 67 int nverr; 68 69 SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_n_esps); 70 71 return (0); 72} 73 74static int 75enc_lid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 76{ 77 nvlist_t *lid; 78 int nverr; 79 80 if ((nverr = nvlist_alloc(&lid, NV_UNIQUE_NAME, 0)) != 0) 81 return (ses_set_nverrno(nverr, NULL)); 82 83 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_INT, 84 SCSI_READ64(&tp->st_logical_id)); 85 86 switch (tp->st_logical_id.sni8i_naa) { 87 case NAA_IEEE_EXT: 88 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE, 89 NAA_IEEE_EXT); 90 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID, 91 NAA_IEEE_EXT_COMPANY_ID(&tp->st_logical_id.sni8i_ext_id)); 92 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A, 93 NAA_IEEE_EXT_VENDOR_A(&tp->st_logical_id.sni8i_ext_id)); 94 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_B, 95 NAA_IEEE_EXT_VENDOR_B(&tp->st_logical_id.sni8i_ext_id)); 96 break; 97 case NAA_IEEE_REG: 98 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE, 99 NAA_IEEE_REG); 100 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID, 101 NAA_IEEE_REG_COMPANY_ID(&tp->st_logical_id.sni8i_reg_id)); 102 SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A, 103 NAA_IEEE_REG_VENDOR_ID(&tp->st_logical_id.sni8i_reg_id)); 104 break; 105 default: 106 break; 107 } 108 109 if ((nverr = nvlist_add_nvlist(nvl, name, lid)) != 0) { 110 nvlist_free(lid); 111 return (ses_set_nverrno(nverr, name)); 112 } 113 114 nvlist_free(lid); 115 116 return (0); 117} 118 119static int 120enc_vid(const ses2_ed_impl_t *tp, nvlist_t *nvl, 121 const char *name) 122{ 123 int nverr; 124 125 SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_vendor_id); 126 127 return (0); 128} 129 130static int 131enc_pid(const ses2_ed_impl_t *tp, nvlist_t *nvl, 132 const char *name) 133{ 134 int nverr; 135 136 SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_id); 137 138 return (0); 139} 140 141static int 142enc_rev(const ses2_ed_impl_t *tp, nvlist_t *nvl, 143 const char *name) 144{ 145 int nverr; 146 147 SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_revision); 148 149 return (0); 150} 151 152static int 153enc_vs(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 154{ 155 int nverr; 156 157 SES_NV_ADD(byte_array, nverr, nvl, name, (uchar_t *)tp->st_priv, 158 tp->st_hdr.sehi_ed_len - offsetof(ses2_ed_impl_t, st_priv[0])); 159 160 return (0); 161} 162 163/* LINTED - unused */ 164static const ses2_ed_impl_t __ed = { 0 }; 165 166#define ED_REQ_LEN(member) \ 167 (offsetof(ses2_ed_impl_t, member) - sizeof (ses2_ed_hdr_impl_t) + \ 168 sizeof (__ed.member)) 169 170static const struct config_member { 171 const char *name; 172 size_t minsz; 173 int (*func)(const ses2_ed_impl_t *, nvlist_t *, const char *); 174} config_members[] = { 175 { SES_EN_PROP_EID, 0, enc_eid }, 176 { SES_EN_PROP_ESPID, 0, enc_espid }, 177 { SES_EN_PROP_NESP, 0, enc_nesp }, 178 { SES_EN_PROP_LID, ED_REQ_LEN(st_logical_id), enc_lid }, 179 { SES_EN_PROP_VID, ED_REQ_LEN(st_vendor_id), enc_vid }, 180 { SES_EN_PROP_PID, ED_REQ_LEN(st_product_id), enc_pid }, 181 { SES_EN_PROP_REV, ED_REQ_LEN(st_product_revision), enc_rev }, 182 { SES_EN_PROP_VS, ED_REQ_LEN(st_priv), enc_vs }, 183 { NULL, 0, NULL } 184}; 185 186int 187enc_parse_ed(ses2_ed_impl_t *tp, nvlist_t *nvl) 188{ 189 const struct config_member *mp; 190 int err; 191 192 if (tp == NULL) 193 return (0); 194 195 for (mp = &config_members[0]; mp->name != NULL; mp++) { 196 if (mp->func != NULL && tp->st_hdr.sehi_ed_len >= mp->minsz) { 197 err = mp->func(tp, nvl, mp->name); 198 if (err != 0) 199 return (err); 200 } 201 } 202 203 return (0); 204} 205 206ses_target_t * 207ses_open_scsi(uint_t version, libscsi_target_t *stp) 208{ 209 ses_target_t *tp; 210 ses_snap_t *sp; 211 212 if (version != LIBSES_VERSION) { 213 (void) ses_set_errno(ESES_VERSION); 214 return (NULL); 215 } 216 217 if ((tp = ses_zalloc(sizeof (ses_target_t))) == NULL) 218 return (NULL); 219 220 tp->st_target = stp; 221 tp->st_scsi_hdl = libscsi_get_handle(stp); 222 tp->st_truncate = (getenv("LIBSES_TRUNCATE") != NULL); 223 if (tp->st_truncate) 224 srand48(gethrtime()); 225 226 (void) pthread_mutex_init(&tp->st_lock, NULL); 227 228 if (ses_plugin_load(tp) != 0) { 229 ses_close(tp); 230 return (NULL); 231 } 232 233 if ((sp = ses_snap_new(tp)) == NULL) { 234 ses_close(tp); 235 return (NULL); 236 } 237 238 ses_snap_rele(sp); 239 240 return (tp); 241} 242 243ses_target_t * 244ses_open(uint_t version, const char *target) 245{ 246 ses_target_t *tp; 247 libscsi_errno_t serr; 248 libscsi_target_t *stp; 249 libscsi_hdl_t *hp; 250 251 if ((hp = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) { 252 (void) ses_error(ESES_LIBSCSI, "failed to initialize " 253 "libscsi: %s", libscsi_strerror(serr)); 254 return (NULL); 255 } 256 257 if ((stp = libscsi_open(hp, NULL, target)) == NULL) { 258 (void) ses_libscsi_error(hp, "failed to open SES target"); 259 libscsi_fini(hp); 260 return (NULL); 261 } 262 263 if ((tp = ses_open_scsi(version, stp)) == NULL) { 264 libscsi_close(hp, stp); 265 libscsi_fini(hp); 266 return (NULL); 267 } 268 269 tp->st_closescsi = B_TRUE; 270 271 return (tp); 272} 273 274libscsi_target_t * 275ses_scsi_target(ses_target_t *tp) 276{ 277 return (tp->st_target); 278} 279 280void 281ses_close(ses_target_t *tp) 282{ 283 if (tp->st_snapshots != NULL) 284 ses_snap_rele(tp->st_snapshots); 285 if (tp->st_snapshots != NULL) 286 ses_panic("attempt to close SES target with active snapshots"); 287 ses_plugin_unload(tp); 288 if (tp->st_closescsi) { 289 libscsi_close(tp->st_scsi_hdl, tp->st_target); 290 libscsi_fini(tp->st_scsi_hdl); 291 } 292 ses_free(tp); 293} 294