diff options
author | Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com> | 2013-08-17 00:53:28 +0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-08-19 22:53:20 +0400 |
commit | adb42f5e105502aff2fc4518b16ba79c203fae4f (patch) | |
tree | b600e1292775e66dcbcc9f2d5a02ab4bf0a9372a /fs | |
parent | 9a4e1398208d147a9240731a1f8cfe7d8cc4c553 (diff) | |
download | linux-adb42f5e105502aff2fc4518b16ba79c203fae4f.tar.xz |
pstore: Add decompression support to pstore
Based on the flag 'compressed' set or not, pstore will decompress the
data returning a plain text file. If decompression fails for a particular
record it will have the compressed data in the file which can be
decompressed with 'openssl' command line tool.
Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/pstore/platform.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 6418eb77d64b..76bc5c12c0cf 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -162,6 +162,36 @@ error: return ret; } +/* Derived from logfs_uncompress */ +static int pstore_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 void allocate_buf_for_compression(void) { size_t size; @@ -429,6 +459,7 @@ void pstore_get_records(int quiet) struct timespec time; int failed = 0, rc; bool compressed; + int unzipped_len = -1; if (!psi) return; @@ -439,10 +470,28 @@ void pstore_get_records(int quiet) while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, psi)) > 0) { + if (compressed && (type == PSTORE_TYPE_DMESG)) { + if (big_oops_buf) + unzipped_len = pstore_decompress(buf, + big_oops_buf, size, + big_oops_buf_sz); + + if (unzipped_len > 0) { + buf = big_oops_buf; + size = unzipped_len; + } else { + pr_err("pstore: decompression failed;" + "returned %d\n", unzipped_len); + } + } rc = pstore_mkfile(type, psi->name, id, count, buf, (size_t)size, time, psi); - kfree(buf); - buf = NULL; + if (unzipped_len < 0) { + /* Free buffer other than big oops */ + kfree(buf); + buf = NULL; + } else + unzipped_len = -1; if (rc && (rc != -EEXIST || !quiet)) failed++; } |