Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1262835 > unrolled thread

[PATCH 0/5] pstore: ramoops: support multiple pmsg instances

Started byHiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
First post2015-11-05 03:40 +0100
Last post2015-11-05 03:40 +0100
Articles 4 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH 0/5] pstore: ramoops: support multiple pmsg instances Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com> - 2015-11-05 03:40 +0100
    [PATCH 2/5] ramoops: introduce generic init/free functions for prz Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com> - 2015-11-05 03:40 +0100
    [PATCH 4/5] ramoops: support multiple pmsg instances Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com> - 2015-11-05 03:40 +0100
    [PATCH 5/5] selftests/pstore: add testcases for multiple pmsg  instances Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com> - 2015-11-05 03:40 +0100

#1262835 — [PATCH 0/5] pstore: ramoops: support multiple pmsg instances

FromHiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Date2015-11-05 03:40 +0100
Subject[PATCH 0/5] pstore: ramoops: support multiple pmsg instances
Message-ID<qriCZ-v7-3@gated-at.bofh.it>
The following series implements multiple pmsg. This feature allows
userspace program to control individual content aging or priority.

If a pstore backend module(e.g. ramoops) requires the multiple pmsg
instances when registering itself to pstore, multiple /dev/pmsg[ID]
are created. Writes to each /dev/pmsg[ID] are isolated each other. After
reboot, the contents are available in /sys/fs/pstore/pmsg-[backend]-[ID].

In addition, we add multiple pmsg support for ramoops. We can
specify multiple pmsg area size by its module parameter as follows.

 pmsg_size=0x1000,0x2000,...

---

Hiraku Toyooka (5):
      ramoops: use persistent_ram_free() instead of kfree() for freeing prz
      ramoops: introduce generic init/free functions for prz
      pstore: support multiple pmsg instances
      ramoops: support multiple pmsg instances
      selftests/pstore: add testcases for multiple pmsg instances


 Documentation/ramoops.txt                          |   22 ++
 fs/pstore/pmsg.c                                   |   20 ++
 fs/pstore/ram.c                                    |  213 +++++++++++++++-----
 include/linux/pstore.h                             |    1 
 include/linux/pstore_ram.h                         |    8 +
 tools/testing/selftests/pstore/common_tests        |   21 ++
 .../selftests/pstore/pstore_post_reboot_tests      |   27 +--
 tools/testing/selftests/pstore/pstore_tests        |   16 +-
 8 files changed, 257 insertions(+), 71 deletions(-)

--
Hiraku Toyooka
--
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/

[toc] | [next] | [standalone]


#1262836 — [PATCH 2/5] ramoops: introduce generic init/free functions for prz

FromHiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Date2015-11-05 03:40 +0100
Subject[PATCH 2/5] ramoops: introduce generic init/free functions for prz
Message-ID<qriCZ-v7-9@gated-at.bofh.it>
In reply to#1262835
We modifies initialization and freeing code for prz for generic usage.
This change

 * add generic function __ramoops_init_prz() to reduce redundancy
   between ramoops_init_prz() and ramoops_init_przs().
 * rename 'przs' member in struct ramoops_context to 'dprzs' so that
   it stands for 'dump przs'.
 * rename ramoops_init_prz() to ramoops_init_dprzs().
 * change parameter of ramoops_free_przs() from struct ramoops_context *
   into struct persistent_ram_zone * in order to make it available for
   all prz array.

Signed-off-by: Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Colin Cross <ccross@android.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Salyzyn <salyzyn@android.com>
Cc: Seiji Aguchi <seiji.aguchi.tr@hitachi.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-kernel@vger.kernel.org
---
 fs/pstore/ram.c |   63 +++++++++++++++++++++++++++++++------------------------
 1 file changed, 35 insertions(+), 28 deletions(-)

diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 6363768..89cc90e 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -83,7 +83,7 @@ MODULE_PARM_DESC(ramoops_ecc,
 		"bytes ECC)");
 
 struct ramoops_context {
-	struct persistent_ram_zone **przs;
+	struct persistent_ram_zone **dprzs;
 	struct persistent_ram_zone *cprz;
 	struct persistent_ram_zone *fprz;
 	struct persistent_ram_zone *mprz;
@@ -199,7 +199,7 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 
 	/* Find the next valid persistent_ram_zone for DMESG */
 	while (cxt->dump_read_cnt < cxt->max_dump_cnt && !prz) {
-		prz = ramoops_get_next_prz(cxt->przs, &cxt->dump_read_cnt,
+		prz = ramoops_get_next_prz(cxt->dprzs, &cxt->dump_read_cnt,
 					   cxt->max_dump_cnt, id, type,
 					   PSTORE_TYPE_DMESG, 1);
 		if (!prz_ok(prz))
@@ -314,10 +314,10 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
 	if (part != 1)
 		return -ENOSPC;
 
-	if (!cxt->przs)
+	if (!cxt->dprzs)
 		return -ENOSPC;
 
-	prz = cxt->przs[cxt->dump_write_cnt];
+	prz = cxt->dprzs[cxt->dump_write_cnt];
 
 	hlen = ramoops_write_kmsg_hdr(prz, compressed);
 	if (size + hlen > prz->buffer_size)
@@ -339,7 +339,7 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
 	case PSTORE_TYPE_DMESG:
 		if (id >= cxt->max_dump_cnt)
 			return -EINVAL;
-		prz = cxt->przs[id];
+		prz = cxt->dprzs[id];
 		break;
 	case PSTORE_TYPE_CONSOLE:
 		prz = cxt->cprz;
@@ -371,21 +371,24 @@ static struct ramoops_context oops_cxt = {
 	},
 };
 
-static void ramoops_free_przs(struct ramoops_context *cxt)
+static void ramoops_free_przs(struct persistent_ram_zone **przs)
 {
 	int i;
 
-	cxt->max_dump_cnt = 0;
-	if (!cxt->przs)
+	if (!przs)
 		return;
 
-	for (i = 0; !IS_ERR_OR_NULL(cxt->przs[i]); i++)
-		persistent_ram_free(cxt->przs[i]);
-	kfree(cxt->przs);
+	for (i = 0; i < !IS_ERR_OR_NULL(przs[i]); i++)
+		persistent_ram_free(przs[i]);
+	kfree(przs);
 }
 
-static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
-			     phys_addr_t *paddr, size_t dump_mem_sz)
+static int __ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
+			      struct persistent_ram_zone **prz,
+			      phys_addr_t *paddr, size_t sz, u32 sig, bool zap);
+
+static int ramoops_init_dprzs(struct device *dev, struct ramoops_context *cxt,
+			      phys_addr_t *paddr, size_t dump_mem_sz)
 {
 	int err = -ENOMEM;
 	int i;
@@ -402,29 +405,24 @@ static int ramoops_init_przs(struct device *dev, struct ramoops_context *cxt,
 	if (!cxt->max_dump_cnt)
 		return -ENOMEM;
 
-	cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_dump_cnt,
+	cxt->dprzs = kcalloc(cxt->max_dump_cnt, sizeof(*cxt->dprzs),
 			     GFP_KERNEL);
-	if (!cxt->przs) {
+	if (!cxt->dprzs) {
 		dev_err(dev, "failed to initialize a prz array for dumps\n");
 		goto fail_prz;
 	}
 
 	for (i = 0; i < cxt->max_dump_cnt; i++) {
-		cxt->przs[i] = persistent_ram_new(*paddr, cxt->record_size, 0,
-						  &cxt->ecc_info,
-						  cxt->memtype);
-		if (IS_ERR(cxt->przs[i])) {
-			err = PTR_ERR(cxt->przs[i]);
-			dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
-				cxt->record_size, (unsigned long long)*paddr, err);
+		err = __ramoops_init_prz(dev, cxt, &cxt->dprzs[i], paddr,
+					 cxt->record_size, 0, false);
+		if (err)
 			goto fail_prz;
-		}
-		*paddr += cxt->record_size;
 	}
 
 	return 0;
 fail_prz:
-	ramoops_free_przs(cxt);
+	cxt->max_dump_cnt = 0;
+	ramoops_free_przs(cxt->dprzs);
 	return err;
 }
 
@@ -432,6 +430,13 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 			    struct persistent_ram_zone **prz,
 			    phys_addr_t *paddr, size_t sz, u32 sig)
 {
+	return __ramoops_init_prz(dev, cxt, prz, paddr, sz, sig, true);
+}
+
+static int __ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
+			      struct persistent_ram_zone **prz,
+			      phys_addr_t *paddr, size_t sz, u32 sig, bool zap)
+{
 	if (!sz)
 		return 0;
 
@@ -451,7 +456,8 @@ static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 		return err;
 	}
 
-	persistent_ram_zap(*prz);
+	if (zap)
+		persistent_ram_zap(*prz);
 
 	*paddr += sz;
 
@@ -503,7 +509,7 @@ static int ramoops_probe(struct platform_device *pdev)
 
 	dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
 			- cxt->pmsg_size;
-	err = ramoops_init_przs(dev, cxt, &paddr, dump_mem_sz);
+	err = ramoops_init_dprzs(dev, cxt, &paddr, dump_mem_sz);
 	if (err)
 		goto fail_out;
 
@@ -573,7 +579,8 @@ fail_init_mprz:
 fail_init_fprz:
 	persistent_ram_free(cxt->cprz);
 fail_init_cprz:
-	ramoops_free_przs(cxt);
+	cxt->max_dump_cnt = 0;
+	ramoops_free_przs(cxt->dprzs);
 fail_out:
 	return err;
 }

--
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/

[toc] | [prev] | [next] | [standalone]


#1262838 — [PATCH 4/5] ramoops: support multiple pmsg instances

FromHiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Date2015-11-05 03:40 +0100
Subject[PATCH 4/5] ramoops: support multiple pmsg instances
Message-ID<qriCZ-v7-15@gated-at.bofh.it>
In reply to#1262835
This patch enables ramoops to deal with multiple pmsg instances.
We can configure the size of each buffers by its module parameter
as follows.

  pmsg_size=0x1000,0x2000,...

Then, the ramoops allocates multiple buffers and tells the number
of buffers to pstore to create multiple /dev/pmsg[ID].

Signed-off-by: Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Colin Cross <ccross@android.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Salyzyn <salyzyn@android.com>
Cc: Seiji Aguchi <seiji.aguchi.tr@hitachi.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-doc@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 Documentation/ramoops.txt  |   22 +++++++
 fs/pstore/ram.c            |  146 ++++++++++++++++++++++++++++++++++++++------
 include/linux/pstore_ram.h |    8 ++
 3 files changed, 154 insertions(+), 22 deletions(-)

diff --git a/Documentation/ramoops.txt b/Documentation/ramoops.txt
index 5d86756..cff6ac7 100644
--- a/Documentation/ramoops.txt
+++ b/Documentation/ramoops.txt
@@ -126,3 +126,25 @@ file. Here is an example of usage:
  0 ffffffff811d9c54  ffffffff8101a7a0  __const_udelay <- native_machine_emergency_restart+0x110/0x1e0
  0 ffffffff811d9c34  ffffffff811d9c80  __delay <- __const_udelay+0x30/0x40
  0 ffffffff811d9d14  ffffffff811d9c3f  delay_tsc <- __delay+0xf/0x20
+
+6. Pmsg support
+
+Ramoops supports pmsg - logging userspace mesages in persistent store. By
+default, one pmsg area becomes available in ramoops. You can write data into
+/dev/pmsg0, e.g.:
+
+ # echo foo > /dev/pmsg0
+
+After reboot, the stored data can be read from pmsg-ramoops-0 on the pstore
+filesystem.
+
+You can specify size of the pmsg area by additional kernel command line, e.g.:
+
+ "ramoops.pmsg_size=0x1000"
+
+You can also use multiple pmsg areas, e.g.:
+
+ "ramoops.pmsg_size=0x1000,0x2000,..."
+
+Then, pmsg0, pmsg1, ... will appear on /dev. This is useful to control
+individual content aging or priority.
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 89cc90e..1d1378c 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -51,8 +51,8 @@ static ulong ramoops_ftrace_size = MIN_MEM_SIZE;
 module_param_named(ftrace_size, ramoops_ftrace_size, ulong, 0400);
 MODULE_PARM_DESC(ftrace_size, "size of ftrace log");
 
-static ulong ramoops_pmsg_size = MIN_MEM_SIZE;
-module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400);
+static char *ramoops_pmsg_size_str;
+module_param_named(pmsg_size, ramoops_pmsg_size_str, charp, 0400);
 MODULE_PARM_DESC(pmsg_size, "size of user space message log");
 
 static ulong mem_address;
@@ -86,14 +86,14 @@ struct ramoops_context {
 	struct persistent_ram_zone **dprzs;
 	struct persistent_ram_zone *cprz;
 	struct persistent_ram_zone *fprz;
-	struct persistent_ram_zone *mprz;
+	struct persistent_ram_zone **mprzs;
 	phys_addr_t phys_addr;
 	unsigned long size;
 	unsigned int memtype;
 	size_t record_size;
 	size_t console_size;
 	size_t ftrace_size;
-	size_t pmsg_size;
+	size_t *pmsg_size;
 	int dump_oops;
 	struct persistent_ram_ecc_info ecc_info;
 	unsigned int max_dump_cnt;
@@ -103,6 +103,7 @@ struct ramoops_context {
 	unsigned int console_read_cnt;
 	unsigned int ftrace_read_cnt;
 	unsigned int pmsg_read_cnt;
+	unsigned int num_pmsg;
 	struct pstore_info pstore;
 };
 
@@ -220,9 +221,10 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
 	if (!prz_ok(prz))
 		prz = ramoops_get_next_prz(&cxt->fprz, &cxt->ftrace_read_cnt,
 					   1, id, type, PSTORE_TYPE_FTRACE, 0);
-	if (!prz_ok(prz))
-		prz = ramoops_get_next_prz(&cxt->mprz, &cxt->pmsg_read_cnt,
-					   1, id, type, PSTORE_TYPE_PMSG, 0);
+	while (cxt->pmsg_read_cnt < cxt->num_pmsg && !prz)
+		prz = ramoops_get_next_prz(cxt->mprzs, &cxt->pmsg_read_cnt,
+					   cxt->num_pmsg, id, type,
+					   PSTORE_TYPE_PMSG, 0);
 	if (!prz_ok(prz))
 		return 0;
 
@@ -286,9 +288,11 @@ static int notrace ramoops_pstore_write_buf(enum pstore_type_id type,
 		persistent_ram_write(cxt->fprz, buf, size);
 		return 0;
 	} else if (type == PSTORE_TYPE_PMSG) {
-		if (!cxt->mprz)
+		if (part >= cxt->num_pmsg)
+			return -EINVAL;
+		if (!cxt->mprzs || !cxt->mprzs[part])
 			return -ENOMEM;
-		persistent_ram_write(cxt->mprz, buf, size);
+		persistent_ram_write(cxt->mprzs[part], buf, size);
 		return 0;
 	}
 
@@ -348,7 +352,9 @@ static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, int count,
 		prz = cxt->fprz;
 		break;
 	case PSTORE_TYPE_PMSG:
-		prz = cxt->mprz;
+		if (id >= cxt->num_pmsg)
+			return -EINVAL;
+		prz = cxt->mprzs[id];
 		break;
 	default:
 		return -EINVAL;
@@ -426,6 +432,39 @@ fail_prz:
 	return err;
 }
 
+static int ramoops_init_mprzs(struct device *dev, struct ramoops_context *cxt,
+			      phys_addr_t *paddr, unsigned long total)
+{
+	int err = -ENOMEM;
+	int i;
+
+	if (!total)
+		return 0;
+
+	if (*paddr + total - cxt->phys_addr > cxt->size) {
+		dev_err(dev, "no room for pmsg\n");
+		return -ENOMEM;
+	}
+
+	cxt->mprzs = kcalloc(cxt->num_pmsg, sizeof(*cxt->mprzs), GFP_KERNEL);
+	if (!cxt->mprzs) {
+		dev_err(dev, "failed to initialize a mprz array for pmsg\n");
+		goto fail_prz;
+	}
+
+	for (i = 0; i < cxt->num_pmsg; i++) {
+		err = __ramoops_init_prz(dev, cxt, &cxt->mprzs[i], paddr,
+					 cxt->pmsg_size[i], 0, true);
+		if (err)
+			goto fail_prz;
+	}
+
+	return 0;
+fail_prz:
+	ramoops_free_przs(cxt->mprzs);
+	return err;
+}
+
 static int ramoops_init_prz(struct device *dev, struct ramoops_context *cxt,
 			    struct persistent_ram_zone **prz,
 			    phys_addr_t *paddr, size_t sz, u32 sig)
@@ -472,6 +511,8 @@ static int ramoops_probe(struct platform_device *pdev)
 	size_t dump_mem_sz;
 	phys_addr_t paddr;
 	int err = -EINVAL;
+	unsigned long pmsg_size_total = 0;
+	unsigned int num_pmsg = 0;
 
 	/* Only a single ramoops area allowed at a time, so fail extra
 	 * probes.
@@ -492,8 +533,18 @@ static int ramoops_probe(struct platform_device *pdev)
 		pdata->console_size = rounddown_pow_of_two(pdata->console_size);
 	if (pdata->ftrace_size && !is_power_of_2(pdata->ftrace_size))
 		pdata->ftrace_size = rounddown_pow_of_two(pdata->ftrace_size);
-	if (pdata->pmsg_size && !is_power_of_2(pdata->pmsg_size))
-		pdata->pmsg_size = rounddown_pow_of_two(pdata->pmsg_size);
+	if (pdata->pmsg_size) {
+		for (;; num_pmsg++) {
+			unsigned long size = pdata->pmsg_size[num_pmsg];
+
+			if (!size)
+				break;
+			if (!is_power_of_2(size))
+				pdata->pmsg_size[num_pmsg]
+					= rounddown_pow_of_two(size);
+			pmsg_size_total += size;
+		}
+	}
 
 	cxt->size = pdata->mem_size;
 	cxt->phys_addr = pdata->mem_address;
@@ -501,17 +552,26 @@ static int ramoops_probe(struct platform_device *pdev)
 	cxt->record_size = pdata->record_size;
 	cxt->console_size = pdata->console_size;
 	cxt->ftrace_size = pdata->ftrace_size;
-	cxt->pmsg_size = pdata->pmsg_size;
 	cxt->dump_oops = pdata->dump_oops;
 	cxt->ecc_info = pdata->ecc_info;
+	cxt->num_pmsg = num_pmsg;
+	if (num_pmsg) {
+		cxt->pmsg_size = kcalloc(num_pmsg, sizeof(size_t), GFP_KERNEL);
+		if (!cxt->pmsg_size) {
+			err = -ENOMEM;
+			goto fail_out;
+		}
+		memcpy(cxt->pmsg_size, pdata->pmsg_size,
+		       sizeof(size_t) * num_pmsg);
+	}
 
 	paddr = cxt->phys_addr;
 
 	dump_mem_sz = cxt->size - cxt->console_size - cxt->ftrace_size
-			- cxt->pmsg_size;
+			- pmsg_size_total;
 	err = ramoops_init_dprzs(dev, cxt, &paddr, dump_mem_sz);
 	if (err)
-		goto fail_out;
+		goto fail_init_dprzs;
 
 	err = ramoops_init_prz(dev, cxt, &cxt->cprz, &paddr,
 			       cxt->console_size, 0);
@@ -523,11 +583,12 @@ static int ramoops_probe(struct platform_device *pdev)
 	if (err)
 		goto fail_init_fprz;
 
-	err = ramoops_init_prz(dev, cxt, &cxt->mprz, &paddr, cxt->pmsg_size, 0);
+	err = ramoops_init_mprzs(dev, cxt, &paddr, pmsg_size_total);
 	if (err)
-		goto fail_init_mprz;
+		goto fail_init_mprzs;
 
 	cxt->pstore.data = cxt;
+	cxt->pstore.num_pmsg = num_pmsg;
 	/*
 	 * Console can handle any buffer size, so prefer LOG_LINE_MAX. If we
 	 * have to handle dumps, we must have at least record_size buffer. And
@@ -560,7 +621,6 @@ static int ramoops_probe(struct platform_device *pdev)
 	record_size = pdata->record_size;
 	dump_oops = pdata->dump_oops;
 	ramoops_console_size = pdata->console_size;
-	ramoops_pmsg_size = pdata->pmsg_size;
 	ramoops_ftrace_size = pdata->ftrace_size;
 
 	pr_info("attached 0x%lx@0x%llx, ecc: %d/%d\n",
@@ -573,14 +633,16 @@ fail_buf:
 	kfree(cxt->pstore.buf);
 fail_clear:
 	cxt->pstore.bufsize = 0;
-	persistent_ram_free(cxt->mprz);
-fail_init_mprz:
+	ramoops_free_przs(cxt->mprzs);
+fail_init_mprzs:
 	persistent_ram_free(cxt->fprz);
 fail_init_fprz:
 	persistent_ram_free(cxt->cprz);
 fail_init_cprz:
 	cxt->max_dump_cnt = 0;
 	ramoops_free_przs(cxt->dprzs);
+fail_init_dprzs:
+	kfree(cxt->pmsg_size);
 fail_out:
 	return err;
 }
@@ -600,6 +662,7 @@ static int __exit ramoops_remove(struct platform_device *pdev)
 	/* TODO(kees): When pstore supports unregistering, call it here. */
 	kfree(cxt->pstore.buf);
 	cxt->pstore.bufsize = 0;
+	kfree(cxt->pmsg_size);
 
 	return 0;
 #endif
@@ -614,6 +677,38 @@ static struct platform_driver ramoops_driver = {
 	},
 };
 
+static unsigned long *parse_size_str(char *size_str)
+{
+	int i, ret;
+	unsigned long *size_array, count = 1;
+
+	if (size_str) {
+		char *s = size_str;
+		/* Necessary array size is the number of commas + 1 */
+		for (; (s = strchr(s, ',')); s++)
+			count++;
+	}
+
+	size_array = kcalloc(count + 1, sizeof(unsigned long), GFP_KERNEL);
+	if (!size_array)
+		goto out;
+
+	if (size_str) {
+		for (i = 0; i < count; i++) {
+			ret = get_option(&size_str, (int *)&size_array[i]);
+			if (ret == 1)
+				break;
+			else if (ret != 2) {
+				size_array[i] = 0;
+				break;
+			}
+		}
+	} else
+		size_array[0] = MIN_MEM_SIZE;
+out:
+	return size_array;
+}
+
 static void ramoops_register_dummy(void)
 {
 	if (!mem_size)
@@ -633,7 +728,9 @@ static void ramoops_register_dummy(void)
 	dummy_data->record_size = record_size;
 	dummy_data->console_size = ramoops_console_size;
 	dummy_data->ftrace_size = ramoops_ftrace_size;
-	dummy_data->pmsg_size = ramoops_pmsg_size;
+	dummy_data->pmsg_size = parse_size_str(ramoops_pmsg_size_str);
+	if (!dummy_data->pmsg_size)
+		goto fail_pmsg_size;
 	dummy_data->dump_oops = dump_oops;
 	/*
 	 * For backwards compatibility ramoops.ecc=1 means 16 bytes ECC
@@ -646,7 +743,13 @@ static void ramoops_register_dummy(void)
 	if (IS_ERR(dummy)) {
 		pr_info("could not create platform device: %ld\n",
 			PTR_ERR(dummy));
+		goto fail_pdev;
 	}
+	return;
+fail_pdev:
+	kfree(dummy_data->pmsg_size);
+fail_pmsg_size:
+	kfree(dummy_data);
 }
 
 static int __init ramoops_init(void)
@@ -660,6 +763,7 @@ static void __exit ramoops_exit(void)
 {
 	platform_driver_unregister(&ramoops_driver);
 	platform_device_unregister(dummy);
+	kfree(dummy_data->pmsg_size);
 	kfree(dummy_data);
 }
 module_exit(ramoops_exit);
diff --git a/include/linux/pstore_ram.h b/include/linux/pstore_ram.h
index 9c9d6c1..e808789 100644
--- a/include/linux/pstore_ram.h
+++ b/include/linux/pstore_ram.h
@@ -72,6 +72,12 @@ ssize_t persistent_ram_ecc_string(struct persistent_ram_zone *prz,
  * Ramoops platform data
  * @mem_size	memory size for ramoops
  * @mem_address	physical memory address to contain ramoops
+ * @pmsg_size	array containing size of each pmsg area. 0 value in the array
+ *		indicates the end of the content. For example, if the following
+ *		array is given,
+ *		    .pmsg_size = { 0x1000, 0x2000, 0x0, 0x3000, };
+ *		then, pmsg areas are allocated for the first two size values
+ *		and '0x3000' is just ignored.
  */
 
 struct ramoops_platform_data {
@@ -81,7 +87,7 @@ struct ramoops_platform_data {
 	unsigned long	record_size;
 	unsigned long	console_size;
 	unsigned long	ftrace_size;
-	unsigned long	pmsg_size;
+	unsigned long	*pmsg_size;
 	int		dump_oops;
 	struct persistent_ram_ecc_info ecc_info;
 };

--
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/

[toc] | [prev] | [next] | [standalone]


#1262840 — [PATCH 5/5] selftests/pstore: add testcases for multiple pmsg instances

FromHiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Date2015-11-05 03:40 +0100
Subject[PATCH 5/5] selftests/pstore: add testcases for multiple pmsg instances
Message-ID<qriD0-v7-21@gated-at.bofh.it>
In reply to#1262835
To test multiple pmsg, we should check that /dev/pmsg[N] (N > 0) is
available. After reboot, we should check that pmsg-[backend]-[N] which
keeps content is detected even if pmsg-[backend]-[N-M] (0 < M <= N)
doesn't exist due to lack of contents.

So we add the following testcases.
 - pstore_tests
   - Write unique string to the last /dev/pmsgN
 - pstore_post_reboot_tests
   - Check the last pmsg area is detected

Signed-off-by: Hiraku Toyooka <hiraku.toyooka.gu@hitachi.com>
Cc: Anton Vorontsov <anton@enomsg.org>
Cc: Colin Cross <ccross@android.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Mark Salyzyn <salyzyn@android.com>
Cc: Seiji Aguchi <seiji.aguchi.tr@hitachi.com>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: linux-api@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
 tools/testing/selftests/pstore/common_tests        |   21 ++++++++++++++--
 .../selftests/pstore/pstore_post_reboot_tests      |   27 +++++++++++---------
 tools/testing/selftests/pstore/pstore_tests        |   16 ++++++++++--
 3 files changed, 47 insertions(+), 17 deletions(-)

diff --git a/tools/testing/selftests/pstore/common_tests b/tools/testing/selftests/pstore/common_tests
index 3ea64d7..566a25d 100755
--- a/tools/testing/selftests/pstore/common_tests
+++ b/tools/testing/selftests/pstore/common_tests
@@ -27,9 +27,9 @@ show_result() { # result_value
 }
 
 check_files_exist() { # type of pstorefs file
-    if [ -e ${1}-${backend}-0 ]; then
+    if [ -e ${1}0 ]; then
 	prlog "ok"
-	for f in `ls ${1}-${backend}-*`; do
+	for f in `ls ${1}*`; do
             prlog -e "\t${f}"
 	done
     else
@@ -53,6 +53,23 @@ operate_files() { # tested value, files, operation
     fi
 }
 
+check_pmsg_content() { # pmsg filename
+    prev_uuid=`cat $TOP_DIR/prev_uuid`
+    if [ $? -eq 0 ]; then
+	nr_matched=`grep -c "$TEST_STRING_PATTERN" $1`
+	if [ "$nr_matched" = "1" ]; then
+	    grep -q "$TEST_STRING_PATTERN"$prev_uuid $1
+	    show_result $?
+	else
+	    prlog "FAIL"
+	    rc=1
+	fi
+    else
+	prlog "FAIL"
+	rc=1
+    fi
+}
+
 # Parameters
 TEST_STRING_PATTERN="Testing pstore: uuid="
 UUID=`cat /proc/sys/kernel/random/uuid`
diff --git a/tools/testing/selftests/pstore/pstore_post_reboot_tests b/tools/testing/selftests/pstore/pstore_post_reboot_tests
index 6ccb154..272498f 100755
--- a/tools/testing/selftests/pstore/pstore_post_reboot_tests
+++ b/tools/testing/selftests/pstore/pstore_post_reboot_tests
@@ -35,13 +35,13 @@ fi
 cd ${mount_point}
 
 prlog -n "Checking dmesg files exist in pstore filesystem ... "
-check_files_exist dmesg
+check_files_exist dmesg-${backend}-
 
 prlog -n "Checking console files exist in pstore filesystem ... "
-check_files_exist console
+check_files_exist console-${backend}-
 
 prlog -n "Checking pmsg files exist in pstore filesystem ... "
-check_files_exist pmsg
+check_files_exist pmsg-${backend}-
 
 prlog -n "Checking dmesg files contain oops end marker"
 grep_end_trace() {
@@ -54,16 +54,19 @@ prlog -n "Checking console file contains oops end marker ... "
 grep -q "\---\[ end trace" console-${backend}-0
 show_result $?
 
-prlog -n "Checking pmsg file properly keeps the content written before crash ... "
-prev_uuid=`cat $TOP_DIR/prev_uuid`
-if [ $? -eq 0 ]; then
-    nr_matched=`grep -c "$TEST_STRING_PATTERN" pmsg-${backend}-0`
-    if [ $nr_matched -eq 1 ]; then
-	grep -q "$TEST_STRING_PATTERN"$prev_uuid pmsg-${backend}-0
-	show_result $?
+prlog -n "Checking pmsg-"${backend}"-0 properly keeps the content written before crash ... "
+check_pmsg_content pmsg-${backend}-0
+
+prlog -n "Checking the last pmsg area is detected "
+last_num_pmsg=`ls -v pmsg-* | tail -n1 | sed -e "s/^pmsg-${backend}-\([0-9]*\).*$/\1/"`
+last_num_devpmsg=`ls -v /dev/pmsg* | tail -n1 | sed -e "s/^\/dev\/pmsg\([0-9]*\).*$/\1/"`
+#checks the last number of pmsg-*-* and /dev/pmsg* correspond.
+if [ "$last_num_pmsg" -eq "$last_num_devpmsg" ]; then
+    if [ "$last_num_pmsg" = "0" ]; then
+	prlog "... No multiple pmsg-*-* exists. We skip this testcase."
     else
-	prlog "FAIL"
-	rc=1
+	prlog -n "(pmsg-${backend}-${last_num_pmsg}) ... "
+	check_pmsg_content pmsg-${backend}-${last_num_pmsg}
     fi
 else
     prlog "FAIL"
diff --git a/tools/testing/selftests/pstore/pstore_tests b/tools/testing/selftests/pstore/pstore_tests
index f25d2a3..5abf0e5 100755
--- a/tools/testing/selftests/pstore/pstore_tests
+++ b/tools/testing/selftests/pstore/pstore_tests
@@ -13,9 +13,8 @@ prlog -n "Checking pstore console is registered ... "
 dmesg | grep -q "console \[pstore"
 show_result $?
 
-prlog -n "Checking /dev/pmsg0 exists ... "
-test -e /dev/pmsg0
-show_result $?
+prlog -n "Checking /dev/pmsg files exist ... "
+check_files_exist /dev/pmsg
 
 prlog -n "Writing unique string to /dev/pmsg0 ... "
 if [ -e "/dev/pmsg0" ]; then
@@ -27,4 +26,15 @@ else
     rc=1
 fi
 
+last_devpmsg=`ls -v /dev/pmsg* | tail -n1`
+prlog -n "Writing unique string to the last /dev/pmsgN "
+if [ "$last_devpmsg" = "/dev/pmsg0" ]; then
+    prlog "... No multiple /dev/pmsg* exists. We skip this testcase."
+else
+    prlog -n "(${last_devpmsg}) ... "
+    echo "${TEST_STRING_PATTERN}""$UUID" > ${last_devpmsg}
+    show_result $?
+
+fi
+
 exit $rc

--
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/

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web