From owner-svn-src-head@freebsd.org Wed Apr 19 15:04:55 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 5AAD5D45AA9; Wed, 19 Apr 2017 15:04:55 +0000 (UTC) (envelope-from scottl@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F1D891D4F; Wed, 19 Apr 2017 15:04:54 +0000 (UTC) (envelope-from scottl@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v3JF4sST050485; Wed, 19 Apr 2017 15:04:54 GMT (envelope-from scottl@FreeBSD.org) Received: (from scottl@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v3JF4r5T050468; Wed, 19 Apr 2017 15:04:53 GMT (envelope-from scottl@FreeBSD.org) Message-Id: <201704191504.v3JF4r5T050468@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: scottl set sender to scottl@FreeBSD.org using -f From: Scott Long Date: Wed, 19 Apr 2017 15:04:53 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r317143 - in head/sys/cam: . ata scsi X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 19 Apr 2017 15:04:55 -0000 Author: scottl Date: Wed Apr 19 15:04:52 2017 New Revision: 317143 URL: https://svnweb.freebsd.org/changeset/base/317143 Log: Add infrastructure to the ATA and SCSI transports that supports using a driver-supplied sbuf for printing device discovery announcements. This helps ensure that messages to the console will be properly serialized (through sbuf_putbuf) and not be truncated and interleaved with other messages. The infrastructure mirrors the existing xpt_announce_periph() entry point and is opt-in for now. No content or formatting changes are visible to the operator other than the new coherency. While here, eliminate the stack usage of the temporary announcement buffer in some of the drivers. It's moved to the softc for now, but future work will eliminate it entirely by making the code flow more linear. Future work will also address locking so that the sbufs can be dynamically sized. The scsi_da, scs_cd, scsi_ses, and ata_da drivers are converted at this point, other drivers can be converted at a later date. A tunable+sysctl, kern.cam.announce_nosbuf, exists for testing purposes but will be removed later. TODO: Eliminate all of the code duplication and temporary buffers. The old printf-based methods will be retired, and xpt_announce_periph() will just be a wrapper that uses a dynamically sized sbuf. This requires that the register and deregister paths be made malloc-safe, which they aren't currently. Sponsored by: Netflix Modified: head/sys/cam/ata/ata_all.c head/sys/cam/ata/ata_all.h head/sys/cam/ata/ata_da.c head/sys/cam/ata/ata_xpt.c head/sys/cam/cam_periph.c head/sys/cam/cam_xpt.c head/sys/cam/cam_xpt_internal.h head/sys/cam/cam_xpt_periph.h head/sys/cam/scsi/scsi_all.c head/sys/cam/scsi/scsi_all.h head/sys/cam/scsi/scsi_cd.c head/sys/cam/scsi/scsi_da.c head/sys/cam/scsi/scsi_enc.c head/sys/cam/scsi/scsi_enc_internal.h head/sys/cam/scsi/scsi_xpt.c Modified: head/sys/cam/ata/ata_all.c ============================================================================== --- head/sys/cam/ata/ata_all.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/ata/ata_all.c Wed Apr 19 15:04:52 2017 (r317143) @@ -382,12 +382,10 @@ void ata_print_ident(struct ata_params *ident_data) { const char *proto; - char product[48], revision[16], ata[12], sata[12]; + char ata[12], sata[12]; + + ata_print_ident_short(ident_data); - cam_strvis(product, ident_data->model, sizeof(ident_data->model), - sizeof(product)); - cam_strvis(revision, ident_data->revision, sizeof(ident_data->revision), - sizeof(revision)); proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" : (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA"; if (ata_version(ident_data->version_major) == 0) { @@ -412,7 +410,55 @@ ata_print_ident(struct ata_params *ident snprintf(sata, sizeof(sata), " SATA"); } else sata[0] = 0; - printf("<%s %s> %s%s device\n", product, revision, ata, sata); + printf(" %s%s device\n", ata, sata); +} + +void +ata_print_ident_sbuf(struct ata_params *ident_data, struct sbuf *sb) +{ + const char *proto, *sata; + int version; + + ata_print_ident_short_sbuf(ident_data, sb); + sbuf_printf(sb, " "); + + proto = (ident_data->config == ATA_PROTO_CFA) ? "CFA" : + (ident_data->config & ATA_PROTO_ATAPI) ? "ATAPI" : "ATA"; + version = ata_version(ident_data->version_major); + + switch (version) { + case 0: + sbuf_printf(sb, "%s", proto); + break; + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + sbuf_printf(sb, "%s-%d", proto, version); + break; + case 8: + sbuf_printf(sb, "%s8-ACS", proto); + break; + default: + sbuf_printf(sb, "ACS-%d %s", version - 7, proto); + break; + } + + if (ident_data->satacapabilities && ident_data->satacapabilities != 0xffff) { + if (ident_data->satacapabilities & ATA_SATA_GEN3) + sata = " SATA 3.x"; + else if (ident_data->satacapabilities & ATA_SATA_GEN2) + sata = " SATA 2.x"; + else if (ident_data->satacapabilities & ATA_SATA_GEN1) + sata = " SATA 1.x"; + else + sata = " SATA"; + } else + sata = ""; + sbuf_printf(sb, "%s device\n", sata); } void @@ -428,18 +474,38 @@ ata_print_ident_short(struct ata_params } void +ata_print_ident_short_sbuf(struct ata_params *ident_data, struct sbuf *sb) +{ + + sbuf_printf(sb, "<"); + cam_strvis_sbuf(sb, ident_data->model, sizeof(ident_data->model), 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, ident_data->revision, sizeof(ident_data->revision), 0); + sbuf_printf(sb, ">"); +} + +void semb_print_ident(struct sep_identify_data *ident_data) { - char vendor[9], product[17], revision[5], fw[5], in[7], ins[5]; + char in[7], ins[5]; - cam_strvis(vendor, ident_data->vendor_id, 8, sizeof(vendor)); - cam_strvis(product, ident_data->product_id, 16, sizeof(product)); - cam_strvis(revision, ident_data->product_rev, 4, sizeof(revision)); - cam_strvis(fw, ident_data->firmware_rev, 4, sizeof(fw)); + semb_print_ident_short(ident_data); cam_strvis(in, ident_data->interface_id, 6, sizeof(in)); cam_strvis(ins, ident_data->interface_rev, 4, sizeof(ins)); - printf("<%s %s %s %s> SEMB %s %s device\n", - vendor, product, revision, fw, in, ins); + printf(" SEMB %s %s device\n", in, ins); +} + +void +semb_print_ident_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb) +{ + + semb_print_ident_short_sbuf(ident_data, sb); + + sbuf_printf(sb, " SEMB "); + cam_strvis_sbuf(sb, ident_data->interface_id, 6, 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, ident_data->interface_rev, 4, 0); + sbuf_printf(sb, " device\n"); } void @@ -454,6 +520,21 @@ semb_print_ident_short(struct sep_identi printf("<%s %s %s %s>", vendor, product, revision, fw); } +void +semb_print_ident_short_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb) +{ + + sbuf_printf(sb, "<"); + cam_strvis_sbuf(sb, ident_data->vendor_id, 8, 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, ident_data->product_id, 16, 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, ident_data->product_rev, 4, 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, ident_data->firmware_rev, 4, 0); + sbuf_printf(sb, ">"); +} + uint32_t ata_logical_sector_size(struct ata_params *ident_data) { Modified: head/sys/cam/ata/ata_all.h ============================================================================== --- head/sys/cam/ata/ata_all.h Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/ata/ata_all.h Wed Apr 19 15:04:52 2017 (r317143) @@ -110,7 +110,9 @@ int ata_status_sbuf(struct ccb_ataio *at int ata_res_sbuf(struct ata_res *res, struct sbuf *sb); void ata_print_ident(struct ata_params *ident_data); +void ata_print_ident_sbuf(struct ata_params *ident_data, struct sbuf *sb); void ata_print_ident_short(struct ata_params *ident_data); +void ata_print_ident_short_sbuf(struct ata_params *ident_data, struct sbuf *sb); uint32_t ata_logical_sector_size(struct ata_params *ident_data); uint64_t ata_physical_sector_size(struct ata_params *ident_data); @@ -150,7 +152,9 @@ int ata_identify_match(caddr_t identbuff int ata_static_identify_match(caddr_t identbuffer, caddr_t table_entry); void semb_print_ident(struct sep_identify_data *ident_data); +void semb_print_ident_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb); void semb_print_ident_short(struct sep_identify_data *ident_data); +void semb_print_ident_short_sbuf(struct sep_identify_data *ident_data, struct sbuf *sb); void semb_receive_diagnostic_results(struct ccb_ataio *ataio, u_int32_t retries, void (*cbfcnp)(struct cam_periph *, union ccb*), Modified: head/sys/cam/ata/ata_da.c ============================================================================== --- head/sys/cam/ata/ata_da.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/ata/ata_da.c Wed Apr 19 15:04:52 2017 (r317143) @@ -256,6 +256,10 @@ struct ada_softc { u_int errors; u_int invalidations; #endif +#define ADA_ANNOUNCETMP_SZ 80 + char announce_temp[ADA_ANNOUNCETMP_SZ]; +#define ADA_ANNOUNCE_SZ 400 + char announce_buffer[ADA_ANNOUNCE_SZ]; }; struct ada_quirk_entry { @@ -1659,8 +1663,9 @@ adaregister(struct cam_periph *periph, v struct ada_softc *softc; struct ccb_pathinq cpi; struct ccb_getdev *cgd; - char announce_buf[80]; struct disk_params *dp; + struct sbuf sb; + char *announce_buf; caddr_t match; u_int maxio; int quirks; @@ -1680,6 +1685,9 @@ adaregister(struct cam_periph *periph, v return(CAM_REQ_CMP_ERR); } + announce_buf = softc->announce_temp; + bzero(announce_buf, ADA_ANNOUNCETMP_SZ); + if (cam_iosched_init(&softc->cam_iosched, periph) != 0) { printf("adaregister: Unable to probe new device. " "Unable to allocate iosched memory\n"); @@ -1713,17 +1721,17 @@ adaregister(struct cam_periph *periph, v */ (void)cam_periph_hold(periph, PRIBIO); cam_periph_unlock(periph); - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, "kern.cam.ada.%d.quirks", periph->unit_number); quirks = softc->quirks; TUNABLE_INT_FETCH(announce_buf, &quirks); softc->quirks = quirks; softc->read_ahead = -1; - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, "kern.cam.ada.%d.read_ahead", periph->unit_number); TUNABLE_INT_FETCH(announce_buf, &softc->read_ahead); softc->write_cache = -1; - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, "kern.cam.ada.%d.write_cache", periph->unit_number); TUNABLE_INT_FETCH(announce_buf, &softc->write_cache); @@ -1829,12 +1837,16 @@ adaregister(struct cam_periph *periph, v cam_periph_lock(periph); dp = &softc->params; - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, ADA_ANNOUNCETMP_SZ, "%juMB (%ju %u byte sectors)", ((uintmax_t)dp->secsize * dp->sectors) / (1024 * 1024), (uintmax_t)dp->sectors, dp->secsize); - xpt_announce_periph(periph, announce_buf); - xpt_announce_quirks(periph, softc->quirks, ADA_Q_BIT_STRING); + + sbuf_new(&sb, softc->announce_buffer, ADA_ANNOUNCE_SZ, SBUF_FIXEDLEN); + xpt_announce_periph_sbuf(periph, &sb, announce_buf); + xpt_announce_quirks_sbuf(periph, &sb, softc->quirks, ADA_Q_BIT_STRING); + sbuf_finish(&sb); + sbuf_putbuf(&sb); /* * Create our sysctl variables, now that we know Modified: head/sys/cam/ata/ata_xpt.c ============================================================================== --- head/sys/cam/ata/ata_xpt.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/ata/ata_xpt.c Wed Apr 19 15:04:52 2017 (r317143) @@ -189,11 +189,16 @@ static void ata_dev_async(u_int32_t asy void *async_arg); static void ata_action(union ccb *start_ccb); static void ata_announce_periph(struct cam_periph *periph); +static void ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); static void ata_proto_announce(struct cam_ed *device); +static void ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); static void ata_proto_denounce(struct cam_ed *device); +static void ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); static void ata_proto_debug_out(union ccb *ccb); static void semb_proto_announce(struct cam_ed *device); +static void semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb); static void semb_proto_denounce(struct cam_ed *device); +static void semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb); static int ata_dma = 1; static int atapi_dma = 1; @@ -206,6 +211,7 @@ static struct xpt_xport_ops ata_xport_op .action = ata_action, .async = ata_dev_async, .announce = ata_announce_periph, + .announce_sbuf = ata_announce_periph_sbuf, }; #define ATA_XPT_XPORT(x, X) \ static struct xpt_xport ata_xport_ ## x = { \ @@ -222,7 +228,9 @@ ATA_XPT_XPORT(sata, SATA); static struct xpt_proto_ops ata_proto_ops_ata = { .announce = ata_proto_announce, + .announce_sbuf = ata_proto_announce_sbuf, .denounce = ata_proto_denounce, + .denounce_sbuf = ata_proto_denounce_sbuf, .debug_out = ata_proto_debug_out, }; static struct xpt_proto ata_proto_ata = { @@ -233,7 +241,9 @@ static struct xpt_proto ata_proto_ata = static struct xpt_proto_ops ata_proto_ops_satapm = { .announce = ata_proto_announce, + .announce_sbuf = ata_proto_announce_sbuf, .denounce = ata_proto_denounce, + .denounce_sbuf = ata_proto_denounce_sbuf, .debug_out = ata_proto_debug_out, }; static struct xpt_proto ata_proto_satapm = { @@ -244,7 +254,9 @@ static struct xpt_proto ata_proto_satapm static struct xpt_proto_ops ata_proto_ops_semb = { .announce = semb_proto_announce, + .announce_sbuf = semb_proto_announce_sbuf, .denounce = semb_proto_denounce, + .denounce_sbuf = semb_proto_denounce_sbuf, .debug_out = ata_proto_debug_out, }; static struct xpt_proto ata_proto_semb = { @@ -2072,42 +2084,51 @@ ata_dev_async(u_int32_t async_code, stru } static void -ata_announce_periph(struct cam_periph *periph) +_ata_announce_periph(struct cam_periph *periph, struct ccb_trans_settings *cts, u_int *speed) { struct ccb_pathinq cpi; - struct ccb_trans_settings cts; struct cam_path *path = periph->path; - u_int speed; - u_int mb; cam_periph_assert(periph, MA_OWNED); - xpt_setup_ccb(&cts.ccb_h, path, CAM_PRIORITY_NORMAL); - cts.ccb_h.func_code = XPT_GET_TRAN_SETTINGS; - cts.type = CTS_TYPE_CURRENT_SETTINGS; - xpt_action((union ccb*)&cts); - if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) + xpt_setup_ccb(&cts->ccb_h, path, CAM_PRIORITY_NORMAL); + cts->ccb_h.func_code = XPT_GET_TRAN_SETTINGS; + cts->type = CTS_TYPE_CURRENT_SETTINGS; + xpt_action((union ccb*)cts); + if ((cts->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) return; /* Ask the SIM for its base transfer speed */ xpt_setup_ccb(&cpi.ccb_h, path, CAM_PRIORITY_NORMAL); cpi.ccb_h.func_code = XPT_PATH_INQ; xpt_action((union ccb *)&cpi); /* Report connection speed */ - speed = cpi.base_transfer_speed; - if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { + *speed = cpi.base_transfer_speed; + if (cts->transport == XPORT_ATA) { struct ccb_trans_settings_pata *pata = - &cts.xport_specific.ata; + &cts->xport_specific.ata; if (pata->valid & CTS_ATA_VALID_MODE) - speed = ata_mode2speed(pata->mode); + *speed = ata_mode2speed(pata->mode); } - if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { + if (cts->transport == XPORT_SATA) { struct ccb_trans_settings_sata *sata = - &cts.xport_specific.sata; + &cts->xport_specific.sata; if (sata->valid & CTS_SATA_VALID_REVISION) - speed = ata_revision2speed(sata->revision); + *speed = ata_revision2speed(sata->revision); } +} + +static void +ata_announce_periph(struct cam_periph *periph) +{ + struct ccb_trans_settings cts; + u_int speed, mb; + + _ata_announce_periph(periph, &cts, &speed); + if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) + return; + mb = speed / 1000; if (mb > 0) printf("%s%d: %d.%03dMB/s transfers", @@ -2117,7 +2138,7 @@ ata_announce_periph(struct cam_periph *p printf("%s%d: %dKB/s transfers", periph->periph_name, periph->unit_number, speed); /* Report additional information about connection */ - if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_ATA) { + if (cts.transport == XPORT_ATA) { struct ccb_trans_settings_pata *pata = &cts.xport_specific.ata; @@ -2130,7 +2151,7 @@ ata_announce_periph(struct cam_periph *p printf("PIO %dbytes", pata->bytecount); printf(")"); } - if (cts.ccb_h.status == CAM_REQ_CMP && cts.transport == XPORT_SATA) { + if (cts.transport == XPORT_SATA) { struct ccb_trans_settings_sata *sata = &cts.xport_specific.sata; @@ -2151,6 +2172,64 @@ ata_announce_periph(struct cam_periph *p } static void +ata_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) +{ + struct ccb_trans_settings cts; + u_int speed, mb; + + _ata_announce_periph(periph, &cts, &speed); + if ((cts.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) + return; + + mb = speed / 1000; + if (mb > 0) + sbuf_printf(sb, "%s%d: %d.%03dMB/s transfers", + periph->periph_name, periph->unit_number, + mb, speed % 1000); + else + sbuf_printf(sb, "%s%d: %dKB/s transfers", periph->periph_name, + periph->unit_number, speed); + /* Report additional information about connection */ + if (cts.transport == XPORT_ATA) { + struct ccb_trans_settings_pata *pata = + &cts.xport_specific.ata; + + sbuf_printf(sb, " ("); + if (pata->valid & CTS_ATA_VALID_MODE) + sbuf_printf(sb, "%s, ", ata_mode2string(pata->mode)); + if ((pata->valid & CTS_ATA_VALID_ATAPI) && pata->atapi != 0) + sbuf_printf(sb, "ATAPI %dbytes, ", pata->atapi); + if (pata->valid & CTS_ATA_VALID_BYTECOUNT) + sbuf_printf(sb, "PIO %dbytes", pata->bytecount); + sbuf_printf(sb, ")"); + } + if (cts.transport == XPORT_SATA) { + struct ccb_trans_settings_sata *sata = + &cts.xport_specific.sata; + + sbuf_printf(sb, " ("); + if (sata->valid & CTS_SATA_VALID_REVISION) + sbuf_printf(sb, "SATA %d.x, ", sata->revision); + else + sbuf_printf(sb, "SATA, "); + if (sata->valid & CTS_SATA_VALID_MODE) + sbuf_printf(sb, "%s, ", ata_mode2string(sata->mode)); + if ((sata->valid & CTS_ATA_VALID_ATAPI) && sata->atapi != 0) + sbuf_printf(sb, "ATAPI %dbytes, ", sata->atapi); + if (sata->valid & CTS_SATA_VALID_BYTECOUNT) + sbuf_printf(sb, "PIO %dbytes", sata->bytecount); + sbuf_printf(sb, ")"); + } + sbuf_printf(sb, "\n"); +} + +static void +ata_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) +{ + ata_print_ident_sbuf(&device->ident_data, sb); +} + +static void ata_proto_announce(struct cam_ed *device) { ata_print_ident(&device->ident_data); @@ -2163,6 +2242,18 @@ ata_proto_denounce(struct cam_ed *device } static void +ata_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) +{ + ata_print_ident_short_sbuf(&device->ident_data, sb); +} + +static void +semb_proto_announce_sbuf(struct cam_ed *device, struct sbuf *sb) +{ + semb_print_ident_sbuf((struct sep_identify_data *)&device->ident_data, sb); +} + +static void semb_proto_announce(struct cam_ed *device) { semb_print_ident((struct sep_identify_data *)&device->ident_data); @@ -2175,6 +2266,12 @@ semb_proto_denounce(struct cam_ed *devic } static void +semb_proto_denounce_sbuf(struct cam_ed *device, struct sbuf *sb) +{ + semb_print_ident_short_sbuf((struct sep_identify_data *)&device->ident_data, sb); +} + +static void ata_proto_debug_out(union ccb *ccb) { char cdb_str[(sizeof(struct ata_cmd) * 3) + 1]; Modified: head/sys/cam/cam_periph.c ============================================================================== --- head/sys/cam/cam_periph.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/cam_periph.c Wed Apr 19 15:04:52 2017 (r317143) @@ -641,8 +641,14 @@ cam_periph_invalidate(struct cam_periph return; CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("Periph invalidated\n")); - if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) - xpt_denounce_periph(periph); + if ((periph->flags & CAM_PERIPH_ANNOUNCED) && !rebooting) { + struct sbuf sb; + + sbuf_new(&sb, NULL, 160, SBUF_FIXEDLEN); + xpt_denounce_periph_sbuf(periph, &sb); + sbuf_finish(&sb); + sbuf_putbuf(&sb); + } periph->flags |= CAM_PERIPH_INVALID; periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND; if (periph->periph_oninval != NULL) Modified: head/sys/cam/cam_xpt.c ============================================================================== --- head/sys/cam/cam_xpt.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/cam_xpt.c Wed Apr 19 15:04:52 2017 (r317143) @@ -116,6 +116,7 @@ struct xpt_softc { TAILQ_HEAD(, ccb_hdr) ccb_scanq; int buses_to_config; int buses_config_done; + int announce_nosbuf; /* * Registered buses @@ -174,6 +175,8 @@ SYSCTL_INT(_kern_cam, OID_AUTO, boot_del &xsoftc.boot_delay, 0, "Bus registration wait time"); SYSCTL_UINT(_kern_cam, OID_AUTO, xpt_generation, CTLFLAG_RD, &xsoftc.xpt_generation, 0, "CAM peripheral generation count"); +SYSCTL_INT(_kern_cam, OID_AUTO, announce_nosbuf, CTLFLAG_RWTUN, + &xsoftc.announce_nosbuf, 0, "Don't use sbuf for announcements"); struct cam_doneq { struct mtx_padalign cam_doneq_mtx; @@ -1094,6 +1097,64 @@ xpt_announce_periph(struct cam_periph *p } void +xpt_announce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb, + char *announce_string) +{ + struct cam_path *path = periph->path; + struct xpt_proto *proto; + + cam_periph_assert(periph, MA_OWNED); + periph->flags |= CAM_PERIPH_ANNOUNCED; + + /* Fall back to the non-sbuf method if necessary */ + if (xsoftc.announce_nosbuf != 0) { + xpt_announce_periph(periph, announce_string); + return; + } + proto = xpt_proto_find(path->device->protocol); + if (((proto != NULL) && (proto->ops->announce_sbuf == NULL)) || + (path->bus->xport->ops->announce_sbuf == NULL)) { + xpt_announce_periph(periph, announce_string); + return; + } + + sbuf_printf(sb, "%s%d at %s%d bus %d scbus%d target %d lun %jx\n", + periph->periph_name, periph->unit_number, + path->bus->sim->sim_name, + path->bus->sim->unit_number, + path->bus->sim->bus_id, + path->bus->path_id, + path->target->target_id, + (uintmax_t)path->device->lun_id); + sbuf_printf(sb, "%s%d: ", periph->periph_name, periph->unit_number); + + if (proto) + proto->ops->announce_sbuf(path->device, sb); + else + sbuf_printf(sb, "%s%d: Unknown protocol device %d\n", + periph->periph_name, periph->unit_number, + path->device->protocol); + if (path->device->serial_num_len > 0) { + /* Don't wrap the screen - print only the first 60 chars */ + sbuf_printf(sb, "%s%d: Serial Number %.60s\n", + periph->periph_name, periph->unit_number, + path->device->serial_num); + } + /* Announce transport details. */ + path->bus->xport->ops->announce_sbuf(periph, sb); + /* Announce command queueing. */ + if (path->device->inq_flags & SID_CmdQue + || path->device->flags & CAM_DEV_TAG_AFTER_COUNT) { + sbuf_printf(sb, "%s%d: Command Queueing enabled\n", + periph->periph_name, periph->unit_number); + } + /* Announce caller's details if they've passed in. */ + if (announce_string != NULL) + sbuf_printf(sb, "%s%d: %s\n", periph->periph_name, + periph->unit_number, announce_string); +} + +void xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string) { if (quirks != 0) { @@ -1103,6 +1164,21 @@ xpt_announce_quirks(struct cam_periph *p } void +xpt_announce_quirks_sbuf(struct cam_periph *periph, struct sbuf *sb, + int quirks, char *bit_string) +{ + if (xsoftc.announce_nosbuf != 0) { + xpt_announce_quirks(periph, quirks, bit_string); + return; + } + + if (quirks != 0) { + sbuf_printf(sb, "%s%d: quirks=0x%b\n", periph->periph_name, + periph->unit_number, quirks, bit_string); + } +} + +void xpt_denounce_periph(struct cam_periph *periph) { struct cam_path *path = periph->path; @@ -1130,6 +1206,45 @@ xpt_denounce_periph(struct cam_periph *p printf(" detached\n"); } +void +xpt_denounce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb) +{ + struct cam_path *path = periph->path; + struct xpt_proto *proto; + + cam_periph_assert(periph, MA_OWNED); + + /* Fall back to the non-sbuf method if necessary */ + if (xsoftc.announce_nosbuf != 0) { + xpt_denounce_periph(periph); + return; + } + proto = xpt_proto_find(path->device->protocol); + if ((proto != NULL) && (proto->ops->denounce_sbuf == NULL)) { + xpt_denounce_periph(periph); + return; + } + + sbuf_printf(sb, "%s%d at %s%d bus %d scbus%d target %d lun %jx\n", + periph->periph_name, periph->unit_number, + path->bus->sim->sim_name, + path->bus->sim->unit_number, + path->bus->sim->bus_id, + path->bus->path_id, + path->target->target_id, + (uintmax_t)path->device->lun_id); + sbuf_printf(sb, "%s%d: ", periph->periph_name, periph->unit_number); + + if (proto) + proto->ops->denounce_sbuf(path->device, sb); + else + sbuf_printf(sb, "%s%d: Unknown protocol device %d\n", + periph->periph_name, periph->unit_number, + path->device->protocol); + if (path->device->serial_num_len > 0) + sbuf_printf(sb, " s/n %.60s", path->device->serial_num); + sbuf_printf(sb, " detached\n"); +} int xpt_getattr(char *buf, size_t len, const char *attr, struct cam_path *path) Modified: head/sys/cam/cam_xpt_internal.h ============================================================================== --- head/sys/cam/cam_xpt_internal.h Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/cam_xpt_internal.h Wed Apr 19 15:04:52 2017 (r317143) @@ -47,6 +47,7 @@ typedef void (*xpt_dev_async_func)(u_int struct cam_ed *device, void *async_arg); typedef void (*xpt_announce_periph_func)(struct cam_periph *periph); +typedef void (*xpt_announce_periph_sbuf_func)(struct cam_periph *periph, struct sbuf *sbuf); struct xpt_xport_ops { xpt_alloc_device_func alloc_device; @@ -54,6 +55,7 @@ struct xpt_xport_ops { xpt_action_func action; xpt_dev_async_func async; xpt_announce_periph_func announce; + xpt_announce_periph_sbuf_func announce_sbuf; }; struct xpt_xport { @@ -67,11 +69,14 @@ SET_DECLARE(cam_xpt_xport_set, struct xp DATA_SET(cam_xpt_xport_set, data) typedef void (*xpt_proto_announce_func)(struct cam_ed *); +typedef void (*xpt_proto_announce_sbuf_func)(struct cam_ed *, struct sbuf *); typedef void (*xpt_proto_debug_out_func)(union ccb *); struct xpt_proto_ops { xpt_proto_announce_func announce; + xpt_proto_announce_sbuf_func announce_sbuf; xpt_proto_announce_func denounce; + xpt_proto_announce_sbuf_func denounce_sbuf; xpt_proto_debug_out_func debug_out; }; Modified: head/sys/cam/cam_xpt_periph.h ============================================================================== --- head/sys/cam/cam_xpt_periph.h Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/cam_xpt_periph.h Wed Apr 19 15:04:52 2017 (r317143) @@ -45,9 +45,16 @@ int32_t xpt_add_periph(struct cam_perip void xpt_remove_periph(struct cam_periph *periph); void xpt_announce_periph(struct cam_periph *periph, char *announce_string); +void xpt_announce_periph_sbuf(struct cam_periph *periph, + struct sbuf *sb, + char *announce_string); void xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string); +void xpt_announce_quirks_sbuf(struct cam_periph *periph, + struct sbuf *sb, + int quirks, char *bit_string); void xpt_denounce_periph(struct cam_periph *periph); +void xpt_denounce_periph_sbuf(struct cam_periph *periph, struct sbuf *sb); #endif #endif /* _CAM_CAM_XPT_PERIPH_H */ Modified: head/sys/cam/scsi/scsi_all.c ============================================================================== --- head/sys/cam/scsi/scsi_all.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/scsi/scsi_all.c Wed Apr 19 15:04:52 2017 (r317143) @@ -5169,7 +5169,7 @@ scsi_sense_print(struct ccb_scsiio *csio sbuf_finish(&sb); - printf("%s", sbuf_data(&sb)); + sbuf_putbuf(&sb); } #else /* !_KERNEL */ @@ -5361,11 +5361,10 @@ scsi_get_ascq(struct scsi_sense_data *se * for this routine to function properly. */ void -scsi_print_inquiry(struct scsi_inquiry_data *inq_data) +scsi_print_inquiry_sbuf(struct sbuf *sb, struct scsi_inquiry_data *inq_data) { u_int8_t type; char *dtype, *qtype; - char vendor[16], product[48], revision[16], rstr[12]; type = SID_TYPE(inq_data); @@ -5454,41 +5453,55 @@ scsi_print_inquiry(struct scsi_inquiry_d break; } - cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), - sizeof(vendor)); - cam_strvis(product, inq_data->product, sizeof(inq_data->product), - sizeof(product)); - cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), - sizeof(revision)); + scsi_print_inquiry_short_sbuf(sb, inq_data); + + sbuf_printf(sb, "%s %s ", SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", dtype); if (SID_ANSI_REV(inq_data) == SCSI_REV_0) - snprintf(rstr, sizeof(rstr), "SCSI"); + sbuf_printf(sb, "SCSI "); else if (SID_ANSI_REV(inq_data) <= SCSI_REV_SPC) { - snprintf(rstr, sizeof(rstr), "SCSI-%d", - SID_ANSI_REV(inq_data)); + sbuf_printf(sb, "SCSI-%d ", SID_ANSI_REV(inq_data)); } else { - snprintf(rstr, sizeof(rstr), "SPC-%d SCSI", - SID_ANSI_REV(inq_data) - 2); + sbuf_printf(sb, "SPC-%d SCSI ", SID_ANSI_REV(inq_data) - 2); } - printf("<%s %s %s> %s %s %s device%s\n", - vendor, product, revision, - SID_IS_REMOVABLE(inq_data) ? "Removable" : "Fixed", - dtype, rstr, qtype); + sbuf_printf(sb, "device%s\n", qtype); } void -scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data) +scsi_print_inquiry(struct scsi_inquiry_data *inq_data) +{ + struct sbuf sb; + char buffer[120]; + + sbuf_new(&sb, buffer, 120, SBUF_FIXEDLEN); + scsi_print_inquiry_sbuf(&sb, inq_data); + sbuf_finish(&sb); + sbuf_putbuf(&sb); +} + +void +scsi_print_inquiry_short_sbuf(struct sbuf *sb, struct scsi_inquiry_data *inq_data) { - char vendor[16], product[48], revision[16]; - cam_strvis(vendor, inq_data->vendor, sizeof(inq_data->vendor), - sizeof(vendor)); - cam_strvis(product, inq_data->product, sizeof(inq_data->product), - sizeof(product)); - cam_strvis(revision, inq_data->revision, sizeof(inq_data->revision), - sizeof(revision)); + sbuf_printf(sb, "<"); + cam_strvis_sbuf(sb, inq_data->vendor, sizeof(inq_data->vendor), 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, inq_data->product, sizeof(inq_data->product), 0); + sbuf_printf(sb, " "); + cam_strvis_sbuf(sb, inq_data->revision, sizeof(inq_data->revision), 0); + sbuf_printf(sb, "> "); +} + +void +scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data) +{ + struct sbuf sb; + char buffer[84]; - printf("<%s %s %s>", vendor, product, revision); + sbuf_new(&sb, buffer, 84, SBUF_FIXEDLEN); + scsi_print_inquiry_short_sbuf(&sb, inq_data); + sbuf_finish(&sb); + sbuf_putbuf(&sb); } /* Modified: head/sys/cam/scsi/scsi_all.h ============================================================================== --- head/sys/cam/scsi/scsi_all.h Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/scsi/scsi_all.h Wed Apr 19 15:04:52 2017 (r317143) @@ -3820,7 +3820,11 @@ char * scsi_cdb_string(u_int8_t *cdb_pt void scsi_cdb_sbuf(u_int8_t *cdb_ptr, struct sbuf *sb); void scsi_print_inquiry(struct scsi_inquiry_data *inq_data); +void scsi_print_inquiry_sbuf(struct sbuf *sb, + struct scsi_inquiry_data *inq_data); void scsi_print_inquiry_short(struct scsi_inquiry_data *inq_data); +void scsi_print_inquiry_short_sbuf(struct sbuf *sb, + struct scsi_inquiry_data *inq_data); u_int scsi_calc_syncsrate(u_int period_factor); u_int scsi_calc_syncparam(u_int period); Modified: head/sys/cam/scsi/scsi_cd.c ============================================================================== --- head/sys/cam/scsi/scsi_cd.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/scsi/scsi_cd.c Wed Apr 19 15:04:52 2017 (r317143) @@ -61,6 +61,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -158,6 +159,11 @@ struct cd_softc { struct cd_tocdata toc; struct disk *disk; struct callout mediapoll_c; + +#define CD_ANNOUNCETMP_SZ 120 + char announce_temp[CD_ANNOUNCETMP_SZ]; +#define CD_ANNOUNCE_SZ 400 + char announce_buf[CD_ANNOUNCE_SZ]; }; struct cd_page_sizes { @@ -1046,28 +1052,12 @@ cddone(struct cam_periph *periph, union case CD_CCB_PROBE: { struct scsi_read_capacity_data *rdcap; - char announce_buf[120]; /* - * Currently (9/30/97) the - * longest possible announce - * buffer is 108 bytes, for the - * first error case below. - * That is 39 bytes for the - * basic string, 16 bytes for the - * biggest sense key (hardware - * error), 52 bytes for the - * text of the largest sense - * qualifier valid for a CDROM, - * (0x72, 0x03 or 0x04, - * 0x03), and one byte for the - * null terminating character. - * To allow for longer strings, - * the announce buffer is 120 - * bytes. - */ + char *announce_buf; struct cd_params *cdp; int error; cdp = &softc->params; + announce_buf = softc->announce_temp; rdcap = (struct scsi_read_capacity_data *)csio->data_ptr; @@ -1081,7 +1071,7 @@ cddone(struct cam_periph *periph, union if ((csio->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP || (error = cderror(done_ccb, CAM_RETRY_SELTO, SF_RETRY_UA | SF_NO_PRINT)) == 0) { - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, CD_ANNOUNCETMP_SZ, "%juMB (%ju %u byte sectors)", ((uintmax_t)cdp->disksize * cdp->blksize) / (1024 * 1024), @@ -1186,22 +1176,29 @@ cddone(struct cam_periph *periph, union */ cam_periph_invalidate(periph); - announce_buf[0] = '\0'; + announce_buf = NULL; } else { /* * Invalidate this peripheral. */ cam_periph_invalidate(periph); - announce_buf[0] = '\0'; + announce_buf = NULL; } } } free(rdcap, M_SCSICD); - if (announce_buf[0] != '\0') { - xpt_announce_periph(periph, announce_buf); - xpt_announce_quirks(periph, softc->quirks, + if (announce_buf != NULL) { + struct sbuf sb; + + sbuf_new(&sb, softc->announce_buf, CD_ANNOUNCE_SZ, + SBUF_FIXEDLEN); + xpt_announce_periph_sbuf(periph, &sb, announce_buf); + xpt_announce_quirks_sbuf(periph, &sb, softc->quirks, CD_Q_BIT_STRING); + sbuf_finish(&sb); + sbuf_putbuf(&sb); + /* * Create our sysctl variables, now that we know * we have successfully attached. Modified: head/sys/cam/scsi/scsi_da.c ============================================================================== --- head/sys/cam/scsi/scsi_da.c Wed Apr 19 14:49:18 2017 (r317142) +++ head/sys/cam/scsi/scsi_da.c Wed Apr 19 15:04:52 2017 (r317143) @@ -338,6 +338,10 @@ struct da_softc { u_int timeouts; u_int invalidations; #endif +#define DA_ANNOUNCETMP_SZ 80 + char announce_temp[DA_ANNOUNCETMP_SZ]; +#define DA_ANNOUNCE_SZ 400 + char announcebuf[DA_ANNOUNCE_SZ]; }; #define dadeleteflag(softc, delete_method, enable) \ @@ -4219,12 +4223,16 @@ dadone(struct cam_periph *periph, union { struct scsi_read_capacity_data *rdcap; struct scsi_read_capacity_data_long *rcaplong; - char announce_buf[80]; + char *announce_buf; int lbp; lbp = 0; rdcap = NULL; rcaplong = NULL; + /* XXX TODO: can this be a malloc? */ + announce_buf = softc->announce_temp; + bzero(announce_buf, DA_ANNOUNCETMP_SZ); + if (state == DA_CCB_PROBE_RC) rdcap =(struct scsi_read_capacity_data *)csio->data_ptr; else @@ -4277,7 +4285,7 @@ dadone(struct cam_periph *periph, union xpt_print(periph->path, "unsupportable block size %ju\n", (uintmax_t) block_size); - announce_buf[0] = '\0'; + announce_buf = NULL; cam_periph_invalidate(periph); } else { /* @@ -4289,7 +4297,7 @@ dadone(struct cam_periph *periph, union rcaplong, sizeof(*rcaplong)); lbp = (lalba & SRC16_LBPME_A); dp = &softc->params; - snprintf(announce_buf, sizeof(announce_buf), + snprintf(announce_buf, DA_ANNOUNCETMP_SZ, "%juMB (%ju %u byte sectors)", ((uintmax_t)dp->secsize * dp->sectors) / (1024 * 1024), @@ -4298,8 +4306,6 @@ dadone(struct cam_periph *periph, union } else { int error; - announce_buf[0] = '\0'; - /* * Retry any UNIT ATTENTION type errors. They * are expected at boot. @@ -4383,11 +4389,10 @@ dadone(struct cam_periph *periph, union &sense_key_desc, &asc_desc); snprintf(announce_buf, - sizeof(announce_buf), - "Attempt to query device " - "size failed: %s, %s", - sense_key_desc, - asc_desc); + DA_ANNOUNCETMP_SZ, + "Attempt to query device " + "size failed: %s, %s", + sense_key_desc, asc_desc); } else { if (have_sense) scsi_sense_print( @@ -4401,6 +4406,8 @@ dadone(struct cam_periph *periph, union xpt_print(periph->path, "fatal error, " "failed to attach to device\n"); + announce_buf = NULL; + /* * Free up resources. *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***