summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChen Gong <gong.chen@linux.intel.com>2011-05-16 11:00:27 -0700
committerTony Luck <tony.luck@intel.com>2011-05-16 11:05:00 -0700
commit06cf91b4b4aafa50ee0a94c81d2c6922a18af242 (patch)
treef45fe916103b323a714c8958048b8adab1f944b1
parent8d38d74b648513dd8ed8bd2b67d899208ef4e09e (diff)
downloadblackbird-op-linux-06cf91b4b4aafa50ee0a94c81d2c6922a18af242.tar.gz
blackbird-op-linux-06cf91b4b4aafa50ee0a94c81d2c6922a18af242.zip
pstore: fix pstore filesystem mount/remount issue
Currently after mount/remount operation on pstore filesystem, the content on pstore will be lost. It is because current ERST implementation doesn't support multi-user usage, which moves internal pointer to the end after accessing it. Adding multi-user support for pstore usage. Signed-off-by: Chen Gong <gong.chen@linux.intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--drivers/acpi/apei/erst.c48
-rw-r--r--fs/pstore/platform.c8
-rw-r--r--include/linux/pstore.h2
3 files changed, 44 insertions, 14 deletions
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index d5a89d067f98..ddb68c4f8d3e 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -929,6 +929,8 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
return 0;
}
+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);
@@ -936,6 +938,8 @@ 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 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,21 @@ static ssize_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) +
+ len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
erst_erange.size);
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 +1026,8 @@ skip:
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 912403c2a93d..f2c3ff20ea68 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -156,17 +156,23 @@ void pstore_get_records(void)
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_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 14ce2f5d08af..2455ef2683f0 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -35,6 +35,8 @@ struct pstore_info {
struct mutex buf_mutex; /* serialize access to 'buf' */
char *buf;
size_t bufsize;
+ 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);
OpenPOWER on IntegriCloud