SCSI opcode printing is tricky and needs to take into account
several different corner cases. So instead of trying to come
up with an elaborate printk() statement we should be printing
it into a local buffer.

Signed-off-by: Hannes Reinecke <h...@suse.de>
---
 drivers/scsi/constants.c | 72 ++++++++++++++++++++++++++++++------------------
 1 file changed, 45 insertions(+), 27 deletions(-)

diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 813c482..e9c099d 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -295,18 +295,20 @@ static int scsi_opcode_sa_name(int cmd, int 
service_action,
 }
 
 /* attempt to guess cdb length if cdb_len==0 . No trailing linefeed. */
-static void print_opcode_name(unsigned char * cdbp, int cdb_len)
+static int print_opcode_name(unsigned char * cdbp, int cdb_len,
+                            char *buf, int buf_len)
 {
-       int sa, len, cdb0;
-       const char * name;
+       int sa, len, cdb0, off;
+       const char * name = NULL;
 
        cdb0 = cdbp[0];
        if (cdb0 == VARIABLE_LENGTH_CMD) {
                len = scsi_varlen_cdb_length(cdbp);
                if (len < 10) {
-                       printk("short variable length command, "
-                              "len=%d ext_len=%d", len, cdb_len);
-                       return;
+                       off = scnprintf(buf, buf_len,
+                                       "short variable length command, "
+                                       "len=%d ext_len=%d", len, cdb_len);
+                       return off;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
        } else {
@@ -318,41 +320,51 @@ static void print_opcode_name(unsigned char * cdbp, int 
cdb_len)
                if (cdb0 < 0xc0) {
                        name = cdb_byte0_names[cdb0];
                        if (name)
-                               printk("%s", name);
+                               off = scnprintf(buf, buf_len, "%s", name);
                        else
-                               printk("cdb[0]=0x%x (reserved)", cdb0);
+                               off = scnprintf(buf, buf_len,
+                                               "cdb[0]=0x%x (reserved)", cdb0);
                } else
-                       printk("cdb[0]=0x%x (vendor)", cdb0);
+                       off = scnprintf(buf, buf_len,
+                                       "cdb[0]=0x%x (vendor)", cdb0);
        } else {
                if (name)
-                       printk("%s", name);
+                       off = scnprintf(buf, buf_len, "%s", name);
                else
-                       printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+                       off = scnprintf(buf, buf_len,
+                                       "cdb[0]=0x%x, sa=0x%x", cdb0, sa);
 
                if ((cdb_len > 0) && (len != cdb_len))
-                       printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
+                       off += scnprintf(buf + off, buf_len - off,
+                                        ", in_cdb_len=%d, ext_len=%d",
+                                        len, cdb_len);
        }
+       return off;
 }
 
 #else /* ifndef CONFIG_SCSI_CONSTANTS */
 
-static void print_opcode_name(unsigned char * cdbp, int cdb_len)
+static int print_opcode_name(unsigned char * cdbp, int cdb_len,
+                            char *buf, int buf_len)
 {
-       int sa, len, cdb0;
+       int sa, len, cdb0, off;
 
        cdb0 = cdbp[0];
        switch(cdb0) {
        case VARIABLE_LENGTH_CMD:
                len = scsi_varlen_cdb_length(cdbp);
                if (len < 10) {
-                       printk("short opcode=0x%x command, len=%d "
-                              "ext_len=%d", cdb0, len, cdb_len);
+                       off = scnprintf(buf, buf_len,
+                                       "short opcode=0x%x command, len=%d "
+                                       "ext_len=%d", cdb0, len, cdb_len);
                        break;
                }
                sa = (cdbp[8] << 8) + cdbp[9];
-               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+               off = scnprintf(buf, buf_len, "cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                if (len != cdb_len)
-                       printk(", in_cdb_len=%d, ext_len=%d", len, cdb_len);
+                       off += scnprintf(buf + off, buflen - off,
+                                        ", in_cdb_len=%d, ext_len=%d",
+                                        len, cdb_len);
                break;
        case MAINTENANCE_IN:
        case MAINTENANCE_OUT:
@@ -366,23 +378,29 @@ static void print_opcode_name(unsigned char * cdbp, int 
cdb_len)
        case THIRD_PARTY_COPY_IN:
        case THIRD_PARTY_COPY_OUT:
                sa = cdbp[1] & 0x1f;
-               printk("cdb[0]=0x%x, sa=0x%x", cdb0, sa);
+               off = scnprintf(buf + off, buflen - off,
+                               "cdb[0]=0x%x, sa=0x%x", cdb0, sa);
                break;
        default:
                if (cdb0 < 0xc0)
-                       printk("cdb[0]=0x%x", cdb0);
+                       off = scnprintf(buf + off, buf_len - off,
+                                       "cdb[0]=0x%x", cdb0);
                else
-                       printk("cdb[0]=0x%x (vendor)", cdb0);
+                       off = scnprintf(buf + off, buf_len - off,
+                                       "cdb[0]=0x%x (vendor)", cdb0);
                break;
        }
+       return off;
 }
 #endif
 
 void __scsi_print_command(unsigned char *cdb)
 {
-       int k, len;
+       char buf[80];
+       int k, len, off = 0;
 
-       print_opcode_name(cdb, 0);
+       off = print_opcode_name(cdb, 0, buf, 80);
+       printk("%s", buf);
        len = scsi_command_size(cdb);
        /* print out all bytes in cdb */
        for (k = 0; k < len; ++k)
@@ -393,16 +411,16 @@ EXPORT_SYMBOL(__scsi_print_command);
 
 void scsi_print_command(struct scsi_cmnd *cmd)
 {
-       int k;
+       char buf[80];
+       int k, off = 0;
 
        if (cmd->cmnd == NULL)
                return;
 
-       scmd_printk(KERN_INFO, cmd, "CDB: ");
-       print_opcode_name(cmd->cmnd, cmd->cmd_len);
+       off = print_opcode_name(cmd->cmnd, cmd->cmd_len, buf, 80);
+       scmd_printk(KERN_INFO, cmd, "CDB: %s:", buf);
 
        /* print out all bytes in cdb */
-       printk(":");
        for (k = 0; k < cmd->cmd_len; ++k)
                printk(" %02x", cmd->cmnd[k]);
        printk("\n");
-- 
1.8.5.2

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to