summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/cam/cam.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/cam/cam.c')
-rw-r--r--freebsd/sys/cam/cam.c125
1 files changed, 106 insertions, 19 deletions
diff --git a/freebsd/sys/cam/cam.c b/freebsd/sys/cam/cam.c
index 18628cd0..71523db2 100644
--- a/freebsd/sys/cam/cam.c
+++ b/freebsd/sys/cam/cam.c
@@ -107,9 +107,6 @@ const struct cam_status_entry cam_status_table[] = {
{ CAM_SCSI_BUSY, "SCSI Bus Busy" },
};
-const int num_cam_status_entries =
- sizeof(cam_status_table)/sizeof(*cam_status_table);
-
#ifdef _KERNEL
SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem");
@@ -118,7 +115,6 @@ SYSCTL_NODE(_kern, OID_AUTO, cam, CTLFLAG_RD, 0, "CAM Subsystem");
#endif
int cam_sort_io_queues = CAM_DEFAULT_SORT_IO_QUEUES;
-TUNABLE_INT("kern.cam.sort_io_queues", &cam_sort_io_queues);
SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN,
&cam_sort_io_queues, 0, "Sort IO queues to try and optimise disk access patterns");
#endif
@@ -160,35 +156,125 @@ cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
*dst = '\0';
}
+void
+cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
+ uint32_t flags)
+{
+
+ /* Trim leading/trailing spaces, nulls. */
+ while (srclen > 0 && src[0] == ' ')
+ src++, srclen--;
+ while (srclen > 0
+ && (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
+ srclen--;
+
+ while (srclen > 0) {
+ if (*src < 0x20 || *src >= 0x80) {
+ /* SCSI-II Specifies that these should never occur. */
+ /* non-printable character */
+ switch (flags & CAM_STRVIS_FLAG_NONASCII_MASK) {
+ case CAM_STRVIS_FLAG_NONASCII_ESC:
+ sbuf_printf(sb, "\\%c%c%c",
+ ((*src & 0300) >> 6) + '0',
+ ((*src & 0070) >> 3) + '0',
+ ((*src & 0007) >> 0) + '0');
+ break;
+ case CAM_STRVIS_FLAG_NONASCII_RAW:
+ /*
+ * If we run into a NUL, just transform it
+ * into a space.
+ */
+ if (*src != 0x00)
+ sbuf_putc(sb, *src);
+ else
+ sbuf_putc(sb, ' ');
+ break;
+ case CAM_STRVIS_FLAG_NONASCII_SPC:
+ sbuf_putc(sb, ' ');
+ break;
+ case CAM_STRVIS_FLAG_NONASCII_TRIM:
+ default:
+ break;
+ }
+ } else {
+ /* normal character */
+ sbuf_putc(sb, *src);
+ }
+ src++;
+ srclen--;
+ }
+}
+
+
/*
* Compare string with pattern, returning 0 on match.
* Short pattern matches trailing blanks in name,
- * wildcard '*' in pattern matches rest of name,
- * wildcard '?' matches a single non-space character.
+ * Shell globbing rules apply: * matches 0 or more characters,
+ * ? matchces one character, [...] denotes a set to match one char,
+ * [^...] denotes a complimented set to match one character.
+ * Spaces in str used to match anything in the pattern string
+ * but was removed because it's a bug. No current patterns require
+ * it, as far as I know, but it's impossible to know what drives
+ * returned.
+ *
+ * Each '*' generates recursion, so keep the number of * in check.
*/
int
cam_strmatch(const u_int8_t *str, const u_int8_t *pattern, int str_len)
{
- while (*pattern != '\0'&& str_len > 0) {
-
+ while (*pattern != '\0' && str_len > 0) {
if (*pattern == '*') {
- return (0);
- }
- if ((*pattern != *str)
- && (*pattern != '?' || *str == ' ')) {
+ pattern++;
+ if (*pattern == '\0')
+ return (0);
+ do {
+ if (cam_strmatch(str, pattern, str_len) == 0)
+ return (0);
+ str++;
+ str_len--;
+ } while (str_len > 0);
return (1);
+ } else if (*pattern == '[') {
+ int negate_range, ok;
+ uint8_t pc, sc;
+
+ ok = 0;
+ sc = *str++;
+ str_len--;
+ if ((negate_range = (*pattern == '^')) != 0)
+ pattern++;
+ while (((pc = *pattern) != ']') && *pattern != '\0') {
+ pattern++;
+ if (*pattern == '-') {
+ if (pattern[1] == '\0') /* Bad pattern */
+ return (1);
+ if (sc >= pc && sc <= pattern[1])
+ ok = 1;
+ pattern += 2;
+ } else if (pc == sc)
+ ok = 1;
+ }
+ if (ok == negate_range)
+ return (1);
+ } else if (*pattern == '?') {
+ /* NB: || *str == ' ' of the old code is a bug and was removed */
+ /* if you add it back, keep this the last if before the naked else */
+ pattern++;
+ str++;
+ str_len--;
+ } else {
+ if (*str != *pattern)
+ return (1);
+ pattern++;
+ str++;
+ str_len--;
}
- pattern++;
- str++;
- str_len--;
}
while (str_len > 0 && *str == ' ') {
str++;
str_len--;
}
- if (str_len > 0 && *str == 0)
- str_len = 0;
return (str_len);
}
@@ -209,7 +295,7 @@ cam_fetch_status_entry(cam_status status)
{
status &= CAM_STATUS_MASK;
return (bsearch(&status, &cam_status_table,
- num_cam_status_entries,
+ nitems(cam_status_table),
sizeof(*cam_status_table),
camstatusentrycomp));
}
@@ -366,7 +452,8 @@ cam_error_string(struct cam_device *device, union ccb *ccb, char *str,
}
if (proto_flags & CAM_EAF_PRINT_RESULT) {
sbuf_cat(&sb, path_str);
- ata_res_sbuf(&ccb->ataio, &sb);
+ sbuf_printf(&sb, "RES: ");
+ ata_res_sbuf(&ccb->ataio.res, &sb);
sbuf_printf(&sb, "\n");
}