Skip to content

Commit

Permalink
Merge tag 'pstore-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/ke…
Browse files Browse the repository at this point in the history
…rnel/git/kees/linux

Pull pstore updates from Kees Cook:
 "This has a large internal refactoring along with several smaller
  fixes.

   - constify compression structures; Bhumika Goyal

   - restore powerpc dumping; Ankit Kumar

   - fix more bugs in the rarely exercises module unloading logic

   - reorganize filesystem locking to fix problems noticed by lockdep

   - refactor internal pstore APIs to make development and review
     easier:
      - improve error reporting
      - add kernel-doc structure and function comments
      - avoid insane argument passing by using a common record
        structure"

* tag 'pstore-v4.12-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (23 commits)
  pstore: Solve lockdep warning by moving inode locks
  pstore: Fix flags to enable dumps on powerpc
  pstore: Remove unused vmalloc.h in pmsg
  pstore: simplify write_user_compat()
  pstore: Remove write_buf() callback
  pstore: Replace arguments for write_buf_user() API
  pstore: Replace arguments for write_buf() API
  pstore: Replace arguments for erase() API
  pstore: Do not duplicate record metadata
  pstore: Allocate records on heap instead of stack
  pstore: Pass record contents instead of copying
  pstore: Always allocate buffer for decompression
  pstore: Replace arguments for write() API
  pstore: Replace arguments for read() API
  pstore: Switch pstore_mkfile to pass record
  pstore: Move record decompression to function
  pstore: Extract common arguments into structure
  pstore: Add kernel-doc for struct pstore_info
  pstore: Improve register_pstore() error reporting
  pstore: Avoid race in module unloading
  ...
  • Loading branch information
torvalds committed May 2, 2017
2 parents c58d405 + 3a7d2fd commit 2575be8
Show file tree
Hide file tree
Showing 11 changed files with 607 additions and 461 deletions.
89 changes: 38 additions & 51 deletions arch/powerpc/kernel/nvram_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,51 +389,40 @@ static int nvram_pstore_open(struct pstore_info *psi)

/**
* nvram_pstore_write - pstore write callback for nvram
* @type: Type of message logged
* @reason: reason behind dump (oops/panic)
* @id: identifier to indicate the write performed
* @part: pstore writes data to registered buffer in parts,
* part number will indicate the same.
* @count: Indicates oops count
* @compressed: Flag to indicate the log is compressed
* @size: number of bytes written to the registered buffer
* @psi: registered pstore_info structure
* @record: pstore record to write, with @id to be set
*
* Called by pstore_dump() when an oops or panic report is logged in the
* printk buffer.
* Returns 0 on successful write.
*/
static int nvram_pstore_write(enum pstore_type_id type,
enum kmsg_dump_reason reason,
u64 *id, unsigned int part, int count,
bool compressed, size_t size,
struct pstore_info *psi)
static int nvram_pstore_write(struct pstore_record *record)
{
int rc;
unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;

/* part 1 has the recent messages from printk buffer */
if (part > 1 || (type != PSTORE_TYPE_DMESG))
if (record->part > 1 || (record->type != PSTORE_TYPE_DMESG))
return -1;

if (clobbering_unread_rtas_event())
return -1;

oops_hdr->version = cpu_to_be16(OOPS_HDR_VERSION);
oops_hdr->report_length = cpu_to_be16(size);
oops_hdr->report_length = cpu_to_be16(record->size);
oops_hdr->timestamp = cpu_to_be64(ktime_get_real_seconds());

if (compressed)
if (record->compressed)
err_type = ERR_TYPE_KERNEL_PANIC_GZ;

rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
(int) (sizeof(*oops_hdr) + size), err_type, count);
(int) (sizeof(*oops_hdr) + record->size), err_type,
record->count);

if (rc != 0)
return rc;

*id = part;
record->id = record->part;
return 0;
}

Expand All @@ -442,10 +431,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
* Returns the length of the data we read from each partition.
* Returns 0 if we've been called before.
*/
static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
int *count, struct timespec *time, char **buf,
bool *compressed, ssize_t *ecc_notice_size,
struct pstore_info *psi)
static ssize_t nvram_pstore_read(struct pstore_record *record)
{
struct oops_log_info *oops_hdr;
unsigned int err_type, id_no, size = 0;
Expand All @@ -459,40 +445,40 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
switch (nvram_type_ids[read_type]) {
case PSTORE_TYPE_DMESG:
part = &oops_log_partition;
*type = PSTORE_TYPE_DMESG;
record->type = PSTORE_TYPE_DMESG;
break;
case PSTORE_TYPE_PPC_COMMON:
sig = NVRAM_SIG_SYS;
part = &common_partition;
*type = PSTORE_TYPE_PPC_COMMON;
*id = PSTORE_TYPE_PPC_COMMON;
time->tv_sec = 0;
time->tv_nsec = 0;
record->type = PSTORE_TYPE_PPC_COMMON;
record->id = PSTORE_TYPE_PPC_COMMON;
record->time.tv_sec = 0;
record->time.tv_nsec = 0;
break;
#ifdef CONFIG_PPC_PSERIES
case PSTORE_TYPE_PPC_RTAS:
part = &rtas_log_partition;
*type = PSTORE_TYPE_PPC_RTAS;
time->tv_sec = last_rtas_event;
time->tv_nsec = 0;
record->type = PSTORE_TYPE_PPC_RTAS;
record->time.tv_sec = last_rtas_event;
record->time.tv_nsec = 0;
break;
case PSTORE_TYPE_PPC_OF:
sig = NVRAM_SIG_OF;
part = &of_config_partition;
*type = PSTORE_TYPE_PPC_OF;
*id = PSTORE_TYPE_PPC_OF;
time->tv_sec = 0;
time->tv_nsec = 0;
record->type = PSTORE_TYPE_PPC_OF;
record->id = PSTORE_TYPE_PPC_OF;
record->time.tv_sec = 0;
record->time.tv_nsec = 0;
break;
#endif
#ifdef CONFIG_PPC_POWERNV
case PSTORE_TYPE_PPC_OPAL:
sig = NVRAM_SIG_FW;
part = &skiboot_partition;
*type = PSTORE_TYPE_PPC_OPAL;
*id = PSTORE_TYPE_PPC_OPAL;
time->tv_sec = 0;
time->tv_nsec = 0;
record->type = PSTORE_TYPE_PPC_OPAL;
record->id = PSTORE_TYPE_PPC_OPAL;
record->time.tv_sec = 0;
record->time.tv_nsec = 0;
break;
#endif
default:
Expand Down Expand Up @@ -520,10 +506,10 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
return 0;
}

*count = 0;
record->count = 0;

if (part->os_partition)
*id = id_no;
record->id = id_no;

if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
size_t length, hdr_size;
Expand All @@ -533,34 +519,35 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
/* Old format oops header had 2-byte record size */
hdr_size = sizeof(u16);
length = be16_to_cpu(oops_hdr->version);
time->tv_sec = 0;
time->tv_nsec = 0;
record->time.tv_sec = 0;
record->time.tv_nsec = 0;
} else {
hdr_size = sizeof(*oops_hdr);
length = be16_to_cpu(oops_hdr->report_length);
time->tv_sec = be64_to_cpu(oops_hdr->timestamp);
time->tv_nsec = 0;
record->time.tv_sec = be64_to_cpu(oops_hdr->timestamp);
record->time.tv_nsec = 0;
}
*buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
record->buf = kmemdup(buff + hdr_size, length, GFP_KERNEL);
kfree(buff);
if (*buf == NULL)
if (record->buf == NULL)
return -ENOMEM;

*ecc_notice_size = 0;
record->ecc_notice_size = 0;
if (err_type == ERR_TYPE_KERNEL_PANIC_GZ)
*compressed = true;
record->compressed = true;
else
*compressed = false;
record->compressed = false;
return length;
}

*buf = buff;
record->buf = buff;
return part->size;
}

static struct pstore_info nvram_pstore_info = {
.owner = THIS_MODULE,
.name = "nvram",
.flags = PSTORE_FLAGS_DMESG,
.open = nvram_pstore_open,
.read = nvram_pstore_read,
.write = nvram_pstore_write,
Expand Down
64 changes: 26 additions & 38 deletions drivers/acpi/apei/erst.c
Original file line number Diff line number Diff line change
Expand Up @@ -925,15 +925,9 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)

static int erst_open_pstore(struct pstore_info *psi);
static int erst_close_pstore(struct pstore_info *psi);
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count,
struct timespec *time, char **buf,
bool *compressed, ssize_t *ecc_notice_size,
struct pstore_info *psi);
static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
u64 *id, unsigned int part, int count, bool compressed,
size_t size, struct pstore_info *psi);
static int erst_clearer(enum pstore_type_id type, u64 id, int count,
struct timespec time, struct pstore_info *psi);
static ssize_t erst_reader(struct pstore_record *record);
static int erst_writer(struct pstore_record *record);
static int erst_clearer(struct pstore_record *record);

static struct pstore_info erst_info = {
.owner = THIS_MODULE,
Expand Down Expand Up @@ -986,10 +980,7 @@ static int erst_close_pstore(struct pstore_info *psi)
return 0;
}

static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count,
struct timespec *time, char **buf,
bool *compressed, ssize_t *ecc_notice_size,
struct pstore_info *psi)
static ssize_t erst_reader(struct pstore_record *record)
{
int rc;
ssize_t len = 0;
Expand Down Expand Up @@ -1027,42 +1018,40 @@ static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, int *count,
if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
goto skip;

*buf = kmalloc(len, GFP_KERNEL);
if (*buf == NULL) {
record->buf = kmalloc(len, GFP_KERNEL);
if (record->buf == NULL) {
rc = -ENOMEM;
goto out;
}
memcpy(*buf, rcd->data, len - sizeof(*rcd));
*id = record_id;
*compressed = false;
*ecc_notice_size = 0;
memcpy(record->buf, rcd->data, len - sizeof(*rcd));
record->id = record_id;
record->compressed = false;
record->ecc_notice_size = 0;
if (uuid_le_cmp(rcd->sec_hdr.section_type,
CPER_SECTION_TYPE_DMESG_Z) == 0) {
*type = PSTORE_TYPE_DMESG;
*compressed = true;
record->type = PSTORE_TYPE_DMESG;
record->compressed = true;
} else if (uuid_le_cmp(rcd->sec_hdr.section_type,
CPER_SECTION_TYPE_DMESG) == 0)
*type = PSTORE_TYPE_DMESG;
record->type = PSTORE_TYPE_DMESG;
else if (uuid_le_cmp(rcd->sec_hdr.section_type,
CPER_SECTION_TYPE_MCE) == 0)
*type = PSTORE_TYPE_MCE;
record->type = PSTORE_TYPE_MCE;
else
*type = PSTORE_TYPE_UNKNOWN;
record->type = PSTORE_TYPE_UNKNOWN;

if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
time->tv_sec = rcd->hdr.timestamp;
record->time.tv_sec = rcd->hdr.timestamp;
else
time->tv_sec = 0;
time->tv_nsec = 0;
record->time.tv_sec = 0;
record->time.tv_nsec = 0;

out:
kfree(rcd);
return (rc < 0) ? rc : (len - sizeof(*rcd));
}

static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
u64 *id, unsigned int part, int count, bool compressed,
size_t size, struct pstore_info *psi)
static int erst_writer(struct pstore_record *record)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));
Expand All @@ -1077,21 +1066,21 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
/* timestamp valid. platform_id, partition_id are invalid */
rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
rcd->hdr.timestamp = get_seconds();
rcd->hdr.record_length = sizeof(*rcd) + size;
rcd->hdr.record_length = sizeof(*rcd) + record->size;
rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
rcd->hdr.notification_type = CPER_NOTIFY_MCE;
rcd->hdr.record_id = cper_next_record_id();
rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;

rcd->sec_hdr.section_offset = sizeof(*rcd);
rcd->sec_hdr.section_length = size;
rcd->sec_hdr.section_length = record->size;
rcd->sec_hdr.revision = CPER_SEC_REV;
/* fru_id and fru_text is invalid */
rcd->sec_hdr.validation_bits = 0;
rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
switch (type) {
switch (record->type) {
case PSTORE_TYPE_DMESG:
if (compressed)
if (record->compressed)
rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG_Z;
else
rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
Expand All @@ -1105,15 +1094,14 @@ static int erst_writer(enum pstore_type_id type, enum kmsg_dump_reason reason,
rcd->sec_hdr.section_severity = CPER_SEV_FATAL;

ret = erst_write(&rcd->hdr);
*id = rcd->hdr.record_id;
record->id = rcd->hdr.record_id;

return ret;
}

static int erst_clearer(enum pstore_type_id type, u64 id, int count,
struct timespec time, struct pstore_info *psi)
static int erst_clearer(struct pstore_record *record)
{
return erst_clear(id);
return erst_clear(record->id);
}

static int __init erst_init(void)
Expand Down
Loading

0 comments on commit 2575be8

Please sign in to comment.