pstore: fix pstore filesystem mount/remount issue
authorChen Gong <gong.chen@linux.intel.com>
Mon, 16 May 2011 18:00:27 +0000 (11:00 -0700)
committerTony Luck <tony.luck@intel.com>
Mon, 16 May 2011 18:05:00 +0000 (11:05 -0700)
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>
drivers/acpi/apei/erst.c
fs/pstore/platform.c
include/linux/pstore.h

index d5a89d067f9882a80c50b2783f03e69b2f778f0a..ddb68c4f8d3e4e4e9d7835d73291304de57e65d3 100644 (file)
@@ -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)
index 912403c2a93d65b028487fe2a2e04609b1aa5cfa..f2c3ff20ea6857f616ddc5381cac6a90336f46b8 100644 (file)
@@ -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)
index 14ce2f5d08afa061a3cbcefec042acdf17d22f67..2455ef2683f050660b32bb1c81fc5a381d775e9f 100644 (file)
@@ -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);