diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 66a03caa2ad92093cf68ce5ddcbc215ea8ef7b3d..f739a70b1c708a0084afa2e8e6605f401c7bfd94 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -1,5 +1,6 @@ config ACPI_APEI bool "ACPI Platform Error Interface (APEI)" + select MISC_FILESYSTEMS select PSTORE depends on X86 help diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c index d6cb0ff6988e2797455e15e98426d021dd4fc005..e6cef8e1b53455db9927668c1da1157c364e6b6e 100644 --- a/drivers/acpi/apei/erst.c +++ b/drivers/acpi/apei/erst.c @@ -929,13 +929,17 @@ static int erst_check_table(struct acpi_table_erst *erst_tab) return 0; } -static size_t erst_reader(u64 *id, enum pstore_type_id *type, +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, struct timespec *time); static u64 erst_writer(enum pstore_type_id type, size_t size); static struct pstore_info erst_info = { .owner = THIS_MODULE, .name = "erst", + .open = erst_open_pstore, + .close = erst_close_pstore, .read = erst_reader, .write = erst_writer, .erase = erst_clear @@ -957,12 +961,32 @@ struct cper_pstore_record { char data[]; } __packed; -static size_t erst_reader(u64 *id, enum pstore_type_id *type, +static int reader_pos; + +static int erst_open_pstore(struct pstore_info *psi) +{ + int rc; + + if (erst_disable) + return -ENODEV; + + rc = erst_get_record_id_begin(&reader_pos); + + return rc; +} + +static int erst_close_pstore(struct pstore_info *psi) +{ + erst_get_record_id_end(); + + return 0; +} + +static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, struct timespec *time) { int rc; - ssize_t len; - unsigned long flags; + ssize_t len = 0; u64 record_id; struct cper_pstore_record *rcd = (struct cper_pstore_record *) (erst_info.buf - sizeof(*rcd)); @@ -970,24 +994,28 @@ static size_t erst_reader(u64 *id, enum pstore_type_id *type, if (erst_disable) return -ENODEV; - raw_spin_lock_irqsave(&erst_lock, flags); skip: - rc = __erst_get_next_record_id(&record_id); - if (rc) { - raw_spin_unlock_irqrestore(&erst_lock, flags); - return rc; - } + rc = erst_get_record_id_next(&reader_pos, &record_id); + if (rc) + goto out; + /* no more record */ if (record_id == APEI_ERST_INVALID_RECORD_ID) { - raw_spin_unlock_irqrestore(&erst_lock, flags); - return 0; + rc = -1; + goto out; } - len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) + - erst_erange.size); + len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + + erst_info.bufsize); + /* The record may be cleared by others, try read next record */ + if (len == -ENOENT) + goto skip; + else if (len < 0) { + rc = -1; + goto out; + } if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) goto skip; - raw_spin_unlock_irqrestore(&erst_lock, flags); *id = record_id; if (uuid_le_cmp(rcd->sec_hdr.section_type, @@ -1005,7 +1033,8 @@ static size_t erst_reader(u64 *id, enum pstore_type_id *type, time->tv_sec = 0; time->tv_nsec = 0; - return len - sizeof(*rcd); +out: + return (rc < 0) ? rc : (len - sizeof(*rcd)); } static u64 erst_writer(enum pstore_type_id type, size_t size) diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c index f835a25625ff5c7e74e5834cc9e6057697d02941..f2c3ff20ea6857f616ddc5381cac6a90336f46b8 100644 --- a/fs/pstore/platform.c +++ b/fs/pstore/platform.c @@ -152,21 +152,27 @@ EXPORT_SYMBOL_GPL(pstore_register); void pstore_get_records(void) { struct pstore_info *psi = psinfo; - size_t size; + ssize_t size; u64 id; enum pstore_type_id type; struct timespec time; - int failed = 0; + int failed = 0, rc; if (!psi) return; mutex_lock(&psinfo->buf_mutex); + rc = psi->open(psi); + if (rc) + goto out; + while ((size = psi->read(&id, &type, &time)) > 0) { - if (pstore_mkfile(type, psi->name, id, psi->buf, size, + if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size, time, psi->erase)) failed++; } + psi->close(psi); +out: mutex_unlock(&psinfo->buf_mutex); if (failed) diff --git a/include/linux/pstore.h b/include/linux/pstore.h index 41977737bb7d3bdf7b7d7be5d2ccf6dd4401ebd8..2455ef2683f050660b32bb1c81fc5a381d775e9f 100644 --- a/include/linux/pstore.h +++ b/include/linux/pstore.h @@ -35,7 +35,9 @@ struct pstore_info { struct mutex buf_mutex; /* serialize access to 'buf' */ char *buf; size_t bufsize; - size_t (*read)(u64 *id, enum pstore_type_id *type, + int (*open)(struct pstore_info *psi); + int (*close)(struct pstore_info *psi); + ssize_t (*read)(u64 *id, enum pstore_type_id *type, struct timespec *time); u64 (*write)(enum pstore_type_id type, size_t size); int (*erase)(u64 id);