Commit e1f0bce3 authored by Rasmus Villemoes's avatar Rasmus Villemoes Committed by Martin K. Petersen

scsi: reduce CONFIG_SCSI_CONSTANTS=y impact by 8k

On 64 bit, struct error_info has 6 bytes of padding, which amounts to
over 4k of wasted space in the additional[] array. We could easily get
rid of that by instead using separate arrays for the codes and the
pointers. However, we can do even better than that and save an
additional 6 bytes per entry: In the table, just store the sizeof()
the corresponding string literal. The cumulative sum of these is then
the appropriate offset into additional_text, which is built from the
concatenation (with '\0's inbetween) of the strings.

$ scripts/bloat-o-meter /tmp/vmlinux vmlinux
add/remove: 0/0 grow/shrink: 1/1 up/down: 24/-8488 (-8464)
function                                     old     new   delta
scsi_extd_sense_format                       136     160     +24
additional                                 11312    2824   -8488

The Kconfig help text used to say that CONFIG_SCSI_CONSTANTS=y costs
around 75 KB, but that was a little exaggerated. The actual number was
closer to 44K, and 36K with this patch.
Signed-off-by: default avatarRasmus Villemoes <linux@rasmusvillemoes.dk>
Reviewed-by: default avatarHannes Reinecke <hare@suse.com>
Tested-by: default avatarDouglas Gilbert <dgilbert@interlog.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9d99a2e3
...@@ -202,12 +202,12 @@ config SCSI_ENCLOSURE ...@@ -202,12 +202,12 @@ config SCSI_ENCLOSURE
certain enclosure conditions to be reported and is not required. certain enclosure conditions to be reported and is not required.
config SCSI_CONSTANTS config SCSI_CONSTANTS
bool "Verbose SCSI error reporting (kernel size +=75K)" bool "Verbose SCSI error reporting (kernel size += 36K)"
depends on SCSI depends on SCSI
help help
The error messages regarding your SCSI hardware will be easier to The error messages regarding your SCSI hardware will be easier to
understand if you say Y here; it will enlarge your kernel by about understand if you say Y here; it will enlarge your kernel by about
75 KB. If in doubt, say Y. 36 KB. If in doubt, say Y.
config SCSI_LOGGING config SCSI_LOGGING
bool "SCSI logging facility" bool "SCSI logging facility"
......
...@@ -292,17 +292,30 @@ bool scsi_opcode_sa_name(int opcode, int service_action, ...@@ -292,17 +292,30 @@ bool scsi_opcode_sa_name(int opcode, int service_action,
struct error_info { struct error_info {
unsigned short code12; /* 0x0302 looks better than 0x03,0x02 */ unsigned short code12; /* 0x0302 looks better than 0x03,0x02 */
const char * text; unsigned short size;
}; };
/*
* There are 700+ entries in this table. To save space, we don't store
* (code, pointer) pairs, which would make sizeof(struct
* error_info)==16 on 64 bits. Rather, the second element just stores
* the size (including \0) of the corresponding string, and we use the
* sum of these to get the appropriate offset into additional_text
* defined below. This approach saves 12 bytes per entry.
*/
static const struct error_info additional[] = static const struct error_info additional[] =
{ {
#define SENSE_CODE(c, s) {c, s}, #define SENSE_CODE(c, s) {c, sizeof(s)},
#include "sense_codes.h" #include "sense_codes.h"
#undef SENSE_CODE #undef SENSE_CODE
{0, NULL}
}; };
static const char *additional_text =
#define SENSE_CODE(c, s) s "\0"
#include "sense_codes.h"
#undef SENSE_CODE
;
struct error_info2 { struct error_info2 {
unsigned char code1, code2_min, code2_max; unsigned char code1, code2_min, code2_max;
const char * str; const char * str;
...@@ -364,11 +377,14 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt) ...@@ -364,11 +377,14 @@ scsi_extd_sense_format(unsigned char asc, unsigned char ascq, const char **fmt)
{ {
int i; int i;
unsigned short code = ((asc << 8) | ascq); unsigned short code = ((asc << 8) | ascq);
unsigned offset = 0;
*fmt = NULL; *fmt = NULL;
for (i = 0; additional[i].text; i++) for (i = 0; i < ARRAY_SIZE(additional); i++) {
if (additional[i].code12 == code) if (additional[i].code12 == code)
return additional[i].text; return additional_text + offset;
offset += additional[i].size;
}
for (i = 0; additional2[i].fmt; i++) { for (i = 0; additional2[i].fmt; i++) {
if (additional2[i].code1 == asc && if (additional2[i].code1 == asc &&
ascq >= additional2[i].code2_min && ascq >= additional2[i].code2_min &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment