53#include <sys/kernel.h>
55#include <sys/kthread.h>
59#include <sys/module.h>
61#include <sys/condvar.h>
62#include <sys/malloc.h>
64#include <sys/ioccom.h>
68#include <sys/endian.h>
71#include <sys/sysctl.h>
201 { 0, 0, 0, 0, 0, 0 },
210 { 0, 0, 0, 0, 0, 0 },
270#define CTL_CEM_LEN (sizeof(struct scsi_control_ext_page) - 4)
305 {0xff, 0xff, 0xff, 0xff},
306 {0xff, 0xff, 0xff, 0xff}
309#define CTL_LBPM_LEN (sizeof(struct ctl_logical_block_provisioning_page) - 4)
316 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
342 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
409SYSCTL_NODE(_kern_cam, OID_AUTO, ctl, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
418SYSCTL_INT(_kern_cam_ctl, OID_AUTO, lun_map_size, CTLFLAG_RWTUN,
422SYSCTL_INT(_kern_cam_ctl, OID_AUTO, time_io_secs, CTLFLAG_RWTUN,
423 &ctl_time_io_secs, 0,
"Log requests taking more seconds");
429#define CTL_DEFAULT_MAX_LUNS 1024
438#define CTL_DEFAULT_MAX_PORTS 256
447#define CTL_MAX_INITIATORS (CTL_MAX_INIT_PER_PORT * ctl_max_ports)
456#define SCSI_EVPD_NUM_SUPPORTED_PAGES 11
464static int ctl_open(
struct cdev *dev,
int flags,
int fmt,
struct thread *td);
465static int ctl_close(
struct cdev *dev,
int flags,
int fmt,
struct thread *td);
470static int ctl_ioctl(
struct cdev *dev, u_long cmd, caddr_t addr,
int flag,
478 uint64_t res_key, uint64_t sa_res_key,
479 uint8_t type, uint32_t residx,
505 union ctl_io *pending_io,
const uint8_t *serialize_row,
508 union ctl_io **starting_io);
533static void ctl_datamove_timer_wakeup(
void *arg);
534static void ctl_done_timer_wakeup(
void *arg);
579 .d_version = D_VERSION,
640 while ((port = STAILQ_FIRST(&
ha_frontend.port_list)) != NULL) {
654 uint32_t sg_entries_sent;
655 int do_sg_copy, i, j;
657 memset(&msg.
dt, 0,
sizeof(msg.
dt));
685 (
"HA does not support BUS_ADDR"));
711 if (do_sg_copy != 0) {
713 for (i = sg_entries_sent, j = 0;
721 (
void *)vtophys(sgl[i].
addr);
726 (
"HA does not support BUS_ADDR"));
772 memset(&msg, 0,
sizeof(msg));
797 printf(
"%s: original_sc == NULL!\n", __func__);
820 printf(
"%s: serializing_sc == NULL!\n", __func__);
841 i =
sizeof(msg->
lun);
847 msg = malloc(i, M_CTL, M_WAITOK);
849 k =
sizeof(msg->
lun);
858 bzero(&msg->
lun,
sizeof(msg->
lun));
906 i =
sizeof(msg->
port) + strlen(
port->port_name) + 1;
908 i +=
port->lun_map_size *
sizeof(uint32_t);
909 if (
port->port_devid)
910 i +=
port->port_devid->len;
911 if (
port->target_devid)
912 i +=
port->target_devid->len;
913 if (
port->init_devid)
914 i +=
port->init_devid->len;
915 msg = malloc(i, M_CTL, M_WAITOK);
916 bzero(&msg->
port,
sizeof(msg->
port));
925 "%d:%s", softc->
ha_id,
port->port_name) + 1;
933 if (
port->port_devid) {
939 if (
port->target_devid) {
945 if (
port->init_devid) {
968 i =
sizeof(msg->
iid);
971 l = strlen(
port->wwpn_iid[
iid].name) + 1;
973 msg = malloc(i, M_CTL, M_NOWAIT);
978 bzero(&msg->
iid,
sizeof(msg->
iid));
994 uint8_t page, uint8_t subpage)
1004 page &&
lun->mode_pages.index[i].subpage == subpage)
1011 if (
lun->mode_pages.index[i].page_data == NULL)
1014 l =
sizeof(msg->
mode) +
lun->mode_pages.index[i].page_len;
1015 msg = malloc(l, M_CTL, M_WAITOK | M_ZERO);
1024 memcpy(msg->
mode.
data,
lun->mode_pages.index[i].page_data,
1049 STAILQ_FOREACH(
port, &softc->port_list, links) {
1052 if (
port->wwpn_iid[i].in_use)
1056 STAILQ_FOREACH(
lun, &softc->lun_list, links)
1069 STAILQ_FOREACH(lun, &softc->lun_list, links) {
1072 lun->
flags &= ~CTL_LUN_PEER_SC_PRIMARY;
1086 STAILQ_FOREACH(port, &softc->port_list, links) {
1090 port->
status &= ~CTL_PORT_STATUS_ONLINE;
1106 if (len <
sizeof(msg->
ua)) {
1107 printf(
"%s: Received truncated message %d < %zu\n",
1108 __func__, len,
sizeof(msg->
ua));
1119 mtx_lock(&
lun->lun_lock);
1135 mtx_unlock(&
lun->lun_lock);
1148 printf(
"%s: Received truncated message %d < %zu\n",
1155 printf(
"%s: Received truncated message data %d < %zu\n",
1164 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
1178 printf(
"%s: Received conflicting HA LUN %d\n",
1179 __func__, targ_lun);
1183 oflags = lun->
flags;
1188 lun->
flags &= ~CTL_LUN_PEER_SC_PRIMARY;
1189 if (oflags != lun->
flags)
1215 "primary" :
"secondary"));
1232 printf(
"%s: Received truncated message %d < %zu\n",
1241 printf(
"%s: Received truncated message data %d < %zu\n",
1252 port = malloc(
sizeof(*port), M_CTL, M_WAITOK | M_ZERO);
1262 printf(
"%s: Received conflicting HA port %d\n",
1339 printf(
"%s: ctl_port_register() failed with error\n",
1344 STAILQ_FOREACH(
lun, &softc->lun_list, links) {
1347 mtx_lock(&
lun->lun_lock);
1349 mtx_unlock(&
lun->lun_lock);
1361 printf(
"%s: Received truncated message %d < %zu\n",
1368 printf(
"%s: Received truncated message data %d < %zu\n",
1376 printf(
"%s: Received IID for unknown port %d\n",
1398 if (len <
sizeof(msg->
login)) {
1399 printf(
"%s: Received truncated message %d < %zu\n",
1400 __func__, len,
sizeof(msg->
login));
1406 printf(
"CTL HA peers have different versions %d != %d\n",
1412 printf(
"CTL HA peers have different ha_mode %d != %d\n",
1418 printf(
"CTL HA peers have same ha_id %d\n", msg->
login.
ha_id);
1425 printf(
"CTL HA peers have different limits\n");
1436 uint32_t initidx, targ_lun;
1439 printf(
"%s: Received truncated message %d < %zu\n",
1446 printf(
"%s: Received truncated message data %d < %zu\n",
1459 mtx_lock(&
lun->lun_lock);
1462 mtx_unlock(&
lun->lun_lock);
1472 mtx_unlock(&
lun->lun_lock);
1475 memcpy(
lun->mode_pages.index[i].page_data, msg->
mode.
data,
1480 mtx_unlock(&
lun->lun_lock);
1499 if (param >
sizeof(msgbuf))
1500 msg = malloc(param, M_CTL, M_WAITOK);
1506 printf(
"%s: Error receiving message: %d\n",
1507 __func__, isc_status);
1563 printf(
"%s: original_sc == NULL!\n", __func__);
1584 sgl = malloc(
sizeof(*sgl) * i, M_CTL,
1629 printf(
"%s: serializing_sc == NULL!\n",
1663 printf(
"%s: original_sc == NULL!\n",
1690 printf(
"%s: Bad JUJU!, original_sc is NULL!\n",
1735 presio->pr_msg = msg->
pr;
1757 printf(
"Received HA message of unknown type %d\n",
1765 printf(
"CTL: HA link status changed from %d to %d\n",
1779 printf(
"ctl_isc_event_handler: Unknown event %d\n", event);
1814 mtx_assert(&lun->
lun_lock, MA_OWNED);
1826 mtx_assert(&lun->
lun_lock, MA_OWNED);
1842 mtx_assert(&lun->
lun_lock, MA_OWNED);
1855 mtx_assert(&lun->
lun_lock, MA_OWNED);
1868 mtx_assert(&lun->
lun_lock, MA_OWNED);
1888 mtx_lock(&
lun->lun_lock);
1890 mtx_unlock(&
lun->lun_lock);
1903 error = sysctl_handle_int(oidp, &value, 0, req);
1904 if ((error != 0) || (req->newptr == NULL))
1911 softc->
flags &= ~CTL_FLAG_ACTIVE_SHELF;
1912 STAILQ_FOREACH(lun, &softc->lun_list, links) {
1914 bzero(&ireq,
sizeof(ireq));
1920 printf(
"%s: CTL_LUNREQ_MODIFY returned %d '%s'\n",
1921 __func__, ireq.status, ireq.error_str);
1932 struct make_dev_args args;
1939 make_dev_args_init(&args);
1941 args.mda_uid = UID_ROOT;
1942 args.mda_gid = GID_OPERATOR;
1943 args.mda_mode = 0600;
1944 args.mda_si_drv1 = softc;
1945 args.mda_si_drv2 = NULL;
1946 error = make_dev_s(&args, &softc->
dev,
"cam/ctl");
1948 free(softc, M_DEVBUF);
1955 SYSCTL_STATIC_CHILDREN(_kern_cam), OID_AUTO,
"ctl",
1956 CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
"CAM Target Layer");
1959 printf(
"%s: unable to allocate sysctl tree\n", __func__);
1960 destroy_dev(softc->
dev);
1961 free(softc, M_DEVBUF);
1966 mtx_init(&softc->
ctl_lock,
"CTL mutex", NULL, MTX_DEF);
1967 softc->
io_zone = uma_zcreate(
"CTL IO",
sizeof(
union ctl_io),
1968 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
1972 OID_AUTO,
"ha_mode", CTLFLAG_RDTUN, (
int *)&softc->
ha_mode, 0,
1973 "HA mode (0 - act/stby, 1 - serialize only, 2 - xfer)");
1976 printf(
"Bad value %d for kern.cam.ctl.max_luns, must be a power of two, using %d\n",
1981 M_DEVBUF, M_WAITOK | M_ZERO);
1983 ((
ctl_max_luns + 31) / 32), M_DEVBUF, M_WAITOK | M_ZERO);
1985 printf(
"Bad value %d for kern.cam.ctl.max_ports, must be a power of two, using %d\n",
1992 M_DEVBUF, M_WAITOK | M_ZERO);
2000 OID_AUTO,
"ha_id", CTLFLAG_RDTUN, &softc->
ha_id, 0,
2001 "HA head ID (0 - no HA)");
2016 OID_AUTO,
"ha_link", CTLFLAG_RD, (
int *)&softc->
ha_link, 0,
2017 "HA link state (0 - offline, 1 - unknown, 2 - online)");
2019 STAILQ_INIT(&softc->lun_list);
2020 STAILQ_INIT(&softc->fe_list);
2021 STAILQ_INIT(&softc->port_list);
2022 STAILQ_INIT(&softc->be_list);
2033 mtx_init(&thr->
queue_lock,
"CTL queue mutex", NULL, MTX_DEF);
2035 STAILQ_INIT(&thr->incoming_queue);
2036 STAILQ_INIT(&thr->rtr_queue);
2037 STAILQ_INIT(&thr->done_queue);
2038 STAILQ_INIT(&thr->isc_queue);
2043 printf(
"error creating CTL work thread!\n");
2050 printf(
"error creating CTL threshold thread!\n");
2055 OID_AUTO,
"ha_role",
2056 CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE,
2075 destroy_dev(softc->
dev);
2081 while (thr->
thread != NULL) {
2084 pause(
"CTL thr shutdown", 1);
2091 pause(
"CTL thr shutdown", 1);
2105 free(softc, M_DEVBUF);
2120 return (EOPNOTSUPP);
2150 mtx_assert(&softc->
ctl_lock, MA_NOTOWNED);
2153 printf(
"%s: initiator ID %u > maximun %u!\n",
2180 mtx_assert(&softc->
ctl_lock, MA_NOTOWNED);
2183 printf(
"%s: WWPN %#jx initiator ID %u > maximum %u!\n",
2191 if (iid < 0 && (wwpn != 0 || name != NULL)) {
2218 best_time = INT32_MAX;
2236 if (port->
wwpn_iid[iid].
in_use > 0 && (wwpn != 0 || name != NULL)) {
2242 printf(
"%s: port %d iid %u WWPN %#jx arrived"
2244 iid, (uintmax_t)wwpn);
2248 if (name != NULL && port->
wwpn_iid[iid].
name != NULL &&
2251 printf(
"%s: port %d iid %u name '%s' arrived"
2263 printf(
"%s: port %d iid %u WWPN %#jx '%s' arrived,"
2264 " but WWPN %#jx '%s' is still at that address\n",
2265 __func__, port->
targ_port, iid, wwpn, name,
2292 memset(
id, 0,
sizeof(*
id));
2295 return (
sizeof(*
id));
2307 len = roundup2(min(len, 252), 4);
2309 return (
sizeof(*
id) + len);
2317 memset(
id, 0,
sizeof(*
id));
2320 return (
sizeof(*
id));
2326 memset(
id, 0,
sizeof(*
id));
2330 return (
sizeof(*
id));
2366 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
2406 if (LIST_EMPTY(&lun->ooa_queue))
2407 lun->idle_time += getsbinuptime() - lun->last_busy;
2409 LIST_INSERT_HEAD(&lun->ooa_queue, &ctsio->
io_hdr, ooa_links);
2411 bio = (
union ctl_io *)LIST_NEXT(&ctsio->
io_hdr, ooa_links);
2428 sizeof(msg_info.
hdr), M_WAITOK);
2433 TAILQ_INSERT_TAIL(&bio->
io_hdr.blocked_queue, &ctsio->
io_hdr,
2438 LIST_REMOVE(&ctsio->
io_hdr, ooa_links);
2443 LIST_REMOVE(&ctsio->
io_hdr, ooa_links);
2452 sizeof(msg_info.
scsi), M_WAITOK);
2456 __assert_unreachable();
2470 ioh = LIST_FIRST(&lun->ooa_queue);
2475 while (LIST_NEXT(ioh, ooa_links) != NULL)
2476 ioh = LIST_NEXT(ioh, ooa_links);
2477 for ( ; ioh; ioh = LIST_PREV(ioh, &lun->ooa_queue,
ctl_io_hdr, ooa_links)) {
2485 if (*cur_fill_num >= ooa_hdr->
alloc_num) {
2490 entry = &kern_entries[*cur_fill_num];
2530 char *end = str + size;
2535 for (; *str && str < end; str++) {
2538 retval = sbuf_printf(sb,
"&");
2541 retval = sbuf_printf(sb,
">");
2544 retval = sbuf_printf(sb,
"<");
2547 retval = sbuf_putc(sb, *str);
2564 if (
id == NULL || id->
len < 4)
2569 sbuf_printf(sb,
"t10.");
2572 sbuf_printf(sb,
"eui.");
2575 sbuf_printf(sb,
"naa.");
2582 for (i = 0; i < desc->
length; i++)
2583 sbuf_printf(sb,
"%02x", desc->
identifier[i]);
2586 sbuf_printf(sb,
"%.*s", (
int)desc->
length,
2590 sbuf_printf(sb,
"%s", (
char *)desc->
identifier);
2596ctl_ioctl(
struct cdev *dev, u_long cmd, caddr_t addr,
int flag,
2619 STAILQ_FOREACH(port, &softc->port_list, links) {
2651 printf(
"%s: Can't set WWNs on "
2652 "multiple ports\n", __func__);
2679 1 : 0, entry->
wwpn);
2690 uint32_t cur_fill_num;
2692 ooa_hdr = (
struct ctl_ooa *)addr;
2696 printf(
"%s: CTL_GET_OOA: alloc len %u and alloc num %u "
2697 "must be non-zero\n", __func__,
2705 printf(
"%s: CTL_GET_OOA: alloc len %u must be alloc "
2706 "num %d * sizeof(struct ctl_ooa_entry) %zd\n",
2715 printf(
"%s: could not allocate %d bytes for OOA "
2716 "dump\n", __func__, ooa_hdr->
alloc_len);
2727 printf(
"%s: CTL_GET_OOA: invalid LUN %ju\n",
2728 __func__, (uintmax_t)ooa_hdr->
lun_num);
2736 STAILQ_FOREACH(lun, &softc->lun_list, links) {
2752 printf(
"%s: error copying out %d bytes for OOA dump\n",
2756 getbinuptime(&ooa_hdr->
cur_bt);
2758 if (cur_fill_num > ooa_hdr->
alloc_num) {
2766 free(entries, M_CTL);
2817 new_err_desc = malloc(
sizeof(*new_err_desc), M_CTL,
2819 bcopy(err_desc, new_err_desc,
sizeof(*new_err_desc));
2825 free(new_err_desc, M_CTL);
2826 printf(
"%s: CTL_ERROR_INJECT: invalid LUN %ju\n",
2827 __func__, (uintmax_t)err_desc->
lun_id);
2843 STAILQ_INSERT_TAIL(&lun->error_list, new_err_desc, links);
2869 printf(
"%s: CTL_ERROR_INJECT_DELETE: invalid LUN %ju\n",
2870 __func__, (uintmax_t)delete_desc->
lun_id);
2876 STAILQ_FOREACH_SAFE(desc, &lun->error_list, links, desc2) {
2886 if (delete_done == 0) {
2887 printf(
"%s: CTL_ERROR_INJECT_DELETE: can't find "
2888 "error serial %ju on LUN %u\n", __func__,
2901 printf(
"CTL Persistent Reservation information start:\n");
2902 STAILQ_FOREACH(lun, &softc->lun_list, links) {
2915 printf(
" LUN %ju port %d iid %d key "
2916 "%#jx\n", lun->
lun, j, k,
2917 (uintmax_t)lun->
pr_keys[j][k]);
2922 printf(
"CTL Persistent Reservation information end\n");
2923 printf(
"CTL Ports:\n");
2924 STAILQ_FOREACH(port, &softc->port_list, links) {
2925 printf(
" Port %d '%s' Frontend '%s' Type %u pp %d vp %d WWNN "
2929 (uintmax_t)port->
wwnn, (uintmax_t)port->
wwpn);
2936 printf(
" iid %u use %d WWPN %#jx '%s'\n",
2942 printf(
"CTL Port information end\n");
2949 printf(
"CTL Frontends:\n");
2950 STAILQ_FOREACH(fe, &softc->fe_list, links) {
2951 printf(
" Frontend '%s'\n", fe->
name);
2955 printf(
"CTL Frontend information end\n");
2962 nvlist_t *tmp_args_nvl;
2973 "Backend \"%s\" not found.",
2978 if (lun_req->
args != NULL) {
2979 packed = malloc(lun_req->
args_len, M_CTL, M_WAITOK);
2980 if (copyin(lun_req->
args, packed, lun_req->
args_len) != 0) {
2981 free(packed, M_CTL);
2984 "Cannot copyin args.");
2987 lun_req->
args_nvl = nvlist_unpack(packed,
2989 free(packed, M_CTL);
2994 "Cannot unpack args nvlist.");
2998 lun_req->
args_nvl = nvlist_create(0);
3000 retval =
backend->ioctl(dev, cmd, addr, flag, td);
3005 if (lun_req->
result != NULL) {
3008 if (packed == NULL) {
3012 "Cannot pack result nvlist.");
3020 "Result nvlist too large.");
3021 free(packed, M_NVLIST);
3025 if (copyout(packed, lun_req->
result, packed_len)) {
3029 "Cannot copyout() the result.");
3030 free(packed, M_NVLIST);
3035 free(packed, M_NVLIST);
3045 const char *name, *value;
3076 sb = sbuf_new(NULL, NULL, list->
alloc_len, SBUF_FIXEDLEN);
3080 "Unable to allocate %d bytes for LUN list",
3085 sbuf_printf(sb,
"<ctllunlist>\n");
3088 STAILQ_FOREACH(lun, &softc->lun_list, links) {
3090 retval = sbuf_printf(sb,
"<lun id=\"%ju\">\n",
3091 (uintmax_t)lun->
lun);
3100 retval = sbuf_printf(sb,
"\t<backend_type>%s"
3101 "</backend_type>\n",
3102 (lun->
backend == NULL) ?
"none" :
3108 retval = sbuf_printf(sb,
"\t<lun_type>%d</lun_type>\n",
3115 retval = sbuf_printf(sb,
"</lun>\n");
3121 retval = sbuf_printf(sb,
"\t<size>%ju</size>\n",
3128 retval = sbuf_printf(sb,
"\t<blocksize>%u</blocksize>\n",
3134 retval = sbuf_printf(sb,
"\t<serial_number>");
3146 retval = sbuf_printf(sb,
"</serial_number>\n");
3151 retval = sbuf_printf(sb,
"\t<device_id>");
3163 retval = sbuf_printf(sb,
"</device_id>\n");
3176 &cookie)) != NULL) {
3177 sbuf_printf(sb,
"\t<%s>", name);
3179 if (type == NV_TYPE_STRING) {
3180 value = dnvlist_get_string(
3183 sbuf_printf(sb,
"%s", value);
3186 sbuf_printf(sb,
"</%s>\n", name);
3189 retval = sbuf_printf(sb,
"</lun>\n");
3200 || ((retval = sbuf_printf(sb,
"</ctllunlist>\n")) != 0)) {
3205 "Out of space, %d bytes is too small",
3212 retval = copyout(sbuf_data(sb), list->
lun_xml,
3230 "Frontend \"iscsi\" not found.");
3234 retval = fe->
ioctl(dev, cmd, addr, flag, td);
3241 nvlist_t *tmp_args_nvl;
3251 "Frontend \"%s\" not found.", req->
driver);
3255 if (req->
args != NULL) {
3256 packed = malloc(req->
args_len, M_CTL, M_WAITOK);
3258 free(packed, M_CTL);
3261 "Cannot copyin args.");
3264 req->
args_nvl = nvlist_unpack(packed,
3266 free(packed, M_CTL);
3271 "Cannot unpack args nvlist.");
3278 retval = fe->
ioctl(dev, cmd, addr, flag, td);
3286 if (req->
result != NULL) {
3289 if (packed == NULL) {
3293 "Cannot pack result nvlist.");
3301 "Result nvlist too large.");
3302 free(packed, M_NVLIST);
3306 if (copyout(packed, req->
result, packed_len)) {
3310 "Cannot copyout() the result.");
3311 free(packed, M_NVLIST);
3316 free(packed, M_NVLIST);
3327 const char *name, *value;
3334 sb = sbuf_new(NULL, NULL, list->
alloc_len, SBUF_FIXEDLEN);
3338 "Unable to allocate %d bytes for LUN list",
3343 sbuf_printf(sb,
"<ctlportlist>\n");
3346 STAILQ_FOREACH(port, &softc->port_list, links) {
3347 retval = sbuf_printf(sb,
"<targ_port id=\"%ju\">\n",
3357 retval = sbuf_printf(sb,
"\t<frontend_type>%s"
3362 retval = sbuf_printf(sb,
"\t<port_type>%d</port_type>\n",
3367 retval = sbuf_printf(sb,
"\t<online>%s</online>\n",
3372 retval = sbuf_printf(sb,
"\t<port_name>%s</port_name>\n",
3377 retval = sbuf_printf(sb,
"\t<physical_port>%d</physical_port>\n",
3382 retval = sbuf_printf(sb,
"\t<virtual_port>%d</virtual_port>\n",
3388 sbuf_printf(sb,
"\t<target>");
3390 sbuf_printf(sb,
"</target>\n");
3394 sbuf_printf(sb,
"\t<port>");
3396 sbuf_printf(sb,
"</port>\n");
3406 while ((name = nvlist_next(port->
options, &type,
3407 &cookie)) != NULL) {
3408 sbuf_printf(sb,
"\t<%s>", name);
3410 if (type == NV_TYPE_STRING) {
3411 value = dnvlist_get_string(port->
options,
3414 sbuf_printf(sb,
"%s", value);
3417 sbuf_printf(sb,
"</%s>\n", name);
3421 sbuf_printf(sb,
"\t<lun_map>on</lun_map>\n");
3424 if (plun == UINT32_MAX)
3427 "\t<lun id=\"%u\">%u</lun>\n",
3439 retval = sbuf_printf(sb,
3440 "\t<initiator id=\"%u\">%s</initiator>\n",
3443 retval = sbuf_printf(sb,
3444 "\t<initiator id=\"%u\">naa.%08jx</initiator>\n",
3452 retval = sbuf_printf(sb,
"</targ_port>\n");
3459 || ((retval = sbuf_printf(sb,
"</ctlportlist>\n")) != 0)) {
3464 "Out of space, %d bytes is too small",
3471 retval = copyout(sbuf_data(sb), list->
lun_xml,
3491 STAILQ_FOREACH(lun, &softc->lun_list, links) {
3502 if (lm->
plun != UINT32_MAX) {
3503 if (lm->
lun == UINT32_MAX)
3511 if (lm->
lun == UINT32_MAX)
3530 stats->fill_len = 0;
3531 STAILQ_FOREACH(lun, &softc->lun_list, links) {
3539 retval = copyout(&lun->
stats, &
stats->stats[i++],
3540 sizeof(lun->
stats));
3550 getnanouptime(&
stats->timestamp);
3563 stats->fill_len = 0;
3564 STAILQ_FOREACH(port, &softc->port_list, links) {
3572 retval = copyout(&port->
stats, &
stats->stats[i++],
3573 sizeof(port->
stats));
3583 getnanouptime(&
stats->timestamp);
3600 type = _IOC_TYPE(cmd);
3602 STAILQ_FOREACH(backend, &softc->be_list, links) {
3603 if (backend->type == type) {
3609 printf(
"ctl: unknown ioctl command %#lx or backend "
3614 retval = backend->
ioctl(dev, cmd, addr, flag, td);
3640 port->
lun_map = malloc(size *
sizeof(uint32_t),
3645 for (i = 0; i < size; i++)
3646 port->
lun_map[i] = UINT32_MAX;
3650 STAILQ_FOREACH(
lun, &softc->lun_list, links)
3671 STAILQ_FOREACH(
lun, &softc->lun_list, links)
3710 port->
lun_map[plun] = UINT32_MAX;
3724 return (UINT32_MAX);
3728 return (UINT32_MAX);
3729 return (port->
lun_map[lun_id]);
3738 return (UINT32_MAX);
3742 if (port->
lun_map[i] == lun_id)
3745 return (UINT32_MAX);
3752 uint32_t result = 0xffffffff;
3754 be64enc(
lun, encoded);
3757 if ((
lun[0] & 0x3f) == 0 &&
lun[2] == 0 &&
lun[3] == 0 &&
3758 lun[4] == 0 &&
lun[5] == 0 &&
lun[6] == 0 &&
lun[7] == 0)
3762 if (
lun[2] == 0 &&
lun[3] == 0 &&
lun[4] == 0 &&
lun[5] == 0 &&
3763 lun[6] == 0 &&
lun[7] == 0)
3764 result = ((
lun[0] & 0x3f) << 8) +
lun[1];
3774 result = (
lun[1] << 16) + (
lun[2] << 8) +
3778 if (
lun[1] == 0 &&
lun[6] == 0 &&
lun[7] == 0)
3779 result = (
lun[2] << 24) +
3780 (
lun[3] << 16) + (
lun[4] << 8) +
3786 result = 0xffffffff;
3797 uint64_t l = decoded;
3810ctl_ffz(uint32_t *mask, uint32_t first, uint32_t last)
3814 for (i = first; i < last; i++) {
3815 if ((mask[i / 32] & (1 << (i % 32))) == 0)
3824 uint32_t chunk, piece;
3827 piece = bit % (
sizeof(uint32_t) * 8);
3829 if ((mask[chunk] & (1 << piece)) != 0)
3832 mask[chunk] |= (1 << piece);
3840 uint32_t chunk, piece;
3843 piece = bit % (
sizeof(uint32_t) * 8);
3845 if ((mask[chunk] & (1 << piece)) == 0)
3848 mask[chunk] &= ~(1 << piece);
3856 uint32_t chunk, piece;
3859 piece = bit % (
sizeof(uint32_t) * 8);
3861 if ((mask[chunk] & (1 << piece)) == 0)
3896 if (
lun->pr_keys[i] != NULL)
3898 mtx_unlock(&
lun->lun_lock);
3901 mtx_lock(&
lun->lun_lock);
3902 if (
lun->pr_keys[i] == NULL)
3903 lun->pr_keys[i] = p;
3914 KASSERT(t != NULL, (
"prkey %d is not allocated", residx));
3924 uint32_t total_ctl_io,
void **npool)
3928 pool = (
struct ctl_io_pool *)malloc(
sizeof(*pool), M_CTL,
3933 snprintf(pool->
name,
sizeof(pool->
name),
"CTL IO %s", pool_name);
3936 pool->
zone = uma_zsecond_create(pool->
name, NULL,
3955 uma_zdestroy(pool->
zone);
3966 io = uma_zalloc(pool->
zone, M_WAITOK);
3970 TAILQ_INIT(&io->
io_hdr.blocked_queue);
3981 io = uma_zalloc(pool->
zone, M_NOWAIT);
3985 TAILQ_INIT(&io->
io_hdr.blocked_queue);
3999 uma_zfree(pool->
zone, io);
4014 memset(io, 0,
sizeof(*io));
4017 TAILQ_INIT(&io->
io_hdr.blocked_queue);
4027 number = strtoq(buf, &endptr, 0);
4029 switch (tolower((
unsigned char)*endptr)) {
4057 if ((number << shift) >> shift != number) {
4061 *num = number << shift;
4096 (
"subpage %#x for page %#x is incorrect!",
4118 (
"subpage %#x for page %#x is incorrect!",
4159 uint32_t sectors_per_cylinder;
4166 (
"subpage %#x for page %#x is incorrect!",
4204 sectors_per_cylinder;
4206 for (shift = 31; shift > 0; shift--) {
4207 if (sectors_per_cylinder & (1 << shift))
4226 "rpm", NULL)) != NULL) {
4244 (
"subpage %#x for page %#x is incorrect!",
4266 (
"subpage %#x for page %#x is incorrect!",
4280 "writecache", NULL);
4281 if (value != NULL && strcmp(value,
"off") == 0)
4282 caching_page->
flags1 &= ~SCP_WCE;
4285 if (value != NULL && strcmp(value,
"off") == 0)
4295 switch (page_index->
subpage) {
4314 "reordering", NULL);
4315 if (value != NULL &&
4316 strcmp(value,
"unrestricted") == 0) {
4318 ~SCP_QUEUE_ALG_MASK;
4353 panic(
"subpage %#x for page %#x is incorrect!",
4359 switch (page_index->
subpage) {
4390 "avail-threshold", NULL);
4391 if (value != NULL &&
4400 page->descr[0].count);
4403 "used-threshold", NULL);
4404 if (value != NULL &&
4413 page->descr[1].count);
4416 "pool-avail-threshold", NULL);
4417 if (value != NULL &&
4426 page->descr[2].count);
4429 "pool-used-threshold", NULL);
4430 if (value != NULL &&
4439 page->descr[3].count);
4449 panic(
"subpage %#x for page %#x is incorrect!",
4456 (
"subpage %#x for page %#x is incorrect!",
4475 panic(
"invalid page code value %#x",
page_code);
4534hex2bin(
const char *str, uint8_t *buf,
int buf_size)
4539 memset(buf, 0, buf_size);
4540 while (isspace(str[0]))
4542 if (str[0] ==
'0' && (str[1] ==
'x' || str[1] ==
'X'))
4545 for (i = 0; str[i] != 0 && i < buf_size; i++) {
4546 while (str[i] ==
'-')
4551 else if (isalpha(c))
4552 c -= isupper(c) ?
'A' - 10 :
'a' - 10;
4558 buf[i / 2] |= (c << 4);
4562 return ((i + 1) / 2);
4577 const char *eui, *naa, *scsiname, *uuid, *
vendor, *value;
4579 int devidlen, idlen1, idlen2 = 0, len;
4594 lun = malloc(
sizeof(*lun), M_CTL, M_WAITOK | M_ZERO);
4599 M_DEVBUF, M_WAITOK | M_ZERO);
4601 M_DEVBUF, M_WAITOK | M_ZERO);
4606 idlen1 =
sizeof(*t10id) + devidlen;
4608 scsiname = dnvlist_get_string(be_lun->
options,
"scsiname", NULL);
4609 if (scsiname != NULL) {
4610 idlen2 = roundup2(strlen(scsiname) + 1, 4);
4613 eui = dnvlist_get_string(be_lun->
options,
"eui", NULL);
4617 naa = dnvlist_get_string(be_lun->
options,
"naa", NULL);
4621 uuid = dnvlist_get_string(be_lun->
options,
"uuid", NULL);
4626 M_CTL, M_WAITOK | M_ZERO);
4633 if ((vendor = dnvlist_get_string(be_lun->
options,
"vendor", NULL)) == NULL) {
4636 strncpy(t10id->
vendor, vendor,
4637 min(
sizeof(t10id->
vendor), strlen(vendor)));
4641 if (scsiname != NULL) {
4658 (desc->
length > 8 ? 12 : 8);
4659 len -= 16 - desc->
length;
4669 len -= 16 - desc->
length;
4693 printf(
"ctl: requested LUN ID %d is higher "
4694 "than ctl_max_luns - 1 (%d)\n",
4701 printf(
"ctl: requested LUN ID %d is already "
4712 if (lun_number == -1) {
4714 printf(
"ctl: can't allocate LUN, out of LUNs\n");
4721 mtx_init(&lun->
lun_lock,
"CTL LUN", NULL, MTX_DEF);
4722 lun->
lun = lun_number;
4731 be_lun->
lun_id = lun_number;
4742 value = dnvlist_get_string(be_lun->
options,
"removable", NULL);
4743 if (value != NULL) {
4744 if (strcmp(value,
"on") == 0)
4751 lun->last_busy = getsbinuptime();
4753 LIST_INIT(&lun->ooa_queue);
4754 STAILQ_INIT(&lun->error_list);
4777 STAILQ_FOREACH(nlun, &
ctl_softc->lun_list, links) {
4782 STAILQ_INSERT_TAIL(&
ctl_softc->lun_list, lun, links);
4791 printf(
"%s: ctl_enable_lun() failed!\n", __func__);
4816 KASSERT(LIST_EMPTY(&
lun->ooa_queue),
4817 (
"Freeing a LUN %p with outstanding I/O!\n",
lun));
4820 STAILQ_REMOVE(&softc->lun_list,
lun,
ctl_lun, links);
4824 STAILQ_FOREACH(nlun, &softc->lun_list, links) {
4834 lun->be_lun->lun_shutdown(
lun->be_lun);
4836 lun->ie_reportcnt = UINT32_MAX;
4837 callout_drain(&
lun->ie_callout);
4839 mtx_destroy(&
lun->lun_lock);
4840 free(
lun->lun_devid, M_CTL);
4842 free(
lun->pending_ua[i], M_CTL);
4843 free(
lun->pending_ua, M_DEVBUF);
4845 free(
lun->pr_keys[i], M_CTL);
4846 free(
lun->pr_keys, M_DEVBUF);
4847 free(
lun->write_buffer, M_CTL);
4848 free(
lun->prevent, M_CTL);
4866 (
"%s: LUN not disabled", __func__));
4867 lun->
flags &= ~CTL_LUN_DISABLED;
4870 STAILQ_FOREACH_SAFE(port, &softc->port_list, links, nport) {
4884 printf(
"%s: FETD %s port %d returned error "
4885 "%d for lun_enable on lun %jd\n",
4887 retval, (intmax_t)lun->
lun);
4909 (
"%s: LUN not enabled", __func__));
4913 STAILQ_FOREACH(port, &softc->port_list, links) {
4929 printf(
"%s: FETD %s port %d returned error "
4930 "%d for lun_disable on lun %jd\n",
4932 retval, (intmax_t)lun->
lun);
4947 mtx_lock(&
lun->lun_lock);
4948 lun->flags &= ~CTL_LUN_STOPPED;
4949 mtx_unlock(&
lun->lun_lock);
4958 mtx_lock(&
lun->lun_lock);
4960 mtx_unlock(&
lun->lun_lock);
4969 mtx_lock(&
lun->lun_lock);
4971 mtx_unlock(&
lun->lun_lock);
4981 mtx_lock(&
lun->lun_lock);
4985 mtx_unlock(&
lun->lun_lock);
4988 bzero(&msg.ua,
sizeof(msg.ua));
4990 msg.hdr.nexus.initid = -1;
4991 msg.hdr.nexus.targ_port = -1;
4992 msg.hdr.nexus.targ_lun =
lun->lun;
4993 msg.hdr.nexus.targ_mapped_lun =
lun->lun;
5008 mtx_lock(&
lun->lun_lock);
5010 mtx_unlock(&
lun->lun_lock);
5019 mtx_lock(&
lun->lun_lock);
5022 mtx_unlock(&
lun->lun_lock);
5032 mtx_lock(&
lun->lun_lock);
5033 lun->flags &= ~CTL_LUN_PRIMARY_SC;
5035 mtx_unlock(&
lun->lun_lock);
5055 mtx_lock(&
lun->lun_lock);
5063 if (LIST_EMPTY(&
lun->ooa_queue)) {
5064 mtx_unlock(&
lun->lun_lock);
5067 mtx_unlock(&
lun->lun_lock);
5078 mtx_lock(&
lun->lun_lock);
5080 mtx_unlock(&
lun->lun_lock);
5083 bzero(&msg.ua,
sizeof(msg.ua));
5085 msg.hdr.nexus.initid = -1;
5086 msg.hdr.nexus.targ_port = -1;
5087 msg.hdr.nexus.targ_lun =
lun->lun;
5088 msg.hdr.nexus.targ_mapped_lun =
lun->lun;
5108 (
"%s: unexpected I/O type %x", __func__, io->
io_hdr.
io_type));
5266 mtx_lock(&
lun->lun_lock);
5276 lun->flags &= ~CTL_LUN_RESERVED;
5278 mtx_unlock(&
lun->lun_lock);
5303 mtx_lock(&
lun->lun_lock);
5316 lun->res_idx = residx;
5320 mtx_unlock(&
lun->lun_lock);
5423 uint64_t starting_lba;
5424 uint32_t block_count;
5432 switch (ctsio->
cdb[0]) {
5464 if ((starting_lba + block_count) > (lun->
be_lun->
maxlba + 1)) {
5472 lbalen->
lba = starting_lba;
5473 lbalen->
len = block_count;
5474 lbalen->
flags = byte2;
5485 int length, defect_list_len;
5567 uint64_t buffer_offset;
5570 static uint8_t descr[4];
5571 static uint8_t echo_descr[4] = { 0 };
5575 switch (ctsio->
cdb[0]) {
5616 len = min(len,
sizeof(descr));
5619 len = min(len,
sizeof(echo_descr));
5642 int buffer_offset, len;
5700 lbalen->
lba += lbalen->
len;
5718 uint32_t num_blocks;
5724 switch (ctsio->
cdb[0]) {
5772 || ((lba + num_blocks) < lba)) {
5780 if (num_blocks == 0) {
5783 "write_same_max_lba", NULL);
5797 num_blocks = 1 << 31;
5824 lbalen->
len = num_blocks;
5825 lbalen->
flags = byte2;
5840 uint32_t num_blocks;
5869 if (len <
sizeof (*hdr) ||
5883 end = buf + len /
sizeof(*buf);
5886 for (range = buf; range < end; range++) {
5890 || ((
lba + num_blocks) <
lba)) {
5896 if (num_blocks != 0)
5904 len = (uint8_t *)endnz - (uint8_t *)buf;
5913 ptrlen->
ptr = (
void *)buf;
5915 ptrlen->
flags = byte2;
5936 uint8_t *current_cp;
5946 mtx_lock(&
lun->lun_lock);
5947 if (memcmp(current_cp, page_ptr, page_index->
page_len)) {
5948 memcpy(current_cp, page_ptr, page_index->
page_len);
5953 mtx_unlock(&
lun->lun_lock);
5968 if (
lun->ie_asc == 0)
5974 lun->ie_reported = 0;
5977 lun->ie_reportcnt++;
5979 if (t == 0 || t == UINT32_MAX)
5981 callout_schedule_sbt(&
lun->ie_callout, SBT_1S / 10 * t,
6012 if (t == 0 || t == UINT32_MAX)
6014 callout_reset_sbt(&lun->
ie_callout, SBT_1S / 10 * t,
6036 int page_len, page_len_offset, page_len_size;
6038 uint16_t *len_left, *len_used;
6055 if (*len_left == 0) {
6137 page_len_offset = 2;
6141 page_len_offset = 1;
6149 if (page_len != page_index->
page_len - page_len_offset - page_len_size) {
6153 *len_used + page_len_offset,
6160 if (*len_left < page_index->page_len) {
6171 for (i = 0; i < page_index->
page_len; i++) {
6172 uint8_t *user_byte, *change_mask, *current_byte;
6176 user_byte = (uint8_t *)page_header + i;
6186 if ((*user_byte & ~(*change_mask)) ==
6187 (*current_byte & ~(*change_mask)))
6194 for (j = 7; j >= 0; j--) {
6195 if ((((1 << i) & ~(*change_mask)) & *user_byte) !=
6196 (((1 << i) & ~(*change_mask)) & *current_byte)) {
6221 (uint8_t *)page_header);
6232 goto bailout_no_done;
6255 int bd_len, i, header_size, param_len, rtd;
6259 switch (ctsio->
cdb[0]) {
6287 if (param_len != 0) {
6315 if (param_len == 0) {
6325 if (param_len < header_size) {
6350 switch (ctsio->
cdb[0]) {
6366 panic(
"%s: Invalid CDB type %#x", __func__, ctsio->
cdb[0]);
6369 if (param_len < (header_size + bd_len)) {
6387 memset(modepage_info, 0,
sizeof(*modepage_info));
6388 modepage_info->
header.
len_left = param_len - header_size - bd_len;
6398 int pc, page_code, llba, subpage;
6399 int alloc_len, page_len, header_len, bd_len, total_len;
6407 switch (ctsio->
cdb[0]) {
6418 header_len += bd_len;
6442 header_len += bd_len;
6462 switch (page_code) {
6502 if ((page_index->
subpage != 0)
6534 if ((page_index->
subpage != subpage)
6541 if (page_len == 0) {
6555 total_len = header_len + page_len;
6557 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
6563 switch (ctsio->
cdb[0]) {
6569 header->
datalen = MIN(total_len - 1, 254);
6573 (lun->MODE_CTRL.eca_and_aen &
SCP_SWP) != 0)
6577 block_desc = &header[1];
6586 datalen = MIN(total_len - 2, 65533);
6591 (lun->MODE_CTRL.eca_and_aen &
SCP_SWP) != 0)
6597 block_desc = &header[1];
6601 panic(
"%s: Invalid CDB type %#x", __func__, ctsio->
cdb[0]);
6631 switch (page_code) {
6635 data_used = header_len;
6656 if ((page_index->
subpage != 0)
6678 data_used = header_len;
6744 if ((value = dnvlist_get_string(lun->
be_lun->
options,
"temperature",
6755 if ((value = dnvlist_get_string(lun->
be_lun->
options,
"reftemperature",
6782 data = (uint8_t *)(phdr + 1);
6795 data = (uint8_t *)(phdr + 1);
6808 data = (uint8_t *)(phdr + 1);
6821 data = (uint8_t *)(phdr + 1);
6837 struct stat_page *data;
6840 data = (
struct stat_page *)page_index->
page_data;
6843 data->sap.hdr.param_control =
SLP_LBIN;
6847 data->sap.read_num);
6849 data->sap.write_num);
6857 scsi_u64to8b((uint64_t)t->sec * 1000 + t->frac / (UINT64_MAX / 1000),
6858 data->sap.read_int);
6860 scsi_u64to8b((uint64_t)t->sec * 1000 + t->frac / (UINT64_MAX / 1000),
6861 data->sap.write_int);
6865 data->it.hdr.param_control =
SLP_LBIN;
6869 scsi_u64to8b(lun->idle_time / SBT_1MS, data->it.idle_int);
6872 data->it.hdr.param_control =
SLP_LBIN;
6897 if ((value = dnvlist_get_string(lun->
be_lun->
options,
"temperature",
6909 int i, pc, page_code, subpage;
6910 int alloc_len, total_len;
6950 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7007 ctsio->
kern_data_ptr = malloc(
sizeof(*data), M_CTL, M_WAITOK | M_ZERO);
7064 ctsio->
kern_data_ptr = malloc(
sizeof(*data), M_CTL, M_WAITOK | M_ZERO);
7094 uint32_t alloc_len, total_len;
7109 total_len =
sizeof(*data) +
sizeof(data->
descr[0]);
7110 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7130 lbalen->
len = total_len;
7143 uint32_t alloc_len, data_len;
7152 data_len =
sizeof(*data10);
7157 data_len =
sizeof(*data12);
7159 if (alloc_len == 0) {
7165 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
7198 const char *oii, *otii;
7199 int retval, alloc_len, total_len = 0, len = 0;
7207 switch (cdb->
type) {
7210 "ident_info", NULL);
7216 "text_ident_info", NULL);
7218 len = strlen(otii) + 1;
7236 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7243 switch (cdb->
type) {
7246 if (oii[0] ==
'0' && oii[1] ==
'x')
7247 len =
hex2bin(oii, (uint8_t *)(rii_ptr + 1), len);
7249 strncpy((uint8_t *)(rii_ptr + 1), oii, len);
7254 strlcpy((uint8_t *)(rii_ptr + 1), otii, len);
7280 int alloc_len, ext, total_len = 0, g, pc, pg, ts, os;
7281 int num_ha_groups, num_target_ports, shared_group;
7310 num_target_ports = 0;
7313 STAILQ_FOREACH(port, &softc->port_list, links) {
7330 (shared_group + num_ha_groups) +
7335 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7347 tpg_desc = &rtg_ext_ptr->
groups[0];
7352 tpg_desc = &rtg_ptr->
groups[0];
7392 STAILQ_FOREACH(port, &softc->port_list, links) {
7401 relative_target_port_identifier);
7408 for (g = 0; g < num_ha_groups; g++) {
7415 STAILQ_FOREACH(port, &softc->port_list, links) {
7426 relative_target_port_identifier);
7452 int alloc_len, total_len;
7453 int opcode, service_action, i, j, num;
7465 for (i = 0; i < 256; i++) {
7468 for (j = 0; j < 32; j++) {
7499 service_action >= 32) {
7526 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7537 for (i = 0; i < 256; i++) {
7540 for (j = 0; j < 32; j++) {
7546 descr = &all->
descr[num++];
7557 descr = &all->
descr[num++];
7578 entry->
execute)[service_action];
7595 entry->
execute)[service_action];
7596 }
else if (service_action != 0) {
7616 int alloc_len, total_len;
7630 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7640 data->
length = total_len - 4;
7657 int alloc_len, total_len;
7668 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7678 timestamp = (int64_t)tv.tv_sec * 1000 + tv.tv_usec / 1000;
7695 int alloc_len, total_len = 0;
7728 panic(
"%s: Invalid PR type %#x", __func__, cdb->
action);
7732 ctsio->
kern_data_ptr = malloc(total_len, M_CTL, M_WAITOK | M_ZERO);
7758 printf(
"%s: reservation length changed, retrying\n",
7790 int tmp_len, header_only;
7815 if (tmp_len != total_len) {
7818 printf(
"%s: reservation status changed, retrying\n",
7826 if (header_only != 0)
7878 printf(
"%s: reservation length changed, retrying\n",
7885 res_desc = &res_status->
desc[0];
7914 panic(
"%s: Invalid PR type %#x", __func__, cdb->
action);
7931 uint64_t sa_res_key, uint8_t type, uint32_t residx,
7938 mtx_lock(&
lun->lun_lock);
7939 if (sa_res_key == 0) {
7944 mtx_unlock(&
lun->lun_lock);
7955 if (type>8 || type==2 || type==4 || type==0) {
7956 mtx_unlock(&
lun->lun_lock);
7984 mtx_unlock(&
lun->lun_lock);
7996 sizeof(persis_io.
pr), M_WAITOK);
7999 mtx_unlock(&
lun->lun_lock);
8014 if (res_key == sa_res_key) {
8025 mtx_unlock(&
lun->lun_lock);
8047 mtx_unlock(&
lun->lun_lock);
8054 mtx_unlock(&
lun->lun_lock);
8066 sizeof(persis_io.
pr), M_WAITOK);
8074 mtx_unlock(&
lun->lun_lock);
8085 if (type>8 || type==2 || type==4 || type==0) {
8086 mtx_unlock(&
lun->lun_lock);
8132 mtx_unlock(&
lun->lun_lock);
8143 sizeof(persis_io.
pr), M_WAITOK);
8162 mtx_unlock(&
lun->lun_lock);
8169 mtx_unlock(&
lun->lun_lock);
8180 sizeof(persis_io.
pr), M_WAITOK);
8189 uint64_t sa_res_key;
8197 if (sa_res_key == 0) {
8259 u_int32_t param_len;
8263 uint64_t
res_key, sa_res_key, key;
8293 if (type>8 || type==2 || type==4 || type==0) {
8405 if (sa_res_key == 0) {
8418 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8432 for (i = softc->
init_min; i < softc->init_max; i++){
8442 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8455 sizeof(persis_io.
pr), M_WAITOK);
8476 sizeof(persis_io.
pr), M_WAITOK);
8522 sizeof(persis_io.
pr), M_WAITOK);
8555 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8564 (lun->MODE_CTRL.queue_flags &
SCP_NUAR) == 0) {
8565 for (i = softc->
init_min; i < softc->init_max; i++) {
8578 sizeof(persis_io.
pr), M_WAITOK);
8585 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8603 sizeof(persis_io.
pr), M_WAITOK);
8611 residx, ctsio, cdb, param);
8617 panic(
"%s: Invalid PR type %#x", __func__, cdb->
action);
8641 uint32_t residx, targ_lun;
8650 mtx_lock(&
lun->lun_lock);
8653 mtx_unlock(&
lun->lun_lock);
8674 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8688 for (i = softc->
init_min; i < softc->init_max; i++) {
8698 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8721 for (i = softc->
init_min; i < softc->init_max; i++) {
8728 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8737 lun->
flags &= ~CTL_LUN_PR_RESERVED;
8752 mtx_unlock(&
lun->lun_lock);
8761 uint32_t num_blocks;
8770 switch (ctsio->
cdb[0]) {
8780 num_blocks = cdb->
length;
8784 if (num_blocks == 0)
8904 || ((lba + num_blocks) < lba)) {
8916 if (num_blocks == 0) {
8924 if ((lun->MODE_CACHING.flags1 &
SCP_RCD) != 0)
8927 if ((lun->MODE_CACHING.flags1 &
SCP_WCE) == 0)
8934 lbalen->
len = num_blocks;
8973 uint32_t num_blocks;
8979 switch (ctsio->
cdb[0]) {
8989 num_blocks = cdb->
length;
9011 || ((lba + num_blocks) < lba)) {
9021 if (num_blocks == 0) {
9028 if ((lun->MODE_CACHING.flags1 &
SCP_WCE) == 0)
9045 lbalen->
len = num_blocks;
9059 uint32_t num_blocks;
9067 switch (ctsio->
cdb[0]) {
9121 || ((lba + num_blocks) < lba)) {
9131 if (num_blocks == 0) {
9140 lbalen->
len = num_blocks;
9163 int num_filled, num_luns, num_port_luns, retval;
9164 uint32_t alloc_len, lun_datalen;
9165 uint32_t initidx, targ_lun_id, lun_id;
9175 for (targ_lun_id = 0; targ_lun_id < num_port_luns; targ_lun_id++) {
9221 lun_datalen =
sizeof(*lun_data) +
9224 ctsio->
kern_data_ptr = malloc(lun_datalen, M_CTL, M_WAITOK | M_ZERO);
9231 for (targ_lun_id = 0, num_filled = 0;
9232 targ_lun_id < num_port_luns && num_filled < num_luns;
9235 if (lun_id == UINT32_MAX)
9260 if (request_lun != NULL) {
9272 lun_datalen =
sizeof(*lun_data) +
9311 uint8_t asc = 0, ascq = 0;
9325 ctsio->
kern_data_ptr = malloc(
sizeof(*sense_ptr), M_CTL, M_WAITOK);
9392 memcpy(sense_ptr, ps,
sizeof(*sense_ptr));
9397 ua_type =
ctl_build_ua(lun, initidx, sense_ptr, &sense_len,
9402 if (have_error == 0) {
9456 ctsio->
kern_data_ptr = malloc(sup_page_size, M_CTL, M_WAITOK | M_ZERO);
9519 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
9567 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
9633 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
9688 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
9787 int data_len, num_target_ports, iid_len, id_len;
9789 num_target_ports = 0;
9793 STAILQ_FOREACH(port, &softc->port_list, links) {
9810 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
9835 STAILQ_FOREACH(port, &softc->port_list, links) {
9875 int sfs_page_size, n;
9877 sfs_page_size =
sizeof(*sfs_ptr) + 5 * 2;
9878 ctsio->
kern_data_ptr = malloc(sfs_page_size, M_CTL, M_WAITOK | M_ZERO);
9930 ctsio->
kern_data_ptr = malloc(
sizeof(*bl_ptr), M_CTL, M_WAITOK | M_ZERO);
9958 "unmap_max_lba", NULL);
9964 "unmap_max_descr", NULL);
9983 "write_same_max_lba", NULL);
10006 ctsio->
kern_data_ptr = malloc(
sizeof(*bdc_ptr), M_CTL, M_WAITOK | M_ZERO);
10026 (value = dnvlist_get_string(lun->
be_lun->
options,
"rpm", NULL)) != NULL)
10027 i = strtol(value, NULL, 0);
10032 (value = dnvlist_get_string(lun->
be_lun->
options,
"formfactor", NULL)) != NULL)
10033 i = strtol(value, NULL, 0);
10053 ctsio->
kern_data_ptr = malloc(
sizeof(*lbp_ptr), M_CTL, M_WAITOK | M_ZERO);
10078 "provisioning_type", NULL);
10079 if (value != NULL) {
10080 if (strcmp(value,
"resource") == 0)
10082 else if (strcmp(value,
"thin") == 0)
10103 int alloc_len, retval;
10176 uint32_t alloc_len, data_len;
10192 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
10253 if (lun == NULL || (val = dnvlist_get_string(lun->
be_lun->
options,
10254 "vendor", NULL)) == NULL) {
10257 memset(inq_ptr->
vendor,
' ',
sizeof(inq_ptr->
vendor));
10258 strncpy(inq_ptr->
vendor, val,
10259 min(
sizeof(inq_ptr->
vendor), strlen(val)));
10264 }
else if ((val = dnvlist_get_string(lun->
be_lun->
options,
"product",
10286 strncpy(inq_ptr->
product, val,
10287 min(
sizeof(inq_ptr->
product), strlen(val)));
10294 if (lun == NULL || (val = dnvlist_get_string(lun->
be_lun->
options,
10295 "revision", NULL)) == NULL) {
10300 min(
sizeof(inq_ptr->
revision), strlen(val)));
10395 uint32_t alloc_len, data_len;
10416 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
10427 if (starting > 0x003b)
10429 if (starting > 0x003a)
10431 if (starting > 0x002b)
10433 if (starting > 0x002a)
10435 if (starting > 0x001f)
10437 if (starting > 0x001e)
10439 if (starting > 0x001d)
10441 if (starting > 0x0010)
10443 if (starting > 0x0003)
10445 if (starting > 0x0002)
10447 if (starting > 0x0001)
10449 if (starting > 0x0000)
10493 feature->
flags = 0x00;
10505 feature->
flags = 0x00;
10514 feature->
flags = 0x00;
10524 feature->
flags = 0x08;
10535 feature->
flags = 0x04;
10546 feature->
flags = 0x00;
10556 feature->
flags = 0x00;
10567 feature->
flags = 0x00;
10576 data_len = (uint8_t *)feature - (uint8_t *)hdr;
10582 data_len = (uint8_t *)feature - (uint8_t *)hdr;
10600 uint32_t alloc_len, data_len;
10612 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
10635 uint32_t alloc_len, data_len;
10641 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
10667 buf[1] = bin2bcd((
lba / 75) / 60);
10668 buf[2] = bin2bcd((
lba / 75) % 60);
10669 buf[3] = bin2bcd(
lba % 75);
10692 ctsio->
kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
10745 (
"%s: unexpected I/O type %x", __func__, io->
io_hdr.
io_type));
10906 uint64_t endlba1, endlba2;
10908 endlba1 = lba1 + len1 - (seq ? 0 : 1);
10909 endlba2 = lba2 + len2 - 1;
10911 if ((endlba1 < lba2) || (endlba2 < lba1))
10926 (
"%s: unexpected I/O type %x", __func__, io->
io_hdr.
io_type));
10936 ptrlen->
ptr == NULL)
10941 end = buf + ptrlen->
len /
sizeof(*buf);
10942 for (range = buf; range < end; range++) {
10945 if ((
lba < lba2 + len2) && (
lba + len > lba2))
10954 uint64_t lba1, lba2;
10955 uint64_t len1, len2;
10959 KASSERT(retval == 0, (
"ctl_get_lba_len() error"));
10966 KASSERT(retval == 0, (
"ctl_get_lba_len() error"));
10976 uint64_t lba1, lba2;
10977 uint64_t len1, len2;
10978 int retval __diagused;
10983 KASSERT(retval == 0, (
"ctl_get_lba_len() error"));
10985 KASSERT(retval == 0, (
"ctl_get_lba_len() error"));
10987 if (lba1 + len1 == lba2)
10994 const uint8_t *serialize_row,
union ctl_io *ooa_io)
11086 __assert_unreachable();
11098 union ctl_io **starting_io)
11100 union ctl_io *ooa_io = *starting_io;
11101 const uint8_t *serialize_row;
11104 mtx_assert(&lun->
lun_lock, MA_OWNED);
11131 for (; ooa_io != NULL;
11132 ooa_io = (
union ctl_io *)LIST_NEXT(&ooa_io->
io_hdr, ooa_links)) {
11136 *starting_io = ooa_io;
11141 *starting_io = NULL;
11156 union ctl_io *bio, *obio;
11161 mtx_assert(&
lun->lun_lock, MA_OWNED);
11168 bio = (
union ctl_io *)LIST_NEXT(&bio->
io_hdr, ooa_links);
11173 TAILQ_REMOVE(&obio->
io_hdr.blocked_queue,
11174 &io->
io_hdr, blocked_links);
11175 TAILQ_INSERT_TAIL(&bio->
io_hdr.blocked_queue,
11176 &io->
io_hdr, blocked_links);
11183 TAILQ_REMOVE(&obio->
io_hdr.blocked_queue, &io->
io_hdr, blocked_links);
11198 sizeof(msg_info.
hdr), M_NOWAIT);
11217 __assert_unreachable();
11229 LIST_REMOVE(&io->
io_hdr, ooa_links);
11236 sizeof(msg_info.
scsi), M_WAITOK);
11257 union ctl_io *io, *next_io;
11259 mtx_assert(&lun->
lun_lock, MA_OWNED);
11261 for (io = (
union ctl_io *)TAILQ_FIRST(&bio->
io_hdr.blocked_queue);
11262 io != NULL; io = next_io) {
11263 next_io = (
union ctl_io *)TAILQ_NEXT(&io->
io_hdr, blocked_links);
11266 (
"I/O %p on blocked list without blocker", io));
11269 KASSERT(!skip || TAILQ_EMPTY(&bio->
io_hdr.blocked_queue),
11270 (
"blocked_queue is not empty after skipping %p", bio));
11295 mtx_assert(&lun->
lun_lock, MA_OWNED);
11332 if ((lun->MODE_CTRL.eca_and_aen &
SCP_SWP) != 0) {
11349 if (lun->
res_idx != residx) {
11419 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
11431 LIST_FOREACH_SAFE(io, &lun->ooa_queue, ooa_links, next_io) {
11438 (
union ctl_io *)io, FALSE);
11441 io->
flags &= ~CTL_FLAG_DMA_INPROG;
11449 io->
flags &= ~CTL_FLAG_SENT_2OTHER_SC;
11460 LIST_FOREACH_SAFE(io, &lun->ooa_queue, ooa_links, next_io) {
11465 io, blocked_links);
11470 LIST_REMOVE(io, ooa_links);
11475 io->
flags &= ~CTL_FLAG_SENT_2OTHER_SC;
11494 uint32_t initidx, targ_lun;
11521 if (LIST_EMPTY(&lun->ooa_queue))
11522 lun->idle_time += getsbinuptime() - lun->last_busy;
11524 LIST_INSERT_HEAD(&lun->ooa_queue, &ctsio->
io_hdr, ooa_links);
11529 if (entry == NULL) {
11554 CTL_DEBUG_PRINT((
"ctl_scsiio_precheck: bailing out due to invalid LUN\n"));
11609 u_int sense_len = 0;
11646 mtx_unlock(&
lun->lun_lock);
11668 bio = (
union ctl_io *)LIST_NEXT(&ctsio->
io_hdr, ooa_links);
11678 TAILQ_INSERT_TAIL(&bio->
io_hdr.blocked_queue, &ctsio->
io_hdr,
11693 __assert_unreachable();
11701 int service_action;
11709 entry->
execute)[service_action];
11723 if (entry->
execute == NULL) {
11736 KASSERT(entry->
length > 0,
11737 (
"Not defined length for command 0x%02x/0x%02x",
11738 ctsio->
cdb[0], ctsio->
cdb[1]));
11739 for (i = 1; i < entry->
length; i++) {
11740 diff = ctsio->
cdb[i] & ~entry->usage[i - 1];
11759 switch (lun_type) {
11803 retval = entry->
execute(ctsio);
11827 sizeof(msg_info.
task), M_WAITOK);
11836 STAILQ_FOREACH(
lun, &softc->lun_list, links) {
11837 if (
port != NULL &&
11876 LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) {
11886 lun->
flags &= ~CTL_LUN_RESERVED;
11909 uint32_t targ_lun, initidx;
11933 sizeof(msg_info.
task), M_WAITOK);
11944 mtx_assert(&lun->
lun_lock, MA_OWNED);
11953 LIST_FOREACH(xioh, &lun->ooa_queue, ooa_links) {
11955 if ((targ_port == UINT32_MAX ||
11957 (init_id == UINT32_MAX ||
11974 sizeof(msg_info.
task), M_NOWAIT);
12000 mtx_lock(&
lun->lun_lock);
12010 mtx_unlock(&
lun->lun_lock);
12026 STAILQ_FOREACH(lun, &softc->lun_list, links) {
12036 lun->
flags &= ~CTL_LUN_RESERVED;
12066 sizeof(msg_info.
task), M_WAITOK);
12095 mtx_lock(&
lun->lun_lock);
12104 LIST_FOREACH(xioh, &
lun->ooa_queue, ooa_links) {
12146 sizeof(msg_info.
task), M_NOWAIT);
12151 mtx_unlock(&
lun->lun_lock);
12173 mtx_lock(&
lun->lun_lock);
12175 LIST_FOREACH(xioh, &
lun->ooa_queue, ooa_links) {
12201 uint32_t targ_lun, initidx;
12211 mtx_lock(&
lun->lun_lock);
12215 mtx_unlock(&
lun->lun_lock);
12230 (
"ctl_run_task: Unextected io_type %d\n", io->
io_hdr.
io_type));
12267 printf(
"%s: got unknown task management event %d\n",
12298 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
12318 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
12324 LIST_REMOVE(&io->
io_hdr, ooa_links);
12346 printf(
"%s: Invalid message type %d\n",
12417 return (filtered_pattern);
12425 mtx_assert(&lun->
lun_lock, MA_OWNED);
12427 STAILQ_FOREACH_SAFE(desc, &lun->error_list, links, desc2) {
12471 desc->
lun_error &= ~CTL_LUN_INJ_CONTINUOUS;
12488ctl_datamove_timer_wakeup(
void *arg)
12492 io = (
union ctl_io *)arg;
12502 struct bintime cur_bt;
12506 (
"%s: unexpected I/O type %x", __func__, io->
io_hdr.
io_type));
12509 getbinuptime(&cur_bt);
12540 void (*fe_datamove)(
union ctl_io *io);
12561 && (
lun->delay_info.datamove_delay > 0)) {
12562 callout_init(&io->
io_hdr.delay_callout, 1);
12564 callout_reset(&io->
io_hdr.delay_callout,
12565 lun->delay_info.datamove_delay * hz,
12566 ctl_datamove_timer_wakeup, io);
12567 if (
lun->delay_info.datamove_type ==
12569 lun->delay_info.datamove_delay = 0;
12580 printf(
"ctl_datamove: tag 0x%04x on (%u:%u:%u) aborted\n",
12597 fe_datamove =
CTL_PORT(io)->fe_datamove;
12606 struct bintime cur_bt;
12609 memset(&msg, 0,
sizeof(msg));
12633 getbinuptime(&cur_bt);
12653 printf(
"%s: ISC DMA write failed with error %d", __func__,
12693 void (*fe_datamove)(
union ctl_io *io);
12714 fe_datamove =
CTL_PORT(io)->fe_datamove;
12742 void (*fe_datamove)(
union ctl_io *io);
12747 printf(
"%s: ISC DMA read failed with error %d\n", __func__,
12767 fe_datamove =
CTL_PORT(io)->fe_datamove;
12775 uint32_t len_to_go;
12789 for (i = 0; len_to_go > 0; i++) {
12791 local_sglist[i].
addr =
12792 malloc(local_sglist[i].
len, M_CTL, M_WAITOK);
12794 len_to_go -= local_sglist[i].
len;
12811 uint32_t local_used, remote_used, total_used;
12872 cur_len = MIN(local_sglist[i].
len - local_used,
12873 remote_sglist[j].
len - remote_used);
12874 rq->
size = cur_len;
12876 tmp_ptr = (uint8_t *)local_sglist[i].
addr;
12877 tmp_ptr += local_used;
12883 rq->
local = vtophys(tmp_ptr);
12885 rq->
local = tmp_ptr;
12888 (
"HA does not support BUS_ADDR"));
12889 rq->
local = tmp_ptr;
12892 tmp_ptr = (uint8_t *)remote_sglist[j].
addr;
12893 tmp_ptr += remote_used;
12898 local_used += cur_len;
12899 if (local_used >= local_sglist[i].
len) {
12904 remote_used += cur_len;
12905 if (remote_used >= remote_sglist[j].
len) {
12909 total_used += cur_len;
12982 printf(
"%s: tag 0x%04x on (%u:%u:%u) aborted\n", __func__,
13007 void (*fe_done)(
union ctl_io *io);
13011 fe_done =
port->fe_done;
13020 sbuf_new(&sb, str,
sizeof(str), SBUF_FIXEDLEN);
13022 sbuf_cat(&sb, path_str);
13026 sbuf_printf(&sb,
"\n");
13027 sbuf_cat(&sb, path_str);
13028 sbuf_printf(&sb,
"Tag: 0x%04x/%d, Prio: %d\n",
13033 sbuf_printf(&sb,
"Task Action: %d Tag: 0x%04x/%d\n",
13038 panic(
"%s: Invalid CTL I/O type %d\n",
13041 sbuf_cat(&sb, path_str);
13042 sbuf_printf(&sb,
"ctl_process_done: %jd seconds\n",
13045 printf(
"%s", sbuf_data(&sb));
13058 panic(
"%s: Invalid CTL I/O type %d\n",
13078 uint8_t mrie = lun->MODE_IE.mrie;
13079 uint8_t per = ((lun->MODE_RWER.byte3 &
SMS_RWER_PER) ||
13102 if (!STAILQ_EMPTY(&lun->error_list) &&
13136 bintime_add(&lun->
stats.
time[type], &bt);
13145 bintime_add(&port->
stats.
time[type], &bt);
13160 LIST_REMOVE(&io->
io_hdr, ooa_links);
13162 if (LIST_EMPTY(&lun->ooa_queue))
13163 lun->last_busy = getsbinuptime();
13171 && LIST_EMPTY(&lun->ooa_queue)) {
13201 memset(&msg, 0,
sizeof(msg));
13224 uint32_t initidx, p, targ_lun;
13240 (lun = softc->
ctl_luns[targ_lun]) == NULL) {
13251 M_CTL, M_NOWAIT | M_ZERO);
13255 memset(ps, 0,
sizeof(*ps));
13293 printf(
"ctl_queue: unknown I/O type %d\n", io->
io_hdr.
io_type);
13328 printf(
"ctl_run: unknown I/O type %d\n", io->
io_hdr.
io_type);
13337ctl_done_timer_wakeup(
void *arg)
13341 io = (
union ctl_io *)arg;
13352 if (!TAILQ_EMPTY(&io->
io_hdr.blocked_queue)) {
13353 mtx_lock(&
lun->lun_lock);
13356 mtx_unlock(&
lun->lun_lock);
13370 printf(
"%s: type %d msg %d cdb %x iptl: "
13371 "%u:%u:%u tag 0x%04x "
13372 "flag %#x status %x\n",
13404 && (
lun->delay_info.done_delay > 0)) {
13405 callout_init(&io->
io_hdr.delay_callout, 1);
13407 callout_reset(&io->
io_hdr.delay_callout,
13408 lun->delay_info.done_delay * hz,
13409 ctl_done_timer_wakeup, io);
13411 lun->delay_info.done_delay = 0;
13429 thread_lock(curthread);
13430 sched_prio(curthread, PUSER - 1);
13431 thread_unlock(curthread);
13445 io = (
union ctl_io *)STAILQ_FIRST(&thr->isc_queue);
13447 STAILQ_REMOVE_HEAD(&thr->isc_queue, links);
13452 io = (
union ctl_io *)STAILQ_FIRST(&thr->done_queue);
13454 STAILQ_REMOVE_HEAD(&thr->done_queue, links);
13460 io = (
union ctl_io *)STAILQ_FIRST(&thr->incoming_queue);
13462 STAILQ_REMOVE_HEAD(&thr->incoming_queue, links);
13470 io = (
union ctl_io *)STAILQ_FIRST(&thr->rtr_queue);
13472 STAILQ_REMOVE_HEAD(&thr->rtr_queue, links);
13481 mtx_sleep(thr, &thr->
queue_lock, PDROP,
"-", 0);
13495 uint64_t thres, val;
13499 thread_lock(curthread);
13500 sched_prio(curthread, PUSER - 1);
13501 thread_unlock(curthread);
13505 STAILQ_FOREACH(
lun, &softc->lun_list, links) {
13508 lun->backend->lun_attr == NULL)
13516 page = &
lun->MODE_LBP;
13524 attr =
"blocksavail";
13527 attr =
"blocksused";
13530 attr =
"poolblocksavail";
13533 attr =
"poolblocksused";
13539 val =
lun->backend->lun_attr(
lun->be_lun, attr);
13541 if (val == UINT64_MAX)
13545 e = (val >= thres);
13547 e = (val <= thres);
13551 mtx_lock(&
lun->lun_lock);
13554 (uint8_t *)page,
lun->ua_tpt_info);
13555 if (
lun->lasttpt == 0 ||
13557 lun->lasttpt = time_uptime;
13567 mtx_unlock(&
lun->lun_lock);
13571 bzero(&msg.
ua,
sizeof(msg.
ua));
13583 sizeof(msg.
ua), M_WAITOK);
13605 STAILQ_INSERT_TAIL(&thr->incoming_queue, &io->
io_hdr, links);
13618 STAILQ_INSERT_TAIL(&thr->rtr_queue, &io->
io_hdr, links);
13631 STAILQ_INSERT_TAIL(&thr->done_queue, &io->
io_hdr, links);
13644 STAILQ_INSERT_TAIL(&thr->isc_queue, &io->
io_hdr, links);
static void ctl_enqueue_incoming(union ctl_io *io)
void ctl_est_ua(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua)
static void ctl_abort_tasks_lun(struct ctl_lun *lun, uint32_t targ_port, uint32_t init_id, int other_sc)
static const struct scsi_caching_page caching_page_default
static int ctl_inquiry_evpd_eid(struct ctl_scsiio *ctsio, int alloc_len)
static int ctl_scsiio(struct ctl_scsiio *ctsio)
static int hex2bin(const char *str, uint8_t *buf, int buf_size)
int ctl_add_lun(struct ctl_be_lun *be_lun)
static ctl_action ctl_seq_check(union ctl_io *io1, union ctl_io *io2)
int ctl_lun_map_set(struct ctl_port *port, uint32_t plun, uint32_t glun)
#define SCSI_EVPD_NUM_SUPPORTED_PAGES
static int ctl_datamove_remote_sgl_setup(union ctl_io *io)
void ctl_est_ua_port(struct ctl_lun *lun, int port, uint32_t except, ctl_ua_type ua)
static const struct scsi_info_exceptions_page ie_page_default
uint32_t ctl_lun_map_to_port(struct ctl_port *port, uint32_t lun_id)
int ctl_start_lun(struct ctl_be_lun *be_lun)
int ctl_get_lba_status(struct ctl_scsiio *ctsio)
uint32_t ctl_decode_lun(uint64_t encoded)
#define CTL_MAX_INITIATORS
static void ctl_ie_timer(void *arg)
int ctl_report_tagret_port_groups(struct ctl_scsiio *ctsio)
int ctl_config_move_done(union ctl_io *io, bool samethr)
static void ctl_datamove_remote(union ctl_io *io)
int ctl_prevent_allow(struct ctl_scsiio *ctsio)
static int ctl_inquiry_evpd_sfs(struct ctl_scsiio *ctsio, int alloc_len)
void ctl_free_io(union ctl_io *io)
int ctl_request_sense(struct ctl_scsiio *ctsio)
int ctl_ie_page_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, uint8_t *page_ptr)
static const struct scsi_cddvd_capabilities_page cddvd_page_default
void ctl_serseq_done(union ctl_io *io)
struct ctl_softc * control_softc
static int ctl_extent_check_unmap(union ctl_io *io, uint64_t lba2, uint64_t len2)
static ctl_action ctl_check_for_blockage(struct ctl_lun *lun, union ctl_io *pending_io, const uint8_t *serialize_row, union ctl_io *ooa_io)
static int ctl_module_event_handler(module_t, int, void *)
static void ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua_type)
static void ctl_alloc_prkey(struct ctl_lun *lun, uint32_t residx)
static int ctl_abort_task_set(union ctl_io *io)
int ctl_report_supported_opcodes(struct ctl_scsiio *ctsio)
static int ctl_query_async_event(union ctl_io *io)
static const struct scsi_control_ext_page control_ext_page_changeable
union ctl_io * ctl_alloc_io_nowait(void *pool_ref)
int ctl_write_same(struct ctl_scsiio *ctsio)
static ctl_action ctl_extent_check_lba(uint64_t lba1, uint64_t len1, uint64_t lba2, uint64_t len2, bool seq)
static void ctl_run_task(union ctl_io *io)
int ctl_remove_initiator(struct ctl_port *port, int iid)
static int ctl_init_page_index(struct ctl_lun *lun)
static void ctl_datamove_remote_write_cb(struct ctl_ha_dt_req *rq)
int ctl_report_ident_info(struct ctl_scsiio *ctsio)
int ctl_lun_no_media(struct ctl_be_lun *be_lun)
static int ctl_ha_init(void)
void ctl_clr_ua(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua)
int ctl_lbp_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc)
static const struct scsi_control_page control_page_default
static ctl_lun_error_pattern ctl_cmd_pattern_match(struct ctl_scsiio *ctsio, struct ctl_error_desc *desc)
int ctl_lun_map_init(struct ctl_port *port)
static const struct ctl_cmd_entry * ctl_get_cmd_entry(struct ctl_scsiio *ctsio, int *sa)
void ctl_datamove(union ctl_io *io)
static int ctl_get_lba_len(union ctl_io *io, uint64_t *lba, uint64_t *len)
static int ctl_write_same_cont(union ctl_io *io)
static int ctl_ha_shutdown(void)
static const struct ctl_logical_block_provisioning_page lbp_page_default
int ctl_lun_map_deinit(struct ctl_port *port)
static void ctl_try_unblock_io(struct ctl_lun *lun, union ctl_io *io, bool skip)
static int ctl_do_mode_select(union ctl_io *io)
void ctl_isc_announce_mode(struct ctl_lun *lun, uint32_t initidx, uint8_t page, uint8_t subpage)
int ctl_ffz(uint32_t *mask, uint32_t first, uint32_t last)
static int ctl_target_reset(union ctl_io *io)
int ctl_ie_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc)
int ctl_expand_number(const char *buf, uint64_t *num)
int ctl_start_stop(struct ctl_scsiio *ctsio)
int ctl_cnw(struct ctl_scsiio *ctsio)
int ctl_persistent_reserve_out(struct ctl_scsiio *ctsio)
int ctl_persistent_reserve_in(struct ctl_scsiio *ctsio)
int ctl_set_mask(uint32_t *mask, uint32_t bit)
static const struct scsi_cddvd_capabilities_page cddvd_page_changeable
static void ctl_enqueue_rtr(union ctl_io *io)
static void ctl_inject_error(struct ctl_lun *lun, union ctl_io *io)
void ctl_clr_ua_all(struct ctl_lun *lun, uint32_t except, ctl_ua_type ua)
static int ctl_datamove_remote_dm_read_cb(union ctl_io *io, bool samethr)
int ctl_lun_ejected(struct ctl_be_lun *be_lun)
int ctl_scsi_release(struct ctl_scsiio *ctsio)
static void ctl_send_datamove_done(union ctl_io *io, int have_lock)
int ctl_read_write(struct ctl_scsiio *ctsio)
#define CTL_DEFAULT_MAX_PORTS
static void ctl_handle_isc(union ctl_io *io)
int ctl_read_buffer(struct ctl_scsiio *ctsio)
static int ctl_inquiry_evpd_block_limits(struct ctl_scsiio *ctsio, int alloc_len)
int ctl_add_initiator(struct ctl_port *port, int iid, uint64_t wwpn, char *name)
static const struct scsi_da_rw_recovery_page rw_er_page_default
SYSCTL_INT(_kern_cam_ctl, OID_AUTO, worker_threads, CTLFLAG_RDTUN, &worker_threads, 1, "Number of worker threads")
static void ctl_enqueue_done(union ctl_io *io)
void ctl_isc_announce_lun(struct ctl_lun *lun)
static void ctl_process_done(union ctl_io *io)
void ctl_datamove_done(union ctl_io *io, bool samethr)
static void ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx, ctl_ua_type ua_type)
static void ctl_isc_login(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
int ctl_write_buffer(struct ctl_scsiio *ctsio)
int ctl_remove_lun(struct ctl_be_lun *be_lun)
static const struct ctl_cmd_entry * ctl_validate_command(struct ctl_scsiio *ctsio)
int ctl_lun_has_media(struct ctl_be_lun *be_lun)
uint32_t ctl_get_initindex(struct ctl_nexus *nexus)
SYSCTL_NODE(_kern_cam, OID_AUTO, ctl, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Target Layer")
static void ctl_isc_port_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
int ctl_sap_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc)
static int ctl_cmd_applicable(uint8_t lun_type, const struct ctl_cmd_entry *entry)
int ctl_mechanism_status(struct ctl_scsiio *ctsio)
static void ctl_isc_iid_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
void ctl_config_write_done(union ctl_io *io)
static void ctl_ha_datamove(union ctl_io *io)
static const struct scsi_control_ext_page control_ext_page_default
static void ctl_enqueue_isc(union ctl_io *io)
static void ctl_isc_ha_link_up(struct ctl_softc *softc)
static const struct scsi_rigid_disk_page rigid_disk_page_changeable
int ctl_read_defect(struct ctl_scsiio *ctsio)
static void ctl_datamove_remote_read(union ctl_io *io)
static void ctl_copy_sense_data(union ctl_ha_msg *src, union ctl_io *dest)
int ctl_read_toc(struct ctl_scsiio *ctsio)
MALLOC_DEFINE(M_CTL, "ctlmem", "Memory used for CTL")
static void ctl_isc_ha_link_down(struct ctl_softc *softc)
static ctl_action ctl_check_ooa(struct ctl_lun *lun, union ctl_io *pending_io, union ctl_io **starting_io)
void ctl_est_ua_all(struct ctl_lun *lun, uint32_t except, ctl_ua_type ua)
static int ctl_ha_role_sysctl(SYSCTL_HANDLER_ARGS)
int ctl_log_sense(struct ctl_scsiio *ctsio)
static ctl_action ctl_extent_check(union ctl_io *io1, union ctl_io *io2, bool seq)
int ctl_format(struct ctl_scsiio *ctsio)
static int ctl_inquiry_evpd_mpp(struct ctl_scsiio *ctsio, int alloc_len)
static void ctl_isc_handler_finish_xfer(struct ctl_softc *ctl_softc, union ctl_ha_msg *msg_info)
static int ctl_datamove_remote_dm_write_cb(union ctl_io *io, bool samethr)
static const struct scsi_caching_page caching_page_changeable
static void ctl_hndl_per_res_out_on_other_sc(union ctl_io *io)
static int ctl_scsiio_lun_check(struct ctl_lun *lun, const struct ctl_cmd_entry *entry, struct ctl_scsiio *ctsio)
int ctl_lun_primary(struct ctl_be_lun *be_lun)
static int ctl_pro_preempt(struct ctl_softc *softc, struct ctl_lun *lun, uint64_t res_key, uint64_t sa_res_key, uint8_t type, uint32_t residx, struct ctl_scsiio *ctsio, struct scsi_per_res_out *cdb, struct scsi_per_res_out_parms *param)
int ctl_lun_map_unset(struct ctl_port *port, uint32_t plun)
int ctl_get_config(struct ctl_scsiio *ctsio)
static void ctl_scsiio_precheck(struct ctl_scsiio *ctsio)
static void ctl_ultomsf(uint32_t lba, uint8_t *buf)
static const struct scsi_da_verify_recovery_page verify_er_page_default
static int ctl_disable_lun(struct ctl_lun *lun)
int ctl_queue_sense(union ctl_io *io)
int ctl_report_luns(struct ctl_scsiio *ctsio)
static const struct scsi_info_exceptions_page ie_page_changeable
int ctl_clear_mask(uint32_t *mask, uint32_t bit)
int ctl_read_capacity_16(struct ctl_scsiio *ctsio)
static struct cdevsw ctl_cdevsw
static const struct ctl_logical_block_provisioning_page lbp_page_changeable
static int ctl_inquiry_evpd(struct ctl_scsiio *ctsio)
static const struct scsi_format_page format_page_changeable
int ctl_queue(union ctl_io *io)
static int ctl_query_task(union ctl_io *io, int task_set)
int ctl_read_capacity(struct ctl_scsiio *ctsio)
int ctl_tur(struct ctl_scsiio *ctsio)
int ctl_report_timestamp(struct ctl_scsiio *ctsio)
static int ctl_shutdown(void)
static int ctl_open(struct cdev *dev, int flags, int fmt, struct thread *td)
int ctl_mode_sense(struct ctl_scsiio *ctsio)
int ctl_report_supported_tmf(struct ctl_scsiio *ctsio)
static void ctl_isc_lun_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
int ctl_unmap(struct ctl_scsiio *ctsio)
static int ctl_close(struct cdev *dev, int flags, int fmt, struct thread *td)
static void ctl_ha_done(union ctl_io *io)
static int ctl_cnw_cont(union ctl_io *io)
void ctl_pool_free(struct ctl_io_pool *pool)
int ctl_mode_select(struct ctl_scsiio *ctsio)
int ctl_stop_lun(struct ctl_be_lun *be_lun)
static void ctl_failover_io(union ctl_io *io, int have_lock)
uint32_t ctl_lun_map_from_port(struct ctl_port *port, uint32_t lun_id)
static void ctl_work_thread(void *arg)
static const struct scsi_control_page control_page_changeable
static void ctl_isc_mode_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
int ctl_lun_secondary(struct ctl_be_lun *be_lun)
void ctl_lun_capacity_changed(struct ctl_be_lun *be_lun)
int ctl_default_page_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, uint8_t *page_ptr)
static int ctl_inquiry_evpd_supported(struct ctl_scsiio *ctsio, int alloc_len)
static int ctl_inquiry_evpd_serial(struct ctl_scsiio *ctsio, int alloc_len)
static const struct scsi_da_rw_recovery_page rw_er_page_changeable
void ctl_isc_announce_port(struct ctl_port *port)
static int ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
static void ctl_try_unblock_others(struct ctl_lun *lun, union ctl_io *io, bool skip)
static void ctl_failover_lun(union ctl_io *io)
static int ctl_inquiry_evpd_bdc(struct ctl_scsiio *ctsio, int alloc_len)
static int ctl_enable_lun(struct ctl_lun *lun)
static void ctl_datamove_done_process(union ctl_io *io)
static void ctl_set_prkey(struct ctl_lun *lun, uint32_t residx, uint64_t key)
static int ctl_lun_reset(union ctl_io *io)
uint64_t ctl_encode_lun(uint32_t decoded)
static void ctl_datamove_remote_read_cb(struct ctl_ha_dt_req *rq)
TUNABLE_INT("kern.cam.ctl.max_luns", &ctl_max_luns)
static int ctl_create_iid(struct ctl_port *port, int iid, uint8_t *buf)
static int ctl_inquiry_std(struct ctl_scsiio *ctsio)
static void ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio)
static int ctl_inquiry_evpd_scsi_ports(struct ctl_scsiio *ctsio, int alloc_len)
static int worker_threads
static int ctl_init(void)
int ctl_get_event_status(struct ctl_scsiio *ctsio)
static int ctl_init_log_page_index(struct ctl_lun *lun)
static moduledata_t ctl_moduledata
static const struct scsi_da_verify_recovery_page verify_er_page_changeable
static void ctl_pro_preempt_other(struct ctl_lun *lun, union ctl_ha_msg *msg)
#define CTL_DEFAULT_MAX_LUNS
static const struct scsi_rigid_disk_page rigid_disk_page_default
static void ctl_datamove_remote_write(union ctl_io *io)
static void ctl_copy_sense_data_back(union ctl_io *src, union ctl_ha_msg *dest)
int ctl_run(union ctl_io *io)
static void ctl_isc_event_handler(ctl_ha_channel chanel, ctl_ha_event event, int param)
static int ctl_free_lun(struct ctl_lun *lun)
static const struct scsi_format_page format_page_default
int ctl_pool_create(struct ctl_softc *ctl_softc, const char *pool_name, uint32_t total_ctl_io, void **npool)
int ctl_sbuf_printf_esc(struct sbuf *sb, char *str, int size)
void ctl_clr_ua_allluns(struct ctl_softc *ctl_softc, uint32_t initidx, ctl_ua_type ua_type)
int ctl_sync_cache(struct ctl_scsiio *ctsio)
int ctl_temp_log_sense_handler(struct ctl_scsiio *ctsio, struct ctl_page_index *page_index, int pc)
static int ctl_i_t_nexus_reset(union ctl_io *io)
static int ctl_abort_task(union ctl_io *io)
static void ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num, struct ctl_ooa *ooa_hdr, struct ctl_ooa_entry *kern_entries)
static int ctl_datamove_remote_xfer(union ctl_io *io, unsigned command, ctl_ha_dt_cb callback)
void ctl_config_read_done(union ctl_io *io)
static void ctl_thresh_thread(void *arg)
static int ctl_inquiry_evpd_lbp(struct ctl_scsiio *ctsio, int alloc_len)
int ctl_verify(struct ctl_scsiio *ctsio)
void ctl_zero_io(union ctl_io *io)
union ctl_io * ctl_alloc_io(void *pool_ref)
static void ctl_clr_prkey(struct ctl_lun *lun, uint32_t residx)
void ctl_done(union ctl_io *io)
void ctl_isc_announce_iid(struct ctl_port *port, int iid)
DECLARE_MODULE(ctl, ctl_moduledata, SI_SUB_CONFIGURE, SI_ORDER_THIRD)
void ctl_data_submit_done(union ctl_io *io)
static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
int ctl_scsi_reserve(struct ctl_scsiio *ctsio)
static void ctl_id_sbuf(struct ctl_devid *id, struct sbuf *sb)
static uint64_t ctl_get_prkey(struct ctl_lun *lun, uint32_t residx)
static struct ctl_frontend ha_frontend
int ctl_inquiry(struct ctl_scsiio *ctsio)
static int ctl_lun_map_size
int ctl_is_set(uint32_t *mask, uint32_t bit)
static void ctl_isc_ua(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
static void ctl_isc_handler_finish_ser_only(struct ctl_softc *ctl_softc, union ctl_ha_msg *msg_info)
#define CTL_PORT_WWPN_VALID
#define CTL_RETVAL_COMPLETE
#define CTL_PORT_WWNN_VALID
#define CTL_DEVID_MIN_LEN
int ctl_ioctl_io(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
struct ctl_backend_driver * ctl_backend_find(char *backend_name)
const struct ctl_cmd_entry ctl_cmd_table[256]
#define CTL_DEBUG_PRINT(X)
void ctl_set_hw_write_protected(struct ctl_scsiio *ctsio)
ctl_ua_type ctl_build_qae(struct ctl_lun *lun, uint32_t initidx, uint8_t *resp)
void ctl_set_task_aborted(struct ctl_scsiio *ctsio)
void ctl_set_sense_data(struct scsi_sense_data *sense_data, u_int *sense_len, void *lunptr, scsi_sense_data_type sense_format, int current_error, int sense_key, int asc, int ascq,...)
void ctl_set_lun_stopped(struct ctl_scsiio *ctsio)
ctl_ua_type ctl_build_ua(struct ctl_lun *lun, uint32_t initidx, struct scsi_sense_data *sense, u_int *sense_len, scsi_sense_data_type sense_format)
void ctl_set_lun_unavail(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_reservation_conflict(struct ctl_scsiio *ctsio)
void ctl_set_success(struct ctl_scsiio *ctsio)
void ctl_set_medium_error(struct ctl_scsiio *ctsio, int read)
void ctl_sense_to_desc(struct scsi_sense_data_fixed *sense_src, struct scsi_sense_data_desc *sense_dest)
void ctl_set_lun_no_media(struct ctl_scsiio *ctsio)
void ctl_set_param_len_error(struct ctl_scsiio *ctsio)
void ctl_set_ua(struct ctl_scsiio *ctsio, int asc, int ascq)
void ctl_set_unsupported_lun(struct ctl_scsiio *ctsio)
void ctl_set_illegal_pr_release(struct ctl_scsiio *ctsio)
void ctl_sense_to_fixed(struct scsi_sense_data_desc *sense_src, struct scsi_sense_data_fixed *sense_dest)
void ctl_set_internal_failure(struct ctl_scsiio *ctsio, int sks_valid, uint16_t retry_count)
void ctl_set_lun_int_reqd(struct ctl_scsiio *ctsio)
void ctl_set_invalid_opcode(struct ctl_scsiio *ctsio)
void ctl_set_lba_out_of_range(struct ctl_scsiio *ctsio, uint64_t lba)
void ctl_set_lun_ejected(struct ctl_scsiio *ctsio)
void ctl_set_lun_transit(struct ctl_scsiio *ctsio)
void ctl_set_overlapped_tag(struct ctl_scsiio *ctsio, uint8_t tag)
void ctl_set_lun_standby(struct ctl_scsiio *ctsio)
void ctl_set_busy(struct ctl_scsiio *ctsio)
void ctl_set_sense(struct ctl_scsiio *ctsio, int current_error, int sense_key, int asc, int ascq,...)
void ctl_set_invalid_field_ciu(struct ctl_scsiio *ctsio)
void ctl_set_overlapped_cmd(struct ctl_scsiio *ctsio)
void ctl_set_aborted(struct ctl_scsiio *ctsio)
int ctl_port_deregister(struct ctl_port *port)
void ctl_port_set_wwns(struct ctl_port *port, int wwnn_valid, uint64_t wwnn, int wwpn_valid, uint64_t wwpn)
int ctl_frontend_deregister(struct ctl_frontend *fe)
struct ctl_frontend * ctl_frontend_find(char *frontend_name)
void ctl_port_offline(struct ctl_port *port)
void ctl_port_online(struct ctl_port *port)
int ctl_port_register(struct ctl_port *port)
int ctl_frontend_register(struct ctl_frontend *fe)
@ CTL_PORT_STATUS_HA_SHARED
ctl_ha_status ctl_ha_msg_recv(ctl_ha_channel channel, void *addr, size_t len, int wait)
ctl_ha_status ctl_dt_single(struct ctl_ha_dt_req *req)
ctl_ha_status ctl_ha_msg_abort(ctl_ha_channel channel)
ctl_ha_status ctl_ha_msg_init(struct ctl_softc *ctl_softc)
void ctl_ha_msg_shutdown(struct ctl_softc *ctl_softc)
ctl_ha_status ctl_ha_msg_register(ctl_ha_channel channel, ctl_evt_handler handler)
ctl_ha_status ctl_ha_msg_deregister(ctl_ha_channel channel)
struct ctl_ha_dt_req * ctl_dt_req_alloc(void)
void ctl_dt_req_free(struct ctl_ha_dt_req *req)
ctl_ha_status ctl_ha_msg_send(ctl_ha_channel channel, const void *addr, size_t len, int wait)
ctl_ha_status ctl_ha_msg_destroy(struct ctl_softc *ctl_softc)
void(* ctl_ha_dt_cb)(struct ctl_ha_dt_req *)
#define CTL_PRIV_MODEPAGE
#define CTL_BACKEND_LUN(io)
#define CTL_TIME_IO_DEFAULT_SECS
@ CTL_TASK_QUERY_ASYNC_EVENT
@ CTL_TASK_QUERY_TASK_SET
@ CTL_TASK_CLEAR_TASK_SET
@ CTL_TASK_ABORT_TASK_SET
@ CTL_TASK_I_T_NEXUS_RESET
@ CTL_FLAG_SENT_2OTHER_SC
#define CTL_HA_DATAMOVE_SEGMENT
@ CTL_TASK_LUN_DOES_NOT_EXIST
@ CTL_TASK_FUNCTION_SUCCEEDED
@ CTL_TASK_FUNCTION_NOT_SUPPORTED
@ CTL_TASK_FUNCTION_COMPLETE
@ CTL_OOA_NEED_MORE_SPACE
#define CTL_SET_PORT_WWNS
@ CTL_OOACMD_FLAG_STATUS_QUEUED
@ CTL_OOACMD_FLAG_STATUS_SENT
@ CTL_OOACMD_FLAG_DMA_QUEUED
@ CTL_OOACMD_FLAG_BLOCKED
#define CTL_ERROR_INJECT_DELETE
@ CTL_DELAY_STATUS_INVALID_LUN
@ CTL_DELAY_STATUS_INVALID_LOC
@ CTL_DELAY_STATUS_INVALID_TYPE
@ CTL_DELAY_STATUS_NOT_IMPLEMENTED
#define CTL_GET_PORT_STATS
#define CTL_GET_LUN_STATS
#define CTL_MAX_INIT_PER_PORT
@ CTL_STATS_FLAG_TIME_VALID
@ CTL_LUN_LIST_NEED_MORE_SPACE
void ctl_tpc_lun_init(struct ctl_lun *lun)
#define CTL_CDROM_PRODUCT
#define CTL_WRITE_BUFFER_SIZE
#define CTL_NUM_LBP_PARAMS
void ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx)
#define CTL_UNKNOWN_PRODUCT
void ctl_tpc_lun_shutdown(struct ctl_lun *lun)
#define CTL_LBP_UA_PERIOD
#define CTL_DEFAULT_SECTORS_PER_TRACK
int ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len)
#define CTL_PAGE_CHANGEABLE
#define CTL_DEFAULT_ROTATION_RATE
#define CTL_DEFAULT_HEADS
static const struct ctl_page_index page_index_template[]
@ CTL_CMD_FLAG_OK_ON_CDROM
@ CTL_CMD_FLAG_OK_ON_NO_MEDIA
@ CTL_CMD_FLAG_ALLOW_ON_PR_RESV
@ CTL_CMD_FLAG_OK_ON_DIRECT
@ CTL_CMD_FLAG_OK_ON_STANDBY
@ CTL_CMD_FLAG_OK_ON_PROC
@ CTL_CMD_FLAG_OK_ON_NO_LUN
@ CTL_CMD_FLAG_OK_ON_UNAVAIL
@ CTL_CMD_FLAG_ALLOW_ON_PR_WRESV
@ CTL_CMD_FLAG_ALLOW_ON_RESV
void ctl_tpc_init(struct ctl_softc *softc)
void ctl_tpc_shutdown(struct ctl_softc *softc)
@ CTL_LUN_PEER_SC_PRIMARY
#define CTL_NUM_LBP_THRESH
#define CTL_NUM_MODE_PAGES
#define CTL_PR_ALL_REGISTRANTS
#define CTL_PROCESSOR_PRODUCT
#define CTL_PR_NO_RESERVATION
#define CTL_DIRECT_PRODUCT
static const struct ctl_page_index log_page_index_template[]
#define CTL_POOL_ENTRIES_OTHER_SC
#define CTL_NUM_LOG_PAGES
int ctl_scsi_command_string(struct ctl_scsiio *ctsio, struct scsi_inquiry_data *inq_data, struct sbuf *sb)
void ctl_scsi_path_string(union ctl_io *io, char *path_str, int len)
static const uint8_t ctl_serialize_table[CTL_SERIDX_COUNT][CTL_SERIDX_COUNT]
void ctl_io_print(union ctl_io *io)
void ctl_data_print(union ctl_io *io)
void ctl_io_error_print(union ctl_io *io, struct scsi_inquiry_data *inq_data)
scsi_sense_data_type scsi_sense_type(struct scsi_sense_data *sense_data)
#define SCP_QUEUE_ALG_MASK
#define SVPD_EXTENDED_INQUIRY_DATA
#define SMS_PAGE_CTRL_MASK
#define SIEP_FLAGS_LOGERR
#define SVPD_UNIT_SERIAL_NUMBER
#define SIEP_FLAGS_DEXCPT
#define TPG_ASYMMETRIC_ACCESS_STANDBY
#define RPL_LUNDATA_EXT_EAM_NOT_SPEC
#define SVPD_ID_TYPE_SCSI_NAME
#define SPC3_SID_TPGS_IMPLICIT
#define RPL_REPORT_DEFAULT
#define SVPD_BLOCK_LIMITS
#define SPR_TYPE_EX_AC_AR
#define SCSI_STATUS_CHECK_COND
#define SYNCHRONIZE_CACHE_16
static __inline uint32_t scsi_3btoul(const uint8_t *bytes)
#define SPRI_FULL_R_HOLDER
static __inline uint64_t scsi_8btou64(const uint8_t *bytes)
#define SVPD_ID_TYPE_RELTARG
#define RPL_REPORT_CONGLOM
static __inline uint32_t scsi_2btoul(const uint8_t *bytes)
#define SLP_REFTEMPERATURE
#define SMS_INFO_EXCEPTIONS_PAGE
#define SVPD_ID_CODESET_UTF8
#define SVPD_ID_TYPE_MASK
#define SVPD_ID_CODESET_BINARY
#define RPL_LUNDATA_ATYP_MASK
#define SVPD_ID_TYPE_UUID
#define SVPD_LBP_RESOURCE
#define SPR_TYPE_EX_AC_RO
#define RPL_LUNDATA_ATYP_EXTLUN
#define SCP_QUEUE_ALG_UNRESTRICTED
#define SIEP_MRIE_REC_COND
#define SLBPPD_ARMING_MASK
#define SVPD_MODE_PAGE_POLICY
#define SYNCHRONIZE_CACHE
#define TPG_ASYMMETRIC_ACCESS_OPTIMIZED
#define SMS_ALL_PAGES_PAGE
#define SLS_PAGE_CTRL_MASK
#define SSD_KEY_RECOVERED_ERROR
#define SVPD_ID_TYPE_TPORTGRP
static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes)
#define SCP_QUEUE_ALG_RESTRICTED
#define SIEP_MRIE_REC_UNCOND
#define SERVICE_ACTION_MASK
#define RWB_MODE_ECHO_DESCR
#define COMPARE_AND_WRITE
#define SSD_KEY_NOT_READY
#define SLBPPD_ARMING_DEC
#define RSO_OPTIONS_OC_SA
#define SLS_LOGICAL_BLOCK_PROVISIONING
#define SCSI_TRN_ISCSI_FORMAT_PORT
#define SVPD_ID_ASSOC_LUN
static __inline uint32_t scsi_4btoul(const uint8_t *bytes)
#define SID_QUAL_LU_CONNECTED
#define RPL_LUNDATA_ATYP_FLAT
#define TPG_ASYMMETRIC_ACCESS_UNAVAILABLE
#define TPG_ASYMMETRIC_ACCESS_NONOPTIMIZED
#define SVPD_ID_CODESET_MASK
#define SMS_CONTROL_MODE_PAGE
#define SPR_TYPE_WR_EX_RO
#define SVPD_SUPPORTED_PAGES
#define SVPD_ID_ASSOC_PORT
static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes)
#define RPL_LUNDATA_ATYP_PERIPH
#define SVPD_ID_TYPE_EUI64
static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes)
#define SERVICE_ACTION_IN
#define RSO_OPTIONS_OC_ASA
#define SID_SPI_CLOCK_DT_ST
#define SMS_FORMAT_DEVICE_PAGE
#define RPL_REPORT_NONSUBSID
#define TPG_ASYMMETRIC_ACCESS_TRANSITIONING
#define SVPD_ID_CODESET_ASCII
#define SID_QUAL_LU_OFFLINE
#define RPL_LUNDATA_EXT_LEN_MASK
static __inline void scsi_ulto3b(u_int32_t val, u_int8_t *bytes)
#define SIEP_MRIE_NO_SENSE
#define SSD_KEY_ILLEGAL_REQUEST
#define RPL_REPORT_WELLKNOWN
#define RPL_LUNDATA_EXT_EAM_MASK
#define SLBPPD_ARMING_INC
#define SSD_KEY_DATA_PROTECT
#define SMS_SUBPAGE_PAGE_0
#define READ_DEFECT_DATA_10
#define SPR_TYPE_WR_EX_AR
#define SMS_CDDVD_CAPS_PAGE
#define SRDP_RPL_DISABLED
#define SMS_RW_ERROR_RECOVERY_PAGE
#define SMS_VERIFY_ERROR_RECOVERY_PAGE
#define SMS_RIGID_DISK_PAGE
char name[CTL_BE_NAME_LEN]
uint8_t device_id[CTL_DEVID_LEN]
uint8_t serial_num[CTL_SN_LEN]
struct ctl_backend_driver * be
ctl_backend_lun_flags flags
ctl_lun_error_pattern pattern
struct scsi_sense_data custom_sense
ctl_lun_error_pattern error_pattern
struct ctl_lba_len lba_range
char name[CTL_DRIVER_NAME_LEN]
struct ctl_io_stats * stats
struct ctl_sg_entry sg_list[CTL_HA_MAX_SG_ENTRIES]
union ctl_io * original_sc
union ctl_io * serializing_sc
unsigned int pr_generation
struct ctl_pr_info pr_info
struct scsi_sense_data sense_data
uint8_t cdb[CTL_MAX_CDBLEN]
ctl_task_type task_action
ctl_delay_location delay_loc
ctl_delay_type delay_type
struct bintime dma_start_bt
union ctl_priv ctl_private[CTL_NUM_PRIV]
struct ctl_softc * ctl_softc
struct bintime dma_time[CTL_STATS_NUM_TYPES]
uint64_t bytes[CTL_STATS_NUM_TYPES]
uint64_t operations[CTL_STATS_NUM_TYPES]
struct bintime time[CTL_STATS_NUM_TYPES]
uint64_t dmas[CTL_STATS_NUM_TYPES]
char error_str[CTL_ERROR_STR_LEN]
uint8_t pages_page[CTL_NUM_LOG_PAGES]
struct scsi_log_informational_exceptions ie_page
uint8_t subpages_page[CTL_NUM_LOG_PAGES *2]
uint8_t lbp_page[12 *CTL_NUM_LBP_PARAMS]
struct scsi_log_temperature temp_page[2]
struct ctl_page_index index[CTL_NUM_LOG_PAGES]
struct ctl_log_pages::stat_page stat_page
struct scsi_logical_block_provisioning_page_descr descr[CTL_NUM_LBP_THRESH]
ctl_delay_type datamove_type
char error_str[CTL_ERROR_STR_LEN]
ctl_lun_list_status status
char backend[CTL_BE_NAME_LEN]
char error_str[CTL_ERROR_STR_LEN]
union ctl_lunreq_data reqdata
struct ctl_mode_pages mode_pages
struct callout ie_callout
struct ctl_devid * lun_devid
ctl_ua_type ** pending_ua
struct ctl_io_stats stats
struct ctl_lun_delay_info delay_info
struct ctl_softc * ctl_softc
struct scsi_sense_data ** pending_sense
struct ctl_be_lun * be_lun
struct ctl_backend_driver * backend
struct ctl_log_pages log_pages
struct scsi_info_exceptions_page ie_page[4]
struct scsi_control_page control_page[4]
struct scsi_control_ext_page control_ext_page[4]
struct scsi_da_verify_recovery_page verify_er_page[4]
struct ctl_page_index index[CTL_NUM_MODE_PAGES]
struct scsi_format_page format_page[4]
struct scsi_cddvd_capabilities_page cddvd_page[4]
struct scsi_caching_page caching_page[4]
struct scsi_da_rw_recovery_page rw_er_page[4]
struct scsi_rigid_disk_page rigid_disk_page[4]
struct ctl_logical_block_provisioning_page lbp_page[4]
uint8_t cdb[CTL_MAX_CDBLEN]
ctl_ooa_cmd_flags cmd_flags
ctl_get_ooa_status status
struct ctl_ooa_entry * entries
ctl_modesel_handler * select_handler
ctl_modesen_handler * sense_handler
ctl_page_flags page_flags
struct ctl_frontend * frontend
port_info_func_t port_info
void(* fe_datamove)(union ctl_io *io)
struct ctl_devid * port_devid
struct ctl_io_stats stats
struct ctl_softc * ctl_softc
struct ctl_devid * init_devid
struct ctl_devid * target_devid
struct ctl_wwpn_iid * wwpn_iid
void(* fe_done)(union ctl_io *io)
struct ctl_ha_msg_pr pr_msg
char driver[CTL_DRIVER_NAME_LEN]
char error_str[CTL_ERROR_STR_LEN]
int(* be_move_done)(union ctl_io *io, bool samethr)
struct scsi_sense_data sense_data
int(* io_cont)(union ctl_io *io)
uint8_t cdb[CTL_MAX_CDBLEN]
struct sysctl_ctx_list sysctl_ctx
struct ctl_lun ** ctl_luns
struct uma_zone * io_zone
ctl_ha_link_state ha_link
struct sysctl_oid * sysctl_tree
struct ctl_thread threads[CTL_MAX_THREADS]
struct ctl_port ** ctl_ports
struct thread * thresh_thread
ctl_task_type task_action
struct ctl_softc * ctl_softc
struct mtx_padalign queue_lock
uint8_t bytes_per_sector[2]
uint8_t starting_feature[2]
struct scsi_get_lba_status_data_descr descr[]
u_int8_t interval_timer[4]
char vendor[SID_VENDOR_SIZE]
u_int8_t additional_length
char product[SID_PRODUCT_SIZE]
char revision[SID_REVISION_SIZE]
struct scsi_log_param_header hdr
u_int8_t block_descr_len[2]
struct scsi_per_res_key res_key
uint8_t additional_length[4]
uint8_t rel_trgt_port_id[2]
struct scsi_per_res_in_full_desc desc[]
struct scsi_per_res_in_header header
struct scsi_per_res_in_header header
struct scsi_per_res_key keys[0]
struct scsi_per_res_in_rsrv_data data
struct scsi_per_res_in_header header
struct scsi_per_res_key res_key
u_int8_t serv_act_res_key[8]
struct scsi_report_luns_lundata luns[0]
struct scsi_report_supported_opcodes_descr descr[0]
uint8_t service_action[2]
uint8_t requested_service_action[2]
uint8_t implicit_transition_time
struct scsi_target_port_group_descriptor groups[]
struct scsi_target_port_group_descriptor groups[]
uint8_t target_port_count
uint8_t target_port_group[2]
struct scsi_target_port_descriptor descriptors[]
uint8_t additional_length[2]
uint8_t rel_trgt_port_id[2]
uint8_t medium_rotation_rate[2]
u_int8_t max_write_same_length[8]
u_int8_t max_atomic_transfer_length_with_atomic_boundary[4]
u_int8_t opt_unmap_grain[4]
u_int8_t max_txfer_len[4]
u_int8_t max_unmap_blk_cnt[4]
u_int8_t max_atomic_transfer_length[4]
u_int8_t opt_txfer_len[4]
u_int8_t atomic_alignment[4]
u_int8_t unmap_grain_align[4]
u_int8_t max_atomic_boundary_size[4]
u_int8_t atomic_transfer_length_granularity[4]
u_int8_t max_cmp_write_len
u_int8_t max_unmap_lba_cnt[4]
u_int8_t vendor_spec_id[0]
u_int8_t threshold_exponent
struct scsi_vpd_mode_page_policy_descr descr[0]
struct scsi_vpd_id_descriptor target_port_descriptors[0]
uint8_t target_port_descriptors_length[2]
uint8_t initiator_transportid_length[2]
uint8_t relative_port_id[2]
uint8_t initiator_transportid[0]
struct scsi_vpd_port_designation design[]
u_int8_t serial_num[SVPD_SERIAL_NUM_SIZE]
struct ctl_ha_msg_mode mode
struct ctl_ha_msg_scsi scsi
struct ctl_ha_msg_hdr hdr
struct ctl_ha_msg_login login
struct ctl_ha_msg_lun lun
struct ctl_ha_msg_iid iid
struct ctl_ha_msg_task task
struct ctl_ha_msg_port port
struct ctl_lun_modify_params modify
struct ctl_modepage_header header
uint8_t bytes[sizeof(uint64_t) *2]