From cb095afd44768bf495894b9ad063bd078e4bb201 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Thu, 18 Oct 2018 11:17:42 -0700 Subject: pstore: Centralize init/exit routines In preparation for having additional actions during init/exit, this moves the init/exit into platform.c, centralizing the logic to make call outs to the fs init/exit. Signed-off-by: Kees Cook Tested-by: Guenter Roeck --- fs/pstore/inode.c | 11 ++--------- fs/pstore/internal.h | 5 +++-- fs/pstore/platform.c | 23 +++++++++++++++++++++++ 3 files changed, 28 insertions(+), 11 deletions(-) (limited to 'fs') diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 5fcb845b9fec..8cf2218b46a7 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c @@ -482,12 +482,10 @@ static struct file_system_type pstore_fs_type = { .kill_sb = pstore_kill_sb, }; -static int __init init_pstore_fs(void) +int __init pstore_init_fs(void) { int err; - pstore_choose_compression(); - /* Create a convenient mount point for people to access pstore */ err = sysfs_create_mount_point(fs_kobj, "pstore"); if (err) @@ -500,14 +498,9 @@ static int __init init_pstore_fs(void) out: return err; } -module_init(init_pstore_fs) -static void __exit exit_pstore_fs(void) +void __exit pstore_exit_fs(void) { unregister_filesystem(&pstore_fs_type); sysfs_remove_mount_point(fs_kobj, "pstore"); } -module_exit(exit_pstore_fs) - -MODULE_AUTHOR("Tony Luck "); -MODULE_LICENSE("GPL"); diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h index fb767e28aeb2..7062ea4bc57c 100644 --- a/fs/pstore/internal.h +++ b/fs/pstore/internal.h @@ -37,7 +37,8 @@ extern bool pstore_is_mounted(void); extern void pstore_record_init(struct pstore_record *record, struct pstore_info *psi); -/* Called during module_init() */ -extern void __init pstore_choose_compression(void); +/* Called during pstore init/exit. */ +int __init pstore_init_fs(void); +void __exit pstore_exit_fs(void); #endif diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 15e99d5a681d..d61e26812af6 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -780,8 +780,31 @@ void __init pstore_choose_compression(void) } } +static int __init pstore_init(void) +{ + int ret; + + pstore_choose_compression(); + + ret = pstore_init_fs(); + if (ret) + return ret; + + return 0; +} +module_init(pstore_init) + +static void __exit pstore_exit(void) +{ + pstore_exit_fs(); +} +module_exit(pstore_exit) + module_param(compress, charp, 0444); MODULE_PARM_DESC(compress, "Pstore compression to use"); module_param(backend, charp, 0444); MODULE_PARM_DESC(backend, "Pstore backend to use"); + +MODULE_AUTHOR("Tony Luck "); +MODULE_LICENSE("GPL"); -- cgit v1.2.3-59-g8ed1b From 416031653eb55f844e3547fb8f8576399a800da0 Mon Sep 17 00:00:00 2001 From: "Joel Fernandes (Google)" Date: Wed, 17 Oct 2018 03:13:55 -0700 Subject: pstore: Allocate compression during late_initcall() ramoops's call of pstore_register() was recently moved to run during late_initcall() because the crypto backend may not have been ready during postcore_initcall(). This meant early-boot crash dumps were not getting caught by pstore any more. Instead, lets allow calls to pstore_register() earlier, and once crypto is ready we can initialize the compression. Reported-by: Sai Prakash Ranjan Signed-off-by: Joel Fernandes (Google) Tested-by: Sai Prakash Ranjan Fixes: cb3bee0369bc ("pstore: Use crypto compress API") [kees: trivial rebase] Signed-off-by: Kees Cook Tested-by: Guenter Roeck --- fs/pstore/platform.c | 10 +++++++++- fs/pstore/ram.c | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index d61e26812af6..578f178a695f 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -786,13 +786,21 @@ static int __init pstore_init(void) pstore_choose_compression(); + /* + * Check if any pstore backends registered earlier but did not + * initialize compression because crypto was not ready. If so, + * initialize compression now. + */ + if (psinfo && !tfm) + allocate_buf_for_compression(); + ret = pstore_init_fs(); if (ret) return ret; return 0; } -module_init(pstore_init) +late_initcall(pstore_init); static void __exit pstore_exit(void) { diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index bbd1e357c23d..98e48d1a9776 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -940,7 +940,7 @@ static int __init ramoops_init(void) ramoops_register_dummy(); return platform_driver_register(&ramoops_driver); } -late_initcall(ramoops_init); +postcore_initcall(ramoops_init); static void __exit ramoops_exit(void) { -- cgit v1.2.3-59-g8ed1b From 95047b0519c17a28e09df5f38750f5354e3db4c4 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 17 Oct 2018 14:00:12 -0700 Subject: pstore: Refactor compression initialization This refactors compression initialization slightly to better handle getting potentially called twice (via early pstore_register() calls and later pstore_init()) and improves the comments and reporting to be more verbose. Signed-off-by: Kees Cook Tested-by: Guenter Roeck --- fs/pstore/platform.c | 48 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 15 deletions(-) (limited to 'fs') diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index 578f178a695f..b821054ca3ed 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -274,36 +274,56 @@ static int pstore_decompress(void *in, void *out, static void allocate_buf_for_compression(void) { + struct crypto_comp *ctx; + int size; + char *buf; + + /* Skip if not built-in or compression backend not selected yet. */ if (!IS_ENABLED(CONFIG_PSTORE_COMPRESS) || !zbackend) return; + /* Skip if no pstore backend yet or compression init already done. */ + if (!psinfo || tfm) + return; + if (!crypto_has_comp(zbackend->name, 0, 0)) { - pr_err("No %s compression\n", zbackend->name); + pr_err("Unknown compression: %s\n", zbackend->name); return; } - big_oops_buf_sz = zbackend->zbufsize(psinfo->bufsize); - if (big_oops_buf_sz <= 0) + size = zbackend->zbufsize(psinfo->bufsize); + if (size <= 0) { + pr_err("Invalid compression size for %s: %d\n", + zbackend->name, size); return; + } - big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); - if (!big_oops_buf) { - pr_err("allocate compression buffer error!\n"); + buf = kmalloc(size, GFP_KERNEL); + if (!buf) { + pr_err("Failed %d byte compression buffer allocation for: %s\n", + size, zbackend->name); return; } - tfm = crypto_alloc_comp(zbackend->name, 0, 0); - if (IS_ERR_OR_NULL(tfm)) { - kfree(big_oops_buf); - big_oops_buf = NULL; - pr_err("crypto_alloc_comp() failed!\n"); + ctx = crypto_alloc_comp(zbackend->name, 0, 0); + if (IS_ERR_OR_NULL(ctx)) { + kfree(buf); + pr_err("crypto_alloc_comp('%s') failed: %ld\n", zbackend->name, + PTR_ERR(ctx)); return; } + + /* A non-NULL big_oops_buf indicates compression is available. */ + tfm = ctx; + big_oops_buf_sz = size; + big_oops_buf = buf; + + pr_info("Using compression: %s\n", zbackend->name); } static void free_buf_for_compression(void) { - if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && !IS_ERR_OR_NULL(tfm)) + if (IS_ENABLED(CONFIG_PSTORE_COMPRESS) && tfm) crypto_free_comp(tfm); kfree(big_oops_buf); big_oops_buf = NULL; @@ -774,7 +794,6 @@ void __init pstore_choose_compression(void) for (step = zbackends; step->name; step++) { if (!strcmp(compress, step->name)) { zbackend = step; - pr_info("using %s compression\n", zbackend->name); return; } } @@ -791,8 +810,7 @@ static int __init pstore_init(void) * initialize compression because crypto was not ready. If so, * initialize compression now. */ - if (psinfo && !tfm) - allocate_buf_for_compression(); + allocate_buf_for_compression(); ret = pstore_init_fs(); if (ret) -- cgit v1.2.3-59-g8ed1b From 1227daa43bce1318ff6fb54e6cd862b4f60245c7 Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 17 Oct 2018 17:20:35 -0700 Subject: pstore/ram: Clarify resource reservation labels When ramoops reserved a memory region in the kernel, it had an unhelpful label of "persistent_memory". When reading /proc/iomem, it would be repeated many times, did not hint that it was ramoops in particular, and didn't clarify very much about what each was used for: 400000000-407ffffff : Persistent Memory (legacy) 400000000-400000fff : persistent_memory 400001000-400001fff : persistent_memory ... 4000ff000-4000fffff : persistent_memory Instead, this adds meaningful labels for how the various regions are being used: 400000000-407ffffff : Persistent Memory (legacy) 400000000-400000fff : ramoops:dump(0/252) 400001000-400001fff : ramoops:dump(1/252) ... 4000fc000-4000fcfff : ramoops:dump(252/252) 4000fd000-4000fdfff : ramoops:console 4000fe000-4000fe3ff : ramoops:ftrace(0/3) 4000fe400-4000fe7ff : ramoops:ftrace(1/3) 4000fe800-4000febff : ramoops:ftrace(2/3) 4000fec00-4000fefff : ramoops:ftrace(3/3) 4000ff000-4000fffff : ramoops:pmsg Signed-off-by: Kees Cook Reviewed-by: Joel Fernandes (Google) Tested-by: Sai Prakash Ranjan Tested-by: Guenter Roeck --- fs/pstore/ram.c | 16 +++++++++++++--- fs/pstore/ram_core.c | 11 +++++++---- include/linux/pstore_ram.h | 3 ++- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c index 98e48d1a9776..712960e117fe 100644 --- a/fs/pstore/ram.c +++ b/fs/pstore/ram.c @@ -587,9 +587,16 @@ static int ramoops_init_przs(const char *name, goto fail; for (i = 0; i < *cnt; i++) { + char *label; + + if (*cnt == 1) + label = kasprintf(GFP_KERNEL, "ramoops:%s", name); + else + label = kasprintf(GFP_KERNEL, "ramoops:%s(%d/%d)", + name, i, *cnt - 1); prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig, - &cxt->ecc_info, - cxt->memtype, flags); + &cxt->ecc_info, + cxt->memtype, flags, label); if (IS_ERR(prz_ar[i])) { err = PTR_ERR(prz_ar[i]); dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n", @@ -619,6 +626,8 @@ static int ramoops_init_prz(const char *name, struct persistent_ram_zone **prz, phys_addr_t *paddr, size_t sz, u32 sig) { + char *label; + if (!sz) return 0; @@ -629,8 +638,9 @@ static int ramoops_init_prz(const char *name, return -ENOMEM; } + label = kasprintf(GFP_KERNEL, "ramoops:%s", name); *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info, - cxt->memtype, 0); + cxt->memtype, 0, label); if (IS_ERR(*prz)) { int err = PTR_ERR(*prz); diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c index 951a14edcf51..f200dcefb3b4 100644 --- a/fs/pstore/ram_core.c +++ b/fs/pstore/ram_core.c @@ -433,11 +433,11 @@ static void *persistent_ram_vmap(phys_addr_t start, size_t size, } static void *persistent_ram_iomap(phys_addr_t start, size_t size, - unsigned int memtype) + unsigned int memtype, char *label) { void *va; - if (!request_mem_region(start, size, "persistent_ram")) { + if (!request_mem_region(start, size, label ?: "ramoops")) { pr_err("request mem region (0x%llx@0x%llx) failed\n", (unsigned long long)size, (unsigned long long)start); return NULL; @@ -460,7 +460,8 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size, if (pfn_valid(start >> PAGE_SHIFT)) prz->vaddr = persistent_ram_vmap(start, size, memtype); else - prz->vaddr = persistent_ram_iomap(start, size, memtype); + prz->vaddr = persistent_ram_iomap(start, size, memtype, + prz->label); if (!prz->vaddr) { pr_err("%s: Failed to map 0x%llx pages at 0x%llx\n", __func__, @@ -530,12 +531,13 @@ void persistent_ram_free(struct persistent_ram_zone *prz) prz->ecc_info.par = NULL; persistent_ram_free_old(prz); + kfree(prz->label); kfree(prz); } struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, u32 sig, struct persistent_ram_ecc_info *ecc_info, - unsigned int memtype, u32 flags) + unsigned int memtype, u32 flags, char *label) { struct persistent_ram_zone *prz; int ret = -ENOMEM; @@ -549,6 +551,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, /* Initialize general buffer state. */ raw_spin_lock_init(&prz->buffer_lock); prz->flags = flags; + prz->label = label; ret = persistent_ram_buffer_map(start, size, prz, memtype); if (ret) diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h index e6d226464838..602d64725222 100644 --- a/include/linux/pstore_ram.h +++ b/include/linux/pstore_ram.h @@ -46,6 +46,7 @@ struct persistent_ram_zone { phys_addr_t paddr; size_t size; void *vaddr; + char *label; struct persistent_ram_buffer *buffer; size_t buffer_size; u32 flags; @@ -65,7 +66,7 @@ struct persistent_ram_zone { struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size, u32 sig, struct persistent_ram_ecc_info *ecc_info, - unsigned int memtype, u32 flags); + unsigned int memtype, u32 flags, char *label); void persistent_ram_free(struct persistent_ram_zone *prz); void persistent_ram_zap(struct persistent_ram_zone *prz); -- cgit v1.2.3-59-g8ed1b