1 /*- 2 * Copyright (c) 2014 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/param.h> 31 #include <sys/systm.h> 32 #include <sys/kernel.h> 33 #include <sys/types.h> 34 #include <sys/lock.h> 35 #include <sys/module.h> 36 #include <sys/mutex.h> 37 #include <sys/condvar.h> 38 #include <sys/malloc.h> 39 #include <sys/conf.h> 40 #include <sys/queue.h> 41 #include <sys/sysctl.h> 42 #include <machine/atomic.h> 43 44 #include <cam/cam.h> 45 #include <cam/scsi/scsi_all.h> 46 #include <cam/scsi/scsi_da.h> 47 #include <cam/ctl/ctl_io.h> 48 #include <cam/ctl/ctl.h> 49 #include <cam/ctl/ctl_frontend.h> 50 #include <cam/ctl/ctl_frontend_internal.h> 51 #include <cam/ctl/ctl_util.h> 52 #include <cam/ctl/ctl_backend.h> 53 #include <cam/ctl/ctl_ioctl.h> 54 #include <cam/ctl/ctl_ha.h> 55 #include <cam/ctl/ctl_private.h> 56 #include <cam/ctl/ctl_debug.h> 57 #include <cam/ctl/ctl_scsi_all.h> 58 #include <cam/ctl/ctl_tpc.h> 59 #include <cam/ctl/ctl_error.h> 60 61 #define TPC_MAX_CSCDS 64 62 #define TPC_MAX_SEGS 64 63 #define TPC_MAX_SEG 0 64 #define TPC_MAX_LIST 8192 65 #define TPC_MAX_INLINE 0 66 #define TPC_MAX_LISTS 255 67 #define TPC_MAX_IO_SIZE (1024 * 1024) 68 69 MALLOC_DEFINE(M_CTL_TPC, "ctltpc", "CTL TPC"); 70 71 typedef enum { 72 TPC_ERR_RETRY = 0x000, 73 TPC_ERR_FAIL = 0x001, 74 TPC_ERR_MASK = 0x0ff, 75 TPC_ERR_NO_DECREMENT = 0x100 76 } tpc_error_action; 77 78 struct tpc_list; 79 TAILQ_HEAD(runl, tpc_io); 80 struct tpc_io { 81 union ctl_io *io; 82 uint64_t lun; 83 struct tpc_list *list; 84 struct runl run; 85 TAILQ_ENTRY(tpc_io) rlinks; 86 TAILQ_ENTRY(tpc_io) links; 87 }; 88 89 struct tpc_list { 90 uint8_t service_action; 91 int init_port; 92 uint32_t init_idx; 93 uint32_t list_id; 94 uint8_t flags; 95 uint8_t *params; 96 struct scsi_ec_cscd *cscd; 97 struct scsi_ec_segment *seg[TPC_MAX_SEGS]; 98 uint8_t *inl; 99 int ncscd; 100 int nseg; 101 int leninl; 102 int curseg; 103 off_t curbytes; 104 int curops; 105 int stage; 106 uint8_t *buf; 107 int segbytes; 108 int tbdio; 109 int error; 110 int abort; 111 int completed; 112 TAILQ_HEAD(, tpc_io) allio; 113 struct scsi_sense_data sense_data; 114 uint8_t sense_len; 115 uint8_t scsi_status; 116 struct ctl_scsiio *ctsio; 117 struct ctl_lun *lun; 118 TAILQ_ENTRY(tpc_list) links; 119 }; 120 121 void 122 ctl_tpc_init(struct ctl_lun *lun) 123 { 124 125 TAILQ_INIT(&lun->tpc_lists); 126 } 127 128 void 129 ctl_tpc_shutdown(struct ctl_lun *lun) 130 { 131 struct tpc_list *list; 132 133 while ((list = TAILQ_FIRST(&lun->tpc_lists)) != NULL) { 134 TAILQ_REMOVE(&lun->tpc_lists, list, links); 135 KASSERT(list->completed, 136 ("Not completed TPC (%p) on shutdown", list)); 137 free(list, M_CTL); 138 } 139 } 140 141 int 142 ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len) 143 { 144 struct scsi_vpd_tpc *tpc_ptr; 145 struct scsi_vpd_tpc_descriptor *d_ptr; 146 struct scsi_vpd_tpc_descriptor_sc *sc_ptr; 147 struct scsi_vpd_tpc_descriptor_sc_descr *scd_ptr; 148 struct scsi_vpd_tpc_descriptor_pd *pd_ptr; 149 struct scsi_vpd_tpc_descriptor_sd *sd_ptr; 150 struct scsi_vpd_tpc_descriptor_sdid *sdid_ptr; 151 struct scsi_vpd_tpc_descriptor_gco *gco_ptr; 152 struct ctl_lun *lun; 153 int data_len; 154 155 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 156 157 data_len = sizeof(struct scsi_vpd_tpc) + 158 roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sc) + 159 2 * sizeof(struct scsi_vpd_tpc_descriptor_sc_descr) + 7, 4) + 160 sizeof(struct scsi_vpd_tpc_descriptor_pd) + 161 roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sd) + 4, 4) + 162 roundup2(sizeof(struct scsi_vpd_tpc_descriptor_sdid) + 2, 4) + 163 sizeof(struct scsi_vpd_tpc_descriptor_gco); 164 165 ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO); 166 tpc_ptr = (struct scsi_vpd_tpc *)ctsio->kern_data_ptr; 167 ctsio->kern_sg_entries = 0; 168 169 if (data_len < alloc_len) { 170 ctsio->residual = alloc_len - data_len; 171 ctsio->kern_data_len = data_len; 172 ctsio->kern_total_len = data_len; 173 } else { 174 ctsio->residual = 0; 175 ctsio->kern_data_len = alloc_len; 176 ctsio->kern_total_len = alloc_len; 177 } 178 ctsio->kern_data_resid = 0; 179 ctsio->kern_rel_offset = 0; 180 ctsio->kern_sg_entries = 0; 181 182 /* 183 * The control device is always connected. The disk device, on the 184 * other hand, may not be online all the time. 185 */ 186 if (lun != NULL) 187 tpc_ptr->device = (SID_QUAL_LU_CONNECTED << 5) | 188 lun->be_lun->lun_type; 189 else 190 tpc_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT; 191 tpc_ptr->page_code = SVPD_SCSI_TPC; 192 scsi_ulto2b(data_len - 4, tpc_ptr->page_length); 193 194 /* Supported commands */ 195 d_ptr = (struct scsi_vpd_tpc_descriptor *)&tpc_ptr->descr[0]; 196 sc_ptr = (struct scsi_vpd_tpc_descriptor_sc *)d_ptr; 197 scsi_ulto2b(SVPD_TPC_SC, sc_ptr->desc_type); 198 sc_ptr->list_length = 2 * sizeof(*scd_ptr) + 7; 199 scsi_ulto2b(roundup2(1 + sc_ptr->list_length, 4), sc_ptr->desc_length); 200 scd_ptr = &sc_ptr->descr[0]; 201 scd_ptr->opcode = EXTENDED_COPY; 202 scd_ptr->sa_length = 3; 203 scd_ptr->supported_service_actions[0] = EC_EC_LID1; 204 scd_ptr->supported_service_actions[1] = EC_EC_LID4; 205 scd_ptr->supported_service_actions[2] = EC_COA; 206 scd_ptr = (struct scsi_vpd_tpc_descriptor_sc_descr *) 207 &scd_ptr->supported_service_actions[scd_ptr->sa_length]; 208 scd_ptr->opcode = RECEIVE_COPY_STATUS; 209 scd_ptr->sa_length = 4; 210 scd_ptr->supported_service_actions[0] = RCS_RCS_LID1; 211 scd_ptr->supported_service_actions[1] = RCS_RCFD; 212 scd_ptr->supported_service_actions[2] = RCS_RCS_LID4; 213 scd_ptr->supported_service_actions[3] = RCS_RCOP; 214 215 /* Parameter data. */ 216 d_ptr = (struct scsi_vpd_tpc_descriptor *) 217 (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length)); 218 pd_ptr = (struct scsi_vpd_tpc_descriptor_pd *)d_ptr; 219 scsi_ulto2b(SVPD_TPC_PD, pd_ptr->desc_type); 220 scsi_ulto2b(sizeof(*pd_ptr) - 4, pd_ptr->desc_length); 221 scsi_ulto2b(TPC_MAX_CSCDS, pd_ptr->maximum_cscd_descriptor_count); 222 scsi_ulto2b(TPC_MAX_SEGS, pd_ptr->maximum_segment_descriptor_count); 223 scsi_ulto4b(TPC_MAX_LIST, pd_ptr->maximum_descriptor_list_length); 224 scsi_ulto4b(TPC_MAX_INLINE, pd_ptr->maximum_inline_data_length); 225 226 /* Supported Descriptors */ 227 d_ptr = (struct scsi_vpd_tpc_descriptor *) 228 (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length)); 229 sd_ptr = (struct scsi_vpd_tpc_descriptor_sd *)d_ptr; 230 scsi_ulto2b(SVPD_TPC_SD, sd_ptr->desc_type); 231 scsi_ulto2b(roundup2(sizeof(*sd_ptr) - 4 + 4, 4), sd_ptr->desc_length); 232 sd_ptr->list_length = 4; 233 sd_ptr->supported_descriptor_codes[0] = EC_SEG_B2B; 234 sd_ptr->supported_descriptor_codes[1] = EC_SEG_VERIFY; 235 sd_ptr->supported_descriptor_codes[2] = EC_SEG_REGISTER_KEY; 236 sd_ptr->supported_descriptor_codes[3] = EC_CSCD_ID; 237 238 /* Supported CSCD Descriptor IDs */ 239 d_ptr = (struct scsi_vpd_tpc_descriptor *) 240 (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length)); 241 sdid_ptr = (struct scsi_vpd_tpc_descriptor_sdid *)d_ptr; 242 scsi_ulto2b(SVPD_TPC_SDID, sdid_ptr->desc_type); 243 scsi_ulto2b(roundup2(sizeof(*sdid_ptr) - 4 + 2, 4), sdid_ptr->desc_length); 244 scsi_ulto2b(2, sdid_ptr->list_length); 245 scsi_ulto2b(0xffff, &sdid_ptr->supported_descriptor_ids[0]); 246 247 /* General Copy Operations */ 248 d_ptr = (struct scsi_vpd_tpc_descriptor *) 249 (&d_ptr->parameters[0] + scsi_2btoul(d_ptr->desc_length)); 250 gco_ptr = (struct scsi_vpd_tpc_descriptor_gco *)d_ptr; 251 scsi_ulto2b(SVPD_TPC_GCO, gco_ptr->desc_type); 252 scsi_ulto2b(sizeof(*gco_ptr) - 4, gco_ptr->desc_length); 253 scsi_ulto4b(TPC_MAX_LISTS, gco_ptr->total_concurrent_copies); 254 scsi_ulto4b(TPC_MAX_LISTS, gco_ptr->maximum_identified_concurrent_copies); 255 scsi_ulto4b(TPC_MAX_SEG, gco_ptr->maximum_segment_length); 256 gco_ptr->data_segment_granularity = 0; 257 gco_ptr->inline_data_granularity = 0; 258 259 ctsio->scsi_status = SCSI_STATUS_OK; 260 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 261 ctsio->be_move_done = ctl_config_move_done; 262 ctl_datamove((union ctl_io *)ctsio); 263 264 return (CTL_RETVAL_COMPLETE); 265 } 266 267 int 268 ctl_receive_copy_operating_parameters(struct ctl_scsiio *ctsio) 269 { 270 struct ctl_lun *lun; 271 struct scsi_receive_copy_operating_parameters *cdb; 272 struct scsi_receive_copy_operating_parameters_data *data; 273 int retval; 274 int alloc_len, total_len; 275 276 CTL_DEBUG_PRINT(("ctl_report_supported_tmf\n")); 277 278 cdb = (struct scsi_receive_copy_operating_parameters *)ctsio->cdb; 279 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 280 281 retval = CTL_RETVAL_COMPLETE; 282 283 total_len = sizeof(*data) + 4; 284 alloc_len = scsi_4btoul(cdb->length); 285 286 ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO); 287 288 ctsio->kern_sg_entries = 0; 289 290 if (total_len < alloc_len) { 291 ctsio->residual = alloc_len - total_len; 292 ctsio->kern_data_len = total_len; 293 ctsio->kern_total_len = total_len; 294 } else { 295 ctsio->residual = 0; 296 ctsio->kern_data_len = alloc_len; 297 ctsio->kern_total_len = alloc_len; 298 } 299 ctsio->kern_data_resid = 0; 300 ctsio->kern_rel_offset = 0; 301 302 data = (struct scsi_receive_copy_operating_parameters_data *)ctsio->kern_data_ptr; 303 scsi_ulto4b(sizeof(*data) - 4 + 4, data->length); 304 data->snlid = RCOP_SNLID; 305 scsi_ulto2b(TPC_MAX_CSCDS, data->maximum_cscd_descriptor_count); 306 scsi_ulto2b(TPC_MAX_SEGS, data->maximum_segment_descriptor_count); 307 scsi_ulto4b(TPC_MAX_LIST, data->maximum_descriptor_list_length); 308 scsi_ulto4b(TPC_MAX_SEG, data->maximum_segment_length); 309 scsi_ulto4b(TPC_MAX_INLINE, data->maximum_inline_data_length); 310 scsi_ulto4b(0, data->held_data_limit); 311 scsi_ulto4b(0, data->maximum_stream_device_transfer_size); 312 scsi_ulto2b(TPC_MAX_LISTS, data->total_concurrent_copies); 313 data->maximum_concurrent_copies = TPC_MAX_LISTS; 314 data->data_segment_granularity = 0; 315 data->inline_data_granularity = 0; 316 data->held_data_granularity = 0; 317 data->implemented_descriptor_list_length = 4; 318 data->list_of_implemented_descriptor_type_codes[0] = EC_SEG_B2B; 319 data->list_of_implemented_descriptor_type_codes[1] = EC_SEG_VERIFY; 320 data->list_of_implemented_descriptor_type_codes[2] = EC_SEG_REGISTER_KEY; 321 data->list_of_implemented_descriptor_type_codes[3] = EC_CSCD_ID; 322 323 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 324 ctsio->be_move_done = ctl_config_move_done; 325 326 ctl_datamove((union ctl_io *)ctsio); 327 return (retval); 328 } 329 330 int 331 ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio) 332 { 333 struct ctl_lun *lun; 334 struct scsi_receive_copy_status_lid1 *cdb; 335 struct scsi_receive_copy_status_lid1_data *data; 336 struct tpc_list *list; 337 struct tpc_list list_copy; 338 int retval; 339 int alloc_len, total_len; 340 uint32_t list_id; 341 342 CTL_DEBUG_PRINT(("ctl_receive_copy_status_lid1\n")); 343 344 cdb = (struct scsi_receive_copy_status_lid1 *)ctsio->cdb; 345 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 346 347 retval = CTL_RETVAL_COMPLETE; 348 349 list_id = cdb->list_identifier; 350 mtx_lock(&lun->lun_lock); 351 TAILQ_FOREACH(list, &lun->tpc_lists, links) { 352 if ((list->flags & EC_LIST_ID_USAGE_MASK) != 353 EC_LIST_ID_USAGE_NONE && list->list_id == list_id) 354 break; 355 } 356 if (list == NULL) { 357 mtx_unlock(&lun->lun_lock); 358 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 359 /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0, 360 /*bit*/ 0); 361 ctl_done((union ctl_io *)ctsio); 362 return (retval); 363 } 364 list_copy = *list; 365 if (list->completed) { 366 TAILQ_REMOVE(&lun->tpc_lists, list, links); 367 free(list, M_CTL); 368 } 369 mtx_unlock(&lun->lun_lock); 370 371 total_len = sizeof(*data); 372 alloc_len = scsi_4btoul(cdb->length); 373 374 ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO); 375 376 ctsio->kern_sg_entries = 0; 377 378 if (total_len < alloc_len) { 379 ctsio->residual = alloc_len - total_len; 380 ctsio->kern_data_len = total_len; 381 ctsio->kern_total_len = total_len; 382 } else { 383 ctsio->residual = 0; 384 ctsio->kern_data_len = alloc_len; 385 ctsio->kern_total_len = alloc_len; 386 } 387 ctsio->kern_data_resid = 0; 388 ctsio->kern_rel_offset = 0; 389 390 data = (struct scsi_receive_copy_status_lid1_data *)ctsio->kern_data_ptr; 391 scsi_ulto4b(sizeof(*data) - 4, data->available_data); 392 if (list_copy.completed) { 393 if (list_copy.error || list_copy.abort) 394 data->copy_command_status = RCS_CCS_ERROR; 395 else 396 data->copy_command_status = RCS_CCS_COMPLETED; 397 } else 398 data->copy_command_status = RCS_CCS_INPROG; 399 scsi_ulto2b(list_copy.curseg, data->segments_processed); 400 if (list_copy.curbytes <= UINT32_MAX) { 401 data->transfer_count_units = RCS_TC_BYTES; 402 scsi_ulto4b(list_copy.curbytes, data->transfer_count); 403 } else { 404 data->transfer_count_units = RCS_TC_MBYTES; 405 scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count); 406 } 407 408 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 409 ctsio->be_move_done = ctl_config_move_done; 410 411 ctl_datamove((union ctl_io *)ctsio); 412 return (retval); 413 } 414 415 int 416 ctl_receive_copy_failure_details(struct ctl_scsiio *ctsio) 417 { 418 struct ctl_lun *lun; 419 struct scsi_receive_copy_failure_details *cdb; 420 struct scsi_receive_copy_failure_details_data *data; 421 struct tpc_list *list; 422 struct tpc_list list_copy; 423 int retval; 424 int alloc_len, total_len; 425 uint32_t list_id; 426 427 CTL_DEBUG_PRINT(("ctl_receive_copy_failure_details\n")); 428 429 cdb = (struct scsi_receive_copy_failure_details *)ctsio->cdb; 430 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 431 432 retval = CTL_RETVAL_COMPLETE; 433 434 list_id = cdb->list_identifier; 435 mtx_lock(&lun->lun_lock); 436 TAILQ_FOREACH(list, &lun->tpc_lists, links) { 437 if (list->completed && (list->flags & EC_LIST_ID_USAGE_MASK) != 438 EC_LIST_ID_USAGE_NONE && list->list_id == list_id) 439 break; 440 } 441 if (list == NULL) { 442 mtx_unlock(&lun->lun_lock); 443 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 444 /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0, 445 /*bit*/ 0); 446 ctl_done((union ctl_io *)ctsio); 447 return (retval); 448 } 449 list_copy = *list; 450 TAILQ_REMOVE(&lun->tpc_lists, list, links); 451 free(list, M_CTL); 452 mtx_unlock(&lun->lun_lock); 453 454 total_len = sizeof(*data) + list_copy.sense_len; 455 alloc_len = scsi_4btoul(cdb->length); 456 457 ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO); 458 459 ctsio->kern_sg_entries = 0; 460 461 if (total_len < alloc_len) { 462 ctsio->residual = alloc_len - total_len; 463 ctsio->kern_data_len = total_len; 464 ctsio->kern_total_len = total_len; 465 } else { 466 ctsio->residual = 0; 467 ctsio->kern_data_len = alloc_len; 468 ctsio->kern_total_len = alloc_len; 469 } 470 ctsio->kern_data_resid = 0; 471 ctsio->kern_rel_offset = 0; 472 473 data = (struct scsi_receive_copy_failure_details_data *)ctsio->kern_data_ptr; 474 if (list_copy.completed && (list_copy.error || list_copy.abort)) { 475 scsi_ulto4b(sizeof(*data) - 4, data->available_data); 476 data->copy_command_status = RCS_CCS_ERROR; 477 } else 478 scsi_ulto4b(0, data->available_data); 479 scsi_ulto2b(list_copy.sense_len, data->sense_data_length); 480 memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len); 481 482 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 483 ctsio->be_move_done = ctl_config_move_done; 484 485 ctl_datamove((union ctl_io *)ctsio); 486 return (retval); 487 } 488 489 int 490 ctl_receive_copy_status_lid4(struct ctl_scsiio *ctsio) 491 { 492 struct ctl_lun *lun; 493 struct scsi_receive_copy_status_lid4 *cdb; 494 struct scsi_receive_copy_status_lid4_data *data; 495 struct tpc_list *list; 496 struct tpc_list list_copy; 497 int retval; 498 int alloc_len, total_len; 499 uint32_t list_id; 500 501 CTL_DEBUG_PRINT(("ctl_receive_copy_status_lid4\n")); 502 503 cdb = (struct scsi_receive_copy_status_lid4 *)ctsio->cdb; 504 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 505 506 retval = CTL_RETVAL_COMPLETE; 507 508 list_id = scsi_4btoul(cdb->list_identifier); 509 mtx_lock(&lun->lun_lock); 510 TAILQ_FOREACH(list, &lun->tpc_lists, links) { 511 if ((list->flags & EC_LIST_ID_USAGE_MASK) != 512 EC_LIST_ID_USAGE_NONE && list->list_id == list_id) 513 break; 514 } 515 if (list == NULL) { 516 mtx_unlock(&lun->lun_lock); 517 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 518 /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0, 519 /*bit*/ 0); 520 ctl_done((union ctl_io *)ctsio); 521 return (retval); 522 } 523 list_copy = *list; 524 if (list->completed) { 525 TAILQ_REMOVE(&lun->tpc_lists, list, links); 526 free(list, M_CTL); 527 } 528 mtx_unlock(&lun->lun_lock); 529 530 total_len = sizeof(*data) + list_copy.sense_len; 531 alloc_len = scsi_4btoul(cdb->length); 532 533 ctsio->kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO); 534 535 ctsio->kern_sg_entries = 0; 536 537 if (total_len < alloc_len) { 538 ctsio->residual = alloc_len - total_len; 539 ctsio->kern_data_len = total_len; 540 ctsio->kern_total_len = total_len; 541 } else { 542 ctsio->residual = 0; 543 ctsio->kern_data_len = alloc_len; 544 ctsio->kern_total_len = alloc_len; 545 } 546 ctsio->kern_data_resid = 0; 547 ctsio->kern_rel_offset = 0; 548 549 data = (struct scsi_receive_copy_status_lid4_data *)ctsio->kern_data_ptr; 550 scsi_ulto4b(sizeof(*data) - 4, data->available_data); 551 data->response_to_service_action = list_copy.service_action; 552 if (list_copy.completed) { 553 if (list_copy.error) 554 data->copy_command_status = RCS_CCS_ERROR; 555 else if (list_copy.abort) 556 data->copy_command_status = RCS_CCS_ABORTED; 557 else 558 data->copy_command_status = RCS_CCS_COMPLETED; 559 } else 560 data->copy_command_status = RCS_CCS_INPROG_FG; 561 scsi_ulto2b(list_copy.curops, data->operation_counter); 562 scsi_ulto4b(UINT32_MAX, data->estimated_status_update_delay); 563 if (list_copy.curbytes <= UINT32_MAX) { 564 data->transfer_count_units = RCS_TC_BYTES; 565 scsi_ulto4b(list_copy.curbytes, data->transfer_count); 566 } else { 567 data->transfer_count_units = RCS_TC_MBYTES; 568 scsi_ulto4b(list_copy.curbytes >> 20, data->transfer_count); 569 } 570 scsi_ulto2b(list_copy.curseg, data->segments_processed); 571 data->sense_data_length = list_copy.sense_len; 572 memcpy(data->sense_data, &list_copy.sense_data, list_copy.sense_len); 573 574 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 575 ctsio->be_move_done = ctl_config_move_done; 576 577 ctl_datamove((union ctl_io *)ctsio); 578 return (retval); 579 } 580 581 int 582 ctl_copy_operation_abort(struct ctl_scsiio *ctsio) 583 { 584 struct ctl_lun *lun; 585 struct scsi_copy_operation_abort *cdb; 586 struct tpc_list *list; 587 int retval; 588 uint32_t list_id; 589 590 CTL_DEBUG_PRINT(("ctl_copy_operation_abort\n")); 591 592 cdb = (struct scsi_copy_operation_abort *)ctsio->cdb; 593 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 594 595 retval = CTL_RETVAL_COMPLETE; 596 597 list_id = scsi_4btoul(cdb->list_identifier); 598 mtx_lock(&lun->lun_lock); 599 TAILQ_FOREACH(list, &lun->tpc_lists, links) { 600 if ((list->flags & EC_LIST_ID_USAGE_MASK) != 601 EC_LIST_ID_USAGE_NONE && list->list_id == list_id) 602 break; 603 } 604 if (list == NULL) { 605 mtx_unlock(&lun->lun_lock); 606 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 607 /*command*/ 1, /*field*/ 2, /*bit_valid*/ 0, 608 /*bit*/ 0); 609 ctl_done((union ctl_io *)ctsio); 610 return (retval); 611 } 612 list->abort = 1; 613 mtx_unlock(&lun->lun_lock); 614 615 ctl_set_success(ctsio); 616 ctl_done((union ctl_io *)ctsio); 617 return (retval); 618 } 619 620 static uint64_t 621 tpc_resolve(struct tpc_list *list, uint16_t idx, uint32_t *ss) 622 { 623 624 if (idx == 0xffff) { 625 if (ss && list->lun->be_lun) 626 *ss = list->lun->be_lun->blocksize; 627 return (list->lun->lun); 628 } 629 if (idx >= list->ncscd) 630 return (UINT64_MAX); 631 return (tpcl_resolve(list->init_port, &list->cscd[idx], ss)); 632 } 633 634 static int 635 tpc_process_b2b(struct tpc_list *list) 636 { 637 struct scsi_ec_segment_b2b *seg; 638 struct scsi_ec_cscd_dtsp *sdstp, *ddstp; 639 struct tpc_io *tior, *tiow; 640 struct runl run, *prun; 641 uint64_t sl, dl; 642 off_t srclba, dstlba, numbytes, donebytes, roundbytes; 643 int numlba; 644 uint32_t srcblock, dstblock; 645 646 if (list->stage == 1) { 647 complete: 648 while ((tior = TAILQ_FIRST(&list->allio)) != NULL) { 649 TAILQ_REMOVE(&list->allio, tior, links); 650 ctl_free_io(tior->io); 651 free(tior, M_CTL); 652 } 653 free(list->buf, M_CTL); 654 if (list->abort) { 655 ctl_set_task_aborted(list->ctsio); 656 return (CTL_RETVAL_ERROR); 657 } else if (list->error) { 658 ctl_set_sense(list->ctsio, /*current_error*/ 1, 659 /*sense_key*/ SSD_KEY_COPY_ABORTED, 660 /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE); 661 return (CTL_RETVAL_ERROR); 662 } else { 663 list->curbytes += list->segbytes; 664 return (CTL_RETVAL_COMPLETE); 665 } 666 } 667 668 TAILQ_INIT(&list->allio); 669 seg = (struct scsi_ec_segment_b2b *)list->seg[list->curseg]; 670 sl = tpc_resolve(list, scsi_2btoul(seg->src_cscd), &srcblock); 671 dl = tpc_resolve(list, scsi_2btoul(seg->dst_cscd), &dstblock); 672 if (sl >= CTL_MAX_LUNS || dl >= CTL_MAX_LUNS) { 673 ctl_set_sense(list->ctsio, /*current_error*/ 1, 674 /*sense_key*/ SSD_KEY_COPY_ABORTED, 675 /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE); 676 return (CTL_RETVAL_ERROR); 677 } 678 sdstp = &list->cscd[scsi_2btoul(seg->src_cscd)].dtsp; 679 if (scsi_3btoul(sdstp->block_length) != 0) 680 srcblock = scsi_3btoul(sdstp->block_length); 681 ddstp = &list->cscd[scsi_2btoul(seg->dst_cscd)].dtsp; 682 if (scsi_3btoul(ddstp->block_length) != 0) 683 dstblock = scsi_3btoul(ddstp->block_length); 684 numlba = scsi_2btoul(seg->number_of_blocks); 685 if (seg->flags & EC_SEG_DC) 686 numbytes = (off_t)numlba * dstblock; 687 else 688 numbytes = (off_t)numlba * srcblock; 689 srclba = scsi_8btou64(seg->src_lba); 690 dstlba = scsi_8btou64(seg->dst_lba); 691 692 // printf("Copy %ju bytes from %ju @ %ju to %ju @ %ju\n", 693 // (uintmax_t)numbytes, sl, scsi_8btou64(seg->src_lba), 694 // dl, scsi_8btou64(seg->dst_lba)); 695 696 if (numbytes == 0) 697 return (CTL_RETVAL_COMPLETE); 698 699 if (numbytes % srcblock != 0 || numbytes % dstblock != 0) { 700 ctl_set_sense(list->ctsio, /*current_error*/ 1, 701 /*sense_key*/ SSD_KEY_COPY_ABORTED, 702 /*asc*/ 0x26, /*ascq*/ 0x0A, SSD_ELEM_NONE); 703 return (CTL_RETVAL_ERROR); 704 } 705 706 list->buf = malloc(numbytes, M_CTL, M_WAITOK); 707 list->segbytes = numbytes; 708 donebytes = 0; 709 TAILQ_INIT(&run); 710 prun = &run; 711 list->tbdio = 1; 712 while (donebytes < numbytes) { 713 roundbytes = MIN(numbytes - donebytes, TPC_MAX_IO_SIZE); 714 715 tior = malloc(sizeof(*tior), M_CTL, M_WAITOK | M_ZERO); 716 TAILQ_INIT(&tior->run); 717 tior->list = list; 718 TAILQ_INSERT_TAIL(&list->allio, tior, links); 719 tior->io = tpcl_alloc_io(); 720 if (tior->io == NULL) { 721 list->error = 1; 722 goto complete; 723 } 724 ctl_scsi_read_write(tior->io, 725 /*data_ptr*/ &list->buf[donebytes], 726 /*data_len*/ roundbytes, 727 /*read_op*/ 1, 728 /*byte2*/ 0, 729 /*minimum_cdb_size*/ 0, 730 /*lba*/ srclba + donebytes / srcblock, 731 /*num_blocks*/ roundbytes / srcblock, 732 /*tag_type*/ CTL_TAG_SIMPLE, 733 /*control*/ 0); 734 tior->io->io_hdr.retries = 3; 735 tior->lun = sl; 736 tior->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tior; 737 738 tiow = malloc(sizeof(*tior), M_CTL, M_WAITOK | M_ZERO); 739 TAILQ_INIT(&tiow->run); 740 tiow->list = list; 741 TAILQ_INSERT_TAIL(&list->allio, tiow, links); 742 tiow->io = tpcl_alloc_io(); 743 if (tiow->io == NULL) { 744 list->error = 1; 745 goto complete; 746 } 747 ctl_scsi_read_write(tiow->io, 748 /*data_ptr*/ &list->buf[donebytes], 749 /*data_len*/ roundbytes, 750 /*read_op*/ 0, 751 /*byte2*/ 0, 752 /*minimum_cdb_size*/ 0, 753 /*lba*/ dstlba + donebytes / dstblock, 754 /*num_blocks*/ roundbytes / dstblock, 755 /*tag_type*/ CTL_TAG_SIMPLE, 756 /*control*/ 0); 757 tiow->io->io_hdr.retries = 3; 758 tiow->lun = dl; 759 tiow->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tior; 760 761 TAILQ_INSERT_TAIL(&tior->run, tiow, rlinks); 762 TAILQ_INSERT_TAIL(prun, tior, rlinks); 763 prun = &tior->run; 764 donebytes += roundbytes; 765 } 766 767 while ((tior = TAILQ_FIRST(&run)) != NULL) { 768 TAILQ_REMOVE(&run, tior, rlinks); 769 if (tpcl_queue(tior->io, tior->lun) != CTL_RETVAL_COMPLETE) 770 panic("tpcl_queue() error"); 771 } 772 773 list->stage++; 774 return (CTL_RETVAL_QUEUED); 775 } 776 777 static int 778 tpc_process_verify(struct tpc_list *list) 779 { 780 struct scsi_ec_segment_verify *seg; 781 struct tpc_io *tio; 782 uint64_t sl; 783 784 if (list->stage == 1) { 785 complete: 786 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) { 787 TAILQ_REMOVE(&list->allio, tio, links); 788 ctl_free_io(tio->io); 789 free(tio, M_CTL); 790 } 791 if (list->abort) { 792 ctl_set_task_aborted(list->ctsio); 793 return (CTL_RETVAL_ERROR); 794 } else if (list->error) { 795 ctl_set_sense(list->ctsio, /*current_error*/ 1, 796 /*sense_key*/ SSD_KEY_COPY_ABORTED, 797 /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE); 798 return (CTL_RETVAL_ERROR); 799 } else 800 return (CTL_RETVAL_COMPLETE); 801 } 802 803 TAILQ_INIT(&list->allio); 804 seg = (struct scsi_ec_segment_verify *)list->seg[list->curseg]; 805 sl = tpc_resolve(list, scsi_2btoul(seg->src_cscd), NULL); 806 if (sl >= CTL_MAX_LUNS) { 807 ctl_set_sense(list->ctsio, /*current_error*/ 1, 808 /*sense_key*/ SSD_KEY_COPY_ABORTED, 809 /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE); 810 return (CTL_RETVAL_ERROR); 811 } 812 813 // printf("Verify %ju\n", sl); 814 815 if ((seg->tur & 0x01) == 0) 816 return (CTL_RETVAL_COMPLETE); 817 818 list->tbdio = 1; 819 tio = malloc(sizeof(*tio), M_CTL, M_WAITOK | M_ZERO); 820 TAILQ_INIT(&tio->run); 821 tio->list = list; 822 TAILQ_INSERT_TAIL(&list->allio, tio, links); 823 tio->io = tpcl_alloc_io(); 824 if (tio->io == NULL) { 825 list->error = 1; 826 goto complete; 827 } 828 ctl_scsi_tur(tio->io, /*tag_type*/ CTL_TAG_SIMPLE, /*control*/ 0); 829 tio->io->io_hdr.retries = 3; 830 tio->lun = sl; 831 tio->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tio; 832 list->stage++; 833 if (tpcl_queue(tio->io, tio->lun) != CTL_RETVAL_COMPLETE) 834 panic("tpcl_queue() error"); 835 return (CTL_RETVAL_QUEUED); 836 } 837 838 static int 839 tpc_process_register_key(struct tpc_list *list) 840 { 841 struct scsi_ec_segment_register_key *seg; 842 struct tpc_io *tio; 843 uint64_t dl; 844 int datalen; 845 846 if (list->stage == 1) { 847 complete: 848 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) { 849 TAILQ_REMOVE(&list->allio, tio, links); 850 ctl_free_io(tio->io); 851 free(tio, M_CTL); 852 } 853 free(list->buf, M_CTL); 854 if (list->abort) { 855 ctl_set_task_aborted(list->ctsio); 856 return (CTL_RETVAL_ERROR); 857 } else if (list->error) { 858 ctl_set_sense(list->ctsio, /*current_error*/ 1, 859 /*sense_key*/ SSD_KEY_COPY_ABORTED, 860 /*asc*/ 0x0d, /*ascq*/ 0x01, SSD_ELEM_NONE); 861 return (CTL_RETVAL_ERROR); 862 } else 863 return (CTL_RETVAL_COMPLETE); 864 } 865 866 TAILQ_INIT(&list->allio); 867 seg = (struct scsi_ec_segment_register_key *)list->seg[list->curseg]; 868 dl = tpc_resolve(list, scsi_2btoul(seg->dst_cscd), NULL); 869 if (dl >= CTL_MAX_LUNS) { 870 ctl_set_sense(list->ctsio, /*current_error*/ 1, 871 /*sense_key*/ SSD_KEY_COPY_ABORTED, 872 /*asc*/ 0x08, /*ascq*/ 0x04, SSD_ELEM_NONE); 873 return (CTL_RETVAL_ERROR); 874 } 875 876 // printf("Register Key %ju\n", dl); 877 878 list->tbdio = 1; 879 tio = malloc(sizeof(*tio), M_CTL, M_WAITOK | M_ZERO); 880 TAILQ_INIT(&tio->run); 881 tio->list = list; 882 TAILQ_INSERT_TAIL(&list->allio, tio, links); 883 tio->io = tpcl_alloc_io(); 884 if (tio->io == NULL) { 885 list->error = 1; 886 goto complete; 887 } 888 datalen = sizeof(struct scsi_per_res_out_parms); 889 list->buf = malloc(datalen, M_CTL, M_WAITOK); 890 ctl_scsi_persistent_res_out(tio->io, 891 list->buf, datalen, SPRO_REGISTER, -1, 892 scsi_8btou64(seg->res_key), scsi_8btou64(seg->sa_res_key), 893 /*tag_type*/ CTL_TAG_SIMPLE, /*control*/ 0); 894 tio->io->io_hdr.retries = 3; 895 tio->lun = dl; 896 tio->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tio; 897 list->stage++; 898 if (tpcl_queue(tio->io, tio->lun) != CTL_RETVAL_COMPLETE) 899 panic("tpcl_queue() error"); 900 return (CTL_RETVAL_QUEUED); 901 } 902 903 static void 904 tpc_process(struct tpc_list *list) 905 { 906 struct ctl_lun *lun = list->lun; 907 struct scsi_ec_segment *seg; 908 struct ctl_scsiio *ctsio = list->ctsio; 909 int retval = CTL_RETVAL_COMPLETE; 910 911 //printf("ZZZ %d cscd, %d segs\n", list->ncscd, list->nseg); 912 while (list->curseg < list->nseg) { 913 seg = list->seg[list->curseg]; 914 switch (seg->type_code) { 915 case EC_SEG_B2B: 916 retval = tpc_process_b2b(list); 917 break; 918 case EC_SEG_VERIFY: 919 retval = tpc_process_verify(list); 920 break; 921 case EC_SEG_REGISTER_KEY: 922 retval = tpc_process_register_key(list); 923 break; 924 default: 925 ctl_set_sense(ctsio, /*current_error*/ 1, 926 /*sense_key*/ SSD_KEY_COPY_ABORTED, 927 /*asc*/ 0x26, /*ascq*/ 0x09, SSD_ELEM_NONE); 928 goto done; 929 } 930 if (retval == CTL_RETVAL_QUEUED) 931 return; 932 if (retval == CTL_RETVAL_ERROR) { 933 list->error = 1; 934 goto done; 935 } 936 list->curseg++; 937 list->stage = 0; 938 } 939 940 ctl_set_success(ctsio); 941 942 done: 943 //printf("ZZZ done\n"); 944 mtx_lock(&lun->lun_lock); 945 if ((list->flags & EC_LIST_ID_USAGE_MASK) == EC_LIST_ID_USAGE_NONE) { 946 TAILQ_REMOVE(&lun->tpc_lists, list, links); 947 free(list, M_CTL); 948 } else { 949 list->completed = 1; 950 list->sense_data = ctsio->sense_data; 951 list->sense_len = ctsio->sense_len; 952 list->scsi_status = ctsio->scsi_status; 953 } 954 mtx_unlock(&lun->lun_lock); 955 956 ctl_done((union ctl_io *)ctsio); 957 } 958 959 /* 960 * For any sort of check condition, busy, etc., we just retry. We do not 961 * decrement the retry count for unit attention type errors. These are 962 * normal, and we want to save the retry count for "real" errors. Otherwise, 963 * we could end up with situations where a command will succeed in some 964 * situations and fail in others, depending on whether a unit attention is 965 * pending. Also, some of our error recovery actions, most notably the 966 * LUN reset action, will cause a unit attention. 967 * 968 * We can add more detail here later if necessary. 969 */ 970 static tpc_error_action 971 tpc_checkcond_parse(union ctl_io *io) 972 { 973 tpc_error_action error_action; 974 int error_code, sense_key, asc, ascq; 975 976 /* 977 * Default to retrying the command. 978 */ 979 error_action = TPC_ERR_RETRY; 980 981 scsi_extract_sense_len(&io->scsiio.sense_data, 982 io->scsiio.sense_len, 983 &error_code, 984 &sense_key, 985 &asc, 986 &ascq, 987 /*show_errors*/ 1); 988 989 switch (error_code) { 990 case SSD_DEFERRED_ERROR: 991 case SSD_DESC_DEFERRED_ERROR: 992 error_action |= TPC_ERR_NO_DECREMENT; 993 break; 994 case SSD_CURRENT_ERROR: 995 case SSD_DESC_CURRENT_ERROR: 996 default: 997 switch (sense_key) { 998 case SSD_KEY_UNIT_ATTENTION: 999 error_action |= TPC_ERR_NO_DECREMENT; 1000 break; 1001 case SSD_KEY_HARDWARE_ERROR: 1002 /* 1003 * This is our generic "something bad happened" 1004 * error code. It often isn't recoverable. 1005 */ 1006 if ((asc == 0x44) && (ascq == 0x00)) 1007 error_action = TPC_ERR_FAIL; 1008 break; 1009 case SSD_KEY_NOT_READY: 1010 /* 1011 * If the LUN is powered down, there likely isn't 1012 * much point in retrying right now. 1013 */ 1014 if ((asc == 0x04) && (ascq == 0x02)) 1015 error_action = TPC_ERR_FAIL; 1016 /* 1017 * If the LUN is offline, there probably isn't much 1018 * point in retrying, either. 1019 */ 1020 if ((asc == 0x04) && (ascq == 0x03)) 1021 error_action = TPC_ERR_FAIL; 1022 break; 1023 } 1024 } 1025 return (error_action); 1026 } 1027 1028 static tpc_error_action 1029 tpc_error_parse(union ctl_io *io) 1030 { 1031 tpc_error_action error_action = TPC_ERR_RETRY; 1032 1033 switch (io->io_hdr.io_type) { 1034 case CTL_IO_SCSI: 1035 switch (io->io_hdr.status & CTL_STATUS_MASK) { 1036 case CTL_SCSI_ERROR: 1037 switch (io->scsiio.scsi_status) { 1038 case SCSI_STATUS_CHECK_COND: 1039 error_action = tpc_checkcond_parse(io); 1040 break; 1041 default: 1042 break; 1043 } 1044 break; 1045 default: 1046 break; 1047 } 1048 break; 1049 case CTL_IO_TASK: 1050 break; 1051 default: 1052 panic("%s: invalid ctl_io type %d\n", __func__, 1053 io->io_hdr.io_type); 1054 break; 1055 } 1056 return (error_action); 1057 } 1058 1059 void 1060 tpc_done(union ctl_io *io) 1061 { 1062 struct tpc_io *tio, *tior; 1063 1064 /* 1065 * Very minimal retry logic. We basically retry if we got an error 1066 * back, and the retry count is greater than 0. If we ever want 1067 * more sophisticated initiator type behavior, the CAM error 1068 * recovery code in ../common might be helpful. 1069 */ 1070 // if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) 1071 // ctl_io_error_print(io, NULL); 1072 tio = io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr; 1073 if (((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) 1074 && (io->io_hdr.retries > 0)) { 1075 ctl_io_status old_status; 1076 tpc_error_action error_action; 1077 1078 error_action = tpc_error_parse(io); 1079 switch (error_action & TPC_ERR_MASK) { 1080 case TPC_ERR_FAIL: 1081 break; 1082 case TPC_ERR_RETRY: 1083 default: 1084 if ((error_action & TPC_ERR_NO_DECREMENT) == 0) 1085 io->io_hdr.retries--; 1086 old_status = io->io_hdr.status; 1087 io->io_hdr.status = CTL_STATUS_NONE; 1088 io->io_hdr.flags &= ~CTL_FLAG_ABORT; 1089 io->io_hdr.flags &= ~CTL_FLAG_SENT_2OTHER_SC; 1090 if (tpcl_queue(io, tio->lun) != CTL_RETVAL_COMPLETE) { 1091 printf("%s: error returned from ctl_queue()!\n", 1092 __func__); 1093 io->io_hdr.status = old_status; 1094 } else 1095 return; 1096 } 1097 } 1098 1099 if ((io->io_hdr.status & CTL_STATUS_MASK) != CTL_SUCCESS) 1100 tio->list->error = 1; 1101 else 1102 atomic_add_int(&tio->list->curops, 1); 1103 if (!tio->list->error && !tio->list->abort) { 1104 while ((tior = TAILQ_FIRST(&tio->run)) != NULL) { 1105 TAILQ_REMOVE(&tio->run, tior, rlinks); 1106 atomic_add_int(&tio->list->tbdio, 1); 1107 if (tpcl_queue(tior->io, tior->lun) != CTL_RETVAL_COMPLETE) 1108 panic("tpcl_queue() error"); 1109 } 1110 } 1111 if (atomic_fetchadd_int(&tio->list->tbdio, -1) == 1) 1112 tpc_process(tio->list); 1113 } 1114 1115 int 1116 ctl_extended_copy_lid1(struct ctl_scsiio *ctsio) 1117 { 1118 struct scsi_extended_copy *cdb; 1119 struct scsi_extended_copy_lid1_data *data; 1120 struct ctl_lun *lun; 1121 struct tpc_list *list, *tlist; 1122 uint8_t *ptr; 1123 char *value; 1124 int len, off, lencscd, lenseg, leninl, nseg; 1125 1126 CTL_DEBUG_PRINT(("ctl_extended_copy_lid1\n")); 1127 1128 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 1129 cdb = (struct scsi_extended_copy *)ctsio->cdb; 1130 len = scsi_4btoul(cdb->length); 1131 1132 if (len < sizeof(struct scsi_extended_copy_lid1_data) || 1133 len > sizeof(struct scsi_extended_copy_lid1_data) + 1134 TPC_MAX_LIST + TPC_MAX_INLINE) { 1135 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1, 1136 /*field*/ 9, /*bit_valid*/ 0, /*bit*/ 0); 1137 goto done; 1138 } 1139 1140 /* 1141 * If we've got a kernel request that hasn't been malloced yet, 1142 * malloc it and tell the caller the data buffer is here. 1143 */ 1144 if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) { 1145 ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK); 1146 ctsio->kern_data_len = len; 1147 ctsio->kern_total_len = len; 1148 ctsio->kern_data_resid = 0; 1149 ctsio->kern_rel_offset = 0; 1150 ctsio->kern_sg_entries = 0; 1151 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 1152 ctsio->be_move_done = ctl_config_move_done; 1153 ctl_datamove((union ctl_io *)ctsio); 1154 1155 return (CTL_RETVAL_COMPLETE); 1156 } 1157 1158 data = (struct scsi_extended_copy_lid1_data *)ctsio->kern_data_ptr; 1159 lencscd = scsi_2btoul(data->cscd_list_length); 1160 lenseg = scsi_4btoul(data->segment_list_length); 1161 leninl = scsi_4btoul(data->inline_data_length); 1162 if (len < sizeof(struct scsi_extended_copy_lid1_data) + 1163 lencscd + lenseg + leninl || 1164 leninl > TPC_MAX_INLINE) { 1165 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 0, 1166 /*field*/ 2, /*bit_valid*/ 0, /*bit*/ 0); 1167 goto done; 1168 } 1169 if (lencscd > TPC_MAX_CSCDS * sizeof(struct scsi_ec_cscd)) { 1170 ctl_set_sense(ctsio, /*current_error*/ 1, 1171 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 1172 /*asc*/ 0x26, /*ascq*/ 0x06, SSD_ELEM_NONE); 1173 goto done; 1174 } 1175 if (lencscd + lenseg > TPC_MAX_LIST) { 1176 ctl_set_param_len_error(ctsio); 1177 goto done; 1178 } 1179 1180 list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO); 1181 list->service_action = cdb->service_action; 1182 value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc"); 1183 if (value != NULL && strcmp(value, "on") == 0) 1184 list->init_port = -1; 1185 else 1186 list->init_port = ctsio->io_hdr.nexus.targ_port; 1187 list->init_idx = ctl_get_resindex(&ctsio->io_hdr.nexus); 1188 list->list_id = data->list_identifier; 1189 list->flags = data->flags; 1190 list->params = ctsio->kern_data_ptr; 1191 list->cscd = (struct scsi_ec_cscd *)&data->data[0]; 1192 ptr = &data->data[lencscd]; 1193 for (nseg = 0, off = 0; off < lenseg; nseg++) { 1194 if (nseg >= TPC_MAX_SEGS) { 1195 free(list, M_CTL); 1196 ctl_set_sense(ctsio, /*current_error*/ 1, 1197 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 1198 /*asc*/ 0x26, /*ascq*/ 0x08, SSD_ELEM_NONE); 1199 goto done; 1200 } 1201 list->seg[nseg] = (struct scsi_ec_segment *)(ptr + off); 1202 off += sizeof(struct scsi_ec_segment) + 1203 scsi_2btoul(list->seg[nseg]->descr_length); 1204 } 1205 list->inl = &data->data[lencscd + lenseg]; 1206 list->ncscd = lencscd / sizeof(struct scsi_ec_cscd); 1207 list->nseg = nseg; 1208 list->leninl = leninl; 1209 list->ctsio = ctsio; 1210 list->lun = lun; 1211 mtx_lock(&lun->lun_lock); 1212 if ((list->flags & EC_LIST_ID_USAGE_MASK) != EC_LIST_ID_USAGE_NONE) { 1213 TAILQ_FOREACH(tlist, &lun->tpc_lists, links) { 1214 if ((tlist->flags & EC_LIST_ID_USAGE_MASK) != 1215 EC_LIST_ID_USAGE_NONE && 1216 tlist->list_id == list->list_id) 1217 break; 1218 } 1219 if (tlist != NULL && !tlist->completed) { 1220 mtx_unlock(&lun->lun_lock); 1221 free(list, M_CTL); 1222 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 1223 /*command*/ 0, /*field*/ 0, /*bit_valid*/ 0, 1224 /*bit*/ 0); 1225 goto done; 1226 } 1227 if (tlist != NULL) { 1228 TAILQ_REMOVE(&lun->tpc_lists, tlist, links); 1229 free(tlist, M_CTL); 1230 } 1231 } 1232 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links); 1233 mtx_unlock(&lun->lun_lock); 1234 1235 tpc_process(list); 1236 return (CTL_RETVAL_COMPLETE); 1237 1238 done: 1239 ctl_done((union ctl_io *)ctsio); 1240 return (CTL_RETVAL_COMPLETE); 1241 } 1242 1243 int 1244 ctl_extended_copy_lid4(struct ctl_scsiio *ctsio) 1245 { 1246 struct scsi_extended_copy *cdb; 1247 struct scsi_extended_copy_lid4_data *data; 1248 struct ctl_lun *lun; 1249 struct tpc_list *list, *tlist; 1250 uint8_t *ptr; 1251 char *value; 1252 int len, off, lencscd, lenseg, leninl, nseg; 1253 1254 CTL_DEBUG_PRINT(("ctl_extended_copy_lid4\n")); 1255 1256 lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr; 1257 cdb = (struct scsi_extended_copy *)ctsio->cdb; 1258 len = scsi_4btoul(cdb->length); 1259 1260 if (len < sizeof(struct scsi_extended_copy_lid4_data) || 1261 len > sizeof(struct scsi_extended_copy_lid4_data) + 1262 TPC_MAX_LIST + TPC_MAX_INLINE) { 1263 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 1, 1264 /*field*/ 9, /*bit_valid*/ 0, /*bit*/ 0); 1265 goto done; 1266 } 1267 1268 /* 1269 * If we've got a kernel request that hasn't been malloced yet, 1270 * malloc it and tell the caller the data buffer is here. 1271 */ 1272 if ((ctsio->io_hdr.flags & CTL_FLAG_ALLOCATED) == 0) { 1273 ctsio->kern_data_ptr = malloc(len, M_CTL, M_WAITOK); 1274 ctsio->kern_data_len = len; 1275 ctsio->kern_total_len = len; 1276 ctsio->kern_data_resid = 0; 1277 ctsio->kern_rel_offset = 0; 1278 ctsio->kern_sg_entries = 0; 1279 ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED; 1280 ctsio->be_move_done = ctl_config_move_done; 1281 ctl_datamove((union ctl_io *)ctsio); 1282 1283 return (CTL_RETVAL_COMPLETE); 1284 } 1285 1286 data = (struct scsi_extended_copy_lid4_data *)ctsio->kern_data_ptr; 1287 lencscd = scsi_2btoul(data->cscd_list_length); 1288 lenseg = scsi_2btoul(data->segment_list_length); 1289 leninl = scsi_2btoul(data->inline_data_length); 1290 if (len < sizeof(struct scsi_extended_copy_lid4_data) + 1291 lencscd + lenseg + leninl || 1292 leninl > TPC_MAX_INLINE) { 1293 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, /*command*/ 0, 1294 /*field*/ 2, /*bit_valid*/ 0, /*bit*/ 0); 1295 goto done; 1296 } 1297 if (lencscd > TPC_MAX_CSCDS * sizeof(struct scsi_ec_cscd)) { 1298 ctl_set_sense(ctsio, /*current_error*/ 1, 1299 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 1300 /*asc*/ 0x26, /*ascq*/ 0x06, SSD_ELEM_NONE); 1301 goto done; 1302 } 1303 if (lencscd + lenseg > TPC_MAX_LIST) { 1304 ctl_set_param_len_error(ctsio); 1305 goto done; 1306 } 1307 1308 list = malloc(sizeof(struct tpc_list), M_CTL, M_WAITOK | M_ZERO); 1309 list->service_action = cdb->service_action; 1310 value = ctl_get_opt(&lun->be_lun->options, "insecure_tpc"); 1311 if (value != NULL && strcmp(value, "on") == 0) 1312 list->init_port = -1; 1313 else 1314 list->init_port = ctsio->io_hdr.nexus.targ_port; 1315 list->init_idx = ctl_get_resindex(&ctsio->io_hdr.nexus); 1316 list->list_id = scsi_4btoul(data->list_identifier); 1317 list->flags = data->flags; 1318 list->params = ctsio->kern_data_ptr; 1319 list->cscd = (struct scsi_ec_cscd *)&data->data[0]; 1320 ptr = &data->data[lencscd]; 1321 for (nseg = 0, off = 0; off < lenseg; nseg++) { 1322 if (nseg >= TPC_MAX_SEGS) { 1323 free(list, M_CTL); 1324 ctl_set_sense(ctsio, /*current_error*/ 1, 1325 /*sense_key*/ SSD_KEY_ILLEGAL_REQUEST, 1326 /*asc*/ 0x26, /*ascq*/ 0x08, SSD_ELEM_NONE); 1327 goto done; 1328 } 1329 list->seg[nseg] = (struct scsi_ec_segment *)(ptr + off); 1330 off += sizeof(struct scsi_ec_segment) + 1331 scsi_2btoul(list->seg[nseg]->descr_length); 1332 } 1333 list->inl = &data->data[lencscd + lenseg]; 1334 list->ncscd = lencscd / sizeof(struct scsi_ec_cscd); 1335 list->nseg = nseg; 1336 list->leninl = leninl; 1337 list->ctsio = ctsio; 1338 list->lun = lun; 1339 mtx_lock(&lun->lun_lock); 1340 if ((list->flags & EC_LIST_ID_USAGE_MASK) != EC_LIST_ID_USAGE_NONE) { 1341 TAILQ_FOREACH(tlist, &lun->tpc_lists, links) { 1342 if ((tlist->flags & EC_LIST_ID_USAGE_MASK) != 1343 EC_LIST_ID_USAGE_NONE && 1344 tlist->list_id == list->list_id) 1345 break; 1346 } 1347 if (tlist != NULL && !tlist->completed) { 1348 mtx_unlock(&lun->lun_lock); 1349 free(list, M_CTL); 1350 ctl_set_invalid_field(ctsio, /*sks_valid*/ 1, 1351 /*command*/ 0, /*field*/ 0, /*bit_valid*/ 0, 1352 /*bit*/ 0); 1353 goto done; 1354 } 1355 if (tlist != NULL) { 1356 TAILQ_REMOVE(&lun->tpc_lists, tlist, links); 1357 free(tlist, M_CTL); 1358 } 1359 } 1360 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links); 1361 mtx_unlock(&lun->lun_lock); 1362 1363 tpc_process(list); 1364 return (CTL_RETVAL_COMPLETE); 1365 1366 done: 1367 ctl_done((union ctl_io *)ctsio); 1368 return (CTL_RETVAL_COMPLETE); 1369 } 1370 1371