Re: [PATCH 13/22] scsi: use local buffer for printing the opcode

2014-09-01 Thread Hannes Reinecke
On 09/01/2014 12:19 AM, Christoph Hellwig wrote:
 On Thu, Aug 28, 2014 at 07:33:27PM +0200, Hannes Reinecke wrote:
 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.
 
 scsi_print_command callers are usually deep down the call chain., so I'd
 rather avoid using up even more stack here.  What are the exact reasons
 that we need the local buffer?
 
I know, and I'm not happy with this patch, either.

However, we really, _really_, want to print the decode command name
and the CDB in one line ie with one printk() statement.
If we don't we'll end up with individual logging messages with one
byte per line under high load.
Making it impossible to figure out to which CDB these individual
bytes are related to.

It would be possible to unroll the CDB decoding loop, as we're
typically have only 3 formats. But it's near impossible to find some
common ground when decoding the command; I've ended up having
really convoluted #defines calling into each other, making debugging
that code really horrible.

You're more than welcome to try...

But for now I fear we have to bite the bullet, and ensure the
additional stack space it only used when logging is enabled.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries  Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
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


Re: [PATCH 13/22] scsi: use local buffer for printing the opcode

2014-09-01 Thread Hannes Reinecke
On 09/01/2014 10:57 AM, Hannes Reinecke wrote:
 On 09/01/2014 12:19 AM, Christoph Hellwig wrote:
 On Thu, Aug 28, 2014 at 07:33:27PM +0200, Hannes Reinecke wrote:
 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.

 scsi_print_command callers are usually deep down the call chain., so I'd
 rather avoid using up even more stack here.  What are the exact reasons
 that we need the local buffer?

 I know, and I'm not happy with this patch, either.
 
 However, we really, _really_, want to print the decode command name
 and the CDB in one line ie with one printk() statement.
 If we don't we'll end up with individual logging messages with one
 byte per line under high load.
 Making it impossible to figure out to which CDB these individual
 bytes are related to.
 
 It would be possible to unroll the CDB decoding loop, as we're
 typically have only 3 formats. But it's near impossible to find some
 common ground when decoding the command; I've ended up having
 really convoluted #defines calling into each other, making debugging
 that code really horrible.
 

Actually, I'm not sure we _can_ avoid increase stack usage when
printing the CDB.

At the end of the day, we want to print a CDB with one printk()
statement. So we'll be having at least 9 arguments to printk per CDB
(format, device name, opcode name, and CDB bytes).
And as we only have a limited register set available we'll be ending
up putting most things on the stack _anyway_, especially for larger
CDBs.
Hiding that behind an elaborate set of preprocessor definitions
and va_format thingies just serves to obfuscate the matter.

Hence I'll be voting to make this explicit and use a local buffer
and only two or three function arguments.
We can optimize it by calling printk() directly for smaller CDB
lengths, but with 16-byte CDBs we'll be using probably the stack
size as with a local buffer.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries  Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
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


Re: [PATCH 13/22] scsi: use local buffer for printing the opcode

2014-08-31 Thread Christoph Hellwig
On Thu, Aug 28, 2014 at 07:33:27PM +0200, Hannes Reinecke wrote:
 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.

scsi_print_command callers are usually deep down the call chain., so I'd
rather avoid using up even more stack here.  What are the exact reasons
that we need the local buffer?

--
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


[PATCH 13/22] scsi: use local buffer for printing the opcode

2014-08-28 Thread Hannes Reinecke
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)
-