On 7/26/19 6:48 PM, Bart Van Assche wrote:
> The data structure used for log messages is so large that it can cause a
> boot failure. Since allocations from that data structure can fail anyway,
> use kmalloc() / kfree() instead of that data structure.
> 
> See also https://bugzilla.kernel.org/show_bug.cgi?id=204119.
> See also commit ded85c193a39 ("scsi: Implement per-cpu logging buffer") # 
> v4.0.
> 
> Reported-by: Jan Palus <jpa...@fastmail.com>
> Cc: Christoph Hellwig <h...@lst.de>
> Cc: Hannes Reinecke <h...@suse.com>
> Cc: Johannes Thumshirn <jthumsh...@suse.de>
> Cc: Ming Lei <ming....@redhat.com>
> Cc: Jan Palus <jpa...@fastmail.com>
> Signed-off-by: Bart Van Assche <bvanass...@acm.org>
> ---
>  drivers/scsi/scsi_logging.c | 48 +++----------------------------------
>  include/scsi/scsi_dbg.h     |  2 --
>  2 files changed, 3 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/scsi/scsi_logging.c b/drivers/scsi/scsi_logging.c
> index 39b8cc4574b4..c6ed0b12e807 100644
> --- a/drivers/scsi/scsi_logging.c
> +++ b/drivers/scsi/scsi_logging.c
> @@ -15,57 +15,15 @@
>  #include <scsi/scsi_eh.h>
>  #include <scsi/scsi_dbg.h>
>  
> -#define SCSI_LOG_SPOOLSIZE 4096
> -
> -#if (SCSI_LOG_SPOOLSIZE / SCSI_LOG_BUFSIZE) > BITS_PER_LONG
> -#warning SCSI logging bitmask too large
> -#endif
> -
> -struct scsi_log_buf {
> -     char buffer[SCSI_LOG_SPOOLSIZE];
> -     unsigned long map;
> -};
> -
> -static DEFINE_PER_CPU(struct scsi_log_buf, scsi_format_log);
> -
>  static char *scsi_log_reserve_buffer(size_t *len)
>  {
> -     struct scsi_log_buf *buf;
> -     unsigned long map_bits = sizeof(buf->buffer) / SCSI_LOG_BUFSIZE;
> -     unsigned long idx = 0;
> -
> -     preempt_disable();
> -     buf = this_cpu_ptr(&scsi_format_log);
> -     idx = find_first_zero_bit(&buf->map, map_bits);
> -     if (likely(idx < map_bits)) {
> -             while (test_and_set_bit(idx, &buf->map)) {
> -                     idx = find_next_zero_bit(&buf->map, map_bits, idx);
> -                     if (idx >= map_bits)
> -                             break;
> -             }
> -     }
> -     if (WARN_ON(idx >= map_bits)) {
> -             preempt_enable();
> -             return NULL;
> -     }
> -     *len = SCSI_LOG_BUFSIZE;
> -     return buf->buffer + idx * SCSI_LOG_BUFSIZE;
> +     *len = 128;
> +     return kmalloc(*len, GFP_ATOMIC);
>  }
>  
>  static void scsi_log_release_buffer(char *bufptr)
>  {
> -     struct scsi_log_buf *buf;
> -     unsigned long idx;
> -     int ret;
> -
> -     buf = this_cpu_ptr(&scsi_format_log);
> -     if (bufptr >= buf->buffer &&
> -         bufptr < buf->buffer + SCSI_LOG_SPOOLSIZE) {
> -             idx = (bufptr - buf->buffer) / SCSI_LOG_BUFSIZE;
> -             ret = test_and_clear_bit(idx, &buf->map);
> -             WARN_ON(!ret);
> -     }
> -     preempt_enable();
> +     kfree(bufptr);
>  }
>  
>  static inline const char *scmd_name(const struct scsi_cmnd *scmd)
> diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h
> index e03bd9d41fa8..7b196d234626 100644
> --- a/include/scsi/scsi_dbg.h
> +++ b/include/scsi/scsi_dbg.h
> @@ -6,8 +6,6 @@ struct scsi_cmnd;
>  struct scsi_device;
>  struct scsi_sense_hdr;
>  
> -#define SCSI_LOG_BUFSIZE 128
> -
>  extern void scsi_print_command(struct scsi_cmnd *);
>  extern size_t __scsi_format_command(char *, size_t,
>                                  const unsigned char *, size_t);
> 
Nope.

You've just disabled the prime reason why I did implement SCSI logging;
namely to provide per-cpu buffers where messages can be printed into.

We can move to kmalloc (or even kvmalloc), but the per-cpu pointer need
to be kept.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                Teamlead Storage & Networking
h...@suse.de                                   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Mary Higgins, Sri Rasiah
HRB 21284 (AG Nürnberg)

Reply via email to