On Fri, 2013-04-26 at 15:26 +0530, Aruna Balakrishnaiah wrote:
> The patch set supports compression of oops messages while writing to NVRAM,
> this helps in capturing more of oops data to lnx,oops-log. The pstore file
> for oops messages will be in decompressed format making it readable.
> 
> In case compression fails, the patch takes care of copying the header added
> by pstore and last oops_data_sz bytes of big_oops_buf to NVRAM so that we
> have recent oops messages in lnx,oops-log.
> 
> In case decompression fails, it will result in absence of oops file but still
> have files (in /dev/pstore) for other partitions.

Any reason that isn't handled by pstore itself rather than here ? Ie
make a flag indicating that the partition supports compression and have
pstore do it (so we don't compress everything such as ofw common etc...)

Cheers,
Ben.

> 
> Signed-off-by: Aruna Balakrishnaiah <ar...@linux.vnet.ibm.com>
> ---
>  arch/powerpc/platforms/pseries/nvram.c |  132 
> +++++++++++++++++++++++++++++---
>  1 file changed, 118 insertions(+), 14 deletions(-)
> 
> diff --git a/arch/powerpc/platforms/pseries/nvram.c 
> b/arch/powerpc/platforms/pseries/nvram.c
> index 0159d74..b5ba5e2 100644
> --- a/arch/powerpc/platforms/pseries/nvram.c
> +++ b/arch/powerpc/platforms/pseries/nvram.c
> @@ -539,6 +539,65 @@ static int zip_oops(size_t text_len)
>  }
>  
>  #ifdef CONFIG_PSTORE
> +/* Derived from logfs_uncompress */
> +int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen)
> +{
> +     int err, ret;
> +
> +     ret = -EIO;
> +     err = zlib_inflateInit(&stream);
> +     if (err != Z_OK)
> +             goto error;
> +
> +     stream.next_in = in;
> +     stream.avail_in = inlen;
> +     stream.total_in = 0;
> +     stream.next_out = out;
> +     stream.avail_out = outlen;
> +     stream.total_out = 0;
> +
> +     err = zlib_inflate(&stream, Z_FINISH);
> +     if (err != Z_STREAM_END)
> +             goto error;
> +
> +     err = zlib_inflateEnd(&stream);
> +     if (err != Z_OK)
> +             goto error;
> +
> +     ret = stream.total_out;
> +error:
> +     return ret;
> +}
> +
> +static int unzip_oops(char *oops_buf, char *big_buf)
> +{
> +     struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
> +     u64 timestamp = oops_hdr->timestamp;
> +     char *big_oops_data = NULL;
> +     char *oops_data_buf = NULL;
> +     size_t big_oops_data_sz;
> +     int unzipped_len;
> +
> +     big_oops_data = big_buf + sizeof(struct oops_log_info);
> +     big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
> +     oops_data_buf = oops_buf + sizeof(struct oops_log_info);
> +
> +     unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
> +                                     oops_hdr->report_length,
> +                                     big_oops_data_sz);
> +
> +     if (unzipped_len < 0) {
> +             pr_err("nvram: decompression failed; returned %d\n",
> +                                                             unzipped_len);
> +             return -1;
> +     }
> +     oops_hdr = (struct oops_log_info *)big_buf;
> +     oops_hdr->version = OOPS_HDR_VERSION;
> +     oops_hdr->report_length = (u16) unzipped_len;
> +     oops_hdr->timestamp = timestamp;
> +     return 0;
> +}
> +
>  static int nvram_pstore_open(struct pstore_info *psi)
>  {
>       /* Reset the iterator to start reading partitions again */
> @@ -567,6 +626,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
>                               size_t size, struct pstore_info *psi)
>  {
>       int rc;
> +     unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
>       struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
>  
>       /* part 1 has the recent messages from printk buffer */
> @@ -577,8 +637,31 @@ static int nvram_pstore_write(enum pstore_type_id type,
>       oops_hdr->version = OOPS_HDR_VERSION;
>       oops_hdr->report_length = (u16) size;
>       oops_hdr->timestamp = get_seconds();
> +
> +     if (big_oops_buf) {
> +             rc = zip_oops(size);
> +             /*
> +              * If compression fails copy recent log messages from
> +              * big_oops_buf to oops_data.
> +              */
> +             if (rc != 0) {
> +                     int hsize = pstore_get_header_size();
> +                     size_t diff = size - oops_data_sz + hsize;
> +
> +                     if (size > oops_data_sz) {
> +                             memcpy(oops_data, big_oops_buf, hsize);
> +                             memcpy(oops_data + hsize, big_oops_buf + diff,
> +                                     oops_data_sz - hsize);
> +
> +                             oops_hdr->report_length = (u16) oops_data_sz;
> +                     } else
> +                             memcpy(oops_data, big_oops_buf, size);
> +             } else
> +                     err_type = ERR_TYPE_KERNEL_PANIC_GZ;
> +     }
> +
>       rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
> -             (int) (sizeof(*oops_hdr) + size), ERR_TYPE_KERNEL_PANIC,
> +             (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
>               count);
>  
>       if (rc != 0)
> @@ -600,10 +683,11 @@ static ssize_t nvram_pstore_read(u64 *id, enum 
> pstore_type_id *type,
>       struct oops_log_info *oops_hdr;
>       unsigned int err_type, id_no, size = 0;
>       struct nvram_os_partition *part = NULL;
> -     char *buff = NULL;
> -     int sig = 0;
> +     char *buff = NULL, *big_buff = NULL;
> +     int rc, sig = 0;
>       loff_t p;
>  
> +read_partition:
>       read_type++;
>  
>       switch (nvram_type_ids[read_type]) {
> @@ -666,6 +750,25 @@ static ssize_t nvram_pstore_read(u64 *id, enum 
> pstore_type_id *type,
>       if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
>               oops_hdr = (struct oops_log_info *)buff;
>               *buf = buff + sizeof(*oops_hdr);
> +
> +             if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
> +                     big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
> +                     if (!big_buff)
> +                             return -ENOMEM;
> +
> +                     rc = unzip_oops(buff, big_buff);
> +
> +                     if (rc != 0) {
> +                             kfree(buff);
> +                             kfree(big_buff);
> +                             goto read_partition;
> +                     }
> +
> +                     oops_hdr = (struct oops_log_info *)big_buff;
> +                     *buf = big_buff + sizeof(*oops_hdr);
> +                     kfree(buff);
> +             }
> +
>               time->tv_sec = oops_hdr->timestamp;
>               time->tv_nsec = 0;
>               return oops_hdr->report_length;
> @@ -687,17 +790,18 @@ static int nvram_pstore_init(void)
>  {
>       int rc = 0;
>  
> -     nvram_pstore_info.buf = oops_data;
> -     nvram_pstore_info.bufsize = oops_data_sz;
> +     if (big_oops_buf) {
> +             nvram_pstore_info.buf = big_oops_buf;
> +             nvram_pstore_info.bufsize = big_oops_buf_sz;
> +     } else {
> +             nvram_pstore_info.buf = oops_data;
> +             nvram_pstore_info.bufsize = oops_data_sz;
> +     }
>  
>       rc = pstore_register(&nvram_pstore_info);
>       if (rc != 0)
>               pr_err("nvram: pstore_register() failed, defaults to "
>                               "kmsg_dump; returned %d\n", rc);
> -     else
> -             /*TODO: Support compression when pstore is configured */
> -             pr_info("nvram: Compression of oops text supported only when "
> -                             "pstore is not configured");
>  
>       return rc;
>  }
> @@ -731,11 +835,6 @@ static void __init nvram_init_oops_partition(int 
> rtas_partition_exists)
>       oops_data = oops_buf + sizeof(struct oops_log_info);
>       oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
>  
> -     rc = nvram_pstore_init();
> -
> -     if (!rc)
> -             return;
> -
>       /*
>        * Figure compression (preceded by elimination of each line's <n>
>        * severity prefix) will reduce the oops/panic report to at most
> @@ -759,6 +858,11 @@ static void __init nvram_init_oops_partition(int 
> rtas_partition_exists)
>               stream.workspace = NULL;
>       }
>  
> +     rc = nvram_pstore_init();
> +
> +     if (!rc)
> +             return;
> +
>       rc = kmsg_dump_register(&nvram_kmsg_dumper);
>       if (rc != 0) {
>               pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to