Commit b10b4711 authored by Kees Cook's avatar Kees Cook

pstore: Replace arguments for write_buf() API

As with the other API updates, this removes the long argument list in favor
of passing a single pstore recaord.
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
parent a61072aa
...@@ -37,6 +37,12 @@ static void notrace pstore_ftrace_call(unsigned long ip, ...@@ -37,6 +37,12 @@ static void notrace pstore_ftrace_call(unsigned long ip,
{ {
unsigned long flags; unsigned long flags;
struct pstore_ftrace_record rec = {}; struct pstore_ftrace_record rec = {};
struct pstore_record record = {
.type = PSTORE_TYPE_FTRACE,
.buf = (char *)&rec,
.size = sizeof(rec),
.psi = psinfo,
};
if (unlikely(oops_in_progress)) if (unlikely(oops_in_progress))
return; return;
...@@ -47,8 +53,7 @@ static void notrace pstore_ftrace_call(unsigned long ip, ...@@ -47,8 +53,7 @@ static void notrace pstore_ftrace_call(unsigned long ip,
rec.parent_ip = parent_ip; rec.parent_ip = parent_ip;
pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++);
pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id());
psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, psinfo->write_buf(&record);
0, sizeof(rec), psinfo);
local_irq_restore(flags); local_irq_restore(flags);
} }
......
...@@ -587,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) ...@@ -587,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
const char *e = s + c; const char *e = s + c;
while (s < e) { while (s < e) {
struct pstore_record record = {
.type = PSTORE_TYPE_CONSOLE,
.psi = psinfo,
};
unsigned long flags; unsigned long flags;
u64 id;
if (c > psinfo->bufsize) if (c > psinfo->bufsize)
c = psinfo->bufsize; c = psinfo->bufsize;
...@@ -599,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) ...@@ -599,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)
} else { } else {
spin_lock_irqsave(&psinfo->buf_lock, flags); spin_lock_irqsave(&psinfo->buf_lock, flags);
} }
psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, record.buf = (char *)s;
s, 0, c, psinfo); record.size = c;
psinfo->write_buf(&record);
spin_unlock_irqrestore(&psinfo->buf_lock, flags); spin_unlock_irqrestore(&psinfo->buf_lock, flags);
s += c; s += c;
c = e - s; c = e - s;
...@@ -630,10 +634,9 @@ static void pstore_unregister_console(void) {} ...@@ -630,10 +634,9 @@ static void pstore_unregister_console(void) {}
static int pstore_write_compat(struct pstore_record *record) static int pstore_write_compat(struct pstore_record *record)
{ {
return record->psi->write_buf(record->type, record->reason, record->buf = psinfo->buf;
&record->id, record->part,
psinfo->buf, record->compressed, return record->psi->write_buf(record);
record->size, record->psi);
} }
static int pstore_write_buf_user_compat(enum pstore_type_id type, static int pstore_write_buf_user_compat(enum pstore_type_id type,
...@@ -653,6 +656,15 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, ...@@ -653,6 +656,15 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type,
bufsize = psinfo->bufsize; bufsize = psinfo->bufsize;
spin_lock_irqsave(&psinfo->buf_lock, flags); spin_lock_irqsave(&psinfo->buf_lock, flags);
for (i = 0; i < size; ) { for (i = 0; i < size; ) {
struct pstore_record record = {
.type = type,
.reason = reason,
.id = id,
.part = part,
.buf = psinfo->buf,
.compressed = compressed,
.psi = psi,
};
size_t c = min(size - i, bufsize); size_t c = min(size - i, bufsize);
ret = __copy_from_user(psinfo->buf, buf + i, c); ret = __copy_from_user(psinfo->buf, buf + i, c);
...@@ -660,8 +672,8 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, ...@@ -660,8 +672,8 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type,
ret = -EFAULT; ret = -EFAULT;
break; break;
} }
ret = psi->write_buf(type, reason, id, part, psinfo->buf, record.size = c;
compressed, c, psi); ret = psi->write_buf(&record);
if (unlikely(ret < 0)) if (unlikely(ret < 0))
break; break;
i += c; i += c;
......
...@@ -378,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, ...@@ -378,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz,
return len; return len;
} }
static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, static int notrace ramoops_pstore_write_buf(struct pstore_record *record)
enum kmsg_dump_reason reason,
u64 *id, unsigned int part,
const char *buf,
bool compressed, size_t size,
struct pstore_info *psi)
{ {
struct ramoops_context *cxt = psi->data; struct ramoops_context *cxt = record->psi->data;
struct persistent_ram_zone *prz; struct persistent_ram_zone *prz;
size_t hlen; size_t size, hlen;
if (type == PSTORE_TYPE_CONSOLE) { if (record->type == PSTORE_TYPE_CONSOLE) {
if (!cxt->cprz) if (!cxt->cprz)
return -ENOMEM; return -ENOMEM;
persistent_ram_write(cxt->cprz, buf, size); persistent_ram_write(cxt->cprz, record->buf, record->size);
return 0; return 0;
} else if (type == PSTORE_TYPE_FTRACE) { } else if (record->type == PSTORE_TYPE_FTRACE) {
int zonenum; int zonenum;
if (!cxt->fprzs) if (!cxt->fprzs)
...@@ -407,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, ...@@ -407,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
else else
zonenum = 0; zonenum = 0;
persistent_ram_write(cxt->fprzs[zonenum], buf, size); persistent_ram_write(cxt->fprzs[zonenum], record->buf,
record->size);
return 0; return 0;
} else if (type == PSTORE_TYPE_PMSG) { } else if (record->type == PSTORE_TYPE_PMSG) {
pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__); pr_warn_ratelimited("PMSG shouldn't call %s\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (type != PSTORE_TYPE_DMESG) if (record->type != PSTORE_TYPE_DMESG)
return -EINVAL; return -EINVAL;
/* Out of the various dmesg dump types, ramoops is currently designed /*
* Out of the various dmesg dump types, ramoops is currently designed
* to only store crash logs, rather than storing general kernel logs. * to only store crash logs, rather than storing general kernel logs.
*/ */
if (reason != KMSG_DUMP_OOPS && if (record->reason != KMSG_DUMP_OOPS &&
reason != KMSG_DUMP_PANIC) record->reason != KMSG_DUMP_PANIC)
return -EINVAL; return -EINVAL;
/* Skip Oopes when configured to do so. */ /* Skip Oopes when configured to do so. */
if (reason == KMSG_DUMP_OOPS && !cxt->dump_oops) if (record->reason == KMSG_DUMP_OOPS && !cxt->dump_oops)
return -EINVAL; return -EINVAL;
/* Explicitly only take the first part of any new crash. /*
* Explicitly only take the first part of any new crash.
* If our buffer is larger than kmsg_bytes, this can never happen, * If our buffer is larger than kmsg_bytes, this can never happen,
* and if our buffer is smaller than kmsg_bytes, we don't want the * and if our buffer is smaller than kmsg_bytes, we don't want the
* report split across multiple records. * report split across multiple records.
*/ */
if (part != 1) if (record->part != 1)
return -ENOSPC; return -ENOSPC;
if (!cxt->dprzs) if (!cxt->dprzs)
...@@ -441,10 +439,12 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, ...@@ -441,10 +439,12 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
prz = cxt->dprzs[cxt->dump_write_cnt]; prz = cxt->dprzs[cxt->dump_write_cnt];
hlen = ramoops_write_kmsg_hdr(prz, compressed); /* Build header and append record contents. */
hlen = ramoops_write_kmsg_hdr(prz, record->compressed);
size = record->size;
if (size + hlen > prz->buffer_size) if (size + hlen > prz->buffer_size)
size = prz->buffer_size - hlen; size = prz->buffer_size - hlen;
persistent_ram_write(prz, buf, size); persistent_ram_write(prz, record->buf, size);
cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt; cxt->dump_write_cnt = (cxt->dump_write_cnt + 1) % cxt->max_dump_cnt;
......
...@@ -142,19 +142,11 @@ struct pstore_record { ...@@ -142,19 +142,11 @@ struct pstore_record {
* Returns 0 on success, and non-zero on error. * Returns 0 on success, and non-zero on error.
* *
* @write_buf: * @write_buf:
* Perform a frontend write to a backend record, using a specified * Perform a frontend write to a backend record. The record contains
* buffer. Unlike @write, this does not use the @psi @buf. * all metadata and the buffer to write to backend storage. (Unlike
* @write, this does not use the @psi @buf.)
* *
* @type: in: pstore record type to write * @record: pointer to record metadata.
* @reason:
* in: pstore write reason
* @id: out: unique identifier for the record
* @part: in: position in a multipart write
* @buf: in: pointer to contents to write to backend record
* @compressed:
* in: if the record is compressed
* @size: in: size of the write
* @psi: in: pointer to the struct pstore_info for the backend
* *
* Returns 0 on success, and non-zero on error. * Returns 0 on success, and non-zero on error.
* *
...@@ -203,10 +195,7 @@ struct pstore_info { ...@@ -203,10 +195,7 @@ struct pstore_info {
int (*close)(struct pstore_info *psi); int (*close)(struct pstore_info *psi);
ssize_t (*read)(struct pstore_record *record); ssize_t (*read)(struct pstore_record *record);
int (*write)(struct pstore_record *record); int (*write)(struct pstore_record *record);
int (*write_buf)(enum pstore_type_id type, int (*write_buf)(struct pstore_record *record);
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, int (*write_buf_user)(enum pstore_type_id type,
enum kmsg_dump_reason reason, u64 *id, enum kmsg_dump_reason reason, u64 *id,
unsigned int part, const char __user *buf, unsigned int part, const char __user *buf,
......
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