diff options
Diffstat (limited to 'sys/cam/ctl/ctl.c')
-rw-r--r-- | sys/cam/ctl/ctl.c | 292 |
1 files changed, 46 insertions, 246 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 1fda5bde72c2..5230a2694544 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -1,5 +1,5 @@ /*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2003-2009 Silicon Graphics International Corp. * Copyright (c) 2012 The FreeBSD Foundation @@ -44,9 +44,6 @@ * Author: Ken Merry <ken@FreeBSD.org> */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/systm.h> #include <sys/ctype.h> @@ -127,72 +124,6 @@ const static struct scsi_da_rw_recovery_page rw_er_page_changeable = { /*recovery_time_limit*/{0, 0}, }; -const static struct scsi_format_page format_page_default = { - /*page_code*/SMS_FORMAT_DEVICE_PAGE, - /*page_length*/sizeof(struct scsi_format_page) - 2, - /*tracks_per_zone*/ {0, 0}, - /*alt_sectors_per_zone*/ {0, 0}, - /*alt_tracks_per_zone*/ {0, 0}, - /*alt_tracks_per_lun*/ {0, 0}, - /*sectors_per_track*/ {(CTL_DEFAULT_SECTORS_PER_TRACK >> 8) & 0xff, - CTL_DEFAULT_SECTORS_PER_TRACK & 0xff}, - /*bytes_per_sector*/ {0, 0}, - /*interleave*/ {0, 0}, - /*track_skew*/ {0, 0}, - /*cylinder_skew*/ {0, 0}, - /*flags*/ SFP_HSEC, - /*reserved*/ {0, 0, 0} -}; - -const static struct scsi_format_page format_page_changeable = { - /*page_code*/SMS_FORMAT_DEVICE_PAGE, - /*page_length*/sizeof(struct scsi_format_page) - 2, - /*tracks_per_zone*/ {0, 0}, - /*alt_sectors_per_zone*/ {0, 0}, - /*alt_tracks_per_zone*/ {0, 0}, - /*alt_tracks_per_lun*/ {0, 0}, - /*sectors_per_track*/ {0, 0}, - /*bytes_per_sector*/ {0, 0}, - /*interleave*/ {0, 0}, - /*track_skew*/ {0, 0}, - /*cylinder_skew*/ {0, 0}, - /*flags*/ 0, - /*reserved*/ {0, 0, 0} -}; - -const static struct scsi_rigid_disk_page rigid_disk_page_default = { - /*page_code*/SMS_RIGID_DISK_PAGE, - /*page_length*/sizeof(struct scsi_rigid_disk_page) - 2, - /*cylinders*/ {0, 0, 0}, - /*heads*/ CTL_DEFAULT_HEADS, - /*start_write_precomp*/ {0, 0, 0}, - /*start_reduced_current*/ {0, 0, 0}, - /*step_rate*/ {0, 0}, - /*landing_zone_cylinder*/ {0, 0, 0}, - /*rpl*/ SRDP_RPL_DISABLED, - /*rotational_offset*/ 0, - /*reserved1*/ 0, - /*rotation_rate*/ {(CTL_DEFAULT_ROTATION_RATE >> 8) & 0xff, - CTL_DEFAULT_ROTATION_RATE & 0xff}, - /*reserved2*/ {0, 0} -}; - -const static struct scsi_rigid_disk_page rigid_disk_page_changeable = { - /*page_code*/SMS_RIGID_DISK_PAGE, - /*page_length*/sizeof(struct scsi_rigid_disk_page) - 2, - /*cylinders*/ {0, 0, 0}, - /*heads*/ 0, - /*start_write_precomp*/ {0, 0, 0}, - /*start_reduced_current*/ {0, 0, 0}, - /*step_rate*/ {0, 0}, - /*landing_zone_cylinder*/ {0, 0, 0}, - /*rpl*/ 0, - /*rotational_offset*/ 0, - /*reserved1*/ 0, - /*rotation_rate*/ {0, 0}, - /*reserved2*/ {0, 0} -}; - const static struct scsi_da_verify_recovery_page verify_er_page_default = { /*page_code*/SMS_VERIFY_ERROR_RECOVERY_PAGE, /*page_length*/sizeof(struct scsi_da_verify_recovery_page) - 2, @@ -435,7 +366,7 @@ SYSCTL_INT(_kern_cam_ctl, OID_AUTO, max_luns, CTLFLAG_RDTUN, /* * Maximum number of ports registered at one time. */ -#define CTL_DEFAULT_MAX_PORTS 256 +#define CTL_DEFAULT_MAX_PORTS 1024 static int ctl_max_ports = CTL_DEFAULT_MAX_PORTS; TUNABLE_INT("kern.cam.ctl.max_ports", &ctl_max_ports); SYSCTL_INT(_kern_cam_ctl, OID_AUTO, max_ports, CTLFLAG_RDTUN, @@ -2443,7 +2374,7 @@ ctl_serialize_other_sc_cmd(struct ctl_scsiio *ctsio) case CTL_ACTION_OVERLAP_TAG: LIST_REMOVE(&ctsio->io_hdr, ooa_links); mtx_unlock(&lun->lun_lock); - ctl_set_overlapped_tag(ctsio, ctsio->tag_num); + ctl_set_overlapped_tag(ctsio, ctsio->tag_num & 0xff); badjuju: ctl_copy_sense_data_back((union ctl_io *)ctsio, &msg_info); msg_info.hdr.original_sc = ctsio->io_hdr.remote_io; @@ -2491,6 +2422,7 @@ ctl_ioctl_fill_ooa(struct ctl_lun *lun, uint32_t *cur_fill_num, entry = &kern_entries[*cur_fill_num]; entry->tag_num = io->scsiio.tag_num; + entry->tag_type = io->scsiio.tag_type; entry->lun_num = lun->lun; #ifdef CTL_TIME_IO entry->start_bt = io->io_hdr.start_bt; @@ -2536,13 +2468,13 @@ ctl_sbuf_printf_esc(struct sbuf *sb, char *str, int size) for (; *str && str < end; str++) { switch (*str) { case '&': - retval = sbuf_printf(sb, "&"); + retval = sbuf_cat(sb, "&"); break; case '>': - retval = sbuf_printf(sb, ">"); + retval = sbuf_cat(sb, ">"); break; case '<': - retval = sbuf_printf(sb, "<"); + retval = sbuf_cat(sb, "<"); break; default: retval = sbuf_putc(sb, *str); @@ -2567,13 +2499,13 @@ ctl_id_sbuf(struct ctl_devid *id, struct sbuf *sb) desc = (struct scsi_vpd_id_descriptor *)id->data; switch (desc->id_type & SVPD_ID_TYPE_MASK) { case SVPD_ID_TYPE_T10: - sbuf_printf(sb, "t10."); + sbuf_cat(sb, "t10."); break; case SVPD_ID_TYPE_EUI64: - sbuf_printf(sb, "eui."); + sbuf_cat(sb, "eui."); break; case SVPD_ID_TYPE_NAA: - sbuf_printf(sb, "naa."); + sbuf_cat(sb, "naa."); break; case SVPD_ID_TYPE_SCSI_NAME: break; @@ -2588,7 +2520,7 @@ ctl_id_sbuf(struct ctl_devid *id, struct sbuf *sb) (char *)desc->identifier); break; case SVPD_ID_CODESET_UTF8: - sbuf_printf(sb, "%s", (char *)desc->identifier); + sbuf_cat(sb, (char *)desc->identifier); break; } } @@ -2977,6 +2909,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } if (lun_req->args != NULL) { + if (lun_req->args_len > CTL_MAX_ARGS_LEN) { + lun_req->status = CTL_LUN_ERROR; + snprintf(lun_req->error_str, sizeof(lun_req->error_str), + "Too big args."); + break; + } packed = malloc(lun_req->args_len, M_CTL, M_WAITOK); if (copyin(lun_req->args, packed, lun_req->args_len) != 0) { free(packed, M_CTL); @@ -2998,6 +2936,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } else lun_req->args_nvl = nvlist_create(0); + lun_req->result_nvl = NULL; retval = backend->ioctl(dev, cmd, addr, flag, td); nvlist_destroy(lun_req->args_nvl); lun_req->args_nvl = tmp_args_nvl; @@ -3083,7 +3022,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, break; } - sbuf_printf(sb, "<ctllunlist>\n"); + sbuf_cat(sb, "<ctllunlist>\n"); mtx_lock(&softc->ctl_lock); STAILQ_FOREACH(lun, &softc->lun_list, links) { @@ -3113,7 +3052,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, break; if (lun->backend == NULL) { - retval = sbuf_printf(sb, "</lun>\n"); + retval = sbuf_cat(sb, "</lun>\n"); if (retval != 0) break; continue; @@ -3132,7 +3071,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, if (retval != 0) break; - retval = sbuf_printf(sb, "\t<serial_number>"); + retval = sbuf_cat(sb, "\t<serial_number>"); if (retval != 0) break; @@ -3144,12 +3083,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, if (retval != 0) break; - retval = sbuf_printf(sb, "</serial_number>\n"); + retval = sbuf_cat(sb, "</serial_number>\n"); if (retval != 0) break; - retval = sbuf_printf(sb, "\t<device_id>"); + retval = sbuf_cat(sb, "\t<device_id>"); if (retval != 0) break; @@ -3161,7 +3100,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, if (retval != 0) break; - retval = sbuf_printf(sb, "</device_id>\n"); + retval = sbuf_cat(sb, "</device_id>\n"); if (retval != 0) break; @@ -3181,13 +3120,13 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, value = dnvlist_get_string( lun->be_lun->options, name, NULL); if (value != NULL) - sbuf_printf(sb, "%s", value); + sbuf_cat(sb, value); } sbuf_printf(sb, "</%s>\n", name); } - retval = sbuf_printf(sb, "</lun>\n"); + retval = sbuf_cat(sb, "</lun>\n"); if (retval != 0) break; @@ -3198,7 +3137,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, mtx_unlock(&softc->ctl_lock); if ((retval != 0) - || ((retval = sbuf_printf(sb, "</ctllunlist>\n")) != 0)) { + || ((retval = sbuf_cat(sb, "</ctllunlist>\n")) != 0)) { retval = 0; sbuf_delete(sb); list->status = CTL_LUN_LIST_NEED_MORE_SPACE; @@ -3254,6 +3193,12 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } if (req->args != NULL) { + if (req->args_len > CTL_MAX_ARGS_LEN) { + req->status = CTL_LUN_ERROR; + snprintf(req->error_str, sizeof(req->error_str), + "Too big args."); + break; + } packed = malloc(req->args_len, M_CTL, M_WAITOK); if (copyin(req->args, packed, req->args_len) != 0) { free(packed, M_CTL); @@ -3275,6 +3220,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } else req->args_nvl = nvlist_create(0); + req->result_nvl = NULL; if (fe->ioctl) retval = fe->ioctl(dev, cmd, addr, flag, td); else @@ -3341,7 +3287,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, break; } - sbuf_printf(sb, "<ctlportlist>\n"); + sbuf_cat(sb, "<ctlportlist>\n"); mtx_lock(&softc->ctl_lock); STAILQ_FOREACH(port, &softc->port_list, links) { @@ -3386,15 +3332,15 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, break; if (port->target_devid != NULL) { - sbuf_printf(sb, "\t<target>"); + sbuf_cat(sb, "\t<target>"); ctl_id_sbuf(port->target_devid, sb); - sbuf_printf(sb, "</target>\n"); + sbuf_cat(sb, "</target>\n"); } if (port->port_devid != NULL) { - sbuf_printf(sb, "\t<port>"); + sbuf_cat(sb, "\t<port>"); ctl_id_sbuf(port->port_devid, sb); - sbuf_printf(sb, "</port>\n"); + sbuf_cat(sb, "</port>\n"); } if (port->port_info != NULL) { @@ -3419,7 +3365,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, } if (port->lun_map != NULL) { - sbuf_printf(sb, "\t<lun_map>on</lun_map>\n"); + sbuf_cat(sb, "\t<lun_map>on</lun_map>\n"); for (j = 0; j < port->lun_map_size; j++) { plun = ctl_lun_map_from_port(port, j); if (plun == UINT32_MAX) @@ -3450,14 +3396,14 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, if (retval != 0) break; - retval = sbuf_printf(sb, "</targ_port>\n"); + retval = sbuf_cat(sb, "</targ_port>\n"); if (retval != 0) break; } mtx_unlock(&softc->ctl_lock); if ((retval != 0) - || ((retval = sbuf_printf(sb, "</ctlportlist>\n")) != 0)) { + || ((retval = sbuf_cat(sb, "</ctlportlist>\n")) != 0)) { retval = 0; sbuf_delete(sb); list->status = CTL_LUN_LIST_NEED_MORE_SPACE; @@ -4112,134 +4058,6 @@ ctl_init_page_index(struct ctl_lun *lun) (uint8_t *)lun->mode_pages.rw_er_page; break; } - case SMS_FORMAT_DEVICE_PAGE: { - struct scsi_format_page *format_page; - - KASSERT(page_index->subpage == SMS_SUBPAGE_PAGE_0, - ("subpage %#x for page %#x is incorrect!", - page_index->subpage, page_code)); - - /* - * Sectors per track are set above. Bytes per - * sector need to be set here on a per-LUN basis. - */ - memcpy(&lun->mode_pages.format_page[CTL_PAGE_CURRENT], - &format_page_default, - sizeof(format_page_default)); - memcpy(&lun->mode_pages.format_page[ - CTL_PAGE_CHANGEABLE], &format_page_changeable, - sizeof(format_page_changeable)); - memcpy(&lun->mode_pages.format_page[CTL_PAGE_DEFAULT], - &format_page_default, - sizeof(format_page_default)); - memcpy(&lun->mode_pages.format_page[CTL_PAGE_SAVED], - &format_page_default, - sizeof(format_page_default)); - - format_page = &lun->mode_pages.format_page[ - CTL_PAGE_CURRENT]; - scsi_ulto2b(lun->be_lun->blocksize, - format_page->bytes_per_sector); - - format_page = &lun->mode_pages.format_page[ - CTL_PAGE_DEFAULT]; - scsi_ulto2b(lun->be_lun->blocksize, - format_page->bytes_per_sector); - - format_page = &lun->mode_pages.format_page[ - CTL_PAGE_SAVED]; - scsi_ulto2b(lun->be_lun->blocksize, - format_page->bytes_per_sector); - - page_index->page_data = - (uint8_t *)lun->mode_pages.format_page; - break; - } - case SMS_RIGID_DISK_PAGE: { - struct scsi_rigid_disk_page *rigid_disk_page; - uint32_t sectors_per_cylinder; - uint64_t cylinders; -#ifndef __XSCALE__ - int shift; -#endif /* !__XSCALE__ */ - - KASSERT(page_index->subpage == SMS_SUBPAGE_PAGE_0, - ("subpage %#x for page %#x is incorrect!", - page_index->subpage, page_code)); - - /* - * Rotation rate and sectors per track are set - * above. We calculate the cylinders here based on - * capacity. Due to the number of heads and - * sectors per track we're using, smaller arrays - * may turn out to have 0 cylinders. Linux and - * FreeBSD don't pay attention to these mode pages - * to figure out capacity, but Solaris does. It - * seems to deal with 0 cylinders just fine, and - * works out a fake geometry based on the capacity. - */ - memcpy(&lun->mode_pages.rigid_disk_page[ - CTL_PAGE_DEFAULT], &rigid_disk_page_default, - sizeof(rigid_disk_page_default)); - memcpy(&lun->mode_pages.rigid_disk_page[ - CTL_PAGE_CHANGEABLE],&rigid_disk_page_changeable, - sizeof(rigid_disk_page_changeable)); - - sectors_per_cylinder = CTL_DEFAULT_SECTORS_PER_TRACK * - CTL_DEFAULT_HEADS; - - /* - * The divide method here will be more accurate, - * probably, but results in floating point being - * used in the kernel on i386 (__udivdi3()). On the - * XScale, though, __udivdi3() is implemented in - * software. - * - * The shift method for cylinder calculation is - * accurate if sectors_per_cylinder is a power of - * 2. Otherwise it might be slightly off -- you - * might have a bit of a truncation problem. - */ -#ifdef __XSCALE__ - cylinders = (lun->be_lun->maxlba + 1) / - sectors_per_cylinder; -#else - for (shift = 31; shift > 0; shift--) { - if (sectors_per_cylinder & (1 << shift)) - break; - } - cylinders = (lun->be_lun->maxlba + 1) >> shift; -#endif - - /* - * We've basically got 3 bytes, or 24 bits for the - * cylinder size in the mode page. If we're over, - * just round down to 2^24. - */ - if (cylinders > 0xffffff) - cylinders = 0xffffff; - - rigid_disk_page = &lun->mode_pages.rigid_disk_page[ - CTL_PAGE_DEFAULT]; - scsi_ulto3b(cylinders, rigid_disk_page->cylinders); - - if ((value = dnvlist_get_string(lun->be_lun->options, - "rpm", NULL)) != NULL) { - scsi_ulto2b(strtol(value, NULL, 0), - rigid_disk_page->rotation_rate); - } - - memcpy(&lun->mode_pages.rigid_disk_page[CTL_PAGE_CURRENT], - &lun->mode_pages.rigid_disk_page[CTL_PAGE_DEFAULT], - sizeof(rigid_disk_page_default)); - memcpy(&lun->mode_pages.rigid_disk_page[CTL_PAGE_SAVED], - &lun->mode_pages.rigid_disk_page[CTL_PAGE_DEFAULT], - sizeof(rigid_disk_page_default)); - - page_index->page_data = - (uint8_t *)lun->mode_pages.rigid_disk_page; - break; - } case SMS_VERIFY_ERROR_RECOVERY_PAGE: { KASSERT(page_index->subpage == SMS_SUBPAGE_PAGE_0, ("subpage %#x for page %#x is incorrect!", @@ -8257,7 +8075,7 @@ ctl_persistent_reserve_out(struct ctl_scsiio *ctsio) struct ctl_softc *softc = CTL_SOFTC(ctsio); struct ctl_lun *lun = CTL_LUN(ctsio); int retval; - u_int32_t param_len; + uint32_t param_len; struct scsi_per_res_out *cdb; struct scsi_per_res_out_parms* param; uint32_t residx; @@ -12580,7 +12398,7 @@ ctl_datamove(union ctl_io *io) * the data move. */ if (io->io_hdr.flags & CTL_FLAG_ABORT) { - printf("ctl_datamove: tag 0x%04x on (%u:%u:%u) aborted\n", + printf("ctl_datamove: tag 0x%jx on (%u:%u:%u) aborted\n", io->scsiio.tag_num, io->io_hdr.nexus.initid, io->io_hdr.nexus.targ_port, io->io_hdr.nexus.targ_lun); @@ -12982,7 +12800,7 @@ ctl_datamove_remote(union ctl_io *io) * have been done if need be on the other controller. */ if (io->io_hdr.flags & CTL_FLAG_ABORT) { - printf("%s: tag 0x%04x on (%u:%u:%u) aborted\n", __func__, + printf("%s: tag 0x%jx on (%u:%u:%u) aborted\n", __func__, io->scsiio.tag_num, io->io_hdr.nexus.initid, io->io_hdr.nexus.targ_port, io->io_hdr.nexus.targ_lun); @@ -13022,25 +12840,7 @@ ctl_process_done(union ctl_io *io) ctl_scsi_path_string(io, path_str, sizeof(path_str)); sbuf_new(&sb, str, sizeof(str), SBUF_FIXEDLEN); - sbuf_cat(&sb, path_str); - switch (io->io_hdr.io_type) { - case CTL_IO_SCSI: - ctl_scsi_command_string(&io->scsiio, NULL, &sb); - sbuf_printf(&sb, "\n"); - sbuf_cat(&sb, path_str); - sbuf_printf(&sb, "Tag: 0x%04x/%d, Prio: %d\n", - io->scsiio.tag_num, io->scsiio.tag_type, - io->scsiio.priority); - break; - case CTL_IO_TASK: - sbuf_printf(&sb, "Task Action: %d Tag: 0x%04x/%d\n", - io->taskio.task_action, - io->taskio.tag_num, io->taskio.tag_type); - break; - default: - panic("%s: Invalid CTL I/O type %d\n", - __func__, io->io_hdr.io_type); - } + ctl_io_sbuf(io, &sb); sbuf_cat(&sb, path_str); sbuf_printf(&sb, "ctl_process_done: %jd seconds\n", (intmax_t)time_uptime - io->io_hdr.start_time); |