Print this page
NEX-16174 scsi error messages should go to system log only
Reviewed by: Dan Fields <dan.fields@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
1787 SATL fails to handle returned SMART sense data
Reviewed by: Richard Elling <richard.elling@richardelling.com>
Reviewed by: Saso Kiselkov <skiselkov.ml@gmail.com>
Reviewed by: Garrett D'Amore <garrett@damore.org>
Approved by: Robert Mustacchi <rm@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/io/scsi/impl/scsi_subr.c
          +++ new/usr/src/uts/common/io/scsi/impl/scsi_subr.c
↓ open down ↓ 463 lines elided ↑ open up ↑
 464  464          } else if (IS_2BYTE_MSG(msg) &&
 465  465              (int)((msg) & 0xF) < (sizeof (imsgs_2) / sizeof (char *))) {
 466  466                  return (imsgs_2[msg & 0xF]);
 467  467          } else {
 468  468                  return ("<unknown msg>");
 469  469          }
 470  470  
 471  471  }
 472  472  
 473  473  char *
 474      -scsi_cname(uchar_t cmd, register char **cmdvec)
      474 +scsi_cname(uchar_t cmd, char **cmdvec)
 475  475  {
 476      -        while (*cmdvec != (char *)0) {
 477      -                if (cmd == **cmdvec) {
 478      -                        return ((char *)((long)(*cmdvec)+1));
 479      -                }
      476 +        while (*cmdvec != NULL) {
      477 +                if (cmd == **cmdvec)
      478 +                        return ((char *)(uintptr_t)(*cmdvec + 1));
 480  479                  cmdvec++;
 481  480          }
 482  481          return (sprintf(scsi_tmpname, "<undecoded cmd 0x%x>", cmd));
 483  482  }
 484  483  
 485  484  char *
 486  485  scsi_cmd_name(uchar_t cmd, struct scsi_key_strings *cmdlist, char *tmpstr)
 487  486  {
 488  487          int i = 0;
 489  488  
↓ open down ↓ 528 lines elided ↑ open up ↑
1018 1017  char *
1019 1018  scsi_sname(uchar_t sense_key)
1020 1019  {
1021 1020          if (sense_key >= (uchar_t)(NUM_SENSE_KEYS+NUM_IMPL_SENSE_KEYS)) {
1022 1021                  return ("<unknown sense key>");
1023 1022          } else {
1024 1023                  return (sense_keys[sense_key]);
1025 1024          }
1026 1025  }
1027 1026  
1028      -
1029      -/*
1030      - * Print a piece of inquiry data- cleaned up for non-printable characters.
1031      - */
1032      -static void
1033      -inq_fill(char *p, int l, char *s)
1034      -{
1035      -        register unsigned i = 0;
1036      -        char c;
1037      -
1038      -        if (!p)
1039      -                return;
1040      -
1041      -        while (i++ < l) {
1042      -                /* clean string of non-printing chars */
1043      -                if ((c = *p++) < ' ' || c >= 0177) {
1044      -                        c = ' ';
1045      -                }
1046      -                *s++ = c;
1047      -        }
1048      -        *s++ = 0;
1049      -}
1050      -
1051 1027  static char *
1052 1028  scsi_asc_search(uint_t asc, uint_t ascq,
1053 1029      struct scsi_asq_key_strings *list)
1054 1030  {
1055 1031          int i = 0;
1056 1032  
1057 1033          while (list[i].asc != 0xffff) {
1058 1034                  if ((asc == list[i].asc) &&
1059 1035                      ((ascq == list[i].ascq) ||
1060 1036                      (list[i].ascq == 0xffff))) {
1061 1037                          return ((char *)list[i].message);
1062 1038                  }
1063 1039                  i++;
1064 1040          }
1065 1041          return (NULL);
1066 1042  }
1067 1043  
1068 1044  static char *
1069 1045  scsi_asc_ascq_name(uint_t asc, uint_t ascq, char *tmpstr,
1070      -        struct scsi_asq_key_strings *list)
     1046 +    struct scsi_asq_key_strings *list)
1071 1047  {
1072 1048          char *message;
1073 1049  
1074 1050          if (list) {
1075 1051                  if (message = scsi_asc_search(asc, ascq, list)) {
1076 1052                          return (message);
1077 1053                  }
1078 1054          }
1079 1055          if (message = scsi_asc_search(asc, ascq, extended_sense_list)) {
1080 1056                  return (message);
1081 1057          }
1082 1058  
1083 1059          return (sprintf(tmpstr, "<vendor unique code 0x%x>", asc));
1084 1060  }
1085 1061  
1086      -/*
1087      - * The first part/column of the error message will be at least this length.
1088      - * This number has been calculated so that each line fits in 80 chars.
1089      - */
1090      -#define SCSI_ERRMSG_COLUMN_LEN  42
1091      -#define SCSI_ERRMSG_BUF_LEN     256
     1062 +#define SCSI_LOGBUF_LEN 512
1092 1063  
1093 1064  void
1094 1065  scsi_generic_errmsg(struct scsi_device *devp, char *label, int severity,
1095 1066      daddr_t blkno, daddr_t err_blkno,
1096 1067      uchar_t cmd_name, struct scsi_key_strings *cmdlist,
1097 1068      uint8_t *sensep, struct scsi_asq_key_strings *asc_list,
1098 1069      char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1099 1070  {
1100      -        uchar_t com;
1101      -        static char buf[SCSI_ERRMSG_BUF_LEN];
1102      -        static char buf1[SCSI_ERRMSG_BUF_LEN];
1103      -        static char tmpbuf[64];
1104      -        static char pad[SCSI_ERRMSG_COLUMN_LEN];
1105      -        dev_info_t *dev = devp->sd_dev;
     1071 +        char cmdbuf[SCSI_LOGBUF_LEN];
     1072 +        char blkbuf[SCSI_LOGBUF_LEN];
     1073 +        char sensebuf[SCSI_LOGBUF_LEN];
     1074 +        char frubuf[SCSI_LOGBUF_LEN];
     1075 +        char tmpbuf[SCSI_LOGBUF_LEN];
1106 1076          static char *error_classes[] = {
1107 1077                  "All", "Unknown", "Informational",
1108 1078                  "Recovered", "Retryable", "Fatal"
1109 1079          };
1110      -        uchar_t sense_key, asc, ascq, fru_code;
1111      -        uchar_t *fru_code_ptr;
1112      -        int i, buflen;
1113 1080  
1114 1081          mutex_enter(&scsi_log_mutex);
1115 1082  
1116      -        /*
1117      -         * We need to put our space padding code because kernel version
1118      -         * of sprintf(9F) doesn't support %-<number>s type of left alignment.
1119      -         */
1120      -        for (i = 0; i < SCSI_ERRMSG_COLUMN_LEN; i++) {
1121      -                pad[i] = ' ';
1122      -        }
     1083 +        (void) snprintf(cmdbuf, sizeof (cmdbuf), "%s: cmd=%s",
     1084 +            error_classes[severity], scsi_cmd_name(cmd_name, cmdlist, tmpbuf));
1123 1085  
1124      -        bzero(buf, SCSI_ERRMSG_BUF_LEN);
1125      -        com = cmd_name;
1126      -        (void) sprintf(buf, "Error for Command: %s",
1127      -            scsi_cmd_name(com, cmdlist, tmpbuf));
1128      -        buflen = strlen(buf);
1129      -        if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1130      -                pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1131      -                (void) sprintf(&buf[buflen], "%s Error Level: %s",
1132      -                    pad, error_classes[severity]);
1133      -                pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1134      -        } else {
1135      -                (void) sprintf(&buf[buflen], " Error Level: %s",
1136      -                    error_classes[severity]);
     1086 +        blkbuf[0] = '\0';
     1087 +        if ((blkno != -1 || err_blkno != -1) &&
     1088 +            ((cmd_name & 0xf) == SCMD_READ || (cmd_name & 0xf) == SCMD_WRITE)) {
     1089 +                (void) snprintf(blkbuf, sizeof (blkbuf),
     1090 +                    " (reqblk=%ld errblk=%ld)", blkno, err_blkno);
1137 1091          }
1138      -        impl_scsi_log(dev, label, CE_WARN, buf);
1139 1092  
1140      -        if (blkno != -1 || err_blkno != -1 &&
1141      -            ((com & 0xf) == SCMD_READ) || ((com & 0xf) == SCMD_WRITE)) {
1142      -                bzero(buf, SCSI_ERRMSG_BUF_LEN);
1143      -                (void) sprintf(buf, "Requested Block: %ld", blkno);
1144      -                buflen = strlen(buf);
1145      -                if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1146      -                        pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1147      -                        (void) sprintf(&buf[buflen], "%s Error Block: %ld\n",
1148      -                            pad, err_blkno);
1149      -                        pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1150      -                } else {
1151      -                        (void) sprintf(&buf[buflen], " Error Block: %ld\n",
1152      -                            err_blkno);
1153      -                }
1154      -                impl_scsi_log(dev, label, CE_CONT, buf);
1155      -        }
     1093 +        sensebuf[0] = '\0';
     1094 +        frubuf[0] = '\0';
     1095 +        if (sensep != NULL) {
     1096 +                uchar_t sense_key, asc, ascq, fru_code;
     1097 +                uchar_t *fru_code_ptr;
1156 1098  
1157      -        bzero(buf, SCSI_ERRMSG_BUF_LEN);
1158      -        (void) strcpy(buf, "Vendor: ");
1159      -        inq_fill(devp->sd_inq->inq_vid, 8, &buf[strlen(buf)]);
1160      -        buflen = strlen(buf);
1161      -        if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1162      -                pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = '\0';
1163      -                (void) sprintf(&buf[strlen(buf)], "%s Serial Number: ", pad);
1164      -                pad[SCSI_ERRMSG_COLUMN_LEN - buflen] = ' ';
1165      -        } else {
1166      -                (void) sprintf(&buf[strlen(buf)], " Serial Number: ");
1167      -        }
1168      -        inq_fill(devp->sd_inq->inq_serial, 12, &buf[strlen(buf)]);
1169      -        impl_scsi_log(dev, label, CE_CONT, "%s\n", buf);
1170      -
1171      -        if (sensep) {
1172 1099                  sense_key = scsi_sense_key(sensep);
1173 1100                  asc = scsi_sense_asc(sensep);
1174 1101                  ascq = scsi_sense_ascq(sensep);
1175 1102                  scsi_ext_sense_fields(sensep, SENSE_LENGTH,
1176 1103                      NULL, NULL, &fru_code_ptr, NULL, NULL);
1177      -                fru_code = (fru_code_ptr ? *fru_code_ptr : 0);
1178 1104  
1179      -                bzero(buf, SCSI_ERRMSG_BUF_LEN);
1180      -                (void) sprintf(buf, "Sense Key: %s\n",
1181      -                    sense_keys[sense_key]);
1182      -                impl_scsi_log(dev, label, CE_CONT, buf);
     1105 +                (void) snprintf(sensebuf, sizeof (sensebuf),
     1106 +                    " key=%s asc/ascq=0x%x/0x%x (\"%s\")",
     1107 +                    sense_keys[sense_key], asc, ascq,
     1108 +                    scsi_asc_ascq_name(asc, ascq, tmpbuf, asc_list));
1183 1109  
1184      -                bzero(buf, SCSI_ERRMSG_BUF_LEN);
1185      -                if ((fru_code != 0) &&
1186      -                    (decode_fru != NULL)) {
1187      -                        (*decode_fru)(devp, buf, SCSI_ERRMSG_BUF_LEN,
1188      -                            fru_code);
1189      -                        if (buf[0] != NULL) {
1190      -                                bzero(buf1, SCSI_ERRMSG_BUF_LEN);
1191      -                                (void) sprintf(&buf1[strlen(buf1)],
1192      -                                    "ASC: 0x%x (%s)", asc,
1193      -                                    scsi_asc_ascq_name(asc, ascq,
1194      -                                    tmpbuf, asc_list));
1195      -                                buflen = strlen(buf1);
1196      -                                if (buflen < SCSI_ERRMSG_COLUMN_LEN) {
1197      -                                        pad[SCSI_ERRMSG_COLUMN_LEN - buflen] =
1198      -                                            '\0';
1199      -                                        (void) sprintf(&buf1[buflen],
1200      -                                            "%s ASCQ: 0x%x", pad, ascq);
1201      -                                } else {
1202      -                                        (void) sprintf(&buf1[buflen],
1203      -                                            " ASCQ: 0x%x", ascq);
1204      -                                }
1205      -                                impl_scsi_log(dev,
1206      -                                    label, CE_CONT, "%s\n", buf1);
1207      -                                impl_scsi_log(dev,
1208      -                                    label, CE_CONT, "FRU: 0x%x (%s)\n",
1209      -                                    fru_code, buf);
1210      -                                mutex_exit(&scsi_log_mutex);
1211      -                                return;
     1110 +                fru_code = (fru_code_ptr != NULL ? *fru_code_ptr : 0);
     1111 +                if (fru_code != 0 &&
     1112 +                    decode_fru != NULL) {
     1113 +                        (*decode_fru)(devp, tmpbuf, sizeof (tmpbuf), fru_code);
     1114 +                        if (tmpbuf[0] != '\0') {
     1115 +                                (void) snprintf(frubuf, sizeof (frubuf),
     1116 +                                    " fru=0x%x (\"%s\")", fru_code, tmpbuf);
1212 1117                          }
1213 1118                  }
1214      -                (void) sprintf(&buf[strlen(buf)],
1215      -                    "ASC: 0x%x (%s), ASCQ: 0x%x, FRU: 0x%x",
1216      -                    asc, scsi_asc_ascq_name(asc, ascq, tmpbuf, asc_list),
1217      -                    ascq, fru_code);
1218      -                impl_scsi_log(dev, label, CE_CONT, "%s\n", buf);
1219 1119          }
     1120 +
     1121 +        impl_scsi_log(devp->sd_dev, label, CE_WARN, "!%s%s%s%s",
     1122 +            cmdbuf, blkbuf, sensebuf, frubuf);
     1123 +
1220 1124          mutex_exit(&scsi_log_mutex);
1221 1125  }
1222 1126  
1223 1127  void
1224 1128  scsi_vu_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1225 1129      int severity, daddr_t blkno, daddr_t err_blkno,
1226 1130      struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep,
1227 1131      struct scsi_asq_key_strings *asc_list,
1228 1132      char *(*decode_fru)(struct scsi_device *, char *, int, uchar_t))
1229 1133  {
1230 1134          uchar_t com;
1231 1135  
1232 1136          com = ((union scsi_cdb *)pkt->pkt_cdbp)->scc_cmd;
1233 1137  
1234 1138          scsi_generic_errmsg(devp, label, severity, blkno, err_blkno,
1235 1139              com, cmdlist, (uint8_t *)sensep, asc_list, decode_fru);
1236      -
1237      -
1238 1140  }
1239 1141  
1240 1142  void
1241 1143  scsi_errmsg(struct scsi_device *devp, struct scsi_pkt *pkt, char *label,
1242 1144      int severity, daddr_t blkno, daddr_t err_blkno,
1243 1145      struct scsi_key_strings *cmdlist, struct scsi_extended_sense *sensep)
1244 1146  {
1245 1147          scsi_vu_errmsg(devp, pkt, label, severity, blkno,
1246 1148              err_blkno, cmdlist, sensep, NULL, NULL);
1247 1149  }
↓ open down ↓ 19 lines elided ↑ open up ↑
1267 1169  {
1268 1170          va_list ap;
1269 1171  
1270 1172          ASSERT(mutex_owned(&scsi_log_mutex));
1271 1173  
1272 1174          va_start(ap, fmt);
1273 1175          v_scsi_log(dev, label, level, fmt, ap);
1274 1176          va_end(ap);
1275 1177  }
1276 1178  
1277      -
1278      -char *ddi_pathname(dev_info_t *dip, char *path);
1279      -
1280 1179  /*PRINTFLIKE4*/
1281 1180  static void
1282 1181  v_scsi_log(dev_info_t *dev, char *label, uint_t level,
1283 1182      const char *fmt, va_list ap)
1284 1183  {
1285 1184          static char name[256];
1286 1185          int log_only = 0;
1287 1186          int boot_only = 0;
1288 1187          int console_only = 0;
1289 1188  
1290 1189          ASSERT(mutex_owned(&scsi_log_mutex));
1291 1190  
1292      -        if (dev) {
     1191 +        if (dev != NULL) {
1293 1192                  if (level == CE_PANIC || level == CE_WARN ||
1294      -                    level == CE_NOTE) {
1295      -                        (void) sprintf(name, "%s (%s%d):\n",
1296      -                            ddi_pathname(dev, scsi_log_buffer),
1297      -                            label, ddi_get_instance(dev));
1298      -                } else if (level >= (uint_t)SCSI_DEBUG) {
1299      -                        (void) sprintf(name,
1300      -                            "%s%d:", label, ddi_get_instance(dev));
     1193 +                    level == CE_NOTE || level >= (uint_t)SCSI_DEBUG) {
     1194 +                        (void) snprintf(name, sizeof (name), "%s%d: ",
     1195 +                            ddi_driver_name(dev), ddi_get_instance(dev));
1301 1196                  } else {
1302 1197                          name[0] = '\0';
1303 1198                  }
1304 1199          } else {
1305      -                (void) sprintf(name, "%s:", label);
     1200 +                (void) sprintf(name, "%s: ", label);
1306 1201          }
1307 1202  
1308 1203          (void) vsprintf(scsi_log_buffer, fmt, ap);
1309 1204  
1310 1205          switch (scsi_log_buffer[0]) {
1311 1206          case '!':
1312 1207                  log_only = 1;
1313 1208                  break;
1314 1209          case '?':
1315 1210                  boot_only = 1;
↓ open down ↓ 4 lines elided ↑ open up ↑
1320 1215          }
1321 1216  
1322 1217          switch (level) {
1323 1218          case CE_NOTE:
1324 1219                  level = CE_CONT;
1325 1220                  /* FALLTHROUGH */
1326 1221          case CE_CONT:
1327 1222          case CE_WARN:
1328 1223          case CE_PANIC:
1329 1224                  if (boot_only) {
1330      -                        cmn_err(level, "?%s\t%s", name, &scsi_log_buffer[1]);
     1225 +                        cmn_err(level, "?%s%s", name, &scsi_log_buffer[1]);
1331 1226                  } else if (console_only) {
1332      -                        cmn_err(level, "^%s\t%s", name, &scsi_log_buffer[1]);
     1227 +                        cmn_err(level, "^%s%s", name, &scsi_log_buffer[1]);
1333 1228                  } else if (log_only) {
1334      -                        cmn_err(level, "!%s\t%s", name, &scsi_log_buffer[1]);
     1229 +                        cmn_err(level, "!%s%s", name, &scsi_log_buffer[1]);
1335 1230                  } else {
1336      -                        cmn_err(level, "%s\t%s", name, scsi_log_buffer);
     1231 +                        cmn_err(level, "%s%s", name, scsi_log_buffer);
1337 1232                  }
1338 1233                  break;
1339 1234          case (uint_t)SCSI_DEBUG:
1340 1235          default:
1341      -                cmn_err(CE_CONT, "^DEBUG: %s\t%s", name, scsi_log_buffer);
     1236 +                cmn_err(CE_CONT, "?DEBUG: %s%s", name, scsi_log_buffer);
1342 1237                  break;
1343 1238          }
1344 1239  }
1345 1240  
1346 1241  /*
1347 1242   * Lookup the 'prop_name' string array property and walk thru its list of
1348 1243   * tuple values looking for a tuple who's VID/PID string (first part of tuple)
1349 1244   * matches the inquiry VID/PID information for the scsi_device.  On a match,
1350 1245   * return a duplicate of the second part of the tuple.  If no match is found,
1351 1246   * return NULL. On non-NULL return, caller is responsible for freeing return
↓ open down ↓ 1345 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX