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 <sys/cdrio.h>
 #include <sys/dvdio.h>
 #include <sys/devicestat.h>
+#include <sys/sbuf.h>
 #include <sys/sysctl.h>
 #include <sys/taskqueue.h>
 #include <geom/geom_disk.h>
@@ -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 ***
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to