mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 14:11:52 +00:00
Fix bug in module unloading.
Switch to always using spinlock over cmpxchg. Explicitly define pstore backend's supported modes. Remove bounce buffer from pmsg. Switch to using memcpy_to/fromio(). Error checking improvements. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 Comment: Kees Cook <kees@outflux.net> iQIcBAABCgAGBQJX9XPtAAoJEIly9N/cbcAmRr8P/0NoEX3bzEYgQWVMmsvzlk4U /mJ7LUk1+TDL0DOdQ84O1Tr3k6MQ2wRyiGXHjxhQ+aC2ompvmuT+SHEARWlqUZZx bEKr3u6nJ5qz1KZ5KwaPOH2EPs2MDq2jh6VvYDFzDGpBYsueDTzRqWJo7VhO/kmq MyVCePtEY3m1q4dZtaVLfDMGUEAU8s8j+D5HM9lmoijmzQuKAz3BFRuakasBIYSf 4ILY0W1E57HAUWsi19jhnYMHOvJt2Gcog0wRUYo4CYmPTyNqud6I5WU6HXeY2F7v LtWbhaS2QcpJRAxDEzzKBBSZ4IS6TINYDBBOf/0NEVo2qj4PHyy3f14MCtSo2LDg 4hoeI0DUgnAmp+NFgp1mQQ25DhR8TZlunBuntGXdeugb5qgT65NYXGtQxnMp5QJd s3DsfGW/diKbKfLWQN7GVcHHM/GNe+XM1yl1Q3TyDgSLJVjgAB21r/kPE7AIQzTO vDTLcv1w+KLdhDIrHlZqz1IAPATidTA21A7h8JeUWrOSetOhpZ0uXUwBR5+IZhyN tG1Wt0ohZAqlhv9ERXYN1g3iRHCCJ26V0LYOKsf80wAAutT8iRO4iH0PKdEYKX+a U0TqeX4TIh+4Q3FgnR7efFACzPXrM1RG9qnc1o5OR/BiyXIzLPdrpYYCVpejzj9K x6AoYCxRl6qYLJgYUR/H =FRpQ -----END PGP SIGNATURE----- Merge tag 'pstore-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux Pull pstore updates from Kees Cook: - Fix bug in module unloading - Switch to always using spinlock over cmpxchg - Explicitly define pstore backend's supported modes - Remove bounce buffer from pmsg - Switch to using memcpy_to/fromio() - Error checking improvements * tag 'pstore-v4.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: ramoops: move spin_lock_init after kmalloc error checking pstore/ram: Use memcpy_fromio() to save old buffer pstore/ram: Use memcpy_toio instead of memcpy pstore/pmsg: drop bounce buffer pstore/ram: Set pstore flags dynamically pstore: Split pstore fragile flags pstore/core: drop cmpxchg based updates pstore/ramoops: fixup driver removal
This commit is contained in:
commit
0fb3ca447d
@ -938,7 +938,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
|
||||
static struct pstore_info erst_info = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "erst",
|
||||
.flags = PSTORE_FLAGS_FRAGILE,
|
||||
.flags = PSTORE_FLAGS_DMESG,
|
||||
.open = erst_open_pstore,
|
||||
.close = erst_close_pstore,
|
||||
.read = erst_reader,
|
||||
|
@ -380,7 +380,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
|
||||
static struct pstore_info efi_pstore_info = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "efi",
|
||||
.flags = PSTORE_FLAGS_FRAGILE,
|
||||
.flags = PSTORE_FLAGS_DMESG,
|
||||
.open = efi_pstore_open,
|
||||
.close = efi_pstore_close,
|
||||
.read = efi_pstore_read,
|
||||
|
@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type,
|
||||
size, psi);
|
||||
}
|
||||
|
||||
static int pstore_write_buf_user_compat(enum pstore_type_id type,
|
||||
enum kmsg_dump_reason reason,
|
||||
u64 *id, unsigned int part,
|
||||
const char __user *buf,
|
||||
bool compressed, size_t size,
|
||||
struct pstore_info *psi)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
size_t i, bufsize = size;
|
||||
long ret = 0;
|
||||
|
||||
if (unlikely(!access_ok(VERIFY_READ, buf, size)))
|
||||
return -EFAULT;
|
||||
if (bufsize > psinfo->bufsize)
|
||||
bufsize = psinfo->bufsize;
|
||||
spin_lock_irqsave(&psinfo->buf_lock, flags);
|
||||
for (i = 0; i < size; ) {
|
||||
size_t c = min(size - i, bufsize);
|
||||
|
||||
ret = __copy_from_user(psinfo->buf, buf + i, c);
|
||||
if (unlikely(ret != 0)) {
|
||||
ret = -EFAULT;
|
||||
break;
|
||||
}
|
||||
ret = psi->write_buf(type, reason, id, part, psinfo->buf,
|
||||
compressed, c, psi);
|
||||
if (unlikely(ret < 0))
|
||||
break;
|
||||
i += c;
|
||||
}
|
||||
spin_unlock_irqrestore(&psinfo->buf_lock, flags);
|
||||
return unlikely(ret < 0) ? ret : size;
|
||||
}
|
||||
|
||||
/*
|
||||
* platform specific persistent storage driver registers with
|
||||
* us here. If pstore is already mounted, call the platform
|
||||
@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi)
|
||||
|
||||
if (!psi->write)
|
||||
psi->write = pstore_write_compat;
|
||||
if (!psi->write_buf_user)
|
||||
psi->write_buf_user = pstore_write_buf_user_compat;
|
||||
psinfo = psi;
|
||||
mutex_init(&psinfo->read_mutex);
|
||||
spin_unlock(&pstore_lock);
|
||||
@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi)
|
||||
if (pstore_is_mounted())
|
||||
pstore_get_records(0);
|
||||
|
||||
pstore_register_kmsg();
|
||||
|
||||
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
|
||||
if (psi->flags & PSTORE_FLAGS_DMESG)
|
||||
pstore_register_kmsg();
|
||||
if (psi->flags & PSTORE_FLAGS_CONSOLE)
|
||||
pstore_register_console();
|
||||
if (psi->flags & PSTORE_FLAGS_FTRACE)
|
||||
pstore_register_ftrace();
|
||||
if (psi->flags & PSTORE_FLAGS_PMSG)
|
||||
pstore_register_pmsg();
|
||||
}
|
||||
|
||||
if (pstore_update_ms >= 0) {
|
||||
pstore_timer.expires = jiffies +
|
||||
@ -689,12 +726,14 @@ EXPORT_SYMBOL_GPL(pstore_register);
|
||||
|
||||
void pstore_unregister(struct pstore_info *psi)
|
||||
{
|
||||
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
|
||||
if (psi->flags & PSTORE_FLAGS_PMSG)
|
||||
pstore_unregister_pmsg();
|
||||
if (psi->flags & PSTORE_FLAGS_FTRACE)
|
||||
pstore_unregister_ftrace();
|
||||
if (psi->flags & PSTORE_FLAGS_CONSOLE)
|
||||
pstore_unregister_console();
|
||||
}
|
||||
pstore_unregister_kmsg();
|
||||
if (psi->flags & PSTORE_FLAGS_DMESG)
|
||||
pstore_unregister_kmsg();
|
||||
|
||||
free_buf_for_compression();
|
||||
|
||||
|
@ -19,48 +19,25 @@
|
||||
#include "internal.h"
|
||||
|
||||
static DEFINE_MUTEX(pmsg_lock);
|
||||
#define PMSG_MAX_BOUNCE_BUFFER_SIZE (2*PAGE_SIZE)
|
||||
|
||||
static ssize_t write_pmsg(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
size_t i, buffer_size;
|
||||
char *buffer;
|
||||
u64 id;
|
||||
int ret;
|
||||
|
||||
if (!count)
|
||||
return 0;
|
||||
|
||||
/* check outside lock, page in any data. write_buf_user also checks */
|
||||
if (!access_ok(VERIFY_READ, buf, count))
|
||||
return -EFAULT;
|
||||
|
||||
buffer_size = count;
|
||||
if (buffer_size > PMSG_MAX_BOUNCE_BUFFER_SIZE)
|
||||
buffer_size = PMSG_MAX_BOUNCE_BUFFER_SIZE;
|
||||
buffer = vmalloc(buffer_size);
|
||||
if (!buffer)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&pmsg_lock);
|
||||
for (i = 0; i < count; ) {
|
||||
size_t c = min(count - i, buffer_size);
|
||||
u64 id;
|
||||
long ret;
|
||||
|
||||
ret = __copy_from_user(buffer, buf + i, c);
|
||||
if (unlikely(ret != 0)) {
|
||||
mutex_unlock(&pmsg_lock);
|
||||
vfree(buffer);
|
||||
return -EFAULT;
|
||||
}
|
||||
psinfo->write_buf(PSTORE_TYPE_PMSG, 0, &id, 0, buffer, 0, c,
|
||||
psinfo);
|
||||
|
||||
i += c;
|
||||
}
|
||||
|
||||
ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, count,
|
||||
psinfo);
|
||||
mutex_unlock(&pmsg_lock);
|
||||
vfree(buffer);
|
||||
return count;
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
static const struct file_operations pmsg_fops = {
|
||||
|
@ -331,6 +331,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int notrace ramoops_pstore_write_buf_user(enum pstore_type_id type,
|
||||
enum kmsg_dump_reason reason,
|
||||
u64 *id, unsigned int part,
|
||||
const char __user *buf,
|
||||
bool compressed, size_t size,
|
||||
struct pstore_info *psi)
|
||||
{
|
||||
if (type == PSTORE_TYPE_PMSG) {
|
||||
struct ramoops_context *cxt = psi->data;
|
||||
|
||||
if (!cxt->mprz)
|
||||
return -ENOMEM;
|
||||
return persistent_ram_write_user(cxt->mprz, buf, size);
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
|
||||
struct timespec time, struct pstore_info *psi)
|
||||
{
|
||||
@ -369,6 +387,7 @@ static struct ramoops_context oops_cxt = {
|
||||
.open = ramoops_pstore_open,
|
||||
.read = ramoops_pstore_read,
|
||||
.write_buf = ramoops_pstore_write_buf,
|
||||
.write_buf_user = ramoops_pstore_write_buf_user,
|
||||
.erase = ramoops_pstore_erase,
|
||||
},
|
||||
};
|
||||
@ -377,13 +396,14 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
|
||||
{
|
||||
int i;
|
||||
|
||||
cxt->max_dump_cnt = 0;
|
||||
if (!cxt->przs)
|
||||
return;
|
||||
|
||||
for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
|
||||
for (i = 0; i < cxt->max_dump_cnt; i++)
|
||||
persistent_ram_free(cxt->przs[i]);
|
||||
|
||||
kfree(cxt->przs);
|
||||
cxt->max_dump_cnt = 0;
|
||||
}
|
||||
|
||||
static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
|
||||
@ -408,7 +428,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
|
||||
GFP_KERNEL);
|
||||
if (!cxt->przs) {
|
||||
dev_err(dev, "failed to initialize a prz array for dumps\n");
|
||||
goto fail_prz;
|
||||
goto fail_mem;
|
||||
}
|
||||
|
||||
for (i = 0; i < cxt->max_dump_cnt; i++) {
|
||||
@ -419,6 +439,11 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
|
||||
err = PTR_ERR(cxt->przs[i]);
|
||||
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
|
||||
cxt->record_size, (unsigned long long)*paddr, err);
|
||||
|
||||
while (i > 0) {
|
||||
i--;
|
||||
persistent_ram_free(cxt->przs[i]);
|
||||
}
|
||||
goto fail_prz;
|
||||
}
|
||||
*paddr += cxt->record_size;
|
||||
@ -426,7 +451,9 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
|
||||
|
||||
return 0;
|
||||
fail_prz:
|
||||
ramoops_free_przs(cxt);
|
||||
kfree(cxt->przs);
|
||||
fail_mem:
|
||||
cxt->max_dump_cnt = 0;
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -608,12 +635,20 @@ static int ramoops_probe(struct platform_device *pdev)
|
||||
cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
|
||||
cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
|
||||
cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
|
||||
spin_lock_init(&cxt->pstore.buf_lock);
|
||||
if (!cxt->pstore.buf) {
|
||||
pr_err("cannot allocate pstore buffer\n");
|
||||
err = -ENOMEM;
|
||||
goto fail_clear;
|
||||
}
|
||||
spin_lock_init(&cxt->pstore.buf_lock);
|
||||
|
||||
cxt->pstore.flags = PSTORE_FLAGS_DMESG;
|
||||
if (cxt->console_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_CONSOLE;
|
||||
if (cxt->ftrace_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_FTRACE;
|
||||
if (cxt->pmsg_size)
|
||||
cxt->pstore.flags |= PSTORE_FLAGS_PMSG;
|
||||
|
||||
err = pstore_register(&cxt->pstore);
|
||||
if (err) {
|
||||
@ -659,7 +694,6 @@ static int ramoops_remove(struct platform_device *pdev)
|
||||
struct ramoops_context *cxt = &oops_cxt;
|
||||
|
||||
pstore_unregister(&cxt->pstore);
|
||||
cxt->max_dump_cnt = 0;
|
||||
|
||||
kfree(cxt->pstore.buf);
|
||||
cxt->pstore.bufsize = 0;
|
||||
|
@ -17,15 +17,16 @@
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/pstore_ram.h>
|
||||
#include <linux/rslib.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/pstore_ram.h>
|
||||
#include <asm/page.h>
|
||||
|
||||
struct persistent_ram_buffer {
|
||||
@ -47,43 +48,10 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
|
||||
return atomic_read(&prz->buffer->start);
|
||||
}
|
||||
|
||||
/* increase and wrap the start pointer, returning the old value */
|
||||
static size_t buffer_start_add_atomic(struct persistent_ram_zone *prz, size_t a)
|
||||
{
|
||||
int old;
|
||||
int new;
|
||||
|
||||
do {
|
||||
old = atomic_read(&prz->buffer->start);
|
||||
new = old + a;
|
||||
while (unlikely(new >= prz->buffer_size))
|
||||
new -= prz->buffer_size;
|
||||
} while (atomic_cmpxchg(&prz->buffer->start, old, new) != old);
|
||||
|
||||
return old;
|
||||
}
|
||||
|
||||
/* increase the size counter until it hits the max size */
|
||||
static void buffer_size_add_atomic(struct persistent_ram_zone *prz, size_t a)
|
||||
{
|
||||
size_t old;
|
||||
size_t new;
|
||||
|
||||
if (atomic_read(&prz->buffer->size) == prz->buffer_size)
|
||||
return;
|
||||
|
||||
do {
|
||||
old = atomic_read(&prz->buffer->size);
|
||||
new = old + a;
|
||||
if (new > prz->buffer_size)
|
||||
new = prz->buffer_size;
|
||||
} while (atomic_cmpxchg(&prz->buffer->size, old, new) != old);
|
||||
}
|
||||
|
||||
static DEFINE_RAW_SPINLOCK(buffer_lock);
|
||||
|
||||
/* increase and wrap the start pointer, returning the old value */
|
||||
static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a)
|
||||
static size_t buffer_start_add(struct persistent_ram_zone *prz, size_t a)
|
||||
{
|
||||
int old;
|
||||
int new;
|
||||
@ -103,7 +71,7 @@ static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a)
|
||||
}
|
||||
|
||||
/* increase the size counter until it hits the max size */
|
||||
static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a)
|
||||
static void buffer_size_add(struct persistent_ram_zone *prz, size_t a)
|
||||
{
|
||||
size_t old;
|
||||
size_t new;
|
||||
@ -124,9 +92,6 @@ exit:
|
||||
raw_spin_unlock_irqrestore(&buffer_lock, flags);
|
||||
}
|
||||
|
||||
static size_t (*buffer_start_add)(struct persistent_ram_zone *, size_t) = buffer_start_add_atomic;
|
||||
static void (*buffer_size_add)(struct persistent_ram_zone *, size_t) = buffer_size_add_atomic;
|
||||
|
||||
static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
|
||||
uint8_t *data, size_t len, uint8_t *ecc)
|
||||
{
|
||||
@ -299,10 +264,20 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
|
||||
const void *s, unsigned int start, unsigned int count)
|
||||
{
|
||||
struct persistent_ram_buffer *buffer = prz->buffer;
|
||||
memcpy(buffer->data + start, s, count);
|
||||
memcpy_toio(buffer->data + start, s, count);
|
||||
persistent_ram_update_ecc(prz, start, count);
|
||||
}
|
||||
|
||||
static int notrace persistent_ram_update_user(struct persistent_ram_zone *prz,
|
||||
const void __user *s, unsigned int start, unsigned int count)
|
||||
{
|
||||
struct persistent_ram_buffer *buffer = prz->buffer;
|
||||
int ret = unlikely(__copy_from_user(buffer->data + start, s, count)) ?
|
||||
-EFAULT : 0;
|
||||
persistent_ram_update_ecc(prz, start, count);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void persistent_ram_save_old(struct persistent_ram_zone *prz)
|
||||
{
|
||||
struct persistent_ram_buffer *buffer = prz->buffer;
|
||||
@ -322,8 +297,8 @@ void persistent_ram_save_old(struct persistent_ram_zone *prz)
|
||||
}
|
||||
|
||||
prz->old_log_size = size;
|
||||
memcpy(prz->old_log, &buffer->data[start], size - start);
|
||||
memcpy(prz->old_log + size - start, &buffer->data[0], start);
|
||||
memcpy_fromio(prz->old_log, &buffer->data[start], size - start);
|
||||
memcpy_fromio(prz->old_log + size - start, &buffer->data[0], start);
|
||||
}
|
||||
|
||||
int notrace persistent_ram_write(struct persistent_ram_zone *prz,
|
||||
@ -356,6 +331,38 @@ int notrace persistent_ram_write(struct persistent_ram_zone *prz,
|
||||
return count;
|
||||
}
|
||||
|
||||
int notrace persistent_ram_write_user(struct persistent_ram_zone *prz,
|
||||
const void __user *s, unsigned int count)
|
||||
{
|
||||
int rem, ret = 0, c = count;
|
||||
size_t start;
|
||||
|
||||
if (unlikely(!access_ok(VERIFY_READ, s, count)))
|
||||
return -EFAULT;
|
||||
if (unlikely(c > prz->buffer_size)) {
|
||||
s += c - prz->buffer_size;
|
||||
c = prz->buffer_size;
|
||||
}
|
||||
|
||||
buffer_size_add(prz, c);
|
||||
|
||||
start = buffer_start_add(prz, c);
|
||||
|
||||
rem = prz->buffer_size - start;
|
||||
if (unlikely(rem < c)) {
|
||||
ret = persistent_ram_update_user(prz, s, start, rem);
|
||||
s += rem;
|
||||
c -= rem;
|
||||
start = 0;
|
||||
}
|
||||
if (likely(!ret))
|
||||
ret = persistent_ram_update_user(prz, s, start, c);
|
||||
|
||||
persistent_ram_update_header_ecc(prz);
|
||||
|
||||
return unlikely(ret) ? ret : count;
|
||||
}
|
||||
|
||||
size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
|
||||
{
|
||||
return prz->old_log_size;
|
||||
@ -426,9 +433,6 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buffer_start_add = buffer_start_add_locked;
|
||||
buffer_size_add = buffer_size_add_locked;
|
||||
|
||||
if (memtype)
|
||||
va = ioremap(start, size);
|
||||
else
|
||||
|
@ -22,12 +22,13 @@
|
||||
#ifndef _LINUX_PSTORE_H
|
||||
#define _LINUX_PSTORE_H
|
||||
|
||||
#include <linux/time.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/kmsg_dump.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/* types */
|
||||
enum pstore_type_id {
|
||||
@ -68,13 +69,21 @@ struct pstore_info {
|
||||
enum kmsg_dump_reason reason, u64 *id,
|
||||
unsigned int part, const char *buf, bool compressed,
|
||||
size_t size, struct pstore_info *psi);
|
||||
int (*write_buf_user)(enum pstore_type_id type,
|
||||
enum kmsg_dump_reason reason, u64 *id,
|
||||
unsigned int part, const char __user *buf,
|
||||
bool compressed, size_t size, struct pstore_info *psi);
|
||||
int (*erase)(enum pstore_type_id type, u64 id,
|
||||
int count, struct timespec time,
|
||||
struct pstore_info *psi);
|
||||
void *data;
|
||||
};
|
||||
|
||||
#define PSTORE_FLAGS_FRAGILE 1
|
||||
#define PSTORE_FLAGS_DMESG (1 << 0)
|
||||
#define PSTORE_FLAGS_FRAGILE PSTORE_FLAGS_DMESG
|
||||
#define PSTORE_FLAGS_CONSOLE (1 << 1)
|
||||
#define PSTORE_FLAGS_FTRACE (1 << 2)
|
||||
#define PSTORE_FLAGS_PMSG (1 << 3)
|
||||
|
||||
extern int pstore_register(struct pstore_info *);
|
||||
extern void pstore_unregister(struct pstore_info *);
|
||||
|
@ -17,11 +17,12 @@
|
||||
#ifndef __LINUX_PSTORE_RAM_H__
|
||||
#define __LINUX_PSTORE_RAM_H__
|
||||
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
|
||||
struct persistent_ram_buffer;
|
||||
struct rs_control;
|
||||
@ -59,7 +60,9 @@ void persistent_ram_free(struct persistent_ram_zone *prz);
|
||||
void persistent_ram_zap(struct persistent_ram_zone *prz);
|
||||
|
||||
int persistent_ram_write(struct persistent_ram_zone *prz, const void *s,
|
||||
unsigned int count);
|
||||
unsigned int count);
|
||||
int persistent_ram_write_user(struct persistent_ram_zone *prz,
|
||||
const void __user *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);
|
||||
|
Loading…
Reference in New Issue
Block a user