pstore/ram: Should update old dmesg buffer before reading
authorAnton Vorontsov <anton.vorontsov@linaro.org>
Sat, 26 May 2012 13:07:49 +0000 (06:07 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 13 Jun 2012 23:52:39 +0000 (16:52 -0700)
Without the update, we'll only see the new dmesg buffer after the
reboot, but previously we could see it right away. Making an oops
visible in pstore filesystem before reboot is a somewhat dubious
feature, but removing it wasn't an intentional change, so let's
restore it.

For this we have to make persistent_ram_save_old() safe for calling
multiple times, and also extern it.

Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
fs/pstore/ram.c
fs/pstore/ram_core.c
include/linux/pstore_ram.h

index 9123cce28c1e8d6f511738cda7435861f1261ef7..16ff7332eae0a99db545598fcbdf4443e4fa9cfa 100644 (file)
@@ -106,6 +106,8 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
        time->tv_sec = 0;
        time->tv_nsec = 0;
 
+       /* Update old/shadowed buffer. */
+       persistent_ram_save_old(prz);
        size = persistent_ram_old_size(prz);
        *buf = kmalloc(size, GFP_KERNEL);
        if (*buf == NULL)
index 31f8d184f3a0a659cd53a5002c2c013bb13e76a0..235513c46aafbe88e3dbd14ecd7e003639ba8be0 100644 (file)
@@ -250,23 +250,24 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
        persistent_ram_update_ecc(prz, start, count);
 }
 
-static void __init
-persistent_ram_save_old(struct persistent_ram_zone *prz)
+void persistent_ram_save_old(struct persistent_ram_zone *prz)
 {
        struct persistent_ram_buffer *buffer = prz->buffer;
        size_t size = buffer_size(prz);
        size_t start = buffer_start(prz);
-       char *dest;
 
-       persistent_ram_ecc_old(prz);
+       if (!size)
+               return;
 
-       dest = kmalloc(size, GFP_KERNEL);
-       if (dest == NULL) {
+       if (!prz->old_log) {
+               persistent_ram_ecc_old(prz);
+               prz->old_log = kmalloc(size, GFP_KERNEL);
+       }
+       if (!prz->old_log) {
                pr_err("persistent_ram: failed to allocate buffer\n");
                return;
        }
 
-       prz->old_log = dest;
        prz->old_log_size = size;
        memcpy(prz->old_log, &buffer->data[start], size - start);
        memcpy(prz->old_log + size - start, &buffer->data[0], start);
index 7ed7fd4dba49629fe6bd3ed2bef29b244bd7c6d9..4491e8ff36e661f19b4273cec473bd6cb6e1fd03 100644 (file)
@@ -75,6 +75,7 @@ struct persistent_ram_zone *persistent_ram_init_ringbuffer(struct device *dev,
 int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
        unsigned int count);
 
+void persistent_ram_save_old(struct persistent_ram_zone *prz);
 size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
 void *persistent_ram_old(struct persistent_ram_zone *prz);
 void persistent_ram_free_old(struct persistent_ram_zone *prz);