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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright (c) 2017, Joyent, Inc. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/isa_defs.h> 29 #include <sys/systeminfo.h> 30 #include <sys/scsi/generic/commands.h> 31 #include <sys/scsi/impl/commands.h> 32 #include <sys/scsi/impl/uscsi.h> 33 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <stddef.h> 37 #include <string.h> 38 #include <dlfcn.h> 39 #include <limits.h> 40 41 #include <scsi/libscsi.h> 42 #include "libscsi_impl.h" 43 44 static const libscsi_engine_t * 45 get_engine(libscsi_hdl_t *hp, const char *name) 46 { 47 libscsi_engine_impl_t *eip; 48 const libscsi_engine_t *ep; 49 const char *engine_path, *p, *q; 50 char engine_dir[MAXPATHLEN]; 51 char engine_lib[MAXPATHLEN]; 52 char init_name[MAXPATHLEN]; 53 void *dl_hdl; 54 libscsi_engine_init_f init; 55 boolean_t found_lib = B_FALSE, found_init = B_FALSE; 56 int dirs_tried = 0; 57 char isa[257]; 58 59 for (eip = hp->lsh_engines; eip != NULL; eip = eip->lsei_next) { 60 if (strcmp(eip->lsei_engine->lse_name, name) == 0) 61 return (eip->lsei_engine); 62 } 63 64 if ((engine_path = getenv("LIBSCSI_ENGINE_PATH")) == NULL) 65 engine_path = LIBSCSI_DEFAULT_ENGINE_PATH; 66 67 #if defined(_LP64) 68 if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) < 0) 69 isa[0] = '\0'; 70 #else 71 isa[0] = '\0'; 72 #endif 73 74 for (p = engine_path; p != NULL; p = q) { 75 if ((q = strchr(p, ':')) != NULL) { 76 ptrdiff_t len = q - p; 77 (void) strncpy(engine_dir, p, len); 78 engine_dir[len] = '\0'; 79 while (*q == ':') 80 ++q; 81 if (*q == '\0') 82 q = NULL; 83 if (len == 0) 84 continue; 85 } else { 86 (void) strcpy(engine_dir, p); 87 } 88 if (engine_dir[0] != '/') 89 continue; 90 91 ++dirs_tried; 92 93 (void) snprintf(engine_lib, MAXPATHLEN, "%s/%s/%s%s", 94 engine_dir, isa, name, LIBSCSI_ENGINE_EXT); 95 96 dl_hdl = dlopen(engine_lib, 97 RTLD_LOCAL | RTLD_LAZY | RTLD_PARENT); 98 if (dl_hdl == NULL) { 99 if (!found_lib) 100 (void) libscsi_error(hp, ESCSI_NOENGINE, 101 "unable to dlopen %s: %s", engine_lib, 102 dlerror()); 103 continue; 104 } 105 found_lib = B_TRUE; 106 (void) snprintf(init_name, MAXPATHLEN, "libscsi_%s_init", name); 107 init = (libscsi_engine_init_f)dlsym(dl_hdl, init_name); 108 if (init == NULL) { 109 if (!found_init) 110 (void) libscsi_error(hp, ESCSI_NOENGINE, 111 "failed to find %s in %s: %s", init_name, 112 engine_lib, dlerror()); 113 (void) dlclose(dl_hdl); 114 continue; 115 } 116 if ((ep = init(hp)) == NULL) { 117 (void) dlclose(dl_hdl); 118 /* 119 * libscsi errno set by init. 120 */ 121 return (NULL); 122 } 123 if (ep->lse_libversion != hp->lsh_version) { 124 (void) dlclose(dl_hdl); 125 (void) libscsi_error(hp, ESCSI_ENGINE_VER, "engine " 126 "%s version %u does not match library version %u", 127 engine_lib, ep->lse_libversion, hp->lsh_version); 128 return (NULL); 129 } 130 131 eip = libscsi_zalloc(hp, sizeof (libscsi_engine_impl_t)); 132 if (eip == NULL) { 133 (void) dlclose(dl_hdl); 134 return (NULL); 135 } 136 eip->lsei_engine = ep; 137 eip->lsei_dl_hdl = dl_hdl; 138 eip->lsei_next = hp->lsh_engines; 139 hp->lsh_engines = eip; 140 141 return (ep); 142 } 143 144 if (dirs_tried == 0) 145 (void) libscsi_error(hp, ESCSI_ENGINE_BADPATH, "no valid " 146 "directories found in engine path %s", engine_path); 147 148 return (NULL); 149 } 150 151 static void 152 scsi_parse_mtbf(const char *envvar, uint_t *intp) 153 { 154 const char *strval; 155 int intval; 156 157 if ((strval = getenv(envvar)) != NULL && 158 (intval = atoi(strval)) > 0) { 159 srand48(gethrtime()); 160 *intp = intval; 161 } 162 } 163 164 libscsi_target_t * 165 libscsi_open(libscsi_hdl_t *hp, const char *engine, const void *target) 166 { 167 const libscsi_engine_t *ep; 168 libscsi_target_t *tp; 169 void *private; 170 171 if (engine == NULL) { 172 if ((engine = getenv("LIBSCSI_DEFAULT_ENGINE")) == NULL) 173 engine = LIBSCSI_DEFAULT_ENGINE; 174 } 175 176 if ((ep = get_engine(hp, engine)) == NULL) 177 return (NULL); 178 179 if ((tp = libscsi_zalloc(hp, sizeof (libscsi_target_t))) == NULL) 180 return (NULL); 181 182 if ((private = ep->lse_ops->lseo_open(hp, target)) == NULL) { 183 libscsi_free(hp, tp); 184 return (NULL); 185 } 186 187 scsi_parse_mtbf("LIBSCSI_MTBF_CDB", &tp->lst_mtbf_cdb); 188 scsi_parse_mtbf("LIBSCSI_MTBF_READ", &tp->lst_mtbf_read); 189 scsi_parse_mtbf("LIBSCSI_MTBF_WRITE", &tp->lst_mtbf_write); 190 191 tp->lst_hdl = hp; 192 tp->lst_engine = ep; 193 tp->lst_priv = private; 194 195 ++hp->lsh_targets; 196 197 if (libscsi_get_inquiry(hp, tp) != 0) { 198 libscsi_close(hp, tp); 199 return (NULL); 200 } 201 202 return (tp); 203 } 204 205 libscsi_hdl_t * 206 libscsi_get_handle(libscsi_target_t *tp) 207 { 208 return (tp->lst_hdl); 209 } 210 211 void 212 libscsi_close(libscsi_hdl_t *hp, libscsi_target_t *tp) 213 { 214 tp->lst_engine->lse_ops->lseo_close(hp, tp->lst_priv); 215 libscsi_free(hp, tp->lst_vendor); 216 libscsi_free(hp, tp->lst_product); 217 libscsi_free(hp, tp->lst_revision); 218 libscsi_free(hp, tp); 219 --hp->lsh_targets; 220 } 221 222 sam4_status_t 223 libscsi_action_get_status(const libscsi_action_t *ap) 224 { 225 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 226 227 return (aip->lsai_status); 228 } 229 230 /* 231 * Set the timeout in seconds for this action. If no timeout is specified 232 * or if the timeout is set to 0, an implementation-specific timeout will be 233 * used (which may vary based on the target, command or other variables). 234 * Not all engines support all timeout values. Setting the timeout to a value 235 * not supported by the engine will cause engine-defined behavior when the 236 * action is executed. 237 */ 238 void 239 libscsi_action_set_timeout(libscsi_action_t *ap, uint32_t timeout) 240 { 241 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 242 243 aip->lsai_timeout = timeout; 244 } 245 246 /* 247 * Obtain the timeout setting for this action. 248 */ 249 uint32_t 250 libscsi_action_get_timeout(const libscsi_action_t *ap) 251 { 252 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 253 254 return (aip->lsai_timeout); 255 } 256 257 /* 258 * Returns the flags associated with this action. Never fails. 259 */ 260 uint_t 261 libscsi_action_get_flags(const libscsi_action_t *ap) 262 { 263 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 264 265 return (aip->lsai_flags); 266 } 267 268 /* 269 * Return the length of the CDB buffer associated with this action. Never 270 * fails. 271 */ 272 size_t 273 libscsi_action_get_cdblen(const libscsi_action_t *ap) 274 { 275 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 276 277 return (aip->lsai_cdb_len); 278 } 279 280 /* 281 * Returns the address of the action's CDB. The CDB buffer is guaranteed to 282 * be large enough to hold the complete CDB for the command specified when the 283 * action was allocated. Therefore, changing the command/opcode portion of 284 * the CDB has undefined effects. The remainder of the CDB may be modified. 285 */ 286 uint8_t * 287 libscsi_action_get_cdb(const libscsi_action_t *ap) 288 { 289 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 290 291 return (aip->lsai_cdb); 292 } 293 294 /* 295 * Places the address of the action buffer in the location pointed to by bp, 296 * if bp is not NULL. If ap is not NULL, it will contain the allocated size 297 * of the buffer itself. If vp is not NULL, it will contain the number of 298 * bytes of valid data currently stored in the buffer. 299 * 300 * If the action has LIBSCSI_AF_WRITE set and it has not yet been executed 301 * successfully, the entire buffer is assumed to contain valid data. 302 * 303 * If the action has LIBSCSI_AF_READ set and it has not yet been executed 304 * successfully, the amount of valid data is 0. 305 * 306 * If both LIBSCSI_AF_READ and LIBSCSI_AF_WRITE are clear, this function 307 * fails with ESCSI_BADFLAGS to indicate that the action flags are 308 * incompatible with the action data buffer. 309 */ 310 int 311 libscsi_action_get_buffer(const libscsi_action_t *ap, uint8_t **bp, 312 size_t *sp, size_t *vp) 313 { 314 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 315 316 if ((aip->lsai_flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE)) == 0) 317 return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS, 318 "data buffer not supported for actions with both " 319 "LIBSCSI_AF_READ and LIBSCSI_AF_WRITE clear")); 320 321 if ((aip->lsai_flags & LIBSCSI_AF_WRITE) && 322 aip->lsai_status == LIBSCSI_STATUS_INVALID) { 323 if (bp != NULL) 324 *bp = aip->lsai_data; 325 if (sp != NULL) 326 *sp = aip->lsai_data_alloc; 327 if (vp != NULL) 328 *vp = aip->lsai_data_alloc; 329 330 return (0); 331 } 332 333 if ((aip->lsai_flags & LIBSCSI_AF_READ) && 334 aip->lsai_status != LIBSCSI_STATUS_INVALID) { 335 if (bp != NULL) 336 *bp = aip->lsai_data; 337 if (sp != NULL) 338 *sp = aip->lsai_data_alloc; 339 if (vp != NULL) 340 *vp = aip->lsai_data_len; 341 342 return (0); 343 } 344 345 if (aip->lsai_flags & LIBSCSI_AF_WRITE) { 346 if (bp != NULL) 347 *bp = NULL; 348 if (sp != NULL) 349 *sp = NULL; 350 if (vp != NULL) 351 *vp = 0; 352 } else { 353 if (bp != NULL) 354 *bp = aip->lsai_data; 355 if (sp != NULL) 356 *sp = aip->lsai_data_alloc; 357 if (vp != NULL) 358 *vp = 0; 359 } 360 361 return (0); 362 } 363 364 /* 365 * Obtain a pointer to the sense buffer for this action, if any, along with 366 * the size of the sense buffer and the amount of valid data it contains. 367 */ 368 int 369 libscsi_action_get_sense(const libscsi_action_t *ap, uint8_t **bp, 370 size_t *sp, size_t *vp) 371 { 372 const libscsi_action_impl_t *aip = (const libscsi_action_impl_t *)ap; 373 374 if (!(aip->lsai_flags & LIBSCSI_AF_RQSENSE)) 375 return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS, 376 "sense data unavailable: LIBSCSI_AF_RQSENSE is clear")); 377 378 if (vp != NULL) { 379 if (aip->lsai_status == LIBSCSI_STATUS_INVALID) 380 *vp = 0; 381 else 382 *vp = aip->lsai_sense_len; 383 } 384 385 if (bp != NULL) { 386 ASSERT(aip->lsai_sense_data != NULL); 387 *bp = aip->lsai_sense_data; 388 } 389 390 if (sp != NULL) 391 *sp = UINT8_MAX; 392 393 return (0); 394 } 395 396 /* 397 * Set the SCSI status of the action. 398 * 399 * Engines only. 400 */ 401 void 402 libscsi_action_set_status(libscsi_action_t *ap, sam4_status_t status) 403 { 404 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 405 406 ASSERT(aip->lsai_status == LIBSCSI_STATUS_INVALID); 407 408 aip->lsai_status = status; 409 } 410 411 /* 412 * Set the length of valid data returned by a READ action. If the action is 413 * not a READ action, or the length exceeds the size of the buffer, an error 414 * results. 415 * 416 * Engines only. 417 */ 418 int 419 libscsi_action_set_datalen(libscsi_action_t *ap, size_t len) 420 { 421 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 422 423 if ((aip->lsai_flags & LIBSCSI_AF_READ) == 0) 424 return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS, 425 "data cannot be returned for actions with LIBSCSI_AF_READ " 426 "clear")); 427 if (len > aip->lsai_data_alloc) 428 return (libscsi_error(aip->lsai_hdl, ESCSI_BADLENGTH, 429 "data length %lu exceeds allocated buffer capacity %lu", 430 (ulong_t)len, (ulong_t)aip->lsai_data_alloc)); 431 432 ASSERT(aip->lsai_data_len == 0); 433 aip->lsai_data_len = len; 434 435 return (0); 436 } 437 438 /* 439 * Set the length of the valid sense data returned following the command, if 440 * LIBSCSI_AF_RQSENSE is set for this action. Otherwise, fail. 441 * 442 * Engines only. 443 */ 444 int 445 libscsi_action_set_senselen(libscsi_action_t *ap, size_t len) 446 { 447 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 448 449 if (!(aip->lsai_flags & LIBSCSI_AF_RQSENSE)) 450 return (libscsi_error(aip->lsai_hdl, ESCSI_BADFLAGS, 451 "sense data not supported: LIBSCSI_AF_RQSENSE is clear")); 452 453 if (len > UINT8_MAX) 454 return (libscsi_error(aip->lsai_hdl, ESCSI_BADLENGTH, 455 "sense length %lu exceeds allocated buffer capacity %lu", 456 (ulong_t)len, (ulong_t)UINT8_MAX)); 457 458 ASSERT(aip->lsai_sense_len == 0); 459 aip->lsai_sense_len = len; 460 461 return (0); 462 } 463 464 /* 465 * Allocate an action object. The object will contain a CDB area sufficiently 466 * large to hold a CDB for the given command, and the CDB's opcode will be 467 * filled in. A pointer to this CDB, the contents of which may be modified by 468 * the caller, may be obtained by a subsequent call to libscsi_action_cdb(). 469 * 470 * If flags includes LIBSCSI_AF_READ or LIBSCSI_AF_WRITE, buflen must be 471 * greater than zero. Otherwise, buflen must be 0 and buf must be NULL. 472 * If buflen is nonzero but buf is NULL, a suitably-sized buffer will be 473 * allocated; otherwise, the specified buffer will be used. In either case, 474 * a pointer to the buffer may be obtained via a subsequent call to 475 * libscsi_action_buffer(). 476 * 477 * If flags includes LIBSCSI_AF_RQSENSE, a REQUEST SENSE command will be 478 * issued immediately following the termination of the specified command. 479 * A buffer will be allocated to receive this sense data. Following successful 480 * execution of the action, a pointer to this buffer and the length of 481 * valid sense data may be obtained by a call to libscsi_action_sense(). 482 * If cmd is SPC3_CMD_REQUEST_SENSE, this flag must be clear. 483 */ 484 libscsi_action_t * 485 libscsi_action_alloc_vendor(libscsi_hdl_t *hp, spc3_cmd_t cmd, size_t cdbsz, 486 uint_t flags, void *buf, size_t buflen) 487 { 488 libscsi_action_impl_t *aip; 489 size_t sz; 490 ptrdiff_t off; 491 492 /* 493 * If there's no buffer, it makes no sense to try to read or write 494 * data. Likewise, if we're neither reading nor writing data, we 495 * should not have a buffer. Both of these are programmer error. 496 */ 497 if (buflen == 0 && (flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE))) { 498 (void) libscsi_error(hp, ESCSI_NEEDBUF, "a buffer is " 499 "required when reading or writing"); 500 return (NULL); 501 } 502 if (buflen > 0 && !(flags & (LIBSCSI_AF_READ | LIBSCSI_AF_WRITE))) { 503 (void) libscsi_error(hp, ESCSI_BADFLAGS, "one of " 504 "LIBSCSI_AF_READ and LIBSCSI_AF_WRITE must be specified " 505 "in order to use a buffer"); 506 return (NULL); 507 } 508 509 if (cdbsz == 0) { 510 (void) libscsi_error(hp, ESCSI_BADLENGTH, "the supplied CDB " 511 "buffer size has an invalid length, it must be non-zero."); 512 return (NULL); 513 } 514 515 sz = cdbsz; 516 517 /* 518 * If the caller has asked for a buffer but has not provided one, we 519 * will allocate it in our internal buffer along with the CDB and 520 * request sense space (if requested). 521 */ 522 if (buf == NULL) 523 sz += buflen; 524 525 if (flags & LIBSCSI_AF_RQSENSE) 526 sz += UINT8_MAX; 527 528 sz += offsetof(libscsi_action_impl_t, lsai_buf[0]); 529 530 if ((aip = libscsi_zalloc(hp, sz)) == NULL) 531 return (NULL); 532 533 aip->lsai_hdl = hp; 534 aip->lsai_flags = flags; 535 536 off = 0; 537 538 aip->lsai_cdb = aip->lsai_buf + off; 539 aip->lsai_cdb_len = cdbsz; 540 off += cdbsz; 541 aip->lsai_cdb[0] = (uint8_t)cmd; 542 543 if (buflen > 0) { 544 if (buf != NULL) { 545 aip->lsai_data = buf; 546 } else { 547 aip->lsai_data = aip->lsai_buf + off; 548 off += buflen; 549 } 550 aip->lsai_data_alloc = buflen; 551 if (flags & LIBSCSI_AF_WRITE) 552 aip->lsai_data_len = buflen; 553 } 554 555 if (flags & LIBSCSI_AF_RQSENSE) { 556 aip->lsai_sense_data = aip->lsai_buf + off; 557 off += UINT8_MAX; 558 } 559 560 aip->lsai_status = LIBSCSI_STATUS_INVALID; 561 562 return ((libscsi_action_t *)aip); 563 } 564 565 libscsi_action_t * 566 libscsi_action_alloc(libscsi_hdl_t *hp, spc3_cmd_t cmd, uint_t flags, 567 void *buf, size_t buflen) 568 { 569 size_t cdbsz; 570 571 if (cmd == SPC3_CMD_REQUEST_SENSE && (flags & LIBSCSI_AF_RQSENSE)) { 572 (void) libscsi_error(hp, ESCSI_BADFLAGS, "request sense " 573 "flag not allowed for request sense command"); 574 return (NULL); 575 } 576 577 if ((cdbsz = libscsi_cmd_cdblen(hp, cmd)) == 0) 578 return (NULL); 579 580 return (libscsi_action_alloc_vendor(hp, cmd, cdbsz, flags, buf, 581 buflen)); 582 } 583 584 void 585 libscsi_action_free(libscsi_action_t *ap) 586 { 587 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 588 589 libscsi_free(aip->lsai_hdl, aip); 590 } 591 592 /* 593 * For testing purposes, we allow data to be corrupted via an environment 594 * variable setting. This helps ensure that higher level software can cope with 595 * arbitrarily broken targets. The mtbf value represents the number of bytes we 596 * will see, on average, in between each failure. Therefore, for each N bytes, 597 * we would expect to see (N / mtbf) bytes of corruption. 598 */ 599 static void 600 scsi_inject_errors(void *data, size_t len, uint_t mtbf) 601 { 602 char *buf = data; 603 double prob; 604 size_t index; 605 606 if (len == 0) 607 return; 608 609 prob = (double)len / mtbf; 610 611 while (prob > 1) { 612 index = lrand48() % len; 613 buf[index] = (lrand48() % 256); 614 prob -= 1; 615 } 616 617 if (drand48() <= prob) { 618 index = lrand48() % len; 619 buf[index] = (lrand48() % 256); 620 } 621 } 622 623 int 624 libscsi_exec(libscsi_action_t *ap, libscsi_target_t *tp) 625 { 626 libscsi_action_impl_t *aip = (libscsi_action_impl_t *)ap; 627 libscsi_hdl_t *hp = aip->lsai_hdl; 628 int ret; 629 630 if (tp->lst_mtbf_write != 0 && 631 (aip->lsai_flags & LIBSCSI_AF_WRITE)) { 632 scsi_inject_errors(aip->lsai_data, aip->lsai_data_len, 633 tp->lst_mtbf_write); 634 } 635 636 if (tp->lst_mtbf_cdb != 0) { 637 scsi_inject_errors(aip->lsai_cdb, aip->lsai_cdb_len, 638 tp->lst_mtbf_cdb); 639 } 640 641 ret = tp->lst_engine->lse_ops->lseo_exec(hp, tp->lst_priv, ap); 642 643 if (ret == 0 && tp->lst_mtbf_read != 0 && 644 (aip->lsai_flags & LIBSCSI_AF_READ)) { 645 scsi_inject_errors(aip->lsai_data, aip->lsai_data_len, 646 tp->lst_mtbf_read); 647 } 648 649 return (ret); 650 } 651