mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] UBI: add debugfs file for tracking PEB state
@ 2016-09-19 18:47 Zach Brown
  2016-09-19 19:03 ` Richard Weinberger
  2016-09-19 19:42 ` kbuild test robot
  0 siblings, 2 replies; 4+ messages in thread
From: Zach Brown @ 2016-09-19 18:47 UTC (permalink / raw)
  To: dwmw2; +Cc: computersforpeace, dedekind1, richard, linux-mtd, linux-kernel

From: Ben Shelton <ben.shelton@ni.com>

Add a file under debugfs to allow easy access to the erase count for
each physical erase block on an UBI device.  This is useful when
debugging data integrity issues with UBIFS on NAND flash devices.

Signed-off-by: Ben Shelton <ben.shelton@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
---
 drivers/mtd/ubi/debug.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 150 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index f101a49..09eaab6 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/module.h>
+#include <linux/seq_file.h>
 
 
 /**
@@ -386,7 +387,9 @@ out:
 	return count;
 }
 
-/* File operations for all UBI debugfs files */
+/* File operations for all UBI debugfs files except
+ * detailed_erase_block_info
+ */
 static const struct file_operations dfs_fops = {
 	.read   = dfs_file_read,
 	.write  = dfs_file_write,
@@ -395,6 +398,146 @@ static const struct file_operations dfs_fops = {
 	.owner  = THIS_MODULE,
 };
 
+/* As long as the position is less then that total number of erase blocks,
+ * we still have more to print.
+ */
+static void *eraseblk_count_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct ubi_device *ubi = s->private;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	if (*pos < ubi->peb_count)
+		return pos;
+
+	return NULL;
+}
+
+/* Since we are using the position as the iterator, we just need to check if we
+ * are done and increment the position.
+ */
+static void *eraseblk_count_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct ubi_device *ubi = s->private;
+
+	if (v == SEQ_START_TOKEN)
+		return pos;
+	(*pos)++;
+
+	if (*pos < ubi->peb_count)
+		return pos;
+
+	return NULL;
+}
+
+static void eraseblk_count_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+enum block_status {
+	BLOCK_STATUS_OK,
+	BLOCK_STATUS_BAD_BLOCK,
+	BLOCK_STATUS_ERASE_COUNT_BEYOND_MAX
+};
+
+static char const *block_status_names[] = {"OK", "marked_bad",
+					   "erase_count_beyond_max"};
+
+enum read_status {
+	READ_STATUS_OK,
+	READ_STATUS_ERR_READING_BLOCK,
+	READ_STATUS_ERR_READING_ERASE_COUNT
+};
+
+static char const *read_status_names[] = {"OK", "err_reading_block",
+					  "err_reading_erase_count"};
+
+static int eraseblk_count_seq_show(struct seq_file *s, void *iter)
+{
+	struct ubi_device *ubi = s->private;
+	int *block_number = iter;
+	int erase_count = -1;
+	enum block_status b_sts = BLOCK_STATUS_OK;
+	enum read_status r_sts = READ_STATUS_OK;
+	int err;
+
+	/* If this is the start, print a header */
+	if (iter == SEQ_START_TOKEN) {
+		seq_puts(s,
+			 "physical_block_number\terase_count\tblock_status\tread_status\n");
+		return 0;
+	}
+
+	err = ubi_io_is_bad(ubi, *block_number);
+	if (err) {
+		if (err < 0)
+			r_sts = READ_STATUS_ERR_READING_BLOCK;
+		else
+			b_sts = BLOCK_STATUS_BAD_BLOCK;
+	} else {
+		struct ubi_ec_hdr erase_count_header;
+
+		err = ubi_io_read_ec_hdr(ubi, *block_number,
+					 &erase_count_header, 0);
+		if (err && err != UBI_IO_BITFLIPS)
+			r_sts = READ_STATUS_ERR_READING_ERASE_COUNT;
+		else {
+			erase_count = be64_to_cpu(erase_count_header.ec);
+			if (erase_count > UBI_MAX_ERASECOUNTER)
+				b_sts = BLOCK_STATUS_ERASE_COUNT_BEYOND_MAX;
+		}
+	}
+
+	seq_printf(s, "%-22d\t%-11d\t%-12s\t%-12s\n", *block_number,
+		   erase_count, block_status_names[b_sts],
+		   read_status_names[r_sts]);
+	return 0;
+}
+
+static const struct seq_operations eraseblk_count_seq_ops = {
+	.start = eraseblk_count_seq_start,
+	.next = eraseblk_count_seq_next,
+	.stop = eraseblk_count_seq_stop,
+	.show = eraseblk_count_seq_show
+};
+
+static int eraseblk_count_open(struct inode *inode, struct file *f)
+{
+	struct seq_file *s;
+	int err;
+
+	err = seq_open(f, &eraseblk_count_seq_ops);
+	if (err)
+		return err;
+
+	s = f->private_data;
+	s->private = ubi_get_device((int)inode->i_private);
+
+	if (!s->private)
+		return -ENODEV;
+	else
+		return 0;
+}
+
+static int eraseblk_count_release(struct inode *inode, struct file *f)
+{
+	struct seq_file *s = f->private_data;
+	struct ubi_device *ubi = s->private;
+
+	ubi_put_device(ubi);
+
+	return seq_release(inode, f);
+}
+
+static const struct file_operations eraseblk_count_fops = {
+	.owner = THIS_MODULE,
+	.open = eraseblk_count_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = eraseblk_count_release,
+};
+
 /**
  * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
  * @ubi: UBI device description object
@@ -491,6 +634,12 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
 		goto out_remove;
 	d->dfs_power_cut_max = dent;
 
+	fname = "detailed_erase_block_info";
+	dent = debugfs_create_file(fname, S_IRUSR, d->dfs_dir, (void *)ubi_num,
+				   &eraseblk_count_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+
 	return 0;
 
 out_remove:
-- 
2.7.4

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

* Re: [PATCH] UBI: add debugfs file for tracking PEB state
  2016-09-19 18:47 [PATCH] UBI: add debugfs file for tracking PEB state Zach Brown
@ 2016-09-19 19:03 ` Richard Weinberger
  2016-09-19 19:42 ` kbuild test robot
  1 sibling, 0 replies; 4+ messages in thread
From: Richard Weinberger @ 2016-09-19 19:03 UTC (permalink / raw)
  To: Zach Brown, dwmw2; +Cc: computersforpeace, dedekind1, linux-mtd, linux-kernel

Zach,

On 19.09.2016 20:47, Zach Brown wrote:
> +	} else {
> +		struct ubi_ec_hdr erase_count_header;
> +
> +		err = ubi_io_read_ec_hdr(ubi, *block_number,
> +					 &erase_count_header, 0);
> +		if (err && err != UBI_IO_BITFLIPS)
> +			r_sts = READ_STATUS_ERR_READING_ERASE_COUNT;
> +		else {
> +			erase_count = be64_to_cpu(erase_count_header.ec);
> +			if (erase_count > UBI_MAX_ERASECOUNTER)
> +				b_sts = BLOCK_STATUS_ERASE_COUNT_BEYOND_MAX;

Hmm, why don't you use ubi->lookuptbl[] to get a ubi_wl_entry object, it knows
the erase counter. That way you don't have to read from the flash. If you read
you have to deal with all kind of read errors, including bitflips.

Thanks,
//richard

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

* Re: [PATCH] UBI: add debugfs file for tracking PEB state
  2016-09-19 18:47 [PATCH] UBI: add debugfs file for tracking PEB state Zach Brown
  2016-09-19 19:03 ` Richard Weinberger
@ 2016-09-19 19:42 ` kbuild test robot
  1 sibling, 0 replies; 4+ messages in thread
From: kbuild test robot @ 2016-09-19 19:42 UTC (permalink / raw)
  To: Zach Brown
  Cc: kbuild-all, dwmw2, computersforpeace, dedekind1, richard,
	linux-mtd, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2003 bytes --]

Hi Ben,

[auto build test WARNING on mtd/master]
[also build test WARNING on v4.8-rc7 next-20160919]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
[Suggest to use git(>=2.9.0) format-patch --base=<commit> (or --base=auto for convenience) to record what (public, well-known) commit your patch series was built on]
[Check https://git-scm.com/docs/git-format-patch for more information]

url:    https://github.com/0day-ci/linux/commits/Zach-Brown/UBI-add-debugfs-file-for-tracking-PEB-state/20160920-025147
base:   git://git.infradead.org/linux-mtd.git master
config: x86_64-randconfig-i0-201638 (attached as .config)
compiler: gcc-4.9 (Debian 4.9.4-2) 4.9.4
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All warnings (new ones prefixed by >>):

   drivers/mtd/ubi/debug.c: In function 'eraseblk_count_open':
>> drivers/mtd/ubi/debug.c:515:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
     s->private = ubi_get_device((int)inode->i_private);
                                 ^

vim +515 drivers/mtd/ubi/debug.c

   499		.start = eraseblk_count_seq_start,
   500		.next = eraseblk_count_seq_next,
   501		.stop = eraseblk_count_seq_stop,
   502		.show = eraseblk_count_seq_show
   503	};
   504	
   505	static int eraseblk_count_open(struct inode *inode, struct file *f)
   506	{
   507		struct seq_file *s;
   508		int err;
   509	
   510		err = seq_open(f, &eraseblk_count_seq_ops);
   511		if (err)
   512			return err;
   513	
   514		s = f->private_data;
 > 515		s->private = ubi_get_device((int)inode->i_private);
   516	
   517		if (!s->private)
   518			return -ENODEV;
   519		else
   520			return 0;
   521	}
   522	
   523	static int eraseblk_count_release(struct inode *inode, struct file *f)

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 22511 bytes --]

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

* [PATCH] UBI: add debugfs file for tracking PEB state
@ 2016-10-17 15:57 Zach Brown
  0 siblings, 0 replies; 4+ messages in thread
From: Zach Brown @ 2016-10-17 15:57 UTC (permalink / raw)
  To: dwmw2; +Cc: computersforpeace, dedekind1, richard, linux-mtd, linux-kernel

From: Ben Shelton <ben.shelton@ni.com>

Add a file under debugfs to allow easy access to the erase count for
each physical erase block on an UBI device.  This is useful when
debugging data integrity issues with UBIFS on NAND flash devices.

Signed-off-by: Ben Shelton <ben.shelton@ni.com>
Signed-off-by: Zach Brown <zach.brown@ni.com>
---
 drivers/mtd/ubi/debug.c | 151 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 150 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index f101a49..6086822 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/module.h>
+#include <linux/seq_file.h>
 
 
 /**
@@ -386,7 +387,9 @@ out:
 	return count;
 }
 
-/* File operations for all UBI debugfs files */
+/* File operations for all UBI debugfs files except
+ * detailed_erase_block_info
+ */
 static const struct file_operations dfs_fops = {
 	.read   = dfs_file_read,
 	.write  = dfs_file_write,
@@ -395,6 +398,146 @@ static const struct file_operations dfs_fops = {
 	.owner  = THIS_MODULE,
 };
 
+/* As long as the position is less then that total number of erase blocks,
+ * we still have more to print.
+ */
+static void *eraseblk_count_seq_start(struct seq_file *s, loff_t *pos)
+{
+	struct ubi_device *ubi = s->private;
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	if (*pos < ubi->peb_count)
+		return pos;
+
+	return NULL;
+}
+
+/* Since we are using the position as the iterator, we just need to check if we
+ * are done and increment the position.
+ */
+static void *eraseblk_count_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+	struct ubi_device *ubi = s->private;
+
+	if (v == SEQ_START_TOKEN)
+		return pos;
+	(*pos)++;
+
+	if (*pos < ubi->peb_count)
+		return pos;
+
+	return NULL;
+}
+
+static void eraseblk_count_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+enum block_status {
+	BLOCK_STATUS_OK,
+	BLOCK_STATUS_BAD_BLOCK,
+	BLOCK_STATUS_ERASE_COUNT_BEYOND_MAX
+};
+
+static char const *block_status_names[] = {"OK", "marked_bad",
+					   "erase_count_beyond_max"};
+
+enum read_status {
+	READ_STATUS_OK,
+	READ_STATUS_ERR_READING_BLOCK,
+};
+
+static char const *read_status_names[] = {"OK", "err_reading_block"};
+
+static int eraseblk_count_seq_show(struct seq_file *s, void *iter)
+{
+	struct ubi_device *ubi = s->private;
+	struct ubi_wl_entry *wl;
+	int *block_number = iter;
+	int erase_count = -1;
+	enum block_status b_sts = BLOCK_STATUS_OK;
+	enum read_status r_sts = READ_STATUS_OK;
+	int err;
+
+	/* If this is the start, print a header */
+	if (iter == SEQ_START_TOKEN) {
+		seq_puts(s,
+			 "physical_block_number\terase_count\tblock_status\tread_status\n");
+		return 0;
+	}
+
+	err = ubi_io_is_bad(ubi, *block_number);
+	if (err) {
+		if (err < 0)
+			r_sts = READ_STATUS_ERR_READING_BLOCK;
+		else
+			b_sts = BLOCK_STATUS_BAD_BLOCK;
+	} else {
+		spin_lock(&ubi->wl_lock);
+
+		wl = ubi->lookuptbl[*block_number];
+		if (wl)
+			erase_count = wl->ec;
+		else
+			r_sts = READ_STATUS_ERR_READING_BLOCK;
+
+		spin_unlock(&ubi->wl_lock);
+
+		if (erase_count > UBI_MAX_ERASECOUNTER)
+			b_sts = BLOCK_STATUS_ERASE_COUNT_BEYOND_MAX;
+	}
+
+	seq_printf(s, "%-22d\t%-11d\t%-12s\t%-12s\n", *block_number,
+		   erase_count, block_status_names[b_sts],
+		   read_status_names[r_sts]);
+	return 0;
+}
+
+static const struct seq_operations eraseblk_count_seq_ops = {
+	.start = eraseblk_count_seq_start,
+	.next = eraseblk_count_seq_next,
+	.stop = eraseblk_count_seq_stop,
+	.show = eraseblk_count_seq_show
+};
+
+static int eraseblk_count_open(struct inode *inode, struct file *f)
+{
+	struct seq_file *s;
+	int err;
+
+	err = seq_open(f, &eraseblk_count_seq_ops);
+	if (err)
+		return err;
+
+	s = f->private_data;
+	s->private = ubi_get_device((unsigned long)inode->i_private);
+
+	if (!s->private)
+		return -ENODEV;
+	else
+		return 0;
+}
+
+static int eraseblk_count_release(struct inode *inode, struct file *f)
+{
+	struct seq_file *s = f->private_data;
+	struct ubi_device *ubi = s->private;
+
+	ubi_put_device(ubi);
+
+	return seq_release(inode, f);
+}
+
+static const struct file_operations eraseblk_count_fops = {
+	.owner = THIS_MODULE,
+	.open = eraseblk_count_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = eraseblk_count_release,
+};
+
 /**
  * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
  * @ubi: UBI device description object
@@ -491,6 +634,12 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
 		goto out_remove;
 	d->dfs_power_cut_max = dent;
 
+	fname = "detailed_erase_block_info";
+	dent = debugfs_create_file(fname, S_IRUSR, d->dfs_dir, (void *)ubi_num,
+				   &eraseblk_count_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+
 	return 0;
 
 out_remove:
-- 
2.7.4

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

end of thread, other threads:[~2016-10-17 15:58 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-19 18:47 [PATCH] UBI: add debugfs file for tracking PEB state Zach Brown
2016-09-19 19:03 ` Richard Weinberger
2016-09-19 19:42 ` kbuild test robot
2016-10-17 15:57 Zach Brown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®