Date: Sun, 17 Apr 2016 01:35:57 +0000 (UTC) From: Scott Long <scottl@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r298134 - stable/10/sys/cam Message-ID: <201604170135.u3H1Zv1H012441@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: scottl Date: Sun Apr 17 01:35:57 2016 New Revision: 298134 URL: https://svnweb.freebsd.org/changeset/base/298134 Log: MFC r298004: Add a devctl/devd notification conduit for CAM errors that happen at the periph level. Due to not merging the changes to ata_res_sbuf(), this version is a little messy. Sponsored by: Netflix Modified: stable/10/sys/cam/cam_periph.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/cam_periph.c ============================================================================== --- stable/10/sys/cam/cam_periph.c Sat Apr 16 22:02:32 2016 (r298133) +++ stable/10/sys/cam/cam_periph.c Sun Apr 17 01:35:57 2016 (r298134) @@ -86,6 +86,7 @@ static int camperiphscsisenseerror(unio u_int32_t *timeout, u_int32_t *action, const char **action_string); +static void cam_periph_devctl_notify(union ccb *ccb); static int nperiph_drivers; static int initialized = 0; @@ -1615,7 +1616,7 @@ cam_periph_error(union ccb *ccb, cam_fla struct cam_periph *periph; const char *action_string; cam_status status; - int frozen, error, openings; + int frozen, error, openings, devctl_err; u_int32_t action, relsim_flags, timeout; action = SSQ_PRINT_SENSE; @@ -1624,9 +1625,26 @@ cam_periph_error(union ccb *ccb, cam_fla status = ccb->ccb_h.status; frozen = (status & CAM_DEV_QFRZN) != 0; status &= CAM_STATUS_MASK; - openings = relsim_flags = timeout = 0; + devctl_err = openings = relsim_flags = timeout = 0; orig_ccb = ccb; + /* Filter the errors that should be reported via devctl */ + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + case CAM_REQ_ABORTED: + case CAM_REQ_CMP_ERR: + case CAM_REQ_TERMIO: + case CAM_UNREC_HBA_ERROR: + case CAM_DATA_RUN_ERR: + case CAM_SCSI_STATUS_ERROR: + case CAM_ATA_STATUS_ERROR: + case CAM_SMP_STATUS_ERROR: + devctl_err++; + break; + default: + break; + } + switch (status) { case CAM_REQ_CMP: error = 0; @@ -1754,6 +1772,9 @@ cam_periph_error(union ccb *ccb, cam_fla xpt_print(ccb->ccb_h.path, "Retrying command\n"); } + if (devctl_err) + cam_periph_devctl_notify(orig_ccb); + if ((action & SSQ_LOST) != 0) { lun_id_t lun_id; @@ -1824,3 +1845,83 @@ cam_periph_error(union ccb *ccb, cam_fla return (error); } + +#define CAM_PERIPH_DEVD_MSG_SIZE 256 + +static void +cam_periph_devctl_notify(union ccb *ccb) +{ + struct cam_periph *periph; + struct ccb_getdev *cgd; + struct sbuf sb; + int serr, sk, asc, ascq; + char *sbmsg, *type; + + sbmsg = malloc(CAM_PERIPH_DEVD_MSG_SIZE, M_CAMPERIPH, M_NOWAIT); + if (sbmsg == NULL) + return; + + sbuf_new(&sb, sbmsg, CAM_PERIPH_DEVD_MSG_SIZE, SBUF_FIXEDLEN); + + periph = xpt_path_periph(ccb->ccb_h.path); + sbuf_printf(&sb, "device=%s%d ", periph->periph_name, + periph->unit_number); + + sbuf_printf(&sb, "serial=\""); + if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) != NULL) { + xpt_setup_ccb(&cgd->ccb_h, ccb->ccb_h.path, + CAM_PRIORITY_NORMAL); + cgd->ccb_h.func_code = XPT_GDEV_TYPE; + xpt_action((union ccb *)cgd); + + if (cgd->ccb_h.status == CAM_REQ_CMP) + sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len); + } + sbuf_printf(&sb, "\" "); + sbuf_printf(&sb, "cam_status=\"0x%x\" ", ccb->ccb_h.status); + + switch (ccb->ccb_h.status & CAM_STATUS_MASK) { + case CAM_CMD_TIMEOUT: + sbuf_printf(&sb, "timeout=%d ", ccb->ccb_h.timeout); + type = "timeout"; + break; + case CAM_SCSI_STATUS_ERROR: + sbuf_printf(&sb, "scsi_status=%d ", ccb->csio.scsi_status); + if (scsi_extract_sense_ccb(ccb, &serr, &sk, &asc, &ascq)) + sbuf_printf(&sb, "scsi_sense=\"%02x %02x %02x %02x\" ", + serr, sk, asc, ascq); + type = "error"; + break; + case CAM_ATA_STATUS_ERROR: + { + char res_str[(11 * 3) + 1]; + + sbuf_printf(&sb, "RES=\"%s\" ", ata_res_string(&ccb->ataio.res, + res_str, sizeof(res_str))); + type = "error"; + break; + } + default: + type = "error"; + break; + } + + if (ccb->ccb_h.func_code == XPT_SCSI_IO) { + sbuf_printf(&sb, "CDB=\""); + if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) + scsi_cdb_sbuf(ccb->csio.cdb_io.cdb_ptr, &sb); + else + scsi_cdb_sbuf(ccb->csio.cdb_io.cdb_bytes, &sb); + sbuf_printf(&sb, "\" "); + } else if (ccb->ccb_h.func_code == XPT_ATA_IO) { + sbuf_printf(&sb, "ACB=\""); + ata_cmd_sbuf(&ccb->ataio.cmd, &sb); + sbuf_printf(&sb, "\" "); + } + + if (sbuf_finish(&sb) == 0) + devctl_notify("CAM", "periph", type, sbuf_data(&sb)); + sbuf_delete(&sb); + free(sbmsg, M_CAMPERIPH); +} +
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201604170135.u3H1Zv1H012441>