Fix non-printable characters in NVMe model and serial numbers.
The NVMe 1.4 spec simply says that Model and Serial numbers are ASCII strings. Unlike SCSI, it doesn't prohibit non-printable characters or say that the strings should be padded with spaces. Since 2014, we have had cam_strvis_sbuf(), which gives additional options for handling non-ASCII characters. That behavior hasn't been available for non-sbuf consumers, so users of cam_strvis() were left with having octal ASCII codes inserted. So, to avoid having garbage or octal chracters in the strings, use cam_strvis_sbuf() to create a new function, cam_strvis_flag(), and re-implement cam_strvis() using cam_strvis_flag(). Now, for the NVMe drives, we can use cam_strvis_flag with the CAM_STRVIS_FLAG_NONASCII_SPC flag. This transforms non-printable characters into spaces. sys/cam/cam.c: Add a new function, cam_strvis_flag(), that creates an sbuf on the stack with the user's destination buffer, and calls cam_strvis_sbuf() with the given flag argument. Re-implement cam_strvis() to call cam_strvis_flag with the CAM_STRVIS_FLAG_NONASCII_ESC argument. This should be the equivalent of the old cam_strvis() function, except for the overhead of creating the sbuf and calling sbuf_putc/printf. sys/cam/cam.h: Declaration for cam_strvis_flag. sys/cam/nvme/nvme_all.c: In nvme_print_ident, use the NONASCII_SPC flag with cam_strvis_flag(). sys/cam/nvme/nvme_da.c: In ndaregister(), use cam_strvis_flag() with the NONASCII_SPC flag for the disk description and serial number we report to GEOM. sys/cam/nvme/nvme_xpt.c: In nvme_probe_done(), use cam_strvis_flag with the NONASCII_SPC flag when storing the drive serial number in the CAM EDT. MFC after: 1 week Sponsored by: Spectra Logic Differential Revision: https://reviews.freebsd.org/D33973
This commit is contained in:
parent
af7d105379
commit
3090d5045a
@ -123,38 +123,19 @@ SYSCTL_INT(_kern_cam, OID_AUTO, sort_io_queues, CTLFLAG_RWTUN,
|
||||
void
|
||||
cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
|
||||
{
|
||||
cam_strvis_flag(dst, src, srclen, dstlen,
|
||||
CAM_STRVIS_FLAG_NONASCII_ESC);
|
||||
}
|
||||
|
||||
/* Trim leading/trailing spaces, nulls. */
|
||||
while (srclen > 0 && src[0] == ' ')
|
||||
src++, srclen--;
|
||||
while (srclen > 0
|
||||
&& (src[srclen-1] == ' ' || src[srclen-1] == '\0'))
|
||||
srclen--;
|
||||
void
|
||||
cam_strvis_flag(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen,
|
||||
uint32_t flags)
|
||||
{
|
||||
struct sbuf sb;
|
||||
|
||||
while (srclen > 0 && dstlen > 1) {
|
||||
u_int8_t *cur_pos = dst;
|
||||
|
||||
if (*src < 0x20 || *src >= 0x80) {
|
||||
/* SCSI-II Specifies that these should never occur. */
|
||||
/* non-printable character */
|
||||
if (dstlen > 4) {
|
||||
*cur_pos++ = '\\';
|
||||
*cur_pos++ = ((*src & 0300) >> 6) + '0';
|
||||
*cur_pos++ = ((*src & 0070) >> 3) + '0';
|
||||
*cur_pos++ = ((*src & 0007) >> 0) + '0';
|
||||
} else {
|
||||
*cur_pos++ = '?';
|
||||
}
|
||||
} else {
|
||||
/* normal character */
|
||||
*cur_pos++ = *src;
|
||||
}
|
||||
src++;
|
||||
srclen--;
|
||||
dstlen -= cur_pos - dst;
|
||||
dst = cur_pos;
|
||||
}
|
||||
*dst = '\0';
|
||||
sbuf_new(&sb, dst, dstlen, SBUF_FIXEDLEN);
|
||||
cam_strvis_sbuf(&sb, src, srclen, flags);
|
||||
sbuf_finish(&sb);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -378,6 +378,8 @@ caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries,
|
||||
int entry_size, cam_quirkmatch_t *comp_func);
|
||||
|
||||
void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen);
|
||||
void cam_strvis_flag(u_int8_t *dst, const u_int8_t *src, int srclen,
|
||||
int dstlen, uint32_t flags);
|
||||
void cam_strvis_sbuf(struct sbuf *sb, const u_int8_t *src, int srclen,
|
||||
uint32_t flags);
|
||||
|
||||
|
@ -91,11 +91,14 @@ nvme_print_ident(const struct nvme_controller_data *cdata,
|
||||
{
|
||||
|
||||
sbuf_printf(sb, "<");
|
||||
cam_strvis_sbuf(sb, cdata->mn, sizeof(cdata->mn), 0);
|
||||
cam_strvis_sbuf(sb, cdata->mn, sizeof(cdata->mn),
|
||||
CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, cdata->fr, sizeof(cdata->fr), 0);
|
||||
cam_strvis_sbuf(sb, cdata->fr, sizeof(cdata->fr),
|
||||
CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
sbuf_printf(sb, " ");
|
||||
cam_strvis_sbuf(sb, cdata->sn, sizeof(cdata->sn), 0);
|
||||
cam_strvis_sbuf(sb, cdata->sn, sizeof(cdata->sn),
|
||||
CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
sbuf_printf(sb, ">\n");
|
||||
}
|
||||
|
||||
|
@ -930,10 +930,12 @@ ndaregister(struct cam_periph *periph, void *arg)
|
||||
* d_ident and d_descr are both far bigger than the length of either
|
||||
* the serial or model number strings.
|
||||
*/
|
||||
cam_strvis(disk->d_descr, cd->mn,
|
||||
NVME_MODEL_NUMBER_LENGTH, sizeof(disk->d_descr));
|
||||
cam_strvis(disk->d_ident, cd->sn,
|
||||
NVME_SERIAL_NUMBER_LENGTH, sizeof(disk->d_ident));
|
||||
cam_strvis_flag(disk->d_descr, cd->mn, NVME_MODEL_NUMBER_LENGTH,
|
||||
sizeof(disk->d_descr), CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
|
||||
cam_strvis_flag(disk->d_ident, cd->sn, NVME_SERIAL_NUMBER_LENGTH,
|
||||
sizeof(disk->d_ident), CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
|
||||
disk->d_hba_vendor = cpi.hba_vendor;
|
||||
disk->d_hba_device = cpi.hba_device;
|
||||
disk->d_hba_subvendor = cpi.hba_subvendor;
|
||||
|
@ -376,8 +376,11 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
|
||||
path->device->serial_num = (u_int8_t *)
|
||||
malloc(NVME_SERIAL_NUMBER_LENGTH + 1, M_CAMXPT, M_NOWAIT);
|
||||
if (path->device->serial_num != NULL) {
|
||||
cam_strvis(path->device->serial_num, nvme_cdata->sn,
|
||||
NVME_SERIAL_NUMBER_LENGTH, NVME_SERIAL_NUMBER_LENGTH + 1);
|
||||
cam_strvis_flag(path->device->serial_num,
|
||||
nvme_cdata->sn, sizeof(nvme_cdata->sn),
|
||||
NVME_SERIAL_NUMBER_LENGTH + 1,
|
||||
CAM_STRVIS_FLAG_NONASCII_SPC);
|
||||
|
||||
path->device->serial_num_len =
|
||||
strlen(path->device->serial_num);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user