1 From dccc96abfb21dc19d69e707c38c8ba439bba7160 Mon Sep 17 00:00:00 2001
2 From: Bart Van Assche <bvanassche@acm.org>
3 Date: Thu, 1 Aug 2019 15:38:14 -0700
4 Subject: scsi: core: Reduce memory required for SCSI logging
6 The data structure used for log messages is so large that it can cause a
7 boot failure. Since allocations from that data structure can fail anyway,
8 use kmalloc() / kfree() instead of that data structure.
10 See also https://bugzilla.kernel.org/show_bug.cgi?id=204119.
11 See also commit ded85c193a39 ("scsi: Implement per-cpu logging buffer") # v4.0.
13 Reported-by: Jan Palus <jpalus@fastmail.com>
14 Cc: Christoph Hellwig <hch@lst.de>
15 Cc: Hannes Reinecke <hare@suse.com>
16 Cc: Johannes Thumshirn <jthumshirn@suse.de>
17 Cc: Ming Lei <ming.lei@redhat.com>
18 Cc: Jan Palus <jpalus@fastmail.com>
19 Signed-off-by: Bart Van Assche <bvanassche@acm.org>
20 Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
22 drivers/scsi/scsi_logging.c | 48 +++------------------------------------------
23 include/scsi/scsi_dbg.h | 2 --
24 2 files changed, 3 insertions(+), 47 deletions(-)
26 diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c
27 index 39b8cc4574b4..c6ed0b12e807 100644
28 --- a/drivers/scsi/scsi_logging.c
29 +++ b/drivers/scsi/scsi_logging.c
31 #include <scsi/scsi_eh.h>
32 #include <scsi/scsi_dbg.h>
34 -#define SCSI_LOG_SPOOLSIZE 4096
36 -#if (SCSI_LOG_SPOOLSIZE / SCSI_LOG_BUFSIZE) > BITS_PER_LONG
37 -#warning SCSI logging bitmask too large
40 -struct scsi_log_buf {
41 - char buffer[SCSI_LOG_SPOOLSIZE];
45 -static DEFINE_PER_CPU(struct scsi_log_buf, scsi_format_log);
47 static char *scsi_log_reserve_buffer(size_t *len)
49 - struct scsi_log_buf *buf;
50 - unsigned long map_bits = sizeof(buf->buffer) / SCSI_LOG_BUFSIZE;
51 - unsigned long idx = 0;
54 - buf = this_cpu_ptr(&scsi_format_log);
55 - idx = find_first_zero_bit(&buf->map, map_bits);
56 - if (likely(idx < map_bits)) {
57 - while (test_and_set_bit(idx, &buf->map)) {
58 - idx = find_next_zero_bit(&buf->map, map_bits, idx);
59 - if (idx >= map_bits)
63 - if (WARN_ON(idx >= map_bits)) {
67 - *len = SCSI_LOG_BUFSIZE;
68 - return buf->buffer + idx * SCSI_LOG_BUFSIZE;
70 + return kmalloc(*len, GFP_ATOMIC);
73 static void scsi_log_release_buffer(char *bufptr)
75 - struct scsi_log_buf *buf;
79 - buf = this_cpu_ptr(&scsi_format_log);
80 - if (bufptr >= buf->buffer &&
81 - bufptr < buf->buffer + SCSI_LOG_SPOOLSIZE) {
82 - idx = (bufptr - buf->buffer) / SCSI_LOG_BUFSIZE;
83 - ret = test_and_clear_bit(idx, &buf->map);
90 static inline const char *scmd_name(const struct scsi_cmnd *scmd)
91 diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
92 index e03bd9d41fa8..7b196d234626 100644
93 --- a/include/scsi/scsi_dbg.h
94 +++ b/include/scsi/scsi_dbg.h
95 @@ -6,8 +6,6 @@ struct scsi_cmnd;
97 struct scsi_sense_hdr;
99 -#define SCSI_LOG_BUFSIZE 128
101 extern void scsi_print_command(struct scsi_cmnd *);
102 extern size_t __scsi_format_command(char *, size_t,
103 const unsigned char *, size_t);