Commit 0fb3ca44 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 3940ee36 f88baf68
...@@ -938,7 +938,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count, ...@@ -938,7 +938,7 @@ static int erst_clearer(enum pstore_type_id type, u64 id, int count,
static struct pstore_info erst_info = { static struct pstore_info erst_info = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "erst", .name = "erst",
.flags = PSTORE_FLAGS_FRAGILE, .flags = PSTORE_FLAGS_DMESG,
.open = erst_open_pstore, .open = erst_open_pstore,
.close = erst_close_pstore, .close = erst_close_pstore,
.read = erst_reader, .read = erst_reader,
......
...@@ -380,7 +380,7 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, ...@@ -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 = { static struct pstore_info efi_pstore_info = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.name = "efi", .name = "efi",
.flags = PSTORE_FLAGS_FRAGILE, .flags = PSTORE_FLAGS_DMESG,
.open = efi_pstore_open, .open = efi_pstore_open,
.close = efi_pstore_close, .close = efi_pstore_close,
.read = efi_pstore_read, .read = efi_pstore_read,
......
...@@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type, ...@@ -623,6 +623,40 @@ static int pstore_write_compat(enum pstore_type_id type,
size, psi); 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 * platform specific persistent storage driver registers with
* us here. If pstore is already mounted, call the platform * us here. If pstore is already mounted, call the platform
...@@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi) ...@@ -645,6 +679,8 @@ int pstore_register(struct pstore_info *psi)
if (!psi->write) if (!psi->write)
psi->write = pstore_write_compat; psi->write = pstore_write_compat;
if (!psi->write_buf_user)
psi->write_buf_user = pstore_write_buf_user_compat;
psinfo = psi; psinfo = psi;
mutex_init(&psinfo->read_mutex); mutex_init(&psinfo->read_mutex);
spin_unlock(&pstore_lock); spin_unlock(&pstore_lock);
...@@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi) ...@@ -659,13 +695,14 @@ int pstore_register(struct pstore_info *psi)
if (pstore_is_mounted()) if (pstore_is_mounted())
pstore_get_records(0); pstore_get_records(0);
if (psi->flags & PSTORE_FLAGS_DMESG)
pstore_register_kmsg(); pstore_register_kmsg();
if (psi->flags & PSTORE_FLAGS_CONSOLE)
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) {
pstore_register_console(); pstore_register_console();
if (psi->flags & PSTORE_FLAGS_FTRACE)
pstore_register_ftrace(); pstore_register_ftrace();
if (psi->flags & PSTORE_FLAGS_PMSG)
pstore_register_pmsg(); pstore_register_pmsg();
}
if (pstore_update_ms >= 0) { if (pstore_update_ms >= 0) {
pstore_timer.expires = jiffies + pstore_timer.expires = jiffies +
...@@ -689,11 +726,13 @@ EXPORT_SYMBOL_GPL(pstore_register); ...@@ -689,11 +726,13 @@ EXPORT_SYMBOL_GPL(pstore_register);
void pstore_unregister(struct pstore_info *psi) void pstore_unregister(struct pstore_info *psi)
{ {
if ((psi->flags & PSTORE_FLAGS_FRAGILE) == 0) { if (psi->flags & PSTORE_FLAGS_PMSG)
pstore_unregister_pmsg(); pstore_unregister_pmsg();
if (psi->flags & PSTORE_FLAGS_FTRACE)
pstore_unregister_ftrace(); pstore_unregister_ftrace();
if (psi->flags & PSTORE_FLAGS_CONSOLE)
pstore_unregister_console(); pstore_unregister_console();
} if (psi->flags & PSTORE_FLAGS_DMESG)
pstore_unregister_kmsg(); pstore_unregister_kmsg();
free_buf_for_compression(); free_buf_for_compression();
......
...@@ -19,48 +19,25 @@ ...@@ -19,48 +19,25 @@
#include "internal.h" #include "internal.h"
static DEFINE_MUTEX(pmsg_lock); 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, static ssize_t write_pmsg(struct file *file, const char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
size_t i, buffer_size; u64 id;
char *buffer; int ret;
if (!count) if (!count)
return 0; return 0;
/* check outside lock, page in any data. write_buf_user also checks */
if (!access_ok(VERIFY_READ, buf, count)) if (!access_ok(VERIFY_READ, buf, count))
return -EFAULT; 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); mutex_lock(&pmsg_lock);
for (i = 0; i < count; ) { ret = psinfo->write_buf_user(PSTORE_TYPE_PMSG, 0, &id, 0, buf, 0, 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); psinfo);
i += c;
}
mutex_unlock(&pmsg_lock); mutex_unlock(&pmsg_lock);
vfree(buffer); return ret ? ret : count;
return count;
} }
static const struct file_operations pmsg_fops = { static const struct file_operations pmsg_fops = {
......
...@@ -331,6 +331,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, ...@@ -331,6 +331,24 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
return 0; 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, static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
struct timespec time, struct pstore_info *psi) struct timespec time, struct pstore_info *psi)
{ {
...@@ -369,6 +387,7 @@ static struct ramoops_context oops_cxt = { ...@@ -369,6 +387,7 @@ static struct ramoops_context oops_cxt = {
.open = ramoops_pstore_open, .open = ramoops_pstore_open,
.read = ramoops_pstore_read, .read = ramoops_pstore_read,
.write_buf = ramoops_pstore_write_buf, .write_buf = ramoops_pstore_write_buf,
.write_buf_user = ramoops_pstore_write_buf_user,
.erase = ramoops_pstore_erase, .erase = ramoops_pstore_erase,
}, },
}; };
...@@ -377,13 +396,14 @@ static void ramoops_free_przs(struct ramoops_context *cxt) ...@@ -377,13 +396,14 @@ static void ramoops_free_przs(struct ramoops_context *cxt)
{ {
int i; int i;
cxt->max_dump_cnt = 0;
if (!cxt->przs) if (!cxt->przs)
return; 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]); persistent_ram_free(cxt->przs[i]);
kfree(cxt->przs); kfree(cxt->przs);
cxt->max_dump_cnt = 0;
} }
static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, 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, ...@@ -408,7 +428,7 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
GFP_KERNEL); GFP_KERNEL);
if (!cxt->przs) { if (!cxt->przs) {
dev_err(dev, "failed to initialize a prz array for dumps\n"); 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++) { 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, ...@@ -419,6 +439,11 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
err = PTR_ERR(cxt->przs[i]); err = PTR_ERR(cxt->przs[i]);
dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n", dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
cxt->record_size, (unsigned long long)*paddr, err); cxt->record_size, (unsigned long long)*paddr, err);
while (i > 0) {
i--;
persistent_ram_free(cxt->przs[i]);
}
goto fail_prz; goto fail_prz;
} }
*paddr += cxt->record_size; *paddr += cxt->record_size;
...@@ -426,7 +451,9 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt, ...@@ -426,7 +451,9 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
return 0; return 0;
fail_prz: fail_prz:
ramoops_free_przs(cxt); kfree(cxt->przs);
fail_mem:
cxt->max_dump_cnt = 0;
return err; return err;
} }
...@@ -608,12 +635,20 @@ static int ramoops_probe(struct platform_device *pdev) ...@@ -608,12 +635,20 @@ static int ramoops_probe(struct platform_device *pdev)
cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */ cxt->pstore.bufsize = 1024; /* LOG_LINE_MAX */
cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize); cxt->pstore.bufsize = max(cxt->record_size, cxt->pstore.bufsize);
cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
spin_lock_init(&cxt->pstore.buf_lock);
if (!cxt->pstore.buf) { if (!cxt->pstore.buf) {
pr_err("cannot allocate pstore buffer\n"); pr_err("cannot allocate pstore buffer\n");
err = -ENOMEM; err = -ENOMEM;
goto fail_clear; 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); err = pstore_register(&cxt->pstore);
if (err) { if (err) {
...@@ -659,7 +694,6 @@ static int ramoops_remove(struct platform_device *pdev) ...@@ -659,7 +694,6 @@ static int ramoops_remove(struct platform_device *pdev)
struct ramoops_context *cxt = &oops_cxt; struct ramoops_context *cxt = &oops_cxt;
pstore_unregister(&cxt->pstore); pstore_unregister(&cxt->pstore);
cxt->max_dump_cnt = 0;
kfree(cxt->pstore.buf); kfree(cxt->pstore.buf);
cxt->pstore.bufsize = 0; cxt->pstore.bufsize = 0;
......
...@@ -17,15 +17,16 @@ ...@@ -17,15 +17,16 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <linux/pstore_ram.h>
#include <linux/rslib.h> #include <linux/rslib.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <linux/pstore_ram.h>
#include <asm/page.h> #include <asm/page.h>
struct persistent_ram_buffer { struct persistent_ram_buffer {
...@@ -47,43 +48,10 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz) ...@@ -47,43 +48,10 @@ static inline size_t buffer_start(struct persistent_ram_zone *prz)
return atomic_read(&prz->buffer->start); 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); static DEFINE_RAW_SPINLOCK(buffer_lock);
/* increase and wrap the start pointer, returning the old value */ /* 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 old;
int new; int new;
...@@ -103,7 +71,7 @@ static size_t buffer_start_add_locked(struct persistent_ram_zone *prz, size_t a) ...@@ -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 */ /* 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 old;
size_t new; size_t new;
...@@ -124,9 +92,6 @@ static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a) ...@@ -124,9 +92,6 @@ static void buffer_size_add_locked(struct persistent_ram_zone *prz, size_t a)
raw_spin_unlock_irqrestore(&buffer_lock, flags); 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, static void notrace persistent_ram_encode_rs8(struct persistent_ram_zone *prz,
uint8_t *data, size_t len, uint8_t *ecc) uint8_t *data, size_t len, uint8_t *ecc)
{ {
...@@ -299,8 +264,18 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz, ...@@ -299,8 +264,18 @@ static void notrace persistent_ram_update(struct persistent_ram_zone *prz,
const void *s, unsigned int start, unsigned int count) const void *s, unsigned int start, unsigned int count)
{ {
struct persistent_ram_buffer *buffer = prz->buffer; 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); persistent_ram_update_ecc(prz, start, count);
return ret;
} }
void persistent_ram_save_old(struct persistent_ram_zone *prz) void persistent_ram_save_old(struct persistent_ram_zone *prz)
...@@ -322,8 +297,8 @@ void persistent_ram_save_old(struct persistent_ram_zone *prz) ...@@ -322,8 +297,8 @@ void persistent_ram_save_old(struct persistent_ram_zone *prz)
} }
prz->old_log_size = size; prz->old_log_size = size;
memcpy(prz->old_log, &buffer->data[start], size - start); memcpy_fromio(prz->old_log, &buffer->data[start], size - start);
memcpy(prz->old_log + size - start, &buffer->data[0], start); memcpy_fromio(prz->old_log + size - start, &buffer->data[0], start);
} }
int notrace persistent_ram_write(struct persistent_ram_zone *prz, int notrace persistent_ram_write(struct persistent_ram_zone *prz,
...@@ -356,6 +331,38 @@ 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; 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) size_t persistent_ram_old_size(struct persistent_ram_zone *prz)
{ {
return prz->old_log_size; return prz->old_log_size;
...@@ -426,9 +433,6 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size, ...@@ -426,9 +433,6 @@ static void *persistent_ram_iomap(phys_addr_t start, size_t size,
return NULL; return NULL;
} }
buffer_start_add = buffer_start_add_locked;
buffer_size_add = buffer_size_add_locked;
if (memtype) if (memtype)
va = ioremap(start, size); va = ioremap(start, size);
else else
......
...@@ -22,12 +22,13 @@ ...@@ -22,12 +22,13 @@
#ifndef _LINUX_PSTORE_H #ifndef _LINUX_PSTORE_H
#define _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/kmsg_dump.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/errno.h> #include <linux/time.h>
#include <linux/types.h>
/* types */ /* types */
enum pstore_type_id { enum pstore_type_id {
...@@ -68,13 +69,21 @@ struct pstore_info { ...@@ -68,13 +69,21 @@ struct pstore_info {
enum kmsg_dump_reason reason, u64 *id, enum kmsg_dump_reason reason, u64 *id,
unsigned int part, const char *buf, bool compressed, unsigned int part, const char *buf, bool compressed,
size_t size, struct pstore_info *psi); 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 (*erase)(enum pstore_type_id type, u64 id,
int count, struct timespec time, int count, struct timespec time,
struct pstore_info *psi); struct pstore_info *psi);
void *data; 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 int pstore_register(struct pstore_info *);
extern void pstore_unregister(struct pstore_info *); extern void pstore_unregister(struct pstore_info *);
......
...@@ -17,11 +17,12 @@ ...@@ -17,11 +17,12 @@
#ifndef __LINUX_PSTORE_RAM_H__ #ifndef __LINUX_PSTORE_RAM_H__
#define __LINUX_PSTORE_RAM_H__ #define __LINUX_PSTORE_RAM_H__
#include <linux/compiler.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/init.h>
struct persistent_ram_buffer; struct persistent_ram_buffer;
struct rs_control; struct rs_control;
...@@ -60,6 +61,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz); ...@@ -60,6 +61,8 @@ void persistent_ram_zap(struct persistent_ram_zone *prz);
int persistent_ram_write(struct persistent_ram_zone *prz, const void *s, 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); void persistent_ram_save_old(struct persistent_ram_zone *prz);
size_t persistent_ram_old_size(struct persistent_ram_zone *prz); size_t persistent_ram_old_size(struct persistent_ram_zone *prz);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment