Skip to content

Commit

Permalink
pstore/ram: Make tracing log versioned
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Anton Vorontsov authored and Greg Kroah-Hartman committed Jul 17, 2012
1 parent 67a101f commit cbe7cbf
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 11 deletions.
13 changes: 8 additions & 5 deletions fs/pstore/ram.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/pstore.h>
#include <linux/time.h>
#include <linux/io.h>
Expand Down Expand Up @@ -309,7 +310,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
for (i = 0; i < cxt->max_dump_cnt; i++) {
size_t sz = cxt->record_size;

cxt->przs[i] = persistent_ram_new(*paddr, sz, cxt->ecc_size);
cxt->przs[i] = persistent_ram_new(*paddr, sz, 0, cxt->ecc_size);
if (IS_ERR(cxt->przs[i])) {
err = PTR_ERR(cxt->przs[i]);
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
Expand All @@ -327,15 +328,15 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,

static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
struct persistent_ram_zone **prz,
phys_addr_t *paddr, size_t sz)
phys_addr_t *paddr, size_t sz, u32 sig)
{
if (!sz)
return 0;

if (*paddr + sz > *paddr + cxt->size)
return -ENOMEM;

*prz = persistent_ram_new(*paddr, sz, cxt->ecc_size);
*prz = persistent_ram_new(*paddr, sz, sig, cxt->ecc_size);
if (IS_ERR(*prz)) {
int err = PTR_ERR(*prz);

Expand Down Expand Up @@ -394,11 +395,13 @@ static int __devinit ramoops_probe(struct platform_device *pdev)
if (err)
goto fail_out;

err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr, cxt->console_size);
err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr,
cxt->console_size, 0);
if (err)
goto fail_init_cprz;

err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size);
err = ramoops_init_prz(dev, cxt, &cxt->fprz, &paddr, cxt->ftrace_size,
LINUX_VERSION_CODE);
if (err)
goto fail_init_fprz;

Expand Down
12 changes: 7 additions & 5 deletions fs/pstore/ram_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,15 +391,17 @@ static int persistent_ram_buffer_map(phys_addr_t start, phys_addr_t size,
}

static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
int ecc_size)
u32 sig, int ecc_size)
{
int ret;

ret = persistent_ram_init_ecc(prz, ecc_size);
if (ret)
return ret;

if (prz->buffer->sig == PERSISTENT_RAM_SIG) {
sig ^= PERSISTENT_RAM_SIG;

if (prz->buffer->sig == sig) {
if (buffer_size(prz) > prz->buffer_size ||
buffer_start(prz) > buffer_size(prz))
pr_info("persistent_ram: found existing invalid buffer,"
Expand All @@ -417,7 +419,7 @@ static int __devinit persistent_ram_post_init(struct persistent_ram_zone *prz,
" (sig = 0x%08x)\n", prz->buffer->sig);
}

prz->buffer->sig = PERSISTENT_RAM_SIG;
prz->buffer->sig = sig;
persistent_ram_zap(prz);

return 0;
Expand All @@ -442,7 +444,7 @@ void persistent_ram_free(struct persistent_ram_zone *prz)
}

struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
size_t size,
size_t size, u32 sig,
int ecc_size)
{
struct persistent_ram_zone *prz;
Expand All @@ -458,7 +460,7 @@ struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
if (ret)
goto err;

ret = persistent_ram_post_init(prz, ecc_size);
ret = persistent_ram_post_init(prz, sig, ecc_size);
if (ret)
goto err;

Expand Down
2 changes: 1 addition & 1 deletion include/linux/pstore_ram.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ struct persistent_ram_zone {
};

struct persistent_ram_zone * __devinit persistent_ram_new(phys_addr_t start,
size_t size,
size_t size, u32 sig,
int ecc_size);
void persistent_ram_free(struct persistent_ram_zone *prz);
void persistent_ram_zap(struct persistent_ram_zone *prz);
Expand Down

0 comments on commit cbe7cbf

Please sign in to comment.