| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Persistent Storage - platform driver interface parts. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2007-2008 Google, Inc. |
|---|
| 5 | 6 | * Copyright (C) 2010 Intel Corporation <tony.luck@intel.com> |
|---|
| 6 | | - * |
|---|
| 7 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 8 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 9 | | - * published by the Free Software Foundation. |
|---|
| 10 | | - * |
|---|
| 11 | | - * This program is distributed in the hope that it will be useful, |
|---|
| 12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 14 | | - * GNU General Public License for more details. |
|---|
| 15 | | - * |
|---|
| 16 | | - * You should have received a copy of the GNU General Public License |
|---|
| 17 | | - * along with this program; if not, write to the Free Software |
|---|
| 18 | | - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
|---|
| 19 | 7 | */ |
|---|
| 20 | 8 | |
|---|
| 21 | 9 | #define pr_fmt(fmt) "pstore: " fmt |
|---|
| .. | .. |
|---|
| 56 | 44 | module_param_named(update_ms, pstore_update_ms, int, 0600); |
|---|
| 57 | 45 | MODULE_PARM_DESC(update_ms, "milliseconds before pstore updates its content " |
|---|
| 58 | 46 | "(default is -1, which means runtime updates are disabled; " |
|---|
| 59 | | - "enabling this option is not safe, it may lead to further " |
|---|
| 47 | + "enabling this option may not be safe; it may lead to further " |
|---|
| 60 | 48 | "corruption on Oopses)"); |
|---|
| 49 | + |
|---|
| 50 | +/* Names should be in the same order as the enum pstore_type_id */ |
|---|
| 51 | +static const char * const pstore_type_names[] = { |
|---|
| 52 | + "dmesg", |
|---|
| 53 | + "mce", |
|---|
| 54 | + "console", |
|---|
| 55 | + "ftrace", |
|---|
| 56 | + "rtas", |
|---|
| 57 | + "powerpc-ofw", |
|---|
| 58 | + "powerpc-common", |
|---|
| 59 | + "pmsg", |
|---|
| 60 | + "powerpc-opal", |
|---|
| 61 | +#ifdef CONFIG_PSTORE_BOOT_LOG |
|---|
| 62 | + "boot-log", |
|---|
| 63 | +#endif |
|---|
| 64 | +}; |
|---|
| 61 | 65 | |
|---|
| 62 | 66 | static int pstore_new_entry; |
|---|
| 63 | 67 | |
|---|
| .. | .. |
|---|
| 68 | 72 | static DECLARE_WORK(pstore_work, pstore_dowork); |
|---|
| 69 | 73 | |
|---|
| 70 | 74 | /* |
|---|
| 71 | | - * pstore_lock just protects "psinfo" during |
|---|
| 72 | | - * calls to pstore_register() |
|---|
| 75 | + * psinfo_lock protects "psinfo" during calls to |
|---|
| 76 | + * pstore_register(), pstore_unregister(), and |
|---|
| 77 | + * the filesystem mount/unmount routines. |
|---|
| 73 | 78 | */ |
|---|
| 74 | | -static DEFINE_SPINLOCK(pstore_lock); |
|---|
| 79 | +static DEFINE_MUTEX(psinfo_lock); |
|---|
| 75 | 80 | struct pstore_info *psinfo; |
|---|
| 76 | 81 | |
|---|
| 77 | 82 | static char *backend; |
|---|
| 83 | +module_param(backend, charp, 0444); |
|---|
| 84 | +MODULE_PARM_DESC(backend, "specific backend to use"); |
|---|
| 85 | + |
|---|
| 78 | 86 | static char *compress = |
|---|
| 79 | 87 | #ifdef CONFIG_PSTORE_COMPRESS_DEFAULT |
|---|
| 80 | 88 | CONFIG_PSTORE_COMPRESS_DEFAULT; |
|---|
| 81 | 89 | #else |
|---|
| 82 | 90 | NULL; |
|---|
| 83 | 91 | #endif |
|---|
| 92 | +module_param(compress, charp, 0444); |
|---|
| 93 | +MODULE_PARM_DESC(compress, "compression to use"); |
|---|
| 84 | 94 | |
|---|
| 85 | 95 | /* Compression parameters */ |
|---|
| 86 | 96 | static struct crypto_comp *tfm; |
|---|
| .. | .. |
|---|
| 104 | 114 | /* Tag each group of saved records with a sequence number */ |
|---|
| 105 | 115 | static int oopscount; |
|---|
| 106 | 116 | |
|---|
| 107 | | -static const char *get_reason_str(enum kmsg_dump_reason reason) |
|---|
| 117 | +const char *pstore_type_to_name(enum pstore_type_id type) |
|---|
| 108 | 118 | { |
|---|
| 109 | | - switch (reason) { |
|---|
| 110 | | - case KMSG_DUMP_PANIC: |
|---|
| 111 | | - return "Panic"; |
|---|
| 112 | | - case KMSG_DUMP_OOPS: |
|---|
| 113 | | - return "Oops"; |
|---|
| 114 | | - case KMSG_DUMP_EMERG: |
|---|
| 115 | | - return "Emergency"; |
|---|
| 116 | | - case KMSG_DUMP_RESTART: |
|---|
| 117 | | - return "Restart"; |
|---|
| 118 | | - case KMSG_DUMP_HALT: |
|---|
| 119 | | - return "Halt"; |
|---|
| 120 | | - case KMSG_DUMP_POWEROFF: |
|---|
| 121 | | - return "Poweroff"; |
|---|
| 122 | | - default: |
|---|
| 123 | | - return "Unknown"; |
|---|
| 119 | + BUILD_BUG_ON(ARRAY_SIZE(pstore_type_names) != PSTORE_TYPE_MAX); |
|---|
| 120 | + |
|---|
| 121 | + if (WARN_ON_ONCE(type >= PSTORE_TYPE_MAX)) |
|---|
| 122 | + return "unknown"; |
|---|
| 123 | + |
|---|
| 124 | + return pstore_type_names[type]; |
|---|
| 125 | +} |
|---|
| 126 | +EXPORT_SYMBOL_GPL(pstore_type_to_name); |
|---|
| 127 | + |
|---|
| 128 | +enum pstore_type_id pstore_name_to_type(const char *name) |
|---|
| 129 | +{ |
|---|
| 130 | + int i; |
|---|
| 131 | + |
|---|
| 132 | + for (i = 0; i < PSTORE_TYPE_MAX; i++) { |
|---|
| 133 | + if (!strcmp(pstore_type_names[i], name)) |
|---|
| 134 | + return i; |
|---|
| 124 | 135 | } |
|---|
| 136 | + |
|---|
| 137 | + return PSTORE_TYPE_MAX; |
|---|
| 138 | +} |
|---|
| 139 | +EXPORT_SYMBOL_GPL(pstore_name_to_type); |
|---|
| 140 | + |
|---|
| 141 | +static void pstore_timer_kick(void) |
|---|
| 142 | +{ |
|---|
| 143 | + if (pstore_update_ms < 0) |
|---|
| 144 | + return; |
|---|
| 145 | + |
|---|
| 146 | + mod_timer(&pstore_timer, jiffies + msecs_to_jiffies(pstore_update_ms)); |
|---|
| 125 | 147 | } |
|---|
| 126 | 148 | |
|---|
| 127 | 149 | /* |
|---|
| .. | .. |
|---|
| 262 | 284 | return outlen; |
|---|
| 263 | 285 | } |
|---|
| 264 | 286 | |
|---|
| 265 | | -static int pstore_decompress(void *in, void *out, |
|---|
| 266 | | - unsigned int inlen, unsigned int outlen) |
|---|
| 267 | | -{ |
|---|
| 268 | | - int ret; |
|---|
| 269 | | - |
|---|
| 270 | | - ret = crypto_comp_decompress(tfm, in, inlen, out, &outlen); |
|---|
| 271 | | - if (ret) { |
|---|
| 272 | | - pr_err("crypto_comp_decompress failed, ret = %d!\n", ret); |
|---|
| 273 | | - return ret; |
|---|
| 274 | | - } |
|---|
| 275 | | - |
|---|
| 276 | | - return outlen; |
|---|
| 277 | | -} |
|---|
| 278 | | - |
|---|
| 279 | 287 | static void allocate_buf_for_compression(void) |
|---|
| 280 | 288 | { |
|---|
| 281 | 289 | struct crypto_comp *ctx; |
|---|
| .. | .. |
|---|
| 322 | 330 | big_oops_buf_sz = size; |
|---|
| 323 | 331 | big_oops_buf = buf; |
|---|
| 324 | 332 | |
|---|
| 325 | | - pr_info("Using compression: %s\n", zbackend->name); |
|---|
| 333 | + pr_info("Using crash dump compression: %s\n", zbackend->name); |
|---|
| 326 | 334 | } |
|---|
| 327 | 335 | |
|---|
| 328 | 336 | static void free_buf_for_compression(void) |
|---|
| .. | .. |
|---|
| 374 | 382 | } |
|---|
| 375 | 383 | |
|---|
| 376 | 384 | /* |
|---|
| 377 | | - * callback from kmsg_dump. (s2,l2) has the most recently |
|---|
| 378 | | - * written bytes, older bytes are in (s1,l1). Save as much |
|---|
| 379 | | - * as we can from the end of the buffer. |
|---|
| 385 | + * callback from kmsg_dump. Save as much as we can (up to kmsg_bytes) from the |
|---|
| 386 | + * end of the buffer. |
|---|
| 380 | 387 | */ |
|---|
| 381 | 388 | static void pstore_dump(struct kmsg_dumper *dumper, |
|---|
| 382 | 389 | enum kmsg_dump_reason reason) |
|---|
| .. | .. |
|---|
| 386 | 393 | unsigned int part = 1; |
|---|
| 387 | 394 | int ret; |
|---|
| 388 | 395 | |
|---|
| 389 | | - why = get_reason_str(reason); |
|---|
| 396 | + why = kmsg_dump_reason_str(reason); |
|---|
| 390 | 397 | |
|---|
| 391 | 398 | if (down_trylock(&psinfo->buf_lock)) { |
|---|
| 392 | 399 | /* Failed to acquire lock: give up if we cannot wait. */ |
|---|
| .. | .. |
|---|
| 452 | 459 | } |
|---|
| 453 | 460 | |
|---|
| 454 | 461 | ret = psinfo->write(&record); |
|---|
| 455 | | - if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted()) |
|---|
| 462 | + if (ret == 0 && reason == KMSG_DUMP_OOPS) { |
|---|
| 456 | 463 | pstore_new_entry = 1; |
|---|
| 464 | + pstore_timer_kick(); |
|---|
| 465 | + } |
|---|
| 457 | 466 | |
|---|
| 458 | 467 | total += record.size; |
|---|
| 459 | 468 | part++; |
|---|
| .. | .. |
|---|
| 484 | 493 | { |
|---|
| 485 | 494 | struct pstore_record record; |
|---|
| 486 | 495 | |
|---|
| 496 | + if (!c) |
|---|
| 497 | + return; |
|---|
| 498 | + |
|---|
| 487 | 499 | pstore_record_init(&record, psinfo); |
|---|
| 488 | 500 | record.type = PSTORE_TYPE_CONSOLE; |
|---|
| 489 | 501 | |
|---|
| .. | .. |
|---|
| 493 | 505 | } |
|---|
| 494 | 506 | |
|---|
| 495 | 507 | static struct console pstore_console = { |
|---|
| 496 | | - .name = "pstore", |
|---|
| 497 | 508 | .write = pstore_console_write, |
|---|
| 498 | | -#ifdef CON_PSTORE |
|---|
| 499 | | - .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME | CON_PSTORE, |
|---|
| 500 | | -#else |
|---|
| 501 | | - .flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME, |
|---|
| 502 | | -#endif |
|---|
| 503 | 509 | .index = -1, |
|---|
| 504 | 510 | }; |
|---|
| 505 | 511 | |
|---|
| 506 | 512 | static void pstore_register_console(void) |
|---|
| 507 | 513 | { |
|---|
| 514 | + /* Show which backend is going to get console writes. */ |
|---|
| 515 | + strscpy(pstore_console.name, psinfo->name, |
|---|
| 516 | + sizeof(pstore_console.name)); |
|---|
| 517 | + /* |
|---|
| 518 | + * Always initialize flags here since prior unregister_console() |
|---|
| 519 | + * calls may have changed settings (specifically CON_ENABLED). |
|---|
| 520 | + */ |
|---|
| 521 | + pstore_console.flags = CON_PRINTBUFFER | CON_ENABLED | CON_ANYTIME; |
|---|
| 508 | 522 | register_console(&pstore_console); |
|---|
| 509 | 523 | } |
|---|
| 510 | 524 | |
|---|
| .. | .. |
|---|
| 549 | 563 | */ |
|---|
| 550 | 564 | int pstore_register(struct pstore_info *psi) |
|---|
| 551 | 565 | { |
|---|
| 552 | | - struct module *owner = psi->owner; |
|---|
| 553 | | - |
|---|
| 554 | 566 | if (backend && strcmp(backend, psi->name)) { |
|---|
| 555 | 567 | pr_warn("ignoring unexpected backend '%s'\n", psi->name); |
|---|
| 556 | 568 | return -EPERM; |
|---|
| .. | .. |
|---|
| 570 | 582 | return -EINVAL; |
|---|
| 571 | 583 | } |
|---|
| 572 | 584 | |
|---|
| 573 | | - spin_lock(&pstore_lock); |
|---|
| 585 | + mutex_lock(&psinfo_lock); |
|---|
| 574 | 586 | if (psinfo) { |
|---|
| 575 | 587 | pr_warn("backend '%s' already loaded: ignoring '%s'\n", |
|---|
| 576 | 588 | psinfo->name, psi->name); |
|---|
| 577 | | - spin_unlock(&pstore_lock); |
|---|
| 589 | + mutex_unlock(&psinfo_lock); |
|---|
| 578 | 590 | return -EBUSY; |
|---|
| 579 | 591 | } |
|---|
| 580 | 592 | |
|---|
| .. | .. |
|---|
| 583 | 595 | psinfo = psi; |
|---|
| 584 | 596 | mutex_init(&psinfo->read_mutex); |
|---|
| 585 | 597 | sema_init(&psinfo->buf_lock, 1); |
|---|
| 586 | | - spin_unlock(&pstore_lock); |
|---|
| 587 | | - |
|---|
| 588 | | - if (owner && !try_module_get(owner)) { |
|---|
| 589 | | - psinfo = NULL; |
|---|
| 590 | | - return -EINVAL; |
|---|
| 591 | | - } |
|---|
| 592 | 598 | |
|---|
| 593 | 599 | if (psi->flags & PSTORE_FLAGS_DMESG) |
|---|
| 594 | 600 | allocate_buf_for_compression(); |
|---|
| 595 | 601 | |
|---|
| 596 | | - if (pstore_is_mounted()) |
|---|
| 597 | | - pstore_get_records(0); |
|---|
| 602 | + pstore_get_records(0); |
|---|
| 598 | 603 | |
|---|
| 599 | | - if (psi->flags & PSTORE_FLAGS_DMESG) |
|---|
| 604 | + if (psi->flags & PSTORE_FLAGS_DMESG) { |
|---|
| 605 | + pstore_dumper.max_reason = psinfo->max_reason; |
|---|
| 600 | 606 | pstore_register_kmsg(); |
|---|
| 607 | + } |
|---|
| 601 | 608 | if (psi->flags & PSTORE_FLAGS_CONSOLE) |
|---|
| 602 | 609 | pstore_register_console(); |
|---|
| 603 | 610 | if (psi->flags & PSTORE_FLAGS_FTRACE) |
|---|
| .. | .. |
|---|
| 606 | 613 | pstore_register_pmsg(); |
|---|
| 607 | 614 | |
|---|
| 608 | 615 | /* Start watching for new records, if desired. */ |
|---|
| 609 | | - if (pstore_update_ms >= 0) { |
|---|
| 610 | | - pstore_timer.expires = jiffies + |
|---|
| 611 | | - msecs_to_jiffies(pstore_update_ms); |
|---|
| 612 | | - add_timer(&pstore_timer); |
|---|
| 613 | | - } |
|---|
| 616 | + pstore_timer_kick(); |
|---|
| 614 | 617 | |
|---|
| 615 | 618 | /* |
|---|
| 616 | 619 | * Update the module parameter backend, so it is visible |
|---|
| 617 | 620 | * through /sys/module/pstore/parameters/backend |
|---|
| 618 | 621 | */ |
|---|
| 619 | | - backend = psi->name; |
|---|
| 622 | + backend = kstrdup(psi->name, GFP_KERNEL); |
|---|
| 620 | 623 | |
|---|
| 621 | 624 | pr_info("Registered %s as persistent store backend\n", psi->name); |
|---|
| 622 | 625 | |
|---|
| 623 | | - module_put(owner); |
|---|
| 624 | | - |
|---|
| 626 | + mutex_unlock(&psinfo_lock); |
|---|
| 625 | 627 | return 0; |
|---|
| 626 | 628 | } |
|---|
| 627 | 629 | EXPORT_SYMBOL_GPL(pstore_register); |
|---|
| 628 | 630 | |
|---|
| 629 | 631 | void pstore_unregister(struct pstore_info *psi) |
|---|
| 630 | 632 | { |
|---|
| 631 | | - /* Stop timer and make sure all work has finished. */ |
|---|
| 632 | | - pstore_update_ms = -1; |
|---|
| 633 | | - del_timer_sync(&pstore_timer); |
|---|
| 634 | | - flush_work(&pstore_work); |
|---|
| 633 | + /* It's okay to unregister nothing. */ |
|---|
| 634 | + if (!psi) |
|---|
| 635 | + return; |
|---|
| 635 | 636 | |
|---|
| 637 | + mutex_lock(&psinfo_lock); |
|---|
| 638 | + |
|---|
| 639 | + /* Only one backend can be registered at a time. */ |
|---|
| 640 | + if (WARN_ON(psi != psinfo)) { |
|---|
| 641 | + mutex_unlock(&psinfo_lock); |
|---|
| 642 | + return; |
|---|
| 643 | + } |
|---|
| 644 | + |
|---|
| 645 | + /* Unregister all callbacks. */ |
|---|
| 636 | 646 | if (psi->flags & PSTORE_FLAGS_PMSG) |
|---|
| 637 | 647 | pstore_unregister_pmsg(); |
|---|
| 638 | 648 | if (psi->flags & PSTORE_FLAGS_FTRACE) |
|---|
| .. | .. |
|---|
| 642 | 652 | if (psi->flags & PSTORE_FLAGS_DMESG) |
|---|
| 643 | 653 | pstore_unregister_kmsg(); |
|---|
| 644 | 654 | |
|---|
| 655 | + /* Stop timer and make sure all work has finished. */ |
|---|
| 656 | + del_timer_sync(&pstore_timer); |
|---|
| 657 | + flush_work(&pstore_work); |
|---|
| 658 | + |
|---|
| 659 | + /* Remove all backend records from filesystem tree. */ |
|---|
| 660 | + pstore_put_backend_records(psi); |
|---|
| 661 | + |
|---|
| 645 | 662 | free_buf_for_compression(); |
|---|
| 646 | 663 | |
|---|
| 647 | 664 | psinfo = NULL; |
|---|
| 665 | + kfree(backend); |
|---|
| 648 | 666 | backend = NULL; |
|---|
| 667 | + mutex_unlock(&psinfo_lock); |
|---|
| 649 | 668 | } |
|---|
| 650 | 669 | EXPORT_SYMBOL_GPL(pstore_unregister); |
|---|
| 651 | 670 | |
|---|
| 652 | 671 | static void decompress_record(struct pstore_record *record) |
|---|
| 653 | 672 | { |
|---|
| 673 | + int ret; |
|---|
| 654 | 674 | int unzipped_len; |
|---|
| 655 | | - char *decompressed; |
|---|
| 675 | + char *unzipped, *workspace; |
|---|
| 656 | 676 | |
|---|
| 657 | 677 | if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !record->compressed) |
|---|
| 658 | 678 | return; |
|---|
| .. | .. |
|---|
| 663 | 683 | return; |
|---|
| 664 | 684 | } |
|---|
| 665 | 685 | |
|---|
| 666 | | - /* No compression method has created the common buffer. */ |
|---|
| 686 | + /* Missing compression buffer means compression was not initialized. */ |
|---|
| 667 | 687 | if (!big_oops_buf) { |
|---|
| 668 | | - pr_warn("no decompression buffer allocated\n"); |
|---|
| 688 | + pr_warn("no decompression method initialized!\n"); |
|---|
| 669 | 689 | return; |
|---|
| 670 | 690 | } |
|---|
| 671 | 691 | |
|---|
| 672 | | - unzipped_len = pstore_decompress(record->buf, big_oops_buf, |
|---|
| 673 | | - record->size, big_oops_buf_sz); |
|---|
| 674 | | - if (unzipped_len <= 0) { |
|---|
| 675 | | - pr_err("decompression failed: %d\n", unzipped_len); |
|---|
| 692 | + /* Allocate enough space to hold max decompression and ECC. */ |
|---|
| 693 | + unzipped_len = big_oops_buf_sz; |
|---|
| 694 | + workspace = kmalloc(unzipped_len + record->ecc_notice_size, |
|---|
| 695 | + GFP_KERNEL); |
|---|
| 696 | + if (!workspace) |
|---|
| 676 | 697 | return; |
|---|
| 677 | | - } |
|---|
| 678 | 698 | |
|---|
| 679 | | - /* Build new buffer for decompressed contents. */ |
|---|
| 680 | | - decompressed = kmalloc(unzipped_len + record->ecc_notice_size, |
|---|
| 681 | | - GFP_KERNEL); |
|---|
| 682 | | - if (!decompressed) { |
|---|
| 683 | | - pr_err("decompression ran out of memory\n"); |
|---|
| 699 | + /* After decompression "unzipped_len" is almost certainly smaller. */ |
|---|
| 700 | + ret = crypto_comp_decompress(tfm, record->buf, record->size, |
|---|
| 701 | + workspace, &unzipped_len); |
|---|
| 702 | + if (ret) { |
|---|
| 703 | + pr_err("crypto_comp_decompress failed, ret = %d!\n", ret); |
|---|
| 704 | + kfree(workspace); |
|---|
| 684 | 705 | return; |
|---|
| 685 | 706 | } |
|---|
| 686 | | - memcpy(decompressed, big_oops_buf, unzipped_len); |
|---|
| 687 | 707 | |
|---|
| 688 | 708 | /* Append ECC notice to decompressed buffer. */ |
|---|
| 689 | | - memcpy(decompressed + unzipped_len, record->buf + record->size, |
|---|
| 709 | + memcpy(workspace + unzipped_len, record->buf + record->size, |
|---|
| 690 | 710 | record->ecc_notice_size); |
|---|
| 691 | 711 | |
|---|
| 692 | | - /* Swap out compresed contents with decompressed contents. */ |
|---|
| 712 | + /* Copy decompressed contents into an minimum-sized allocation. */ |
|---|
| 713 | + unzipped = kmemdup(workspace, unzipped_len + record->ecc_notice_size, |
|---|
| 714 | + GFP_KERNEL); |
|---|
| 715 | + kfree(workspace); |
|---|
| 716 | + if (!unzipped) |
|---|
| 717 | + return; |
|---|
| 718 | + |
|---|
| 719 | + /* Swap out compressed contents with decompressed contents. */ |
|---|
| 693 | 720 | kfree(record->buf); |
|---|
| 694 | | - record->buf = decompressed; |
|---|
| 721 | + record->buf = unzipped; |
|---|
| 695 | 722 | record->size = unzipped_len; |
|---|
| 696 | 723 | record->compressed = false; |
|---|
| 697 | 724 | } |
|---|
| .. | .. |
|---|
| 774 | 801 | schedule_work(&pstore_work); |
|---|
| 775 | 802 | } |
|---|
| 776 | 803 | |
|---|
| 777 | | - if (pstore_update_ms >= 0) |
|---|
| 778 | | - mod_timer(&pstore_timer, |
|---|
| 779 | | - jiffies + msecs_to_jiffies(pstore_update_ms)); |
|---|
| 804 | + pstore_timer_kick(); |
|---|
| 780 | 805 | } |
|---|
| 781 | 806 | |
|---|
| 782 | | -void __init pstore_choose_compression(void) |
|---|
| 807 | +static void __init pstore_choose_compression(void) |
|---|
| 783 | 808 | { |
|---|
| 784 | 809 | const struct pstore_zbackend *step; |
|---|
| 785 | 810 | |
|---|
| .. | .. |
|---|
| 820 | 845 | pstore_exit_fs(); |
|---|
| 821 | 846 | } |
|---|
| 822 | 847 | module_exit(pstore_exit) |
|---|
| 823 | | - |
|---|
| 824 | | -module_param(compress, charp, 0444); |
|---|
| 825 | | -MODULE_PARM_DESC(compress, "Pstore compression to use"); |
|---|
| 826 | | - |
|---|
| 827 | | -module_param(backend, charp, 0444); |
|---|
| 828 | | -MODULE_PARM_DESC(backend, "Pstore backend to use"); |
|---|
| 829 | 848 | |
|---|
| 830 | 849 | MODULE_AUTHOR("Tony Luck <tony.luck@intel.com>"); |
|---|
| 831 | 850 | MODULE_LICENSE("GPL"); |
|---|