1275c9da8Seschrock /* 2275c9da8Seschrock * CDDL HEADER START 3275c9da8Seschrock * 4275c9da8Seschrock * The contents of this file are subject to the terms of the 5275c9da8Seschrock * Common Development and Distribution License (the "License"). 6275c9da8Seschrock * You may not use this file except in compliance with the License. 7275c9da8Seschrock * 8275c9da8Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9275c9da8Seschrock * or http://www.opensolaris.org/os/licensing. 10275c9da8Seschrock * See the License for the specific language governing permissions 11275c9da8Seschrock * and limitations under the License. 12275c9da8Seschrock * 13275c9da8Seschrock * When distributing Covered Code, include this CDDL HEADER in each 14275c9da8Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15275c9da8Seschrock * If applicable, add the following below this CDDL HEADER, with the 16275c9da8Seschrock * fields enclosed by brackets "[]" replaced with your own identifying 17275c9da8Seschrock * information: Portions Copyright [yyyy] [name of copyright owner] 18275c9da8Seschrock * 19275c9da8Seschrock * CDDL HEADER END 20275c9da8Seschrock */ 21275c9da8Seschrock 22275c9da8Seschrock /* 23*791a814cSSundeep Panicker * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24275c9da8Seschrock * Use is subject to license terms. 25275c9da8Seschrock */ 26275c9da8Seschrock 27275c9da8Seschrock #include <scsi/libses.h> 28275c9da8Seschrock #include "ses_impl.h" 29275c9da8Seschrock 30275c9da8Seschrock int 31275c9da8Seschrock enc_parse_td(ses2_td_hdr_impl_t *tip, const char *tp, nvlist_t *nvl) 32275c9da8Seschrock { 33275c9da8Seschrock int nverr; 34275c9da8Seschrock 35275c9da8Seschrock if (tp != NULL) 36275c9da8Seschrock SES_NV_ADD(fixed_string, nverr, nvl, SES_PROP_CLASS_DESCRIPTION, 37275c9da8Seschrock tp, tip->sthi_text_len); 38275c9da8Seschrock 39275c9da8Seschrock return (0); 40275c9da8Seschrock } 41275c9da8Seschrock 42275c9da8Seschrock static int 43275c9da8Seschrock enc_eid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 44275c9da8Seschrock { 45275c9da8Seschrock int nverr; 46275c9da8Seschrock 47275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_subenclosure_id); 48275c9da8Seschrock 49275c9da8Seschrock return (0); 50275c9da8Seschrock } 51275c9da8Seschrock 52275c9da8Seschrock static int 53275c9da8Seschrock enc_espid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 54275c9da8Seschrock { 55275c9da8Seschrock int nverr; 56275c9da8Seschrock 57275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_rel_esp_id); 58275c9da8Seschrock 59275c9da8Seschrock return (0); 60275c9da8Seschrock } 61275c9da8Seschrock 62275c9da8Seschrock static int 63275c9da8Seschrock enc_nesp(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 64275c9da8Seschrock { 65275c9da8Seschrock int nverr; 66275c9da8Seschrock 67275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, name, tp->st_hdr.sehi_n_esps); 68275c9da8Seschrock 69275c9da8Seschrock return (0); 70275c9da8Seschrock } 71275c9da8Seschrock 72275c9da8Seschrock static int 73275c9da8Seschrock enc_lid(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 74275c9da8Seschrock { 75275c9da8Seschrock nvlist_t *lid; 76275c9da8Seschrock int nverr; 77275c9da8Seschrock 78275c9da8Seschrock if ((nverr = nvlist_alloc(&lid, NV_UNIQUE_NAME, 0)) != 0) 79275c9da8Seschrock return (ses_set_nverrno(nverr, NULL)); 80275c9da8Seschrock 81275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_INT, 82275c9da8Seschrock SCSI_READ64(&tp->st_logical_id)); 83275c9da8Seschrock 84275c9da8Seschrock switch (tp->st_logical_id.sni8i_naa) { 85275c9da8Seschrock case NAA_IEEE_EXT: 86275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE, 87275c9da8Seschrock NAA_IEEE_EXT); 88275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID, 89275c9da8Seschrock NAA_IEEE_EXT_COMPANY_ID(&tp->st_logical_id.sni8i_ext_id)); 90275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A, 91275c9da8Seschrock NAA_IEEE_EXT_VENDOR_A(&tp->st_logical_id.sni8i_ext_id)); 92275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_B, 93275c9da8Seschrock NAA_IEEE_EXT_VENDOR_B(&tp->st_logical_id.sni8i_ext_id)); 94275c9da8Seschrock break; 95275c9da8Seschrock case NAA_IEEE_REG: 96275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_ID_TYPE, 97275c9da8Seschrock NAA_IEEE_REG); 98275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_COMPANY_ID, 99275c9da8Seschrock NAA_IEEE_REG_COMPANY_ID(&tp->st_logical_id.sni8i_reg_id)); 100275c9da8Seschrock SES_NV_ADD_OR_FREE(uint64, nverr, lid, SPC3_NAA_VS_A, 101275c9da8Seschrock NAA_IEEE_REG_VENDOR_ID(&tp->st_logical_id.sni8i_reg_id)); 102275c9da8Seschrock break; 103275c9da8Seschrock default: 104275c9da8Seschrock break; 105275c9da8Seschrock } 106275c9da8Seschrock 107275c9da8Seschrock if ((nverr = nvlist_add_nvlist(nvl, name, lid)) != 0) { 108275c9da8Seschrock nvlist_free(lid); 109275c9da8Seschrock return (ses_set_nverrno(nverr, name)); 110275c9da8Seschrock } 111275c9da8Seschrock 112275c9da8Seschrock nvlist_free(lid); 113275c9da8Seschrock 114275c9da8Seschrock return (0); 115275c9da8Seschrock } 116275c9da8Seschrock 117275c9da8Seschrock static int 118275c9da8Seschrock enc_vid(const ses2_ed_impl_t *tp, nvlist_t *nvl, 119275c9da8Seschrock const char *name) 120275c9da8Seschrock { 121275c9da8Seschrock int nverr; 122275c9da8Seschrock 123275c9da8Seschrock SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_vendor_id); 124275c9da8Seschrock 125275c9da8Seschrock return (0); 126275c9da8Seschrock } 127275c9da8Seschrock 128275c9da8Seschrock static int 129275c9da8Seschrock enc_pid(const ses2_ed_impl_t *tp, nvlist_t *nvl, 130275c9da8Seschrock const char *name) 131275c9da8Seschrock { 132275c9da8Seschrock int nverr; 133275c9da8Seschrock 134275c9da8Seschrock SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_id); 135275c9da8Seschrock 136275c9da8Seschrock return (0); 137275c9da8Seschrock } 138275c9da8Seschrock 139275c9da8Seschrock static int 140275c9da8Seschrock enc_rev(const ses2_ed_impl_t *tp, nvlist_t *nvl, 141275c9da8Seschrock const char *name) 142275c9da8Seschrock { 143275c9da8Seschrock int nverr; 144275c9da8Seschrock 145275c9da8Seschrock SES_NV_ADD_FS_TRUNC(nverr, nvl, name, tp->st_product_revision); 146275c9da8Seschrock 147275c9da8Seschrock return (0); 148275c9da8Seschrock } 149275c9da8Seschrock 150275c9da8Seschrock static int 151275c9da8Seschrock enc_vs(const ses2_ed_impl_t *tp, nvlist_t *nvl, const char *name) 152275c9da8Seschrock { 153275c9da8Seschrock int nverr; 154275c9da8Seschrock 155275c9da8Seschrock SES_NV_ADD(byte_array, nverr, nvl, name, (uchar_t *)tp->st_priv, 156*791a814cSSundeep Panicker tp->st_hdr.sehi_ed_len - offsetof(ses2_ed_impl_t, st_priv[0]) + 157*791a814cSSundeep Panicker offsetof(ses2_ed_impl_t, st_hdr.sehi_ed_len) + 1); 158275c9da8Seschrock 159275c9da8Seschrock return (0); 160275c9da8Seschrock } 161275c9da8Seschrock 162275c9da8Seschrock /* LINTED - unused */ 163275c9da8Seschrock static const ses2_ed_impl_t __ed = { 0 }; 164275c9da8Seschrock 165275c9da8Seschrock #define ED_REQ_LEN(member) \ 166275c9da8Seschrock (offsetof(ses2_ed_impl_t, member) - sizeof (ses2_ed_hdr_impl_t) + \ 167275c9da8Seschrock sizeof (__ed.member)) 168275c9da8Seschrock 169275c9da8Seschrock static const struct config_member { 170275c9da8Seschrock const char *name; 171275c9da8Seschrock size_t minsz; 172275c9da8Seschrock int (*func)(const ses2_ed_impl_t *, nvlist_t *, const char *); 173275c9da8Seschrock } config_members[] = { 174275c9da8Seschrock { SES_EN_PROP_EID, 0, enc_eid }, 175275c9da8Seschrock { SES_EN_PROP_ESPID, 0, enc_espid }, 176275c9da8Seschrock { SES_EN_PROP_NESP, 0, enc_nesp }, 177275c9da8Seschrock { SES_EN_PROP_LID, ED_REQ_LEN(st_logical_id), enc_lid }, 178275c9da8Seschrock { SES_EN_PROP_VID, ED_REQ_LEN(st_vendor_id), enc_vid }, 179275c9da8Seschrock { SES_EN_PROP_PID, ED_REQ_LEN(st_product_id), enc_pid }, 180275c9da8Seschrock { SES_EN_PROP_REV, ED_REQ_LEN(st_product_revision), enc_rev }, 181275c9da8Seschrock { SES_EN_PROP_VS, ED_REQ_LEN(st_priv), enc_vs }, 182275c9da8Seschrock { NULL, 0, NULL } 183275c9da8Seschrock }; 184275c9da8Seschrock 185275c9da8Seschrock int 186275c9da8Seschrock enc_parse_ed(ses2_ed_impl_t *tp, nvlist_t *nvl) 187275c9da8Seschrock { 188275c9da8Seschrock const struct config_member *mp; 189275c9da8Seschrock int err; 190275c9da8Seschrock 191275c9da8Seschrock if (tp == NULL) 192275c9da8Seschrock return (0); 193275c9da8Seschrock 194275c9da8Seschrock for (mp = &config_members[0]; mp->name != NULL; mp++) { 195275c9da8Seschrock if (mp->func != NULL && tp->st_hdr.sehi_ed_len >= mp->minsz) { 196275c9da8Seschrock err = mp->func(tp, nvl, mp->name); 197275c9da8Seschrock if (err != 0) 198275c9da8Seschrock return (err); 199275c9da8Seschrock } 200275c9da8Seschrock } 201275c9da8Seschrock 202275c9da8Seschrock return (0); 203275c9da8Seschrock } 204275c9da8Seschrock 205275c9da8Seschrock ses_target_t * 206275c9da8Seschrock ses_open_scsi(uint_t version, libscsi_target_t *stp) 207275c9da8Seschrock { 208275c9da8Seschrock ses_target_t *tp; 209275c9da8Seschrock ses_snap_t *sp; 210275c9da8Seschrock 211275c9da8Seschrock if (version != LIBSES_VERSION) { 212275c9da8Seschrock (void) ses_set_errno(ESES_VERSION); 213275c9da8Seschrock return (NULL); 214275c9da8Seschrock } 215275c9da8Seschrock 216275c9da8Seschrock if ((tp = ses_zalloc(sizeof (ses_target_t))) == NULL) 217275c9da8Seschrock return (NULL); 218275c9da8Seschrock 219275c9da8Seschrock tp->st_target = stp; 220275c9da8Seschrock tp->st_scsi_hdl = libscsi_get_handle(stp); 221275c9da8Seschrock tp->st_truncate = (getenv("LIBSES_TRUNCATE") != NULL); 222275c9da8Seschrock if (tp->st_truncate) 223275c9da8Seschrock srand48(gethrtime()); 224275c9da8Seschrock 225275c9da8Seschrock (void) pthread_mutex_init(&tp->st_lock, NULL); 226275c9da8Seschrock 227275c9da8Seschrock if (ses_plugin_load(tp) != 0) { 228275c9da8Seschrock ses_close(tp); 229275c9da8Seschrock return (NULL); 230275c9da8Seschrock } 231275c9da8Seschrock 232275c9da8Seschrock if ((sp = ses_snap_new(tp)) == NULL) { 233275c9da8Seschrock ses_close(tp); 234275c9da8Seschrock return (NULL); 235275c9da8Seschrock } 236275c9da8Seschrock 237275c9da8Seschrock ses_snap_rele(sp); 238275c9da8Seschrock 239275c9da8Seschrock return (tp); 240275c9da8Seschrock } 241275c9da8Seschrock 242275c9da8Seschrock ses_target_t * 243275c9da8Seschrock ses_open(uint_t version, const char *target) 244275c9da8Seschrock { 245275c9da8Seschrock ses_target_t *tp; 246275c9da8Seschrock libscsi_errno_t serr; 247275c9da8Seschrock libscsi_target_t *stp; 248275c9da8Seschrock libscsi_hdl_t *hp; 249275c9da8Seschrock 250275c9da8Seschrock if ((hp = libscsi_init(LIBSCSI_VERSION, &serr)) == NULL) { 251275c9da8Seschrock (void) ses_error(ESES_LIBSCSI, "failed to initialize " 252275c9da8Seschrock "libscsi: %s", libscsi_strerror(serr)); 253275c9da8Seschrock return (NULL); 254275c9da8Seschrock } 255275c9da8Seschrock 256275c9da8Seschrock if ((stp = libscsi_open(hp, NULL, target)) == NULL) { 257275c9da8Seschrock (void) ses_libscsi_error(hp, "failed to open SES target"); 258275c9da8Seschrock libscsi_fini(hp); 259275c9da8Seschrock return (NULL); 260275c9da8Seschrock } 261275c9da8Seschrock 262275c9da8Seschrock if ((tp = ses_open_scsi(version, stp)) == NULL) { 263275c9da8Seschrock libscsi_close(hp, stp); 264275c9da8Seschrock libscsi_fini(hp); 265275c9da8Seschrock return (NULL); 266275c9da8Seschrock } 267275c9da8Seschrock 268275c9da8Seschrock tp->st_closescsi = B_TRUE; 269275c9da8Seschrock 270275c9da8Seschrock return (tp); 271275c9da8Seschrock } 272275c9da8Seschrock 273275c9da8Seschrock libscsi_target_t * 274275c9da8Seschrock ses_scsi_target(ses_target_t *tp) 275275c9da8Seschrock { 276275c9da8Seschrock return (tp->st_target); 277275c9da8Seschrock } 278275c9da8Seschrock 279275c9da8Seschrock void 280275c9da8Seschrock ses_close(ses_target_t *tp) 281275c9da8Seschrock { 282275c9da8Seschrock if (tp->st_snapshots != NULL) 283275c9da8Seschrock ses_snap_rele(tp->st_snapshots); 284275c9da8Seschrock if (tp->st_snapshots != NULL) 285275c9da8Seschrock ses_panic("attempt to close SES target with active snapshots"); 286275c9da8Seschrock ses_plugin_unload(tp); 287275c9da8Seschrock if (tp->st_closescsi) { 288275c9da8Seschrock libscsi_close(tp->st_scsi_hdl, tp->st_target); 289275c9da8Seschrock libscsi_fini(tp->st_scsi_hdl); 290275c9da8Seschrock } 291275c9da8Seschrock ses_free(tp); 292275c9da8Seschrock } 293