diff options
| -rw-r--r-- | arch/powerpc/kernel/nvram_64.c | 4 | ||||
| -rw-r--r-- | drivers/acpi/apei/erst.c | 7 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi-pstore.c | 6 | ||||
| -rw-r--r-- | fs/pstore/Kconfig | 31 | ||||
| -rw-r--r-- | fs/pstore/platform.c | 218 | ||||
| -rw-r--r-- | fs/pstore/ram.c | 10 | ||||
| -rw-r--r-- | include/linux/pstore.h | 3 |
7 files changed, 261 insertions, 18 deletions
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 856f9a7944cd..64174bf95611 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
| @@ -444,7 +444,8 @@ static int nvram_pstore_write(enum pstore_type_id type, | |||
| 444 | */ | 444 | */ |
| 445 | static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | 445 | static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, |
| 446 | int *count, struct timespec *time, char **buf, | 446 | int *count, struct timespec *time, char **buf, |
| 447 | bool *compressed, struct pstore_info *psi) | 447 | bool *compressed, ssize_t *ecc_notice_size, |
| 448 | struct pstore_info *psi) | ||
| 448 | { | 449 | { |
| 449 | struct oops_log_info *oops_hdr; | 450 | struct oops_log_info *oops_hdr; |
| 450 | unsigned int err_type, id_no, size = 0; | 451 | unsigned int err_type, id_no, size = 0; |
| @@ -545,6 +546,7 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
| 545 | return -ENOMEM; | 546 | return -ENOMEM; |
| 546 | kfree(buff); | 547 | kfree(buff); |
| 547 | 548 | ||
| 549 | *ecc_notice_size = 0; | ||
| 548 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) | 550 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) |
| 549 | *compressed = true; | 551 | *compressed = true; |
| 550 | else | 552 | else |
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index 006c3894c6ea..f096ab3cb54d 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c | |||
| @@ -927,7 +927,8 @@ static int erst_open_pstore(struct pstore_info *psi); | |||
| 927 | static int erst_close_pstore(struct pstore_info *psi); | 927 | static int erst_close_pstore(struct pstore_info *psi); |
| 928 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, | 928 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, |
| 929 | struct timespec *time, char **buf, | 929 | struct timespec *time, char **buf, |
| 930 | bool *compressed, struct pstore_info *psi); | 930 | bool *compressed, ssize_t *ecc_notice_size, |
| 931 | struct pstore_info *psi); | ||
| 931 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, | 932 | static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason, |
| 932 | u64 *id, unsigned int part, int count, bool compressed, | 933 | u64 *id, unsigned int part, int count, bool compressed, |
| 933 | size_t size, struct pstore_info *psi); | 934 | size_t size, struct pstore_info *psi); |
| @@ -987,7 +988,8 @@ static int erst_close_pstore(struct pstore_info *psi) | |||
| 987 | 988 | ||
| 988 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, | 989 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count, |
| 989 | struct timespec *time, char **buf, | 990 | struct timespec *time, char **buf, |
| 990 | bool *compressed, struct pstore_info *psi) | 991 | bool *compressed, ssize_t *ecc_notice_size, |
| 992 | struct pstore_info *psi) | ||
| 991 | { | 993 | { |
| 992 | int rc; | 994 | int rc; |
| 993 | ssize_t len = 0; | 995 | ssize_t len = 0; |
| @@ -1033,6 +1035,7 @@ skip: | |||
| 1033 | memcpy(*buf, rcd->data, len - sizeof(*rcd)); | 1035 | memcpy(*buf, rcd->data, len - sizeof(*rcd)); |
| 1034 | *id = record_id; | 1036 | *id = record_id; |
| 1035 | *compressed = false; | 1037 | *compressed = false; |
| 1038 | *ecc_notice_size = 0; | ||
| 1036 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1039 | if (uuid_le_cmp(rcd->sec_hdr.section_type, |
| 1037 | CPER_SECTION_TYPE_DMESG_Z) == 0) { | 1040 | CPER_SECTION_TYPE_DMESG_Z) == 0) { |
| 1038 | *type = PSTORE_TYPE_DMESG; | 1041 | *type = PSTORE_TYPE_DMESG; |
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c index eac76a79a880..d5903ea77238 100644 --- a/drivers/firmware/efi/efi-pstore.c +++ b/drivers/firmware/efi/efi-pstore.c | |||
| @@ -34,6 +34,7 @@ struct pstore_read_data { | |||
| 34 | int *count; | 34 | int *count; |
| 35 | struct timespec *timespec; | 35 | struct timespec *timespec; |
| 36 | bool *compressed; | 36 | bool *compressed; |
| 37 | ssize_t *ecc_notice_size; | ||
| 37 | char **buf; | 38 | char **buf; |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| @@ -69,6 +70,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | |||
| 69 | *cb_data->compressed = true; | 70 | *cb_data->compressed = true; |
| 70 | else | 71 | else |
| 71 | *cb_data->compressed = false; | 72 | *cb_data->compressed = false; |
| 73 | *cb_data->ecc_notice_size = 0; | ||
| 72 | } else if (sscanf(name, "dump-type%u-%u-%d-%lu", | 74 | } else if (sscanf(name, "dump-type%u-%u-%d-%lu", |
| 73 | cb_data->type, &part, &cnt, &time) == 4) { | 75 | cb_data->type, &part, &cnt, &time) == 4) { |
| 74 | *cb_data->id = generic_id(time, part, cnt); | 76 | *cb_data->id = generic_id(time, part, cnt); |
| @@ -76,6 +78,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | |||
| 76 | cb_data->timespec->tv_sec = time; | 78 | cb_data->timespec->tv_sec = time; |
| 77 | cb_data->timespec->tv_nsec = 0; | 79 | cb_data->timespec->tv_nsec = 0; |
| 78 | *cb_data->compressed = false; | 80 | *cb_data->compressed = false; |
| 81 | *cb_data->ecc_notice_size = 0; | ||
| 79 | } else if (sscanf(name, "dump-type%u-%u-%lu", | 82 | } else if (sscanf(name, "dump-type%u-%u-%lu", |
| 80 | cb_data->type, &part, &time) == 3) { | 83 | cb_data->type, &part, &time) == 3) { |
| 81 | /* | 84 | /* |
| @@ -88,6 +91,7 @@ static int efi_pstore_read_func(struct efivar_entry *entry, void *data) | |||
| 88 | cb_data->timespec->tv_sec = time; | 91 | cb_data->timespec->tv_sec = time; |
| 89 | cb_data->timespec->tv_nsec = 0; | 92 | cb_data->timespec->tv_nsec = 0; |
| 90 | *cb_data->compressed = false; | 93 | *cb_data->compressed = false; |
| 94 | *cb_data->ecc_notice_size = 0; | ||
| 91 | } else | 95 | } else |
| 92 | return 0; | 96 | return 0; |
| 93 | 97 | ||
| @@ -210,6 +214,7 @@ static int efi_pstore_sysfs_entry_iter(void *data, struct efivar_entry **pos) | |||
| 210 | static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, | 214 | static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, |
| 211 | int *count, struct timespec *timespec, | 215 | int *count, struct timespec *timespec, |
| 212 | char **buf, bool *compressed, | 216 | char **buf, bool *compressed, |
| 217 | ssize_t *ecc_notice_size, | ||
| 213 | struct pstore_info *psi) | 218 | struct pstore_info *psi) |
| 214 | { | 219 | { |
| 215 | struct pstore_read_data data; | 220 | struct pstore_read_data data; |
| @@ -220,6 +225,7 @@ static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, | |||
| 220 | data.count = count; | 225 | data.count = count; |
| 221 | data.timespec = timespec; | 226 | data.timespec = timespec; |
| 222 | data.compressed = compressed; | 227 | data.compressed = compressed; |
| 228 | data.ecc_notice_size = ecc_notice_size; | ||
| 223 | data.buf = buf; | 229 | data.buf = buf; |
| 224 | 230 | ||
| 225 | *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); | 231 | *data.buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL); |
diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index 360ae43f590c..be40813eff52 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig | |||
| @@ -1,8 +1,6 @@ | |||
| 1 | config PSTORE | 1 | config PSTORE |
| 2 | tristate "Persistent store support" | 2 | tristate "Persistent store support" |
| 3 | default n | 3 | default n |
| 4 | select ZLIB_DEFLATE | ||
| 5 | select ZLIB_INFLATE | ||
| 6 | help | 4 | help |
| 7 | This option enables generic access to platform level | 5 | This option enables generic access to platform level |
| 8 | persistent storage via "pstore" filesystem that can | 6 | persistent storage via "pstore" filesystem that can |
| @@ -14,6 +12,35 @@ config PSTORE | |||
| 14 | If you don't have a platform persistent store driver, | 12 | If you don't have a platform persistent store driver, |
| 15 | say N. | 13 | say N. |
| 16 | 14 | ||
| 15 | choice | ||
| 16 | prompt "Choose compression algorithm" | ||
| 17 | depends on PSTORE | ||
| 18 | default PSTORE_ZLIB_COMPRESS | ||
| 19 | help | ||
| 20 | This option chooses compression algorithm. | ||
| 21 | |||
| 22 | config PSTORE_ZLIB_COMPRESS | ||
| 23 | bool "ZLIB" | ||
| 24 | select ZLIB_DEFLATE | ||
| 25 | select ZLIB_INFLATE | ||
| 26 | help | ||
| 27 | This option enables ZLIB compression algorithm support. | ||
| 28 | |||
| 29 | config PSTORE_LZO_COMPRESS | ||
| 30 | bool "LZO" | ||
| 31 | select LZO_COMPRESS | ||
| 32 | select LZO_DECOMPRESS | ||
| 33 | help | ||
| 34 | This option enables LZO compression algorithm support. | ||
| 35 | |||
| 36 | config PSTORE_LZ4_COMPRESS | ||
| 37 | bool "LZ4" | ||
| 38 | select LZ4_COMPRESS | ||
| 39 | select LZ4_DECOMPRESS | ||
| 40 | help | ||
| 41 | This option enables LZ4 compression algorithm support. | ||
| 42 | endchoice | ||
| 43 | |||
| 17 | config PSTORE_CONSOLE | 44 | config PSTORE_CONSOLE |
| 18 | bool "Log kernel console messages" | 45 | bool "Log kernel console messages" |
| 19 | depends on PSTORE | 46 | depends on PSTORE |
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index fe41d8ec663a..16ecca5b72d8 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c | |||
| @@ -28,7 +28,15 @@ | |||
| 28 | #include <linux/console.h> | 28 | #include <linux/console.h> |
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/pstore.h> | 30 | #include <linux/pstore.h> |
| 31 | #ifdef CONFIG_PSTORE_ZLIB_COMPRESS | ||
| 31 | #include <linux/zlib.h> | 32 | #include <linux/zlib.h> |
| 33 | #endif | ||
| 34 | #ifdef CONFIG_PSTORE_LZO_COMPRESS | ||
| 35 | #include <linux/lzo.h> | ||
| 36 | #endif | ||
| 37 | #ifdef CONFIG_PSTORE_LZ4_COMPRESS | ||
| 38 | #include <linux/lz4.h> | ||
| 39 | #endif | ||
| 32 | #include <linux/string.h> | 40 | #include <linux/string.h> |
| 33 | #include <linux/timer.h> | 41 | #include <linux/timer.h> |
| 34 | #include <linux/slab.h> | 42 | #include <linux/slab.h> |
| @@ -69,10 +77,23 @@ struct pstore_info *psinfo; | |||
| 69 | static char *backend; | 77 | static char *backend; |
| 70 | 78 | ||
| 71 | /* Compression parameters */ | 79 | /* Compression parameters */ |
| 80 | #ifdef CONFIG_PSTORE_ZLIB_COMPRESS | ||
| 72 | #define COMPR_LEVEL 6 | 81 | #define COMPR_LEVEL 6 |
| 73 | #define WINDOW_BITS 12 | 82 | #define WINDOW_BITS 12 |
| 74 | #define MEM_LEVEL 4 | 83 | #define MEM_LEVEL 4 |
| 75 | static struct z_stream_s stream; | 84 | static struct z_stream_s stream; |
| 85 | #else | ||
| 86 | static unsigned char *workspace; | ||
| 87 | #endif | ||
| 88 | |||
| 89 | struct pstore_zbackend { | ||
| 90 | int (*compress)(const void *in, void *out, size_t inlen, size_t outlen); | ||
| 91 | int (*decompress)(void *in, void *out, size_t inlen, size_t outlen); | ||
| 92 | void (*allocate)(void); | ||
| 93 | void (*free)(void); | ||
| 94 | |||
| 95 | const char *name; | ||
| 96 | }; | ||
| 76 | 97 | ||
| 77 | static char *big_oops_buf; | 98 | static char *big_oops_buf; |
| 78 | static size_t big_oops_buf_sz; | 99 | static size_t big_oops_buf_sz; |
| @@ -129,9 +150,9 @@ bool pstore_cannot_block_path(enum kmsg_dump_reason reason) | |||
| 129 | } | 150 | } |
| 130 | EXPORT_SYMBOL_GPL(pstore_cannot_block_path); | 151 | EXPORT_SYMBOL_GPL(pstore_cannot_block_path); |
| 131 | 152 | ||
| 153 | #ifdef CONFIG_PSTORE_ZLIB_COMPRESS | ||
| 132 | /* Derived from logfs_compress() */ | 154 | /* Derived from logfs_compress() */ |
| 133 | static int pstore_compress(const void *in, void *out, size_t inlen, | 155 | static int compress_zlib(const void *in, void *out, size_t inlen, size_t outlen) |
| 134 | size_t outlen) | ||
| 135 | { | 156 | { |
| 136 | int err, ret; | 157 | int err, ret; |
| 137 | 158 | ||
| @@ -165,7 +186,7 @@ error: | |||
| 165 | } | 186 | } |
| 166 | 187 | ||
| 167 | /* Derived from logfs_uncompress */ | 188 | /* Derived from logfs_uncompress */ |
| 168 | static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) | 189 | static int decompress_zlib(void *in, void *out, size_t inlen, size_t outlen) |
| 169 | { | 190 | { |
| 170 | int err, ret; | 191 | int err, ret; |
| 171 | 192 | ||
| @@ -194,7 +215,7 @@ error: | |||
| 194 | return ret; | 215 | return ret; |
| 195 | } | 216 | } |
| 196 | 217 | ||
| 197 | static void allocate_buf_for_compression(void) | 218 | static void allocate_zlib(void) |
| 198 | { | 219 | { |
| 199 | size_t size; | 220 | size_t size; |
| 200 | size_t cmpr; | 221 | size_t cmpr; |
| @@ -237,12 +258,190 @@ static void allocate_buf_for_compression(void) | |||
| 237 | 258 | ||
| 238 | } | 259 | } |
| 239 | 260 | ||
| 240 | static void free_buf_for_compression(void) | 261 | static void free_zlib(void) |
| 241 | { | 262 | { |
| 242 | kfree(stream.workspace); | 263 | kfree(stream.workspace); |
| 243 | stream.workspace = NULL; | 264 | stream.workspace = NULL; |
| 244 | kfree(big_oops_buf); | 265 | kfree(big_oops_buf); |
| 245 | big_oops_buf = NULL; | 266 | big_oops_buf = NULL; |
| 267 | big_oops_buf_sz = 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static struct pstore_zbackend backend_zlib = { | ||
| 271 | .compress = compress_zlib, | ||
| 272 | .decompress = decompress_zlib, | ||
| 273 | .allocate = allocate_zlib, | ||
| 274 | .free = free_zlib, | ||
| 275 | .name = "zlib", | ||
| 276 | }; | ||
| 277 | #endif | ||
| 278 | |||
| 279 | #ifdef CONFIG_PSTORE_LZO_COMPRESS | ||
| 280 | static int compress_lzo(const void *in, void *out, size_t inlen, size_t outlen) | ||
| 281 | { | ||
| 282 | int ret; | ||
| 283 | |||
| 284 | ret = lzo1x_1_compress(in, inlen, out, &outlen, workspace); | ||
| 285 | if (ret != LZO_E_OK) { | ||
| 286 | pr_err("lzo_compress error, ret = %d!\n", ret); | ||
| 287 | return -EIO; | ||
| 288 | } | ||
| 289 | |||
| 290 | return outlen; | ||
| 291 | } | ||
| 292 | |||
| 293 | static int decompress_lzo(void *in, void *out, size_t inlen, size_t outlen) | ||
| 294 | { | ||
| 295 | int ret; | ||
| 296 | |||
| 297 | ret = lzo1x_decompress_safe(in, inlen, out, &outlen); | ||
| 298 | if (ret != LZO_E_OK) { | ||
| 299 | pr_err("lzo_decompress error, ret = %d!\n", ret); | ||
| 300 | return -EIO; | ||
| 301 | } | ||
| 302 | |||
| 303 | return outlen; | ||
| 304 | } | ||
| 305 | |||
| 306 | static void allocate_lzo(void) | ||
| 307 | { | ||
| 308 | big_oops_buf_sz = lzo1x_worst_compress(psinfo->bufsize); | ||
| 309 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); | ||
| 310 | if (big_oops_buf) { | ||
| 311 | workspace = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL); | ||
| 312 | if (!workspace) { | ||
| 313 | pr_err("No memory for compression workspace; skipping compression\n"); | ||
| 314 | kfree(big_oops_buf); | ||
| 315 | big_oops_buf = NULL; | ||
| 316 | } | ||
| 317 | } else { | ||
| 318 | pr_err("No memory for uncompressed data; skipping compression\n"); | ||
| 319 | workspace = NULL; | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | static void free_lzo(void) | ||
| 324 | { | ||
| 325 | kfree(workspace); | ||
| 326 | kfree(big_oops_buf); | ||
| 327 | big_oops_buf = NULL; | ||
| 328 | big_oops_buf_sz = 0; | ||
| 329 | } | ||
| 330 | |||
| 331 | static struct pstore_zbackend backend_lzo = { | ||
| 332 | .compress = compress_lzo, | ||
| 333 | .decompress = decompress_lzo, | ||
| 334 | .allocate = allocate_lzo, | ||
| 335 | .free = free_lzo, | ||
| 336 | .name = "lzo", | ||
| 337 | }; | ||
| 338 | #endif | ||
| 339 | |||
| 340 | #ifdef CONFIG_PSTORE_LZ4_COMPRESS | ||
| 341 | static int compress_lz4(const void *in, void *out, size_t inlen, size_t outlen) | ||
| 342 | { | ||
| 343 | int ret; | ||
| 344 | |||
| 345 | ret = lz4_compress(in, inlen, out, &outlen, workspace); | ||
| 346 | if (ret) { | ||
| 347 | pr_err("lz4_compress error, ret = %d!\n", ret); | ||
| 348 | return -EIO; | ||
| 349 | } | ||
| 350 | |||
| 351 | return outlen; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int decompress_lz4(void *in, void *out, size_t inlen, size_t outlen) | ||
| 355 | { | ||
| 356 | int ret; | ||
| 357 | |||
| 358 | ret = lz4_decompress_unknownoutputsize(in, inlen, out, &outlen); | ||
| 359 | if (ret) { | ||
| 360 | pr_err("lz4_decompress error, ret = %d!\n", ret); | ||
| 361 | return -EIO; | ||
| 362 | } | ||
| 363 | |||
| 364 | return outlen; | ||
| 365 | } | ||
| 366 | |||
| 367 | static void allocate_lz4(void) | ||
| 368 | { | ||
| 369 | big_oops_buf_sz = lz4_compressbound(psinfo->bufsize); | ||
| 370 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); | ||
| 371 | if (big_oops_buf) { | ||
| 372 | workspace = kmalloc(LZ4_MEM_COMPRESS, GFP_KERNEL); | ||
| 373 | if (!workspace) { | ||
| 374 | pr_err("No memory for compression workspace; skipping compression\n"); | ||
| 375 | kfree(big_oops_buf); | ||
| 376 | big_oops_buf = NULL; | ||
| 377 | } | ||
| 378 | } else { | ||
| 379 | pr_err("No memory for uncompressed data; skipping compression\n"); | ||
| 380 | workspace = NULL; | ||
| 381 | } | ||
| 382 | } | ||
| 383 | |||
| 384 | static void free_lz4(void) | ||
| 385 | { | ||
| 386 | kfree(workspace); | ||
| 387 | kfree(big_oops_buf); | ||
| 388 | big_oops_buf = NULL; | ||
| 389 | big_oops_buf_sz = 0; | ||
| 390 | } | ||
| 391 | |||
| 392 | static struct pstore_zbackend backend_lz4 = { | ||
| 393 | .compress = compress_lz4, | ||
| 394 | .decompress = decompress_lz4, | ||
| 395 | .allocate = allocate_lz4, | ||
| 396 | .free = free_lz4, | ||
| 397 | .name = "lz4", | ||
| 398 | }; | ||
| 399 | #endif | ||
| 400 | |||
| 401 | static struct pstore_zbackend *zbackend = | ||
| 402 | #if defined(CONFIG_PSTORE_ZLIB_COMPRESS) | ||
| 403 | &backend_zlib; | ||
| 404 | #elif defined(CONFIG_PSTORE_LZO_COMPRESS) | ||
| 405 | &backend_lzo; | ||
| 406 | #elif defined(CONFIG_PSTORE_LZ4_COMPRESS) | ||
| 407 | &backend_lz4; | ||
| 408 | #else | ||
| 409 | NULL; | ||
| 410 | #endif | ||
| 411 | |||
| 412 | static int pstore_compress(const void *in, void *out, | ||
| 413 | size_t inlen, size_t outlen) | ||
| 414 | { | ||
| 415 | if (zbackend) | ||
| 416 | return zbackend->compress(in, out, inlen, outlen); | ||
| 417 | else | ||
| 418 | return -EIO; | ||
| 419 | } | ||
| 420 | |||
| 421 | static int pstore_decompress(void *in, void *out, size_t inlen, size_t outlen) | ||
| 422 | { | ||
| 423 | if (zbackend) | ||
| 424 | return zbackend->decompress(in, out, inlen, outlen); | ||
| 425 | else | ||
| 426 | return -EIO; | ||
| 427 | } | ||
| 428 | |||
| 429 | static void allocate_buf_for_compression(void) | ||
| 430 | { | ||
| 431 | if (zbackend) { | ||
| 432 | pr_info("using %s compression\n", zbackend->name); | ||
| 433 | zbackend->allocate(); | ||
| 434 | } else { | ||
| 435 | pr_err("allocate compression buffer error!\n"); | ||
| 436 | } | ||
| 437 | } | ||
| 438 | |||
| 439 | static void free_buf_for_compression(void) | ||
| 440 | { | ||
| 441 | if (zbackend) | ||
| 442 | zbackend->free(); | ||
| 443 | else | ||
| 444 | pr_err("free compression buffer error!\n"); | ||
| 246 | } | 445 | } |
| 247 | 446 | ||
| 248 | /* | 447 | /* |
| @@ -522,6 +721,7 @@ void pstore_get_records(int quiet) | |||
| 522 | int failed = 0, rc; | 721 | int failed = 0, rc; |
| 523 | bool compressed; | 722 | bool compressed; |
| 524 | int unzipped_len = -1; | 723 | int unzipped_len = -1; |
| 724 | ssize_t ecc_notice_size = 0; | ||
| 525 | 725 | ||
| 526 | if (!psi) | 726 | if (!psi) |
| 527 | return; | 727 | return; |
| @@ -531,7 +731,7 @@ void pstore_get_records(int quiet) | |||
| 531 | goto out; | 731 | goto out; |
| 532 | 732 | ||
| 533 | while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, | 733 | while ((size = psi->read(&id, &type, &count, &time, &buf, &compressed, |
| 534 | psi)) > 0) { | 734 | &ecc_notice_size, psi)) > 0) { |
| 535 | if (compressed && (type == PSTORE_TYPE_DMESG)) { | 735 | if (compressed && (type == PSTORE_TYPE_DMESG)) { |
| 536 | if (big_oops_buf) | 736 | if (big_oops_buf) |
| 537 | unzipped_len = pstore_decompress(buf, | 737 | unzipped_len = pstore_decompress(buf, |
| @@ -539,6 +739,9 @@ void pstore_get_records(int quiet) | |||
| 539 | big_oops_buf_sz); | 739 | big_oops_buf_sz); |
| 540 | 740 | ||
| 541 | if (unzipped_len > 0) { | 741 | if (unzipped_len > 0) { |
| 742 | if (ecc_notice_size) | ||
| 743 | memcpy(big_oops_buf + unzipped_len, | ||
| 744 | buf + size, ecc_notice_size); | ||
| 542 | kfree(buf); | 745 | kfree(buf); |
| 543 | buf = big_oops_buf; | 746 | buf = big_oops_buf; |
| 544 | size = unzipped_len; | 747 | size = unzipped_len; |
| @@ -550,7 +753,8 @@ void pstore_get_records(int quiet) | |||
| 550 | } | 753 | } |
| 551 | } | 754 | } |
| 552 | rc = pstore_mkfile(type, psi->name, id, count, buf, | 755 | rc = pstore_mkfile(type, psi->name, id, count, buf, |
| 553 | compressed, (size_t)size, time, psi); | 756 | compressed, size + ecc_notice_size, |
| 757 | time, psi); | ||
| 554 | if (unzipped_len < 0) { | 758 | if (unzipped_len < 0) { |
| 555 | /* Free buffer other than big oops */ | 759 | /* Free buffer other than big oops */ |
| 556 | kfree(buf); | 760 | kfree(buf); |
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index bd9812e83461..d9668c2b43cb 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c | |||
| @@ -181,10 +181,10 @@ static bool prz_ok(struct persistent_ram_zone *prz) | |||
| 181 | static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | 181 | static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, |
| 182 | int *count, struct timespec *time, | 182 | int *count, struct timespec *time, |
| 183 | char **buf, bool *compressed, | 183 | char **buf, bool *compressed, |
| 184 | ssize_t *ecc_notice_size, | ||
| 184 | struct pstore_info *psi) | 185 | struct pstore_info *psi) |
| 185 | { | 186 | { |
| 186 | ssize_t size; | 187 | ssize_t size; |
| 187 | ssize_t ecc_notice_size; | ||
| 188 | struct ramoops_context *cxt = psi->data; | 188 | struct ramoops_context *cxt = psi->data; |
| 189 | struct persistent_ram_zone *prz = NULL; | 189 | struct persistent_ram_zone *prz = NULL; |
| 190 | int header_length = 0; | 190 | int header_length = 0; |
| @@ -229,16 +229,16 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type, | |||
| 229 | size = persistent_ram_old_size(prz) - header_length; | 229 | size = persistent_ram_old_size(prz) - header_length; |
| 230 | 230 | ||
| 231 | /* ECC correction notice */ | 231 | /* ECC correction notice */ |
| 232 | ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); | 232 | *ecc_notice_size = persistent_ram_ecc_string(prz, NULL, 0); |
| 233 | 233 | ||
| 234 | *buf = kmalloc(size + ecc_notice_size + 1, GFP_KERNEL); | 234 | *buf = kmalloc(size + *ecc_notice_size + 1, GFP_KERNEL); |
| 235 | if (*buf == NULL) | 235 | if (*buf == NULL) |
| 236 | return -ENOMEM; | 236 | return -ENOMEM; |
| 237 | 237 | ||
| 238 | memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); | 238 | memcpy(*buf, (char *)persistent_ram_old(prz) + header_length, size); |
| 239 | persistent_ram_ecc_string(prz, *buf + size, ecc_notice_size + 1); | 239 | persistent_ram_ecc_string(prz, *buf + size, *ecc_notice_size + 1); |
| 240 | 240 | ||
| 241 | return size + ecc_notice_size; | 241 | return size; |
| 242 | } | 242 | } |
| 243 | 243 | ||
| 244 | static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, | 244 | static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, |
diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 831479f8df8f..899e95e84400 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h | |||
| @@ -58,7 +58,8 @@ struct pstore_info { | |||
| 58 | int (*close)(struct pstore_info *psi); | 58 | int (*close)(struct pstore_info *psi); |
| 59 | ssize_t (*read)(u64 *id, enum pstore_type_id *type, | 59 | ssize_t (*read)(u64 *id, enum pstore_type_id *type, |
| 60 | int *count, struct timespec *time, char **buf, | 60 | int *count, struct timespec *time, char **buf, |
| 61 | bool *compressed, struct pstore_info *psi); | 61 | bool *compressed, ssize_t *ecc_notice_size, |
| 62 | struct pstore_info *psi); | ||
| 62 | int (*write)(enum pstore_type_id type, | 63 | int (*write)(enum pstore_type_id type, |
| 63 | enum kmsg_dump_reason reason, u64 *id, | 64 | enum kmsg_dump_reason reason, u64 *id, |
| 64 | unsigned int part, int count, bool compressed, | 65 | unsigned int part, int count, bool compressed, |
