aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pstore
diff options
context:
space:
mode:
authorAnton Vorontsov <anton.vorontsov@linaro.org>2012-07-17 15:11:12 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-17 19:48:09 -0400
commitcbe7cbf5a666ad9dfe2e0c276066131af73769ab (patch)
treea354f2ed2f0a45f336b0172c46d0bb7c718eee0f /fs/pstore
parent67a101f573b0cb1043c8c305112113450cb9fdbf (diff)
pstore/ram: Make tracing log versioned
Decoding the binary trace w/ a different kernel might be troublesome since we convert addresses to symbols. For kernels with minimal changes, the mappings would probably match, but it's not guaranteed at all. (But still we could convert the addresses by hand, since we do print raw addresses.) If we use modules, the symbols could be loaded at different addresses from the previously booted kernel, and so this would also fail, but there's nothing we can do about it. Also, the binary data format that pstore/ram is using in its ringbuffer may change between the kernels, so here we too must ensure that we're running the same kernel. So, there are two questions really: 1. How to compute the unique kernel tag; 2. Where to store it. In this patch we're using LINUX_VERSION_CODE, just as hibernation (suspend-to-disk) does. This way we are protecting from the kernel version mismatch, making sure that we're running the same kernel version and patch level. We could use CRC of a symbol table (as suggested by Tony Luck), but for now let's not be that strict. And as for storing, we are using a small trick here. Instead of allocating a dedicated buffer for the tag (i.e. another prz), or hacking ram_core routines to "reserve" some control data in the buffer, we are just encoding the tag into the buffer signature (and XOR'ing it with the actual signature value, so that buffers not needing a tag can just pass zero, which will result into the plain old PRZ signature). Suggested-by: Steven Rostedt <rostedt@goodmis.org> Suggested-by: Tony Luck <tony.luck@intel.com> Suggested-by: Colin Cross <ccross@android.com> Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/pstore')
-rw-r--r--fs/pstore/ram.c13
-rw-r--r--fs/pstore/ram_core.c12
2 files changed, 15 insertions, 10 deletions
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 1dd108e0cc60..0b311bc18916 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -25,6 +25,7 @@
25#include <linux/kernel.h> 25#include <linux/kernel.h>
26#include <linux/err.h> 26#include <linux/err.h>
27#include <linux/module.h> 27#include <linux/module.h>
28#include <linux/version.h>
28#include <linux/pstore.h> 29#include <linux/pstore.h>
29#include <linux/time.h> 30#include <linux/time.h>
30#include <linux/io.h> 31#include <linux/io.h>
@@ -309,7 +310,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
309 for (i = 0; i < cxt->max_dump_cnt; i++) { 310 for (i = 0; i < cxt->max_dump_cnt; i++) {
310 size_t sz = cxt->record_size; 311 size_t sz = cxt->record_size;
311 312
312 cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc_size); 313 cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, cxt->ecc_size);
313 if (IS_ERR(cxt->przs[i])) { 314 if (IS_ERR(cxt->przs[i])) {
314 err = PTR_ERR(cxt->przs[i]); 315 err = PTR_ERR(cxt->przs[i]);
315 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", 316 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
@@ -327,7 +328,7 @@ fail_prz:
327 328
328static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt, 329static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
329 struct persistent_ram_zone **prz, 330 struct persistent_ram_zone **prz,
330 phys_addr_t *paddr, size_t sz) 331 phys_addr_t *paddr, size_t sz, u32 sig)
331{ 332{
332 if (!sz) 333 if (!sz)
333 return 0; 334 return 0;
@@ -335,7 +336,7 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
335 if (*paddr + sz > *paddr + cxt->size) 336 if (*paddr + sz > *paddr + cxt->size)
336 return -ENOMEM; 337 return -ENOMEM;
337 338
338 *prz = persistent_ram_new(*paddr, sz, cxt->ecc_size); 339 *prz = persistent_ram_new(*paddr, sz, sig, cxt->ecc_size);
339 if (IS_ERR(*prz)) { 340 if (IS_ERR(*prz)) {
340 int err = PTR_ERR(*prz); 341 int err = PTR_ERR(*prz);
341 342
@@ -394,11 +395,13 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
394 if (err) 395 if (err)
395 goto fail_out; 396 goto fail_out;
396 397
397 err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr, cxt->console_size); 398 err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr,
399 cxt->console_size, 0);
398 if (err) 400 if (err)
399 goto fail_init_cprz; 401 goto fail_init_cprz;
400 402
401 err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size); 403 err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
404 LINUX_VERSION_CODE);
402 if (err) 405 if (err)
403 goto fail_init_fprz; 406 goto fail_init_fprz;
404 407
diff --git a/fs/pstore/ram_core.c b/fs/pstore/ram_core.c
index 4dabbb8e4270..eecd2a8a84dd 100644
--- a/fs/pstore/ram_core.c
+++ b/fs/pstore/ram_core.c
@@ -391,7 +391,7 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
391} 391}
392 392
393static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz, 393static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
394 int ecc_size) 394 u32 sig, int ecc_size)
395{ 395{
396 int ret; 396 int ret;
397 397
@@ -399,7 +399,9 @@ static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
399 if (ret) 399 if (ret)
400 return ret; 400 return ret;
401 401
402 if (prz->buffer->sig == PERSISTENT_RAM_SIG) { 402 sig ^= PERSISTENT_RAM_SIG;
403
404 if (prz->buffer->sig == sig) {
403 if (buffer_size(prz) > prz->buffer_size || 405 if (buffer_size(prz) > prz->buffer_size ||
404 buffer_start(prz) > buffer_size(prz)) 406 buffer_start(prz) > buffer_size(prz))
405 pr_info("persistent_ram: found existing invalid buffer," 407 pr_info("persistent_ram: found existing invalid buffer,"
@@ -417,7 +419,7 @@ static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
417 " (sig = 0x%08x)\n", prz->buffer->sig); 419 " (sig = 0x%08x)\n", prz->buffer->sig);
418 } 420 }
419 421
420 prz->buffer->sig = PERSISTENT_RAM_SIG; 422 prz->buffer->sig = sig;
421 persistent_ram_zap(prz); 423 persistent_ram_zap(prz);
422 424
423 return 0; 425 return 0;
@@ -442,7 +444,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
442} 444}
443 445
444struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start, 446struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
445 size_t size, 447 size_t size, u32 sig,
446 int ecc_size) 448 int ecc_size)
447{ 449{
448 struct persistent_ram_zone *prz; 450 struct persistent_ram_zone *prz;
@@ -458,7 +460,7 @@ struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
458 if (ret) 460 if (ret)
459 goto err; 461 goto err;
460 462
461 ret = persistent_ram_post_init(prz, ecc_size); 463 ret = persistent_ram_post_init(prz, sig, ecc_size);
462 if (ret) 464 if (ret)
463 goto err; 465 goto err;
464 466