Loading fs/pstore/ftrace.c +7 −2 Original line number Diff line number Diff line Loading @@ -37,6 +37,12 @@ static void notrace pstore_ftrace_call(unsigned long ip, { unsigned long flags; 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)) return; Loading @@ -47,8 +53,7 @@ static void notrace pstore_ftrace_call(unsigned long ip, rec.parent_ip = parent_ip; pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, 0, sizeof(rec), psinfo); psinfo->write_buf(&record); local_irq_restore(flags); } Loading fs/pstore/platform.c +21 −9 Original line number Diff line number Diff line Loading @@ -587,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) const char *e = s + c; while (s < e) { struct pstore_record record = { .type = PSTORE_TYPE_CONSOLE, .psi = psinfo, }; unsigned long flags; u64 id; if (c > psinfo->bufsize) c = psinfo->bufsize; Loading @@ -599,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) } else { spin_lock_irqsave(&psinfo->buf_lock, flags); } psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, s, 0, c, psinfo); record.buf = (char *)s; record.size = c; psinfo->write_buf(&record); spin_unlock_irqrestore(&psinfo->buf_lock, flags); s += c; c = e - s; Loading Loading @@ -630,10 +634,9 @@ static void pstore_unregister_console(void) {} static int pstore_write_compat(struct pstore_record *record) { return record->psi->write_buf(record->type, record->reason, &record->id, record->part, psinfo->buf, record->compressed, record->size, record->psi); record->buf = psinfo->buf; return record->psi->write_buf(record); } static int pstore_write_buf_user_compat(enum pstore_type_id type, Loading @@ -653,6 +656,15 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, bufsize = psinfo->bufsize; spin_lock_irqsave(&psinfo->buf_lock, flags); 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); ret = __copy_from_user(psinfo->buf, buf + i, c); Loading @@ -660,8 +672,8 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, ret = -EFAULT; break; } ret = psi->write_buf(type, reason, id, part, psinfo->buf, compressed, c, psi); record.size = c; ret = psi->write_buf(&record); if (unlikely(ret < 0)) break; i += c; Loading fs/pstore/ram.c +22 −22 Original line number Diff line number Diff line Loading @@ -378,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, return len; } static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, const char *buf, bool compressed, size_t size, struct pstore_info *psi) static int notrace ramoops_pstore_write_buf(struct pstore_record *record) { struct ramoops_context *cxt = psi->data; struct ramoops_context *cxt = record->psi->data; 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) return -ENOMEM; persistent_ram_write(cxt->cprz, buf, size); persistent_ram_write(cxt->cprz, record->buf, record->size); return 0; } else if (type == PSTORE_TYPE_FTRACE) { } else if (record->type == PSTORE_TYPE_FTRACE) { int zonenum; if (!cxt->fprzs) Loading @@ -407,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, else zonenum = 0; persistent_ram_write(cxt->fprzs[zonenum], buf, size); persistent_ram_write(cxt->fprzs[zonenum], record->buf, record->size); 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__); return -EINVAL; } if (type != PSTORE_TYPE_DMESG) if (record->type != PSTORE_TYPE_DMESG) 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. */ if (reason != KMSG_DUMP_OOPS && reason != KMSG_DUMP_PANIC) if (record->reason != KMSG_DUMP_OOPS && record->reason != KMSG_DUMP_PANIC) return -EINVAL; /* 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; /* 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, * and if our buffer is smaller than kmsg_bytes, we don't want the * report split across multiple records. */ if (part != 1) if (record->part != 1) return -ENOSPC; if (!cxt->dprzs) Loading @@ -441,10 +439,12 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, 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) 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; Loading include/linux/pstore.h +5 −16 Original line number Diff line number Diff line Loading @@ -142,19 +142,11 @@ struct pstore_record { * Returns 0 on success, and non-zero on error. * * @write_buf: * Perform a frontend write to a backend record, using a specified * buffer. Unlike @write, this does not use the @psi @buf. * Perform a frontend write to a backend record. The record contains * 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 * @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 * @record: pointer to record metadata. * * Returns 0 on success, and non-zero on error. * Loading Loading @@ -203,10 +195,7 @@ struct pstore_info { int (*close)(struct pstore_info *psi); ssize_t (*read)(struct pstore_record *record); int (*write)(struct pstore_record *record); int (*write_buf)(enum pstore_type_id type, 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)(struct pstore_record *record); int (*write_buf_user)(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, const char __user *buf, Loading Loading
fs/pstore/ftrace.c +7 −2 Original line number Diff line number Diff line Loading @@ -37,6 +37,12 @@ static void notrace pstore_ftrace_call(unsigned long ip, { unsigned long flags; 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)) return; Loading @@ -47,8 +53,7 @@ static void notrace pstore_ftrace_call(unsigned long ip, rec.parent_ip = parent_ip; pstore_ftrace_write_timestamp(&rec, pstore_ftrace_stamp++); pstore_ftrace_encode_cpu(&rec, raw_smp_processor_id()); psinfo->write_buf(PSTORE_TYPE_FTRACE, 0, NULL, 0, (void *)&rec, 0, sizeof(rec), psinfo); psinfo->write_buf(&record); local_irq_restore(flags); } Loading
fs/pstore/platform.c +21 −9 Original line number Diff line number Diff line Loading @@ -587,8 +587,11 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) const char *e = s + c; while (s < e) { struct pstore_record record = { .type = PSTORE_TYPE_CONSOLE, .psi = psinfo, }; unsigned long flags; u64 id; if (c > psinfo->bufsize) c = psinfo->bufsize; Loading @@ -599,8 +602,9 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c) } else { spin_lock_irqsave(&psinfo->buf_lock, flags); } psinfo->write_buf(PSTORE_TYPE_CONSOLE, 0, &id, 0, s, 0, c, psinfo); record.buf = (char *)s; record.size = c; psinfo->write_buf(&record); spin_unlock_irqrestore(&psinfo->buf_lock, flags); s += c; c = e - s; Loading Loading @@ -630,10 +634,9 @@ static void pstore_unregister_console(void) {} static int pstore_write_compat(struct pstore_record *record) { return record->psi->write_buf(record->type, record->reason, &record->id, record->part, psinfo->buf, record->compressed, record->size, record->psi); record->buf = psinfo->buf; return record->psi->write_buf(record); } static int pstore_write_buf_user_compat(enum pstore_type_id type, Loading @@ -653,6 +656,15 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, bufsize = psinfo->bufsize; spin_lock_irqsave(&psinfo->buf_lock, flags); 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); ret = __copy_from_user(psinfo->buf, buf + i, c); Loading @@ -660,8 +672,8 @@ static int pstore_write_buf_user_compat(enum pstore_type_id type, ret = -EFAULT; break; } ret = psi->write_buf(type, reason, id, part, psinfo->buf, compressed, c, psi); record.size = c; ret = psi->write_buf(&record); if (unlikely(ret < 0)) break; i += c; Loading
fs/pstore/ram.c +22 −22 Original line number Diff line number Diff line Loading @@ -378,23 +378,18 @@ static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz, return len; } static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, const char *buf, bool compressed, size_t size, struct pstore_info *psi) static int notrace ramoops_pstore_write_buf(struct pstore_record *record) { struct ramoops_context *cxt = psi->data; struct ramoops_context *cxt = record->psi->data; 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) return -ENOMEM; persistent_ram_write(cxt->cprz, buf, size); persistent_ram_write(cxt->cprz, record->buf, record->size); return 0; } else if (type == PSTORE_TYPE_FTRACE) { } else if (record->type == PSTORE_TYPE_FTRACE) { int zonenum; if (!cxt->fprzs) Loading @@ -407,33 +402,36 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, else zonenum = 0; persistent_ram_write(cxt->fprzs[zonenum], buf, size); persistent_ram_write(cxt->fprzs[zonenum], record->buf, record->size); 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__); return -EINVAL; } if (type != PSTORE_TYPE_DMESG) if (record->type != PSTORE_TYPE_DMESG) 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. */ if (reason != KMSG_DUMP_OOPS && reason != KMSG_DUMP_PANIC) if (record->reason != KMSG_DUMP_OOPS && record->reason != KMSG_DUMP_PANIC) return -EINVAL; /* 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; /* 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, * and if our buffer is smaller than kmsg_bytes, we don't want the * report split across multiple records. */ if (part != 1) if (record->part != 1) return -ENOSPC; if (!cxt->dprzs) Loading @@ -441,10 +439,12 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type, 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) 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; Loading
include/linux/pstore.h +5 −16 Original line number Diff line number Diff line Loading @@ -142,19 +142,11 @@ struct pstore_record { * Returns 0 on success, and non-zero on error. * * @write_buf: * Perform a frontend write to a backend record, using a specified * buffer. Unlike @write, this does not use the @psi @buf. * Perform a frontend write to a backend record. The record contains * 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 * @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 * @record: pointer to record metadata. * * Returns 0 on success, and non-zero on error. * Loading Loading @@ -203,10 +195,7 @@ struct pstore_info { int (*close)(struct pstore_info *psi); ssize_t (*read)(struct pstore_record *record); int (*write)(struct pstore_record *record); int (*write_buf)(enum pstore_type_id type, 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)(struct pstore_record *record); int (*write_buf_user)(enum pstore_type_id type, enum kmsg_dump_reason reason, u64 *id, unsigned int part, const char __user *buf, Loading