34#include <sys/kernel.h>
37#include <sys/module.h>
39#include <sys/condvar.h>
40#include <sys/malloc.h>
43#include <sys/sysctl.h>
46#include <machine/atomic.h>
64#define TPC_MAX_CSCDS 64
65#define TPC_MAX_SEGS 64
67#define TPC_MAX_LIST 8192
68#define TPC_MAX_INLINE 0
69#define TPC_MAX_LISTS 255
70#define TPC_MAX_IO_SIZE (8 * MIN(1024 * 1024, MAX(128 * 1024, maxphys)))
71#define TPC_MAX_IOCHUNK_SIZE (TPC_MAX_IO_SIZE * 4)
72#define TPC_MIN_TOKEN_TIMEOUT 1
73#define TPC_DFL_TOKEN_TIMEOUT 60
74#define TPC_MAX_TOKEN_TIMEOUT 600
95 TAILQ_ENTRY(
tpc_io) rlinks;
144 uint8_t fwd_sense_len;
145 uint8_t fwd_scsi_status;
154 uint8_t res_token[512];
167 STAILQ_FOREACH(lun, &softc->lun_list, links) {
169 TAILQ_FOREACH_SAFE(list, &lun->tpc_lists, links, tlist) {
173 TAILQ_REMOVE(&lun->tpc_lists, list, links);
181 TAILQ_FOREACH_SAFE(
token, &softc->tpc_tokens, links, ttoken) {
185 TAILQ_REMOVE(&softc->tpc_tokens,
token, links);
190 callout_schedule_sbt(&softc->
tpc_timeout, SBT_1S, SBT_1S, 0);
197 mtx_init(&softc->
tpc_lock,
"CTL TPC mutex", NULL, MTX_DEF);
198 TAILQ_INIT(&softc->tpc_tokens);
200 callout_reset_sbt(&softc->
tpc_timeout, SBT_1S, SBT_1S,
213 while ((
token = TAILQ_FIRST(&softc->tpc_tokens)) != NULL) {
214 TAILQ_REMOVE(&softc->tpc_tokens,
token, links);
215 free(
token->params, M_CTL);
226 TAILQ_INIT(&
lun->tpc_lists);
234 TAILQ_FOREACH_SAFE(list, &lun->tpc_lists, links, tlist) {
235 if (initidx != -1 && list->
init_idx != initidx)
239 TAILQ_REMOVE(&lun->tpc_lists, list, links);
252 while ((list = TAILQ_FIRST(&
lun->tpc_lists)) != NULL) {
253 TAILQ_REMOVE(&
lun->tpc_lists, list, links);
255 (
"Not completed TPC (%p) on shutdown", list));
261 TAILQ_FOREACH_SAFE(
token, &softc->tpc_tokens, links, ttoken) {
264 TAILQ_REMOVE(&softc->tpc_tokens,
token, links);
265 free(
token->params, M_CTL);
303 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
342 scd_ptr = &sc_ptr->
descr[0];
459 int alloc_len, total_len;
467 total_len =
sizeof(*data) + 4;
470 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
509 mtx_assert(&lun->
lun_lock, MA_OWNED);
510 TAILQ_FOREACH(list, &lun->tpc_lists, links) {
528 int alloc_len, total_len;
550 TAILQ_REMOVE(&lun->tpc_lists, list, links);
555 total_len =
sizeof(*data);
558 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
574 if (list_copy.
curbytes <= UINT32_MAX) {
598 int alloc_len, total_len;
619 TAILQ_REMOVE(&lun->tpc_lists, list, links);
623 total_len =
sizeof(*data) + list_copy.sense_len;
626 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
634 scsi_ulto4b(
sizeof(*data) - 4 + list_copy.sense_len,
640 memcpy(data->
sense_data, &list_copy.sense_data, list_copy.sense_len);
658 int alloc_len, total_len;
680 TAILQ_REMOVE(&lun->tpc_lists, list, links);
685 total_len =
sizeof(*data) + list_copy.sense_len;
688 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
695 scsi_ulto4b(
sizeof(*data) - 4 + list_copy.sense_len,
701 else if (list_copy.
abort)
714 memcpy(data->
sense_data, &list_copy.sense_data, list_copy.sense_len);
759 uint32_t *pb, uint32_t *pbo)
764 *ss = list->lun->be_lun->blocksize;
766 *pb = list->lun->be_lun->blocksize <<
767 list->lun->be_lun->pblockexp;
769 *pbo = list->lun->be_lun->blocksize *
770 list->lun->be_lun->pblockoff;
771 return (list->lun->lun);
773 if (idx >= list->
ncscd)
785 uint8_t fbuf[4 + 64];
788 if (list->fwd_cscd <= 0x07ff) {
794 if (list->fwd_scsi_status) {
796 fbuf[2] = list->fwd_target;
797 flen = list->fwd_sense_len;
803 fbuf[3] = list->fwd_scsi_status;
804 bcopy(&list->fwd_sense_data, &fbuf[4], flen);
822 struct tpc_io *tior, *tiow;
825 off_t srclba, dstlba, numbytes, donebytes, roundbytes;
827 uint32_t srcblock, dstblock, pb, pbo, adj;
828 uint16_t scscd, dcscd;
832 if (list->
stage == 1) {
833 while ((tior = TAILQ_FIRST(&list->allio)) != NULL) {
834 TAILQ_REMOVE(&list->allio, tior, links);
836 free(tior->
buf, M_CTL);
842 }
else if (list->
error) {
851 TAILQ_INIT(&list->allio);
855 sl =
tpc_resolve(list, scscd, &srcblock, NULL, NULL);
856 dl =
tpc_resolve(list, dcscd, &dstblock, &pb, &pbo);
857 if (sl == UINT64_MAX || dl == UINT64_MAX) {
875 numbytes = (off_t)numlba * dstblock;
877 numbytes = (off_t)numlba * srcblock;
888 if (numbytes % srcblock != 0 || numbytes % dstblock != 0) {
902 while (donebytes < numbytes) {
903 roundbytes = numbytes - donebytes;
906 roundbytes -= roundbytes % dstblock;
908 adj = (dstlba * dstblock + roundbytes - pbo) % pb;
909 if (roundbytes > adj)
914 tior = malloc(
sizeof(*tior), M_CTL, M_WAITOK | M_ZERO);
915 TAILQ_INIT(&tior->
run);
916 tior->
buf = malloc(roundbytes, M_CTL, M_WAITOK);
918 TAILQ_INSERT_TAIL(&list->allio, tior, links);
927 roundbytes / srcblock,
936 tiow = malloc(
sizeof(*tior), M_CTL, M_WAITOK | M_ZERO);
937 TAILQ_INIT(&tiow->
run);
939 TAILQ_INSERT_TAIL(&list->allio, tiow, links);
948 roundbytes / dstblock,
957 TAILQ_INSERT_TAIL(&tior->
run, tiow, rlinks);
958 TAILQ_INSERT_TAIL(&run, tior, rlinks);
960 donebytes += roundbytes;
961 srclba += roundbytes / srcblock;
962 dstlba += roundbytes / dstblock;
965 while ((tior = TAILQ_FIRST(&run)) != NULL) {
966 TAILQ_REMOVE(&run, tior, rlinks);
968 panic(
"tpcl_queue() error");
986 while ((tio = TAILQ_FIRST(&
list->allio)) != NULL) {
987 TAILQ_REMOVE(&
list->allio, tio, links);
1001 TAILQ_INIT(&
list->allio);
1005 if (sl == UINT64_MAX) {
1016 if ((seg->
tur & 0x01) == 0)
1020 tio = malloc(
sizeof(*tio), M_CTL, M_WAITOK | M_ZERO);
1021 TAILQ_INIT(&tio->
run);
1023 TAILQ_INSERT_TAIL(&list->allio, tio, links);
1033 panic(
"tpcl_queue() error");
1049 while ((tio = TAILQ_FIRST(&
list->allio)) != NULL) {
1050 TAILQ_REMOVE(&
list->allio, tio, links);
1052 free(tio->
buf, M_CTL);
1065 TAILQ_INIT(&
list->allio);
1069 if (dl == UINT64_MAX) {
1081 tio = malloc(
sizeof(*tio), M_CTL, M_WAITOK | M_ZERO);
1082 TAILQ_INIT(&tio->
run);
1084 TAILQ_INSERT_TAIL(&list->allio, tio, links);
1087 tio->
buf = malloc(datalen, M_CTL, M_WAITOK);
1099 panic(
"tpcl_queue() error");
1109 for (r = 0; r < nrange; r++)
1122 for (i = 0; i < nrange; i++) {
1125 if (b1 + l1 < b1 || b1 + l1 > maxlba + 1) {
1126 *lba = MAX(b1, maxlba + 1);
1140 for (i = 0; i < nrange - 1; i++) {
1143 for (j = i + 1; j < nrange; j++) {
1146 if (b1 + l1 > b2 && b2 + l2 > b1)
1155 int *srange, off_t *soffset)
1162 while (r < nrange) {
1165 *soffset = skip - off;
1177 struct tpc_io *tio, *tior, *tiow;
1180 off_t doffset, soffset;
1181 off_t srclba, dstlba, numbytes, donebytes, roundbytes;
1182 uint32_t srcblock, dstblock, pb, pbo, adj;
1184 if (list->
stage > 0) {
1186 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) {
1187 TAILQ_REMOVE(&list->allio, tio, links);
1189 free(tio->
buf, M_CTL);
1195 }
else if (list->
error) {
1196 if (list->fwd_scsi_status) {
1197 list->ctsio->io_hdr.status =
1199 list->ctsio->scsi_status = list->fwd_scsi_status;
1200 list->ctsio->sense_data = list->fwd_sense_data;
1201 list->ctsio->sense_len = list->fwd_sense_len;
1215 &drange, &doffset) != 0)
1217 dstblock = list->lun->be_lun->blocksize;
1218 pb = dstblock << list->lun->be_lun->pblockexp;
1219 if (list->lun->be_lun->pblockoff > 0)
1220 pbo = pb - dstblock * list->lun->be_lun->pblockoff;
1228 &srange, &soffset) != 0) {
1236 numbytes = srcblock *
1238 numbytes = omin(numbytes, dstblock *
1242 numbytes -= numbytes % dstblock;
1243 if (pb > dstblock) {
1244 adj = (dstlba * dstblock + numbytes - pbo) % pb;
1250 if (numbytes % srcblock != 0 || numbytes % dstblock != 0) {
1263 TAILQ_INIT(&list->allio);
1264 while (donebytes < numbytes) {
1265 roundbytes = numbytes - donebytes;
1268 roundbytes -= roundbytes % dstblock;
1269 if (pb > dstblock) {
1270 adj = (dstlba * dstblock + roundbytes - pbo) % pb;
1271 if (roundbytes > adj)
1276 tior = malloc(
sizeof(*tior), M_CTL, M_WAITOK | M_ZERO);
1277 TAILQ_INIT(&tior->
run);
1278 tior->
buf = malloc(roundbytes, M_CTL, M_WAITOK);
1280 TAILQ_INSERT_TAIL(&list->allio, tior, links);
1289 roundbytes / srcblock,
1296 tiow = malloc(
sizeof(*tiow), M_CTL, M_WAITOK | M_ZERO);
1297 TAILQ_INIT(&tiow->
run);
1299 TAILQ_INSERT_TAIL(&list->allio, tiow, links);
1308 roundbytes / dstblock,
1312 tiow->
lun = list->lun->lun;
1315 TAILQ_INSERT_TAIL(&tior->
run, tiow, rlinks);
1316 TAILQ_INSERT_TAIL(&run, tior, rlinks);
1318 donebytes += roundbytes;
1319 srclba += roundbytes / srcblock;
1320 dstlba += roundbytes / dstblock;
1323 while ((tior = TAILQ_FIRST(&run)) != NULL) {
1324 TAILQ_REMOVE(&run, tior, rlinks);
1326 panic(
"tpcl_queue() error");
1336 struct tpc_io *tio, *tiow;
1337 struct runl run, *prun;
1339 uint32_t dstblock, len;
1341 if (list->
stage > 0) {
1344 while ((tio = TAILQ_FIRST(&list->allio)) != NULL) {
1345 TAILQ_REMOVE(&list->allio, tio, links);
1352 }
else if (list->
error) {
1353 if (list->fwd_scsi_status) {
1354 list->ctsio->io_hdr.status =
1356 list->ctsio->scsi_status = list->fwd_scsi_status;
1357 list->ctsio->sense_data = list->fwd_sense_data;
1358 list->ctsio->sense_len = list->fwd_sense_len;
1371 dstblock = list->lun->be_lun->blocksize;
1375 TAILQ_INIT(&list->allio);
1377 for (r = 0; r < list->
nrange; r++) {
1382 tiow = malloc(
sizeof(*tiow), M_CTL, M_WAITOK | M_ZERO);
1383 TAILQ_INIT(&tiow->
run);
1385 TAILQ_INSERT_TAIL(&list->allio, tiow, links);
1396 tiow->
lun = list->lun->lun;
1399 TAILQ_INSERT_TAIL(prun, tiow, rlinks);
1405 if (TAILQ_EMPTY(&run))
1408 while ((tiow = TAILQ_FIRST(&run)) != NULL) {
1409 TAILQ_REMOVE(&run, tiow, rlinks);
1411 panic(
"tpcl_queue() error");
1429 if (list->
token != NULL)
1477 free(list->
params, M_CTL);
1488 TAILQ_REMOVE(&lun->tpc_lists, list, links);
1517 int error_code, sense_key, asc, ascq;
1532 switch (error_code) {
1540 switch (sense_key) {
1549 if ((asc == 0x44) && (ascq == 0x00))
1557 if ((asc == 0x04) && (ascq == 0x02))
1563 if ((asc == 0x04) && (ascq == 0x03))
1568 return (error_action);
1595 panic(
"%s: invalid ctl_io type %d\n", __func__,
1599 return (error_action);
1605 struct tpc_io *tio, *tior;
1632 printf(
"%s: error returned from tpcl_queue()!\n",
1653 while ((tior = TAILQ_FIRST(&tio->
run)) != NULL) {
1654 TAILQ_REMOVE(&tio->
run, tior, rlinks);
1657 panic(
"tpcl_queue() error");
1660 if (atomic_fetchadd_int(&tio->
list->
tbdio, -1) == 1)
1730 lencscd + lenseg + leninl) {
1735 list = malloc(
sizeof(
struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
1737 value = dnvlist_get_string(lun->
be_lun->
options,
"insecure_tpc", NULL);
1738 if (value != NULL && strcmp(value,
"on") == 0)
1747 ptr = &data->
data[0];
1748 for (off = 0; off < lencscd; off +=
sizeof(
struct scsi_ec_cscd)) {
1758 ptr = &data->
data[lencscd];
1759 for (nseg = 0, off = 0; off < lenseg; nseg++) {
1777 list->
seg[nseg] = seg;
1781 list->
inl = &data->
data[lencscd + lenseg];
1785 list->ctsio = ctsio;
1790 if (tlist != NULL && !tlist->
completed) {
1798 if (tlist != NULL) {
1799 TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
1803 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
1884 lencscd + lenseg + leninl) {
1889 list = malloc(
sizeof(
struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
1891 value = dnvlist_get_string(lun->
be_lun->
options,
"insecure_tpc", NULL);
1892 if (value != NULL && strcmp(value,
"on") == 0)
1901 ptr = &data->
data[0];
1902 for (off = 0; off < lencscd; off +=
sizeof(
struct scsi_ec_cscd)) {
1912 ptr = &data->
data[lencscd];
1913 for (nseg = 0, off = 0; off < lenseg; nseg++) {
1931 list->
seg[nseg] = seg;
1935 list->
inl = &data->
data[lencscd + lenseg];
1939 list->ctsio = ctsio;
1944 if (tlist != NULL && !tlist->
completed) {
1952 if (tlist != NULL) {
1953 TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
1957 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
2016 arc4rand(&token->
body[120 + targid_len], 384 - targid_len, 0);
2030 int len, lendata, lendesc;
2119 list = malloc(
sizeof(
struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
2125 list->ctsio = ctsio;
2129 if (tlist != NULL && !tlist->
completed) {
2137 if (tlist != NULL) {
2138 TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
2141 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
2144 token = malloc(
sizeof(*token), M_CTL, M_WAITOK | M_ZERO);
2162 memcpy(list->res_token, token->
token,
sizeof(list->res_token));
2163 list->res_token_valid = 1;
2168 TAILQ_INSERT_TAIL(&softc->tpc_tokens, token, links);
2193 int len, lendata, lendesc;
2265 list = malloc(
sizeof(
struct tpc_list), M_CTL, M_WAITOK | M_ZERO);
2276 list->ctsio = ctsio;
2280 if (tlist != NULL && !tlist->
completed) {
2288 if (tlist != NULL) {
2289 TAILQ_REMOVE(&lun->tpc_lists, tlist, links);
2292 TAILQ_INSERT_TAIL(&lun->tpc_lists, list, links);
2302 TAILQ_FOREACH(token, &softc->tpc_tokens, links) {
2307 if (token != NULL) {
2309 list->
token = token;
2314 if (token == NULL) {
2316 TAILQ_REMOVE(&lun->tpc_lists, list, links);
2347 int alloc_len, total_len, token_len;
2369 TAILQ_REMOVE(&lun->tpc_lists, list, links);
2374 token_len = list_copy.res_token_valid ? 2 +
sizeof(list_copy.res_token) : 0;
2375 total_len =
sizeof(*data) + list_copy.sense_len + 4 + token_len;
2378 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
2385 scsi_ulto4b(
sizeof(*data) - 4 + list_copy.sense_len +
2389 if (list_copy.
error)
2391 else if (list_copy.
abort)
2404 memcpy(data->
sense_data, &list_copy.sense_data, list_copy.sense_len);
2408 if (list_copy.res_token_valid) {
2410 memcpy(&ptr[6], list_copy.res_token,
sizeof(list_copy.res_token));
2431 int alloc_len, total_len, tokens, i;
2440 TAILQ_FOREACH(token, &softc->tpc_tokens, links)
2446 total_len =
sizeof(*data) + tokens * 96;
2449 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
2458 TAILQ_FOREACH(token, &softc->tpc_tokens, links) {
int ctl_config_move_done(union ctl_io *io, bool samethr)
void ctl_free_io(union ctl_io *io)
void ctl_datamove(union ctl_io *io)
uint32_t ctl_get_initindex(struct ctl_nexus *nexus)
void ctl_done(union ctl_io *io)
#define CTL_RETVAL_COMPLETE
#define CTL_RETVAL_QUEUED
#define CTL_DEBUG_PRINT(X)
void ctl_set_task_aborted(struct ctl_scsiio *ctsio)
void ctl_set_invalid_field(struct ctl_scsiio *ctsio, int sks_valid, int command, int field, int bit_valid, int bit)
void ctl_set_success(struct ctl_scsiio *ctsio)
void ctl_set_param_len_error(struct ctl_scsiio *ctsio)
void ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio, uint64_t lba)
void ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, int asc, int ascq,...)
#define CTL_PRIV_FRONTEND
static int tpc_process_zero_wut(struct tpc_list *list)
void ctl_tpc_lun_init(struct ctl_lun *lun)
static int tpc_process_wut(struct tpc_list *list)
static int tpc_skip_ranges(struct scsi_range_desc *range, int nrange, off_t skip, int *srange, off_t *soffset)
int ctl_copy_operation_abort(struct ctl_scsiio *ctsio)
int ctl_report_all_rod_tokens(struct ctl_scsiio *ctsio)
#define TPC_MIN_TOKEN_TIMEOUT
static int tpc_process_verify(struct tpc_list *list)
#define TPC_DFL_TOKEN_TIMEOUT
void tpc_done(union ctl_io *io)
#define TPC_MAX_IOCHUNK_SIZE
static int tpc_check_ranges_l(struct scsi_range_desc *range, int nrange, uint64_t maxlba, uint64_t *lba)
void ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx)
void ctl_tpc_lun_shutdown(struct ctl_lun *lun)
static void tpc_timeout(void *arg)
int ctl_receive_copy_status_lid4(struct ctl_scsiio *ctsio)
int ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len)
int ctl_receive_rod_token_information(struct ctl_scsiio *ctsio)
int ctl_extended_copy_lid1(struct ctl_scsiio *ctsio)
int ctl_receive_copy_failure_details(struct ctl_scsiio *ctsio)
static void tpc_process(struct tpc_list *list)
static void tpc_create_token(struct ctl_lun *lun, struct ctl_port *port, off_t len, struct scsi_token *token)
static off_t tpc_ranges_length(struct scsi_range_desc *range, int nrange)
static tpc_error_action tpc_checkcond_parse(union ctl_io *io)
static tpc_error_action tpc_error_parse(union ctl_io *io)
int ctl_receive_copy_operating_parameters(struct ctl_scsiio *ctsio)
void ctl_tpc_init(struct ctl_softc *softc)
void ctl_tpc_shutdown(struct ctl_softc *softc)
int ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio)
static struct tpc_list * tpc_find_list(struct ctl_lun *lun, uint32_t list_id, uint32_t init_idx)
static int tpc_check_ranges_x(struct scsi_range_desc *range, int nrange)
static void tpc_set_io_error_sense(struct tpc_list *list)
#define TPC_MAX_TOKEN_TIMEOUT
int ctl_write_using_token(struct ctl_scsiio *ctsio)
int ctl_populate_token(struct ctl_scsiio *ctsio)
int ctl_extended_copy_lid4(struct ctl_scsiio *ctsio)
static int tpc_process_b2b(struct tpc_list *list)
static int tpc_process_register_key(struct tpc_list *list)
MALLOC_DEFINE(M_CTL_TPC, "ctltpc", "CTL TPC")
static uint64_t tpc_resolve(struct tpc_list *list, uint16_t idx, uint32_t *ss, uint32_t *pb, uint32_t *pbo)
uint64_t tpcl_resolve(struct ctl_softc *softc, int init_port, struct scsi_ec_cscd *cscd, uint32_t *ss, uint32_t *ps, uint32_t *pso)
union ctl_io * tpcl_alloc_io(void)
int tpcl_queue(union ctl_io *io, uint64_t lun)
void ctl_scsi_read_write(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, int read_op, uint8_t byte2, int minimum_cdb_size, uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type, uint8_t control)
void ctl_scsi_tur(union ctl_io *io, ctl_tag_type tag_type, uint8_t control)
void ctl_scsi_persistent_res_out(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, int action, int type, uint64_t key, uint64_t sa_key, ctl_tag_type tag_type, uint8_t control)
void ctl_scsi_write_same(union ctl_io *io, uint8_t *data_ptr, uint32_t data_len, uint8_t byte2, uint64_t lba, uint32_t num_blocks, ctl_tag_type tag_type, uint8_t control)
int scsi_devid_is_lun_eui64(uint8_t *bufp)
int scsi_devid_is_lun_naa(uint8_t *bufp)
struct scsi_vpd_id_descriptor * scsi_get_devid_desc(struct scsi_vpd_id_descriptor *desc, uint32_t len, scsi_devid_checkfn_t ck_fn)
void scsi_extract_sense_len(struct scsi_sense_data *sense_data, u_int sense_len, int *error_code, int *sense_key, int *asc, int *ascq, int show_errors)
#define EC_LIST_ID_USAGE_MASK
#define SSD_KEY_UNIT_ATTENTION
#define SSD_KEY_HARDWARE_ERROR
#define SSD_DESC_CURRENT_ERROR
#define SCSI_STATUS_CHECK_COND
#define RCS_CCS_COMPLETED
static __inline uint32_t scsi_3btoul(const uint8_t *bytes)
static __inline uint64_t scsi_8btou64(const uint8_t *bytes)
static __inline uint32_t scsi_2btoul(const uint8_t *bytes)
#define SSD_FORWARDED_SDS_EXDST
#define EC_LIST_ID_USAGE_NONE
static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes)
#define SSD_DEFERRED_ERROR
#define SSD_DESC_DEFERRED_ERROR
#define RCS_CCS_INPROG_FG
#define SSD_KEY_NOT_READY
static __inline uint32_t scsi_4btoul(const uint8_t *bytes)
#define SID_QUAL_LU_CONNECTED
#define SSD_FORWARDED_FSDT
#define SVPD_TPC_SRTD_TIN
#define SSD_SKS_SEGMENT_VALID
#define SVPD_TPC_SRTD_TOUT
static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes)
static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes)
#define SSD_FORWARDED_SDS_EXSRC
#define EC_SEG_REGISTER_KEY
#define SID_QUAL_LU_OFFLINE
static __inline void scsi_ulto3b(u_int32_t val, u_int8_t *bytes)
#define SSD_KEY_ILLEGAL_REQUEST
#define ROD_TYPE_BLOCK_ZERO
#define SVPD_TPC_RTF_BLOCK
#define RECEIVE_COPY_STATUS
#define SSD_KEY_COPY_ABORTED
#define SSD_CURRENT_ERROR
ctl_backend_lun_flags flags
union ctl_priv ctl_private[CTL_NUM_PRIV]
struct ctl_devid * lun_devid
struct ctl_softc * ctl_softc
struct ctl_be_lun * be_lun
struct ctl_devid * target_devid
int(* be_move_done)(union ctl_io *io, bool samethr)
struct scsi_sense_data sense_data
uint8_t cdb[CTL_MAX_CDBLEN]
struct callout tpc_timeout
uint8_t list_identifier[4]
struct scsi_ec_cscd_dtsp dtsp
struct scsi_ec_cscd_dtsp dtsp
uint8_t number_of_blocks[2]
uint8_t range_descriptor_length[2]
struct scsi_range_desc desc[]
uint8_t inactivity_timeout[4]
uint8_t list_identifier[4]
uint8_t sense_data_length[2]
uint8_t copy_command_status
uint8_t available_data[4]
uint8_t list_of_implemented_descriptor_type_codes[0]
uint8_t maximum_concurrent_copies
uint8_t maximum_inline_data_length[4]
uint8_t maximum_cscd_descriptor_count[2]
uint8_t total_concurrent_copies[2]
uint8_t maximum_segment_length[4]
uint8_t inline_data_granularity
uint8_t implemented_descriptor_list_length
uint8_t maximum_descriptor_list_length[4]
uint8_t maximum_stream_device_transfer_size[4]
uint8_t held_data_granularity
uint8_t held_data_limit[4]
uint8_t maximum_segment_descriptor_count[2]
uint8_t data_segment_granularity
uint8_t segments_processed[2]
uint8_t copy_command_status
uint8_t transfer_count_units
uint8_t transfer_count[4]
uint8_t available_data[4]
uint8_t available_data[4]
uint8_t response_to_service_action
uint8_t transfer_count[8]
uint8_t transfer_count_units
uint8_t copy_command_status
uint8_t length_of_the_sense_data_field
uint8_t operation_counter[2]
uint8_t sense_data_length
uint8_t segments_processed[2]
uint8_t estimated_status_update_delay[4]
uint8_t list_identifier[4]
uint8_t available_data[4]
uint8_t rod_management_token_list[]
uint8_t maximum_inactivity_timeout[4]
uint8_t default_inactivity_timeout[4]
uint8_t maximum_ranges[2]
uint8_t maximum_token_transfer_size[8]
uint8_t optimal_transfer_count[8]
uint8_t data_segment_granularity
uint8_t inline_data_granularity
uint8_t maximum_identified_concurrent_copies[4]
uint8_t total_concurrent_copies[4]
uint8_t maximum_segment_length[4]
uint8_t maximum_descriptor_list_length[4]
uint8_t maximum_inline_data_length[4]
uint8_t maximum_cscd_descriptor_count[2]
uint8_t maximum_segment_descriptor_count[2]
uint8_t optimal_bytes_from_token_per_segment[8]
uint8_t optimal_bytes_to_token_per_segment[8]
uint8_t optimal_length_granularity[2]
uint8_t type_specific_features_length[2]
uint8_t type_specific_features[0]
uint8_t minimum_token_lifetime[4]
uint8_t maximum_token_inactivity_timeout[4]
uint8_t maximum_token_lifetime[4]
uint8_t supported_service_actions[0]
struct scsi_vpd_tpc_descriptor_sc_descr descr[]
uint8_t supported_descriptor_codes[]
uint8_t supported_descriptor_ids[]
uint8_t rod_type_descriptors[0]
uint8_t rod_type_descriptors_length[2]
uint8_t preference_indicator[2]
struct scsi_vpd_tpc_descriptor descr[]
struct scsi_range_desc desc[]
uint8_t range_descriptor_length[2]
uint8_t offset_into_rod[8]
uint8_t list_identifier[4]
struct scsi_ec_cscd * cscd
struct scsi_range_desc * range
struct scsi_ec_segment * seg[TPC_MAX_SEGS]
struct scsi_range_desc * range