diff options
author | Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com> | 2013-08-16 16:53:28 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2013-08-19 14:53:20 -0400 |
commit | adb42f5e105502aff2fc4518b16ba79c203fae4f (patch) | |
tree | b600e1292775e66dcbcc9f2d5a02ab4bf0a9372a /fs/pstore/platform.c | |
parent | 9a4e1398208d147a9240731a1f8cfe7d8cc4c553 (diff) |
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/pstore/platform.c')
-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: | |||
162 | return ret; | 162 | return ret; |
163 | } | 163 | } |
164 | 164 | ||
165 | /* Derived from logfs_uncompress */ | ||
166 | static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) | ||
167 | { | ||
168 | int err, ret; | ||
169 | |||
170 | ret = -EIO; | ||
171 | err = zlib_inflateInit(&stream); | ||
172 | if (err != Z_OK) | ||
173 | goto error; | ||
174 | |||
175 | stream.next_in = in; | ||
176 | stream.avail_in = inlen; | ||
177 | stream.total_in = 0; | ||
178 | stream.next_out = out; | ||
179 | stream.avail_out = outlen; | ||
180 | stream.total_out = 0; | ||
181 | |||
182 | err = zlib_inflate(&stream, Z_FINISH); | ||
183 | if (err != Z_STREAM_END) | ||
184 | goto error; | ||
185 | |||
186 | err = zlib_inflateEnd(&stream); | ||
187 | if (err != Z_OK) | ||
188 | goto error; | ||
189 | |||
190 | ret = stream.total_out; | ||
191 | error: | ||
192 | return ret; | ||
193 | } | ||
194 | |||
165 | static void allocate_buf_for_compression(void) | 195 | static void allocate_buf_for_compression(void) |
166 | { | 196 | { |
167 | size_t size; | 197 | size_t size; |
@@ -429,6 +459,7 @@ void pstore_get_records(int quiet) | |||
429 | struct timespec time; | 459 | struct timespec time; |
430 | int failed = 0, rc; | 460 | int failed = 0, rc; |
431 | bool compressed; | 461 | bool compressed; |
462 | int unzipped_len = -1; | ||
432 | 463 | ||
433 | if (!psi) | 464 | if (!psi) |
434 | return; | 465 | return; |
@@ -439,10 +470,28 @@ void pstore_get_records(int quiet) | |||
439 | 470 | ||
440 | while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, | 471 | while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, |
441 | psi)) > 0) { | 472 | psi)) > 0) { |
473 | if (compressed && (type == PSTORE_TYPE_DMESG)) { | ||
474 | if (big_oops_buf) | ||
475 | unzipped_len = pstore_decompress(buf, | ||
476 | big_oops_buf, size, | ||
477 | big_oops_buf_sz); | ||
478 | |||
479 | if (unzipped_len > 0) { | ||
480 | buf = big_oops_buf; | ||
481 | size = unzipped_len; | ||
482 | } else { | ||
483 | pr_err("pstore: decompression failed;" | ||
484 | "returned %d\n", unzipped_len); | ||
485 | } | ||
486 | } | ||
442 | rc = pstore_mkfile(type, psi->name, id, count, buf, | 487 | rc = pstore_mkfile(type, psi->name, id, count, buf, |
443 | (size_t)size, time, psi); | 488 | (size_t)size, time, psi); |
444 | kfree(buf); | 489 | if (unzipped_len < 0) { |
445 | buf = NULL; | 490 | /* Free buffer other than big oops */ |
491 | kfree(buf); | ||
492 | buf = NULL; | ||
493 | } else | ||
494 | unzipped_len = -1; | ||
446 | if (rc && (rc != -EEXIST || !quiet)) | 495 | if (rc && (rc != -EEXIST || !quiet)) |
447 | failed++; | 496 | failed++; |
448 | } | 497 | } |