diff options
author | Chen Gong <gong.chen@linux.intel.com> | 2011-05-16 14:00:27 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2011-05-16 14:05:00 -0400 |
commit | 06cf91b4b4aafa50ee0a94c81d2c6922a18af242 (patch) | |
tree | f45fe916103b323a714c8958048b8adab1f944b1 /drivers/acpi/apei | |
parent | 8d38d74b648513dd8ed8bd2b67d899208ef4e09e (diff) |
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>
Diffstat (limited to 'drivers/acpi/apei')
-rw-r--r-- | drivers/acpi/apei/erst.c | 48 |
1 files changed, 35 insertions, 13 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) | |||
929 | return 0; | 929 | return 0; |
930 | } | 930 | } |
931 | 931 | ||
932 | static int erst_open_pstore(struct pstore_info *psi); | ||
933 | static int erst_close_pstore(struct pstore_info *psi); | ||
932 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | 934 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, |
933 | struct timespec *time); | 935 | struct timespec *time); |
934 | static u64 erst_writer(enum pstore_type_id type, size_t size); | 936 | 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); | |||
936 | static struct pstore_info erst_info = { | 938 | static struct pstore_info erst_info = { |
937 | .owner = THIS_MODULE, | 939 | .owner = THIS_MODULE, |
938 | .name = "erst", | 940 | .name = "erst", |
941 | .open = erst_open_pstore, | ||
942 | .close = erst_close_pstore, | ||
939 | .read = erst_reader, | 943 | .read = erst_reader, |
940 | .write = erst_writer, | 944 | .write = erst_writer, |
941 | .erase = erst_clear | 945 | .erase = erst_clear |
@@ -957,12 +961,32 @@ struct cper_pstore_record { | |||
957 | char data[]; | 961 | char data[]; |
958 | } __packed; | 962 | } __packed; |
959 | 963 | ||
964 | static int reader_pos; | ||
965 | |||
966 | static int erst_open_pstore(struct pstore_info *psi) | ||
967 | { | ||
968 | int rc; | ||
969 | |||
970 | if (erst_disable) | ||
971 | return -ENODEV; | ||
972 | |||
973 | rc = erst_get_record_id_begin(&reader_pos); | ||
974 | |||
975 | return rc; | ||
976 | } | ||
977 | |||
978 | static int erst_close_pstore(struct pstore_info *psi) | ||
979 | { | ||
980 | erst_get_record_id_end(); | ||
981 | |||
982 | return 0; | ||
983 | } | ||
984 | |||
960 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | 985 | static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, |
961 | struct timespec *time) | 986 | struct timespec *time) |
962 | { | 987 | { |
963 | int rc; | 988 | int rc; |
964 | ssize_t len; | 989 | ssize_t len = 0; |
965 | unsigned long flags; | ||
966 | u64 record_id; | 990 | u64 record_id; |
967 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) | 991 | struct cper_pstore_record *rcd = (struct cper_pstore_record *) |
968 | (erst_info.buf - sizeof(*rcd)); | 992 | (erst_info.buf - sizeof(*rcd)); |
@@ -970,24 +994,21 @@ static ssize_t erst_reader(u64 *id, enum pstore_type_id *type, | |||
970 | if (erst_disable) | 994 | if (erst_disable) |
971 | return -ENODEV; | 995 | return -ENODEV; |
972 | 996 | ||
973 | raw_spin_lock_irqsave(&erst_lock, flags); | ||
974 | skip: | 997 | skip: |
975 | rc = __erst_get_next_record_id(&record_id); | 998 | rc = erst_get_record_id_next(&reader_pos, &record_id); |
976 | if (rc) { | 999 | if (rc) |
977 | raw_spin_unlock_irqrestore(&erst_lock, flags); | 1000 | goto out; |
978 | return rc; | 1001 | |
979 | } | ||
980 | /* no more record */ | 1002 | /* no more record */ |
981 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { | 1003 | if (record_id == APEI_ERST_INVALID_RECORD_ID) { |
982 | raw_spin_unlock_irqrestore(&erst_lock, flags); | 1004 | rc = -1; |
983 | return 0; | 1005 | goto out; |
984 | } | 1006 | } |
985 | 1007 | ||
986 | len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) + | 1008 | len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) + |
987 | erst_erange.size); | 1009 | erst_erange.size); |
988 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) | 1010 | if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0) |
989 | goto skip; | 1011 | goto skip; |
990 | raw_spin_unlock_irqrestore(&erst_lock, flags); | ||
991 | 1012 | ||
992 | *id = record_id; | 1013 | *id = record_id; |
993 | if (uuid_le_cmp(rcd->sec_hdr.section_type, | 1014 | if (uuid_le_cmp(rcd->sec_hdr.section_type, |
@@ -1005,7 +1026,8 @@ skip: | |||
1005 | time->tv_sec = 0; | 1026 | time->tv_sec = 0; |
1006 | time->tv_nsec = 0; | 1027 | time->tv_nsec = 0; |
1007 | 1028 | ||
1008 | return len - sizeof(*rcd); | 1029 | out: |
1030 | return (rc < 0) ? rc : (len - sizeof(*rcd)); | ||
1009 | } | 1031 | } |
1010 | 1032 | ||
1011 | static u64 erst_writer(enum pstore_type_id type, size_t size) | 1033 | static u64 erst_writer(enum pstore_type_id type, size_t size) |