linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Add an EFI pstore backend
@ 2011-07-18 20:30 Matthew Garrett
  2011-07-18 20:30 ` [PATCH 1/9] pstore: Extend API Matthew Garrett
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck

EFI provides enough non-volatile storage to make it convenient for storing
crash dumps. Extend the pstore API a little to make it easier to handle
this, then add support to efivars. Some cleanup patches from Mike Waychison
then follow.


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/9] pstore: Extend API
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 2/9] pstore: Add extra context for writes and erases Matthew Garrett
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett

Some pstore implementations may not have a static context, so extend the
API to pass the pstore_info struct to all calls and allow for a context
pointer.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/acpi/apei/erst.c |   18 +++++++++++++-----
 fs/pstore/inode.c        |   10 +++++-----
 fs/pstore/internal.h     |    2 +-
 fs/pstore/platform.c     |   13 +++++++------
 include/linux/pstore.h   |    8 +++++---
 5 files changed, 31 insertions(+), 20 deletions(-)

diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index c8ba9da..8aac55e 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -932,8 +932,10 @@ 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,
-		       struct timespec *time);
-static u64 erst_writer(enum pstore_type_id type, size_t size);
+			   struct timespec *time, struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, size_t size,
+		       struct pstore_info *psi);
+static int erst_clearer(u64 id, struct pstore_info *psi);
 
 static struct pstore_info erst_info = {
 	.owner		= THIS_MODULE,
@@ -942,7 +944,7 @@ static struct pstore_info erst_info = {
 	.close		= erst_close_pstore,
 	.read		= erst_reader,
 	.write		= erst_writer,
-	.erase		= erst_clear
+	.erase		= erst_clearer
 };
 
 #define CPER_CREATOR_PSTORE						\
@@ -983,7 +985,7 @@ static int erst_close_pstore(struct pstore_info *psi)
 }
 
 static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
-		       struct timespec *time)
+			   struct timespec *time, struct pstore_info *psi)
 {
 	int rc;
 	ssize_t len = 0;
@@ -1037,7 +1039,8 @@ out:
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, size_t size)
+static u64 erst_writer(enum pstore_type_id type, size_t size,
+		       struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
 					(erst_info.buf - sizeof(*rcd));
@@ -1080,6 +1083,11 @@ static u64 erst_writer(enum pstore_type_id type, size_t size)
 	return rcd->hdr.record_id;
 }
 
+static int erst_clearer(u64 id, struct pstore_info *psi)
+{
+	return erst_clear(id);
+}
+
 static int __init erst_init(void)
 {
 	int rc = 0;
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 977ed27..b19884a 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -40,7 +40,7 @@
 
 struct pstore_private {
 	u64	id;
-	int	(*erase)(u64);
+	struct pstore_info *psi;
 	ssize_t	size;
 	char	data[];
 };
@@ -73,7 +73,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct pstore_private *p = dentry->d_inode->i_private;
 
-	p->erase(p->id);
+	p->psi->erase(p->id, p->psi);
 
 	return simple_unlink(dir, dentry);
 }
@@ -175,8 +175,8 @@ int pstore_is_mounted(void)
  * Set the mtime & ctime to the date that this record was originally stored.
  */
 int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
-			      char *data, size_t size,
-			      struct timespec time, int (*erase)(u64))
+		  char *data, size_t size, struct timespec time,
+		  struct pstore_info *psi)
 {
 	struct dentry		*root = pstore_sb->s_root;
 	struct dentry		*dentry;
@@ -193,7 +193,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
 	if (!private)
 		goto fail_alloc;
 	private->id = id;
-	private->erase = erase;
+	private->psi = psi;
 
 	switch (type) {
 	case PSTORE_TYPE_DMESG:
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 8c9f23e..611c1b3 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -2,5 +2,5 @@ extern void	pstore_set_kmsg_bytes(int);
 extern void	pstore_get_records(void);
 extern int	pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
 			      char *data, size_t size,
-			      struct timespec time, int (*erase)(u64));
+			      struct timespec time, struct pstore_info *psi);
 extern int	pstore_is_mounted(void);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index f2c3ff2..221c04e 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -94,11 +94,12 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 		memcpy(dst, s1 + s1_start, l1_cpy);
 		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
 
-		id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
+		id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy,
+				   psinfo);
 		if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
 				      psinfo->buf, hsize + l1_cpy + l2_cpy,
-				      CURRENT_TIME, psinfo->erase);
+				      CURRENT_TIME, psinfo);
 		l1 -= l1_cpy;
 		l2 -= l2_cpy;
 		total += l1_cpy + l2_cpy;
@@ -166,9 +167,9 @@ void pstore_get_records(void)
 	if (rc)
 		goto out;
 
-	while ((size = psi->read(&id, &type, &time)) > 0) {
+	while ((size = psi->read(&id, &type, &time, psi)) > 0) {
 		if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
-				  time, psi->erase))
+				  time, psi))
 			failed++;
 	}
 	psi->close(psi);
@@ -196,10 +197,10 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 
 	mutex_lock(&psinfo->buf_mutex);
 	memcpy(psinfo->buf, buf, size);
-	id = psinfo->write(type, size);
+	id = psinfo->write(type, size, psinfo);
 	if (pstore_is_mounted())
 		pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
-			      size, CURRENT_TIME, psinfo->erase);
+			      size, CURRENT_TIME, psinfo);
 	mutex_unlock(&psinfo->buf_mutex);
 
 	return 0;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 2455ef2..b2f1d97 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -38,9 +38,11 @@ struct pstore_info {
 	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);
+			struct timespec *time, struct pstore_info *psi);
+	u64		(*write)(enum pstore_type_id type, size_t size,
+			struct pstore_info *psi);
+	int		(*erase)(u64 id, struct pstore_info *psi);
+	void		*data;
 };
 
 #ifdef CONFIG_PSTORE
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/9] pstore: Add extra context for writes and erases
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
  2011-07-18 20:30 ` [PATCH 1/9] pstore: Extend API Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 3/9] pstore: Make "part" unsigned Matthew Garrett
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett

EFI only provides small amounts of individual storage, and conventionally
puts metadata in the storage variable name. Rather than add a metadata
header to the (already limited) variable storage, it's easier for us to
modify pstore to pass all the information we need to construct a unique
variable name to the appropriate functions.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/acpi/apei/erst.c |   10 ++++++----
 fs/pstore/inode.c        |    6 ++++--
 fs/pstore/platform.c     |    9 +++++----
 include/linux/pstore.h   |    5 +++--
 4 files changed, 18 insertions(+), 12 deletions(-)

diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 8aac55e..51cf7ba 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,9 +933,10 @@ 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, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, size_t size,
+static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
 		       struct pstore_info *psi);
-static int erst_clearer(u64 id, struct pstore_info *psi);
+static int erst_clearer(enum pstore_type_id type, u64 id,
+			struct pstore_info *psi);
 
 static struct pstore_info erst_info = {
 	.owner		= THIS_MODULE,
@@ -1039,7 +1040,7 @@ out:
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, size_t size,
+static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
 		       struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
@@ -1083,7 +1084,8 @@ static u64 erst_writer(enum pstore_type_id type, size_t size,
 	return rcd->hdr.record_id;
 }
 
-static int erst_clearer(u64 id, struct pstore_info *psi)
+static int erst_clearer(enum pstore_type_id type, u64 id,
+			struct pstore_info *psi)
 {
 	return erst_clear(id);
 }
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index b19884a..893b961 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -39,8 +39,9 @@
 #define	PSTORE_NAMELEN	64
 
 struct pstore_private {
-	u64	id;
 	struct pstore_info *psi;
+	enum pstore_type_id type;
+	u64	id;
 	ssize_t	size;
 	char	data[];
 };
@@ -73,7 +74,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
 {
 	struct pstore_private *p = dentry->d_inode->i_private;
 
-	p->psi->erase(p->id, p->psi);
+	p->psi->erase(p->type, p->id, p->psi);
 
 	return simple_unlink(dir, dentry);
 }
@@ -192,6 +193,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
 	private = kmalloc(sizeof *private + size, GFP_KERNEL);
 	if (!private)
 		goto fail_alloc;
+	private->type = type;
 	private->id = id;
 	private->psi = psi;
 
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 221c04e..163bb40 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -78,7 +78,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 	oopscount++;
 	while (total < kmsg_bytes) {
 		dst = psinfo->buf;
-		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++);
+		hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
 		size = psinfo->bufsize - hsize;
 		dst += hsize;
 
@@ -94,8 +94,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 		memcpy(dst, s1 + s1_start, l1_cpy);
 		memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
 
-		id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy,
-				   psinfo);
+		id = psinfo->write(PSTORE_TYPE_DMESG, part,
+				   hsize + l1_cpy + l2_cpy, psinfo);
 		if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 			pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
 				      psinfo->buf, hsize + l1_cpy + l2_cpy,
@@ -103,6 +103,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 		l1 -= l1_cpy;
 		l2 -= l2_cpy;
 		total += l1_cpy + l2_cpy;
+		part++;
 	}
 	mutex_unlock(&psinfo->buf_mutex);
 }
@@ -197,7 +198,7 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 
 	mutex_lock(&psinfo->buf_mutex);
 	memcpy(psinfo->buf, buf, size);
-	id = psinfo->write(type, size, psinfo);
+	id = psinfo->write(type, 0, size, psinfo);
 	if (pstore_is_mounted())
 		pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
 			      size, CURRENT_TIME, psinfo);
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index b2f1d97..12be8f1 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,9 +39,10 @@ struct pstore_info {
 	int		(*close)(struct pstore_info *psi);
 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
 			struct timespec *time, struct pstore_info *psi);
-	u64		(*write)(enum pstore_type_id type, size_t size,
+	u64		(*write)(enum pstore_type_id type, int part,
+			size_t size, struct pstore_info *psi);
+	int		(*erase)(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
-	int		(*erase)(u64 id, struct pstore_info *psi);
 	void		*data;
 };
 
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 3/9] pstore: Make "part" unsigned
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
  2011-07-18 20:30 ` [PATCH 1/9] pstore: Extend API Matthew Garrett
  2011-07-18 20:30 ` [PATCH 2/9] pstore: Add extra context for writes and erases Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett

We'll never have a negative part, so just make this an unsigned int.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/acpi/apei/erst.c |    8 ++++----
 fs/pstore/platform.c     |    3 ++-
 include/linux/pstore.h   |    2 +-
 3 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 51cf7ba..2ca59dc 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,8 +933,8 @@ 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, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
-		       struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+		       size_t size, struct pstore_info *psi);
 static int erst_clearer(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
 
@@ -1040,8 +1040,8 @@ out:
 	return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
-		       struct pstore_info *psi)
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+		       size_t size, struct pstore_info *psi)
 {
 	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
 					(erst_info.buf - sizeof(*rcd));
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 163bb40..49ff1de 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -67,7 +67,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
 	unsigned long	size, total = 0;
 	char		*dst, *why;
 	u64		id;
-	int		hsize, part = 1;
+	int		hsize;
+	unsigned int	part = 1;
 
 	if (reason < ARRAY_SIZE(reason_str))
 		why = reason_str[reason];
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 12be8f1..cc03bbf 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,7 +39,7 @@ struct pstore_info {
 	int		(*close)(struct pstore_info *psi);
 	ssize_t		(*read)(u64 *id, enum pstore_type_id *type,
 			struct timespec *time, struct pstore_info *psi);
-	u64		(*write)(enum pstore_type_id type, int part,
+	u64		(*write)(enum pstore_type_id type, unsigned int part,
 			size_t size, struct pstore_info *psi);
 	int		(*erase)(enum pstore_type_id type, u64 id,
 			struct pstore_info *psi);
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (2 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 3/9] pstore: Make "part" unsigned Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:58   ` Tony Luck
  2011-07-20 13:27   ` Konrad Rzeszutek Wilk
  2011-07-18 20:30 ` [PATCH 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
                   ` (4 subsequent siblings)
  8 siblings, 2 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett

pstore only allows one backend to be registered at present, but the
system may provide several. Add a parameter to allow the user to choose
which backend will be used rather than just relying on load order.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 Documentation/ABI/testing/pstore    |    5 +++++
 Documentation/kernel-parameters.txt |    2 ++
 fs/pstore/platform.c                |   11 +++++++++++
 3 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore
index ddf451e..1aa4035 100644
--- a/Documentation/ABI/testing/pstore
+++ b/Documentation/ABI/testing/pstore
@@ -39,3 +39,8 @@ Description:	Generic interface to platform dependent persistent storage.
 		multiple) files based on the record size of the underlying
 		persistent storage until at least this amount is reached.
 		Default is 10 Kbytes.
+
+		Pstore only supports one backend at a time. If multiple
+		backends are available, the preferred backend may be
+		set by passing the pstore.backend= argument to the kernel
+		or writing to /sys/module/pstore/parameters/backend .
\ No newline at end of file
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ede3209..abafa88 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2156,6 +2156,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
 			0 = disabled, 1 = enabled (default).
 
+	pstore.backend=	Specify the name of the pstore backend to use
+
 	pt.		[PARIDE]
 			See Documentation/blockdev/paride.txt.
 
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 49ff1de..94200d6 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -37,6 +37,8 @@
 static DEFINE_SPINLOCK(pstore_lock);
 static struct pstore_info *psinfo;
 
+static char *backend;
+
 /* How much of the console log to snapshot */
 static unsigned long kmsg_bytes = 10240;
 
@@ -131,6 +133,12 @@ int pstore_register(struct pstore_info *psi)
 		spin_unlock(&pstore_lock);
 		return -EBUSY;
 	}
+
+	if (backend && strcmp(backend, psi->name)) {
+		spin_unlock(&pstore_lock);
+		return -EBUSY;
+	}
+
 	psinfo = psi;
 	spin_unlock(&pstore_lock);
 
@@ -208,3 +216,6 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
 	return 0;
 }
 EXPORT_SYMBOL_GPL(pstore_write);
+
+module_param(backend, charp, 0644);
+MODULE_PARM_DESC(backend, "Pstore backend to use");
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 5/9] efi: Add support for using efivars as a pstore backend
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (3 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 6/9] efivars: String functions Matthew Garrett
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett

EFI provides an area of nonvolatile storage managed by the firmware. We
can use this as a pstore backend to maintain copies of oopses, aiding
diagnosis.

Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
 drivers/firmware/efivars.c |  191 +++++++++++++++++++++++++++++++++++++++++++-
 include/linux/efi.h        |    6 ++
 2 files changed, 195 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 5f29aaf..2bbb226 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -78,6 +78,7 @@
 #include <linux/kobject.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/pstore.h>
 
 #include <asm/uaccess.h>
 
@@ -89,6 +90,8 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(EFIVARS_VERSION);
 
+#define DUMP_NAME_LEN 52
+
 /*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
@@ -161,18 +164,28 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 }
 
 static efi_status_t
-get_var_data(struct efivars *efivars, struct efi_variable *var)
+get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
 {
 	efi_status_t status;
 
-	spin_lock(&efivars->lock);
 	var->DataSize = 1024;
 	status = efivars->ops->get_variable(var->VariableName,
 					    &var->VendorGuid,
 					    &var->Attributes,
 					    &var->DataSize,
 					    var->Data);
+	return status;
+}
+
+static efi_status_t
+get_var_data(struct efivars *efivars, struct efi_variable *var)
+{
+	efi_status_t status;
+
+	spin_lock(&efivars->lock);
+	status = get_var_data_locked(efivars, var);
 	spin_unlock(&efivars->lock);
+
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
 			status);
@@ -387,12 +400,176 @@ static struct kobj_type efivar_ktype = {
 	.default_attrs = def_attrs,
 };
 
+static struct pstore_info efi_pstore_info;
+
 static inline void
 efivar_unregister(struct efivar_entry *var)
 {
 	kobject_put(&var->kobj);
 }
 
+#ifdef CONFIG_PSTORE
+
+static int efi_pstore_open(struct pstore_info *psi)
+{
+	struct efivars *efivars = psi->data;
+
+	spin_lock(&efivars->lock);
+	efivars->walk_entry = list_first_entry(&efivars->list,
+					       struct efivar_entry, list);
+	return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+	struct efivars *efivars = psi->data;
+
+	spin_unlock(&efivars->lock);
+	return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+			       struct timespec *timespec, struct pstore_info *psi)
+{
+	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+	struct efivars *efivars = psi->data;
+	char name[DUMP_NAME_LEN];
+	int i;
+	unsigned int part, size;
+	unsigned long time;
+
+	while (&efivars->walk_entry->list != &efivars->list) {
+		if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
+				 vendor)) {
+			for (i = 0; i < DUMP_NAME_LEN; i++) {
+				name[i] = efivars->walk_entry->var.VariableName[i];
+			}
+			if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
+				*id = part;
+				timespec->tv_sec = time;
+				timespec->tv_nsec = 0;
+				get_var_data_locked(efivars, &efivars->walk_entry->var);
+				size = efivars->walk_entry->var.DataSize;
+				memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+				efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+					           struct efivar_entry, list);
+				return size;
+			}
+		}
+		efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+						 struct efivar_entry, list);
+	}
+	return 0;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
+			    size_t size, struct pstore_info *psi)
+{
+	char name[DUMP_NAME_LEN];
+	char stub_name[DUMP_NAME_LEN];
+	efi_char16_t efi_name[DUMP_NAME_LEN];
+	efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+	struct efivars *efivars = psi->data;
+	struct efivar_entry *entry, *found = NULL;
+	int i;
+
+	sprintf(stub_name, "dump-type%u-%u-", type, part);
+	sprintf(name, "%s%lu", stub_name, get_seconds());
+
+	spin_lock(&efivars->lock);
+
+	for (i = 0; i < DUMP_NAME_LEN; i++)
+		efi_name[i] = stub_name[i];
+
+	/*
+	 * Clean up any entries with the same name
+	 */
+
+	list_for_each_entry(entry, &efivars->list, list) {
+		get_var_data_locked(efivars, &entry->var);
+
+		for (i = 0; i < DUMP_NAME_LEN; i++) {
+			if (efi_name[i] == 0) {
+				found = entry;
+				efivars->ops->set_variable(entry->var.VariableName,
+							   &entry->var.VendorGuid,
+							   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+							   0, NULL);
+				break;
+			} else if (efi_name[i] != entry->var.VariableName[i]) {
+				break;
+			}
+		}
+	}
+
+	if (found)
+		list_del(&found->list);
+
+	for (i = 0; i < DUMP_NAME_LEN; i++)
+		efi_name[i] = name[i];
+
+	efivars->ops->set_variable(efi_name, &vendor,
+				   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+				   size, psi->buf);
+
+	spin_unlock(&efivars->lock);
+
+	if (found)
+		efivar_unregister(found);
+
+	if (size)
+		efivar_create_sysfs_entry(efivars, utf8_strsize(efi_name, DUMP_NAME_LEN * 2),
+					  efi_name, &vendor);
+
+	return part;
+};
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+			    struct pstore_info *psi)
+{
+	efi_pstore_write(type, id, 0, psi);
+
+	return 0;
+}
+#else
+static int efi_pstore_open(struct pstore_info *psi)
+{
+	return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+	return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+			       struct timespec *time, struct pstore_info *psi)
+{
+	return -1;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, int part, size_t size,
+			    struct pstore_info *psi)
+{
+	return 0;
+}
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+			    struct pstore_info *psi)
+{
+	return 0;
+}
+#endif
+
+static struct pstore_info efi_pstore_info = {
+	.owner		= THIS_MODULE,
+	.name		= "efi",
+	.open		= efi_pstore_open,
+	.close		= efi_pstore_close,
+	.read		= efi_pstore_read,
+	.write		= efi_pstore_write,
+	.erase		= efi_pstore_erase,
+};
 
 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 			     struct bin_attribute *bin_attr,
@@ -763,6 +940,16 @@ int register_efivars(struct efivars *efivars,
 	if (error)
 		unregister_efivars(efivars);
 
+	efivars->efi_pstore_info = efi_pstore_info;
+
+	efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+	if (efivars->efi_pstore_info.buf) {
+		efivars->efi_pstore_info.bufsize = 1024;
+		efivars->efi_pstore_info.data = efivars;
+		mutex_init(&efivars->efi_pstore_info.buf_mutex);
+		pstore_register(&efivars->efi_pstore_info);
+	}
+
 out:
 	kfree(variable_name);
 
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ec25726..2362a0b 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -19,6 +19,7 @@
 #include <linux/rtc.h>
 #include <linux/ioport.h>
 #include <linux/pfn.h>
+#include <linux/pstore.h>
 
 #include <asm/page.h>
 #include <asm/system.h>
@@ -232,6 +233,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
 #define UV_SYSTEM_TABLE_GUID \
     EFI_GUID(  0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
 
+#define LINUX_EFI_CRASH_GUID \
+    EFI_GUID(  0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
+
 typedef struct {
 	efi_guid_t guid;
 	unsigned long table;
@@ -458,6 +462,8 @@ struct efivars {
 	struct kset *kset;
 	struct bin_attribute *new_var, *del_var;
 	const struct efivar_operations *ops;
+	struct efivar_entry *walk_entry;
+	struct pstore_info efi_pstore_info;
 };
 
 int register_efivars(struct efivars *efivars,
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 6/9] efivars: String functions
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (4 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 7/9] efivars: introduce utf16_strncmp Matthew Garrett
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck

From: Mike Waychison <mikew@google.com>

Fix the string functions in the efivars driver to be called utf16_*
instead of utf8_* as the encoding is utf16, not utf8.

As well, rename utf16_strlen to utf16_strnlen as it takes a maxlength
argument and the name should be consistent with the standard C function
names.  utf16_strlen is still provided for convenience in a subsequent
patch.

Signed-off-by: Mike Waychison <mikew@google.com>
---
 drivers/firmware/efivars.c |   30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 2bbb226..4202a31 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -144,23 +144,29 @@ efivar_create_sysfs_entry(struct efivars *efivars,
 
 /* Return the number of unicode characters in data */
 static unsigned long
-utf8_strlen(efi_char16_t *data, unsigned long maxlength)
+utf16_strnlen(efi_char16_t *s, size_t maxlength)
 {
 	unsigned long length = 0;
 
-	while (*data++ != 0 && length < maxlength)
+	while (*s++ != 0 && length < maxlength)
 		length++;
 	return length;
 }
 
+static unsigned long
+utf16_strlen(efi_char16_t *s)
+{
+	return utf16_strnlen(s, ~0UL);
+}
+
 /*
  * Return the number of bytes is the length of this string
  * Note: this is NOT the same as the number of unicode characters
  */
 static inline unsigned long
-utf8_strsize(efi_char16_t *data, unsigned long maxlength)
+utf16_strsize(efi_char16_t *data, unsigned long maxlength)
 {
-	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+	return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 }
 
 static efi_status_t
@@ -518,7 +524,9 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 		efivar_unregister(found);
 
 	if (size)
-		efivar_create_sysfs_entry(efivars, utf8_strsize(efi_name, DUMP_NAME_LEN * 2),
+		efivar_create_sysfs_entry(efivars,
+					  utf16_strsize(efi_name,
+							DUMP_NAME_LEN * 2),
 					  efi_name, &vendor);
 
 	return part;
@@ -591,8 +599,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 	 * Does this variable already exist?
 	 */
 	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
-		strsize2 = utf8_strsize(new_var->VariableName, 1024);
+		strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+		strsize2 = utf16_strsize(new_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
 			!memcmp(&(search_efivar->var.VariableName),
 				new_var->VariableName, strsize1) &&
@@ -624,8 +632,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
 
 	/* Create the entry in sysfs.  Locking is not required here */
 	status = efivar_create_sysfs_entry(efivars,
-					   utf8_strsize(new_var->VariableName,
-							1024),
+					   utf16_strsize(new_var->VariableName,
+							 1024),
 					   new_var->VariableName,
 					   &new_var->VendorGuid);
 	if (status) {
@@ -654,8 +662,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
 	 * Does this variable already exist?
 	 */
 	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
-		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
-		strsize2 = utf8_strsize(del_var->VariableName, 1024);
+		strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+		strsize2 = utf16_strsize(del_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
 			!memcmp(&(search_efivar->var.VariableName),
 				del_var->VariableName, strsize1) &&
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 7/9] efivars: introduce utf16_strncmp
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (5 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 6/9] efivars: String functions Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 8/9] efivars: Use string functions in pstore_write Matthew Garrett
  2011-07-18 20:30 ` [PATCH 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck

From: Mike Waychison <mikew@google.com>

Introduce utf16_strncmp which is used in the next patch.  Semantics
should be the same as the strncmp C function.

Signed-off-by: Mike Waychison <mikew@google.com>
---
 drivers/firmware/efivars.c |   18 ++++++++++++++++++
 1 files changed, 18 insertions(+), 0 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 4202a31..15b9a01 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -169,6 +169,24 @@ utf16_strsize(efi_char16_t *data, unsigned long maxlength)
 	return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 }
 
+static inline int
+utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
+{
+	while (1) {
+		if (len == 0)
+			return 0;
+		if (*a < *b)
+			return -1;
+		if (*a > *b)
+			return 1;
+		if (*a == 0) /* implies *b == 0 */
+			return 0;
+		a++;
+		b++;
+		len--;
+	}
+}
+
 static efi_status_t
 get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
 {
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 8/9] efivars: Use string functions in pstore_write
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (6 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 7/9] efivars: introduce utf16_strncmp Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  2011-07-18 20:30 ` [PATCH 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck

From: Mike Waychison <mikew@google.com>

Instead of open-coding the string operations for comparing the prefix of
the variable names, use the provided utf16_* string functions.

This patch also changes the calls to efi.set_variable to
efivars->ops->set_variable so that the right function gets called in the
case of gsmi (which doesn't have a valid efi structure).

As well, make sure that we only consider variables with the right vendor
string.

Signed-off-by: Mike Waychison <mikew@google.com>
---
 drivers/firmware/efivars.c |   26 ++++++++++++++------------
 1 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 15b9a01..563492e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -512,18 +512,20 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 	list_for_each_entry(entry, &efivars->list, list) {
 		get_var_data_locked(efivars, &entry->var);
 
-		for (i = 0; i < DUMP_NAME_LEN; i++) {
-			if (efi_name[i] == 0) {
-				found = entry;
-				efivars->ops->set_variable(entry->var.VariableName,
-							   &entry->var.VendorGuid,
-							   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
-							   0, NULL);
-				break;
-			} else if (efi_name[i] != entry->var.VariableName[i]) {
-				break;
-			}
-		}
+		if (efi_guidcmp(entry->var.VendorGuid, vendor))
+			continue;
+		if (utf16_strncmp(entry->var.VariableName, efi_name,
+				  utf16_strlen(efi_name)))
+			continue;
+		/* Needs to be a prefix */
+		if (entry->var.VariableName[utf16_strlen(efi_name)] == 0)
+			continue;
+
+		/* found */
+		found = entry;
+		efivars->ops->set_variable(entry->var.VariableName, &entry->var.VendorGuid,
+					   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+					   0, NULL);
 	}
 
 	if (found)
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES
  2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
                   ` (7 preceding siblings ...)
  2011-07-18 20:30 ` [PATCH 8/9] efivars: Use string functions in pstore_write Matthew Garrett
@ 2011-07-18 20:30 ` Matthew Garrett
  8 siblings, 0 replies; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 20:30 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, mikew, tony.luck

From: Mike Waychison <mikew@google.com>

Consolidate the attributes listed for pstore operations in one place,
PSTORE_EFI_ATTRIBUTES.

Signed-off-by: Mike Waychison <mikew@google.com>
---
 drivers/firmware/efivars.c |   12 ++++++++----
 1 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 563492e..eacb05e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -122,6 +122,10 @@ struct efivar_attribute {
 	ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
 };
 
+#define PSTORE_EFI_ATTRIBUTES \
+	(EFI_VARIABLE_NON_VOLATILE | \
+	 EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+	 EFI_VARIABLE_RUNTIME_ACCESS)
 
 #define EFIVAR_ATTR(_name, _mode, _show, _store) \
 struct efivar_attribute efivar_attr_##_name = { \
@@ -523,8 +527,9 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 
 		/* found */
 		found = entry;
-		efivars->ops->set_variable(entry->var.VariableName, &entry->var.VendorGuid,
-					   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+		efivars->ops->set_variable(entry->var.VariableName,
+					   &entry->var.VendorGuid,
+					   PSTORE_EFI_ATTRIBUTES,
 					   0, NULL);
 	}
 
@@ -534,8 +539,7 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
 	for (i = 0; i < DUMP_NAME_LEN; i++)
 		efi_name[i] = name[i];
 
-	efivars->ops->set_variable(efi_name, &vendor,
-				   EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+	efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
 				   size, psi->buf);
 
 	spin_unlock(&efivars->lock);
-- 
1.7.6


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-18 20:30 ` [PATCH 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
@ 2011-07-18 20:58   ` Tony Luck
  2011-07-18 21:00     ` Matthew Garrett
  2011-07-20 13:27   ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 15+ messages in thread
From: Tony Luck @ 2011-07-18 20:58 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: x86, linux-kernel, mikew

On Mon, Jul 18, 2011 at 1:30 PM, Matthew Garrett <mjg@redhat.com> wrote:.
> +
> +               Pstore only supports one backend at a time. If multiple
> +               backends are available, the preferred backend may be
> +               set by passing the pstore.backend= argument to the kernel
> +               or writing to /sys/module/pstore/parameters/backend .
> \ No newline at end of file

Maybe we should have a newline :-)

We don't allow backends to be unregistered (currently) - Do you think it would
be helpful to mention in this text that you cannot change your mind and
switch to a different back end once you have registered one? Writing
to /sys/module/... sounds a lot more flexible than what reality will allow.


> +       if (backend && strcmp(backend, psi->name)) {
> +               spin_unlock(&pstore_lock);
> +               return -EBUSY;
> +       }

EBUSY doesn't feel like the right error here (and we are using that
to indicate that some other backend is already registered).  Not
sure what is the right one though. ENOENT? EINVAL?

-Tony

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-18 20:58   ` Tony Luck
@ 2011-07-18 21:00     ` Matthew Garrett
  2011-07-18 21:08       ` Tony Luck
  0 siblings, 1 reply; 15+ messages in thread
From: Matthew Garrett @ 2011-07-18 21:00 UTC (permalink / raw)
  To: Tony Luck; +Cc: x86, linux-kernel, mikew

On Mon, Jul 18, 2011 at 01:58:28PM -0700, Tony Luck wrote:
> On Mon, Jul 18, 2011 at 1:30 PM, Matthew Garrett <mjg@redhat.com> wrote:.
> > +
> > +               Pstore only supports one backend at a time. If multiple
> > +               backends are available, the preferred backend may be
> > +               set by passing the pstore.backend= argument to the kernel
> > +               or writing to /sys/module/pstore/parameters/backend .
> > \ No newline at end of file
> 
> Maybe we should have a newline :-)

True...

> We don't allow backends to be unregistered (currently) - Do you think it would
> be helpful to mention in this text that you cannot change your mind and
> switch to a different back end once you have registered one? Writing
> to /sys/module/... sounds a lot more flexible than what reality will allow.

Mm. Yes, the lack of unregistration does make that less helpful. Perhaps 
best to make that unwritable.

> 
> > +       if (backend && strcmp(backend, psi->name)) {
> > +               spin_unlock(&pstore_lock);
> > +               return -EBUSY;
> > +       }
> 
> EBUSY doesn't feel like the right error here (and we are using that
> to indicate that some other backend is already registered).  Not
> sure what is the right one though. ENOENT? EINVAL?

EINVAL, I guess?

-- 
Matthew Garrett | mjg59@srcf.ucam.org

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-18 21:00     ` Matthew Garrett
@ 2011-07-18 21:08       ` Tony Luck
  0 siblings, 0 replies; 15+ messages in thread
From: Tony Luck @ 2011-07-18 21:08 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: x86, linux-kernel, mikew

On Mon, Jul 18, 2011 at 2:00 PM, Matthew Garrett <mjg59@srcf.ucam.org> wrote:
> On Mon, Jul 18, 2011 at 01:58:28PM -0700, Tony Luck wrote:

>> We don't allow backends to be unregistered (currently) - Do you think it would
>> be helpful to mention in this text that you cannot change your mind and
>> switch to a different back end once you have registered one? Writing
>> to /sys/module/... sounds a lot more flexible than what reality will allow.
>
> Mm. Yes, the lack of unregistration does make that less helpful. Perhaps
> best to make that unwritable.

Perhaps .... writable would be useful in this sequence:

1) Load pstore (or pstore is built in)
2) write to /sys/module/pstore/parameters/backend to chose backend
3) load other modules (including multiple pstore backends)

But that seems rather contrived - a user doing this could just adjust step 3
to only load the preferred backend (or make sure the preferred one goes first).

-Tony

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-18 20:30 ` [PATCH 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
  2011-07-18 20:58   ` Tony Luck
@ 2011-07-20 13:27   ` Konrad Rzeszutek Wilk
  2011-07-20 14:29     ` Luck, Tony
  1 sibling, 1 reply; 15+ messages in thread
From: Konrad Rzeszutek Wilk @ 2011-07-20 13:27 UTC (permalink / raw)
  To: Matthew Garrett; +Cc: x86, linux-kernel, mikew, tony.luck

On Mon, Jul 18, 2011 at 04:30:28PM -0400, Matthew Garrett wrote:
> pstore only allows one backend to be registered at present, but the
> system may provide several. Add a parameter to allow the user to choose
> which backend will be used rather than just relying on load order.
> 
> Signed-off-by: Matthew Garrett <mjg@redhat.com>
> ---
>  Documentation/ABI/testing/pstore    |    5 +++++
>  Documentation/kernel-parameters.txt |    2 ++
>  fs/pstore/platform.c                |   11 +++++++++++
>  3 files changed, 18 insertions(+), 0 deletions(-)
> 
> diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore
> index ddf451e..1aa4035 100644
> --- a/Documentation/ABI/testing/pstore
> +++ b/Documentation/ABI/testing/pstore
> @@ -39,3 +39,8 @@ Description:	Generic interface to platform dependent persistent storage.
>  		multiple) files based on the record size of the underlying
>  		persistent storage until at least this amount is reached.
>  		Default is 10 Kbytes.
> +
> +		Pstore only supports one backend at a time. If multiple
> +		backends are available, the preferred backend may be
> +		set by passing the pstore.backend= argument to the kernel
> +		or writing to /sys/module/pstore/parameters/backend .
> \ No newline at end of file
> diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
> index ede3209..abafa88 100644
> --- a/Documentation/kernel-parameters.txt
> +++ b/Documentation/kernel-parameters.txt
> @@ -2156,6 +2156,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
>  			[HW,MOUSE] Controls Logitech smartscroll autorepeat.
>  			0 = disabled, 1 = enabled (default).
>  
> +	pstore.backend=	Specify the name of the pstore backend to use
> +
>  	pt.		[PARIDE]
>  			See Documentation/blockdev/paride.txt.
>  
> diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
> index 49ff1de..94200d6 100644
> --- a/fs/pstore/platform.c
> +++ b/fs/pstore/platform.c
> @@ -37,6 +37,8 @@
>  static DEFINE_SPINLOCK(pstore_lock);
>  static struct pstore_info *psinfo;
>  
> +static char *backend;
> +
>  /* How much of the console log to snapshot */
>  static unsigned long kmsg_bytes = 10240;
>  
> @@ -131,6 +133,12 @@ int pstore_register(struct pstore_info *psi)
>  		spin_unlock(&pstore_lock);
>  		return -EBUSY;
>  	}
> +
> +	if (backend && strcmp(backend, psi->name)) {

Is there a limit of how big the backend name can be? If so would it
make sense to use to strncmp?

> +		spin_unlock(&pstore_lock);
> +		return -EBUSY;
> +	}
> +
>  	psinfo = psi;
>  	spin_unlock(&pstore_lock);
>  
> @@ -208,3 +216,6 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(pstore_write);
> +
> +module_param(backend, charp, 0644);
> +MODULE_PARM_DESC(backend, "Pstore backend to use");
> -- 
> 1.7.6
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH 4/9] pstore: Allow the user to explicitly choose a backend
  2011-07-20 13:27   ` Konrad Rzeszutek Wilk
@ 2011-07-20 14:29     ` Luck, Tony
  0 siblings, 0 replies; 15+ messages in thread
From: Luck, Tony @ 2011-07-20 14:29 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, Matthew Garrett; +Cc: x86, linux-kernel, mikew

> > +	if (backend && strcmp(backend, psi->name)) {
>
> Is there a limit of how big the backend name can be? If so would it
> make sense to use to strncmp?

I'd expect that the name will generally be short. It does get
embedded in the names of files that appear in the pstore file
system - so there is a 255 pathname component limit, which means
that backends should limit themselves to 200 or so characters.

So I suppose we could check to see if the backend is trying
to use a name so long that it would cause problems - but I'm
not sure how much value that would really add. I don't think
that loading pstore modules with dumb names is an interesting
attack vector.

-Tony

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2011-07-20 14:29 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-18 20:30 Add an EFI pstore backend Matthew Garrett
2011-07-18 20:30 ` [PATCH 1/9] pstore: Extend API Matthew Garrett
2011-07-18 20:30 ` [PATCH 2/9] pstore: Add extra context for writes and erases Matthew Garrett
2011-07-18 20:30 ` [PATCH 3/9] pstore: Make "part" unsigned Matthew Garrett
2011-07-18 20:30 ` [PATCH 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
2011-07-18 20:58   ` Tony Luck
2011-07-18 21:00     ` Matthew Garrett
2011-07-18 21:08       ` Tony Luck
2011-07-20 13:27   ` Konrad Rzeszutek Wilk
2011-07-20 14:29     ` Luck, Tony
2011-07-18 20:30 ` [PATCH 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
2011-07-18 20:30 ` [PATCH 6/9] efivars: String functions Matthew Garrett
2011-07-18 20:30 ` [PATCH 7/9] efivars: introduce utf16_strncmp Matthew Garrett
2011-07-18 20:30 ` [PATCH 8/9] efivars: Use string functions in pstore_write Matthew Garrett
2011-07-18 20:30 ` [PATCH 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).