diff mbox

[v5,3/4] ubi-utils: ubidump: introduce ubidump

Message ID 54478A47.3080102@huawei.com
State Changes Requested
Headers show

Commit Message

hujianyang Oct. 22, 2014, 10:43 a.m. UTC
This patch introude a new utility named ubidump. This utiltiy can dump
a specific leb to userspace(maybe a arrange of lebs in the future).

We don't have an useful tool to get data from a specified logical erase
block and to describe what it contains in userspace before. I suppose
if this utility could help us overcome these problems and give us a new
way to analyse the behaviour of UBI/UBIFS without changing kernel.

Artem (dedekind1@gmail.com) and Bill (bpringlemeir@nbsps.com) also
contribute a lot to this utility. I appreciate their help very much.

Only the UBIFS level dumping is supported now, we've discussed and tried
many ways to realize UBI level dumping but didn't reach an agreement.
I'll keep working on it.

I think this work is just the beginning of enriching UBI/UBIFS debugging.

Changes in v5:
	- fix copyright of ubifs-media.h
	
v1:
http://lists.infradead.org/pipermail/linux-mtd/2014-July/054541.html

v2:
http://lists.infradead.org/pipermail/linux-mtd/2014-July/054831.html

v3:
http://lists.infradead.org/pipermail/linux-mtd/2014-September/055463.html

v4:
http://lists.infradead.org/pipermail/linux-mtd/2014-September/055644.html


Signed-off-by: hujianyang <hujianyang@huawei.com>
---
 ubi-utils/ubidump.c |  223 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 223 insertions(+), 0 deletions(-)
 create mode 100644 ubi-utils/ubidump.c

Comments

Artem Bityutskiy Oct. 30, 2014, 8:19 a.m. UTC | #1
On Wed, 2014-10-22 at 18:43 +0800, hujianyang wrote:
> +static const char optionsstr[] =
> +"-h, --help            print help message\n"
> +"-l, --lnum            logic eraseblock num to dump\n"
> +"-i, --info            show explicit information about ubifs-level\n"

So what does this '-i' option do? I cannot grasp this from the comment.
Artem Bityutskiy Oct. 30, 2014, 8:30 a.m. UTC | #2
On Thu, 2014-10-30 at 10:19 +0200, Artem Bityutskiy wrote:
> On Wed, 2014-10-22 at 18:43 +0800, hujianyang wrote:
> > +static const char optionsstr[] =
> > +"-h, --help            print help message\n"
> > +"-l, --lnum            logic eraseblock num to dump\n"
> > +"-i, --info            show explicit information about ubifs-level\n"
> 
> So what does this '-i' option do? I cannot grasp this from the comment.

Ok, I think I see what you mean here. This is about dumping UBIFS data
in addition to the UBI data.

First of all, let's re-phrase this. Do not use word "explicit", it does
not seem to bear any useful meaning here. Just say "also dump UBIFS
nodes" or something like this.

And "-i" / "--info" are not the best names, I think. "-u" / "--ubifs"
would be better.

And regarding the -l option. What if I do not specify it? What will be
dumped? Everything? Nothing? I'd vote for duping everything (all LEBs).

Artem.
hujianyang Oct. 31, 2014, 2:17 a.m. UTC | #3
> 
> And "-i" / "--info" are not the best names, I think. "-u" / "--ubifs"
> would be better.
> 

Oh, I'd like to reserve this "--ubifs" when we are ready to dump ubi-level
stuff. So in my previous design, "--ubifs" and "--ubi" are used to indicate
only dump the specific area of an eraseblock.

How about an option like "--node" ? Do you insist on "--ubifs" or have
another suggestion?

> And regarding the -l option. What if I do not specify it? What will be
> dumped? Everything? Nothing? I'd vote for duping everything (all LEBs).
> 

It will return an error now, like:

"lnum was not specified (use -h for help)"

Dumping everything is useful and easy to achieve. I will do that~!
Artem Bityutskiy Oct. 31, 2014, 7:32 a.m. UTC | #4
On Fri, 2014-10-31 at 10:17 +0800, hujianyang wrote:
> > 
> > And "-i" / "--info" are not the best names, I think. "-u" / "--ubifs"
> > would be better.
> > 
> 
> Oh, I'd like to reserve this "--ubifs" when we are ready to dump ubi-level
> stuff. So in my previous design, "--ubifs" and "--ubi" are used to indicate
> only dump the specific area of an eraseblock.
> 
> How about an option like "--node" ? Do you insist on "--ubifs" or have
> another suggestion?

The idea is that you introduce an option, and then you do not change
it's name. So the name should be informative. What is more informative
for "also dump ubifs nodes": --node or --ubifs ?

You can always add --ubi later.

For now, if --ubifs is not specified, you should do basically nothing,
because you cannot dump UBI right now.

Does this make sense for you?

Artem.
hujianyang Oct. 31, 2014, 10:55 a.m. UTC | #5
On 2014/10/31 15:32, Artem Bityutskiy wrote:
> On Fri, 2014-10-31 at 10:17 +0800, hujianyang wrote:
>>>
>>> And "-i" / "--info" are not the best names, I think. "-u" / "--ubifs"
>>> would be better.
>>>
>>
>> Oh, I'd like to reserve this "--ubifs" when we are ready to dump ubi-level
>> stuff. So in my previous design, "--ubifs" and "--ubi" are used to indicate
>> only dump the specific area of an eraseblock.
>>
>> How about an option like "--node" ? Do you insist on "--ubifs" or have
>> another suggestion?
> 
> The idea is that you introduce an option, and then you do not change
> it's name. So the name should be informative. What is more informative
> for "also dump ubifs nodes": --node or --ubifs ?
> 
> You can always add --ubi later.
> 
> For now, if --ubifs is not specified, you should do basically nothing,
> because you cannot dump UBI right now.
> 
> Does this make sense for you?
> 
> Artem.
> 
> 
> 

I should say it is unfair for me to discuss a problem like this with
you. I will follow your idea because I not good at English.

Give me some days, I will resend this patch set. I'm happy to see the
patch set is thinner than it used to be. Thanks for your help.

Happy Halloween:)

Hu
Artem Bityutskiy Oct. 31, 2014, 1:20 p.m. UTC | #6
On Fri, 2014-10-31 at 18:55 +0800, hujianyang wrote:
> I should say it is unfair for me to discuss a problem like this with
> you. I will follow your idea because I not good at English.
> 
> Give me some days, I will resend this patch set. I'm happy to see the
> patch set is thinner than it used to be. Thanks for your help.

Well, nothing unfair. I might be missing your point. All I want is to
understand what will the options be, what will they mean. If you cannot
come up with a short and concise description for the options, explain
them in a long way in the e-mail, I'll help with the concise version.
And you do not have t agree with me, I am just asking question so at
this point. Do not worry about your English skills too much.
hujianyang Nov. 20, 2014, 9:24 a.m. UTC | #7
On 2014/10/31 21:20, Artem Bityutskiy wrote:
> On Fri, 2014-10-31 at 18:55 +0800, hujianyang wrote:
>> I should say it is unfair for me to discuss a problem like this with
>> you. I will follow your idea because I not good at English.
>>
>> Give me some days, I will resend this patch set. I'm happy to see the
>> patch set is thinner than it used to be. Thanks for your help.
> 
> Well, nothing unfair. I might be missing your point. All I want is to
> understand what will the options be, what will they mean. If you cannot
> come up with a short and concise description for the options, explain
> them in a long way in the e-mail, I'll help with the concise version.
> And you do not have t agree with me, I am just asking question so at
> this point. Do not worry about your English skills too much.
> 
> 
> 

Artem,

Sorry, I'm busy with other stuff these days so I have to leave *ubidump*
behind. I'd like to introduce this option to you and wish you could help
me come up with a suitable name.


This dump tool can print NODEs type only, like this:

/tmp# ./ubidump /dev/ubi0_0 --lnum 0
scan LEB 0:0
look at LEB 0:0 (126976 bytes left)
scanning superblock node at LEB 0:0
look at LEB 0:4096 (122880 bytes left)
hit empty space at LEB 0:4096
stop scanning LEB 0 at offset 126976

/tmp# ./ubidump /dev/ubi0_0 --lnum 1
scan LEB 1:0
look at LEB 1:0 (126976 bytes left)
scanning master node at LEB 1:0
look at LEB 1:512 (126464 bytes left)
scanning padding node at LEB 1:512
1508 bytes padded at LEB 1:512, offset now 2048
look at LEB 1:2048 (124928 bytes left)
scanning master node at LEB 1:2048
look at LEB 1:2560 (124416 bytes left)
scanning padding node at LEB 1:2560
1508 bytes padded at LEB 1:2560, offset now 4096
look at LEB 1:4096 (122880 bytes left)
scanning master node at LEB 1:4096
look at LEB 1:4608 (122368 bytes left)
scanning padding node at LEB 1:4608
1508 bytes padded at LEB 1:4608, offset now 6144
look at LEB 1:6144 (120832 bytes left)
scanning master node at LEB 1:6144
look at LEB 1:6656 (120320 bytes left)
scanning padding node at LEB 1:6656
1508 bytes padded at LEB 1:6656, offset now 8192
look at LEB 1:8192 (118784 bytes left)
hit empty space at LEB 1:8192
stop scanning LEB 1 at offset 126976


But it can do more, print data in NODEs with an additional option:

/tmp# ./ubidump /dev/ubi0_0 --lnum 0 --info(--ubifs As you suggested)
scan LEB 0:0
look at LEB 0:0 (126976 bytes left)
scanning superblock node at LEB 0:0
	magic          0x6101831
	crc            0x1144bca
	node_type      6 (superblock node)
	group_type     0 (no node group)
	sqnum          1
	len            4096
	key_hash       0 (R5)
	key_fmt        0 (simple)
	flags          0
	big_lpt        0
	space_fixup    0
	min_io_size    2048
	leb_size       126976
	leb_cnt        940
	max_leb_cnt    940
	max_bud_bytes  5459968
	log_lebs       4
	lpt_lebs       2
	orph_lebs      2
	jhead_cnt      1
	fanout         8
	lsave_cnt      256
	default_compr  1
	rp_size        5242880
	rp_uid         0
	rp_gid         0
	fmt_version    4
	time_gran      1000000000
	UUID           0x175248cUB
look at LEB 0:4096 (122880 bytes left)
hit empty space at LEB 0:4096
stop scanning LEB 0 at offset 126976


Do you have a good idea about how we call this option?


By the way, I've replied the mail

"UBIFS assert failed in ubifs_set_page_dirty at 1421"

reported by jijiagang@hisilicon.com but mm people do not response.

http://lists.infradead.org/pipermail/linux-mtd/2014-November/056378.html

I will change some mm code and test if it works, do you have any
suggestions about this?


Thanks~!

Hu
Artem Bityutskiy Nov. 27, 2014, 2:32 p.m. UTC | #8
On Thu, 2014-11-20 at 17:24 +0800, hujianyang wrote:
> /tmp# ./ubidump /dev/ubi0_0 --lnum 0
> scan LEB 0:0
> look at LEB 0:0 (126976 bytes left)
> scanning superblock node at LEB 0:0
> look at LEB 0:4096 (122880 bytes left)
> hit empty space at LEB 0:4096
> stop scanning LEB 0 at offset 126976

Just do not introduce any options at all. Print all you can right away.

Let's say: no options means auto-detect everything and print everything.
Since all you can do right now is to dump UBIFS stuff, just do it.

If someone needs more - they will have to start adding options.

> By the way, I've replied the mail
> 
> "UBIFS assert failed in ubifs_set_page_dirty at 1421"
> 
> reported by jijiagang@hisilicon.com but mm people do not response.
> 
> http://lists.infradead.org/pipermail/linux-mtd/2014-November/056378.html
> 
> I will change some mm code and test if it works, do you have any
> suggestions about this?

It looks like mm people are not going to help.. I do not have time to
debug this. You can try implementing the merge handler, or debug this
further.
hujianyang Dec. 1, 2014, 1:45 a.m. UTC | #9
On 2014/11/27 22:32, Artem Bityutskiy wrote:
> On Thu, 2014-11-20 at 17:24 +0800, hujianyang wrote:
>> /tmp# ./ubidump /dev/ubi0_0 --lnum 0
>> scan LEB 0:0
>> look at LEB 0:0 (126976 bytes left)
>> scanning superblock node at LEB 0:0
>> look at LEB 0:4096 (122880 bytes left)
>> hit empty space at LEB 0:4096
>> stop scanning LEB 0 at offset 126976
> 
> Just do not introduce any options at all. Print all you can right away.
> 
> Let's say: no options means auto-detect everything and print everything.
> Since all you can do right now is to dump UBIFS stuff, just do it.
> 
> If someone needs more - they will have to start adding options.
> 

Got it~!
diff mbox

Patch

diff --git a/ubi-utils/ubidump.c b/ubi-utils/ubidump.c
new file mode 100644
index 0000000..40834dd
--- /dev/null
+++ b/ubi-utils/ubidump.c
@@ -0,0 +1,223 @@ 
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
+ * the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to dump UBI/UBIFS format data in eraseblock
+ *
+ * Author: Hu Jianyang <hujianyang@huawei.com>
+ */
+
+#define PROGRAM_NAME	"ubidump"
+
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+
+#include <libubi.h>
+#include <libdump.h>
+#include <libmtd.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	const char *vol;
+	int lnum;
+	int info:1;
+};
+
+static struct args args =
+{
+	.vol	= NULL,
+	.lnum	= -1,
+	.info	= 0,
+};
+
+static const char doc[] = PROGRAM_NAME " version " VERSION
+		" - an utility to dump UBI/UBIFS format data in eraseblock";
+
+static const char optionsstr[] =
+"-h, --help		print help message\n"
+"-l, --lnum		logic eraseblock num to dump\n"
+"-i, --info		show explicit information about ubifs-level\n"
+"-V, --version		print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI volume node file name> [-l <lnum>] [-i]\n"
+"\t\t\t[--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi0_1 --lnum 2 - dump leb 2 in volume 1\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi0_0 -l 1234 -i - dump leb 1234 with explicit info\n";
+
+static const struct option long_options[] = {
+	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "lnum",    .has_arg = 1, .flag = NULL, .val = 'l' },
+	{ .name = "info",    .has_arg = 0, .flag = NULL, .val = 'i' },
+	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0}
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "h?il:", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'l':
+			args.lnum = simple_strtoul(optarg, &error);
+			if (error || args.lnum < 0)
+				return errmsg("bad lnum: \"%s\"", optarg);
+			break;
+
+		case 'i':
+			args.info = 1;
+			break;
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			common_print_version();
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+	if (optind == argc)
+		return errmsg("UBI device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI device specified (use -h for help)");
+
+	args.vol = argv[optind];
+
+	if (args.lnum < 0)
+		return errmsg("lnum was not specified (use -h for help)");
+
+	return 0;
+}
+
+static int dump_eraseblock(int fd, struct ubi_vol_info *vol_info)
+{
+	int ret, leb_size, lnum;
+	off_t offs;
+	char *buf;
+
+	leb_size = vol_info->leb_size;
+	lnum = args.lnum;
+
+	ret = ubi_is_mapped(fd, lnum);
+	if (ret == 0) {
+		errmsg("lnum %d is not mapped", lnum);
+		goto out;
+	} else if (ret < 0) {
+		sys_errmsg("ubi_is_mapped() failed");
+		goto out;
+	}
+
+	buf = malloc(leb_size);
+	if (!buf)
+		return errmsg("cannot allocate %d bytes of memory",
+			      leb_size);
+	offs = lnum * leb_size;
+
+	ret = pread(fd, buf, leb_size, offs);
+	if (ret != leb_size) {
+		errmsg("cannot read %d bytes at lnum %d, read %d",
+		       leb_size, lnum, ret);
+		goto out_free;
+	}
+
+	ret = ubi_dump(lnum, buf, leb_size, args.info);
+
+out_free:
+	free(buf);
+out:
+	return ret;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err, fd;
+	libubi_t libubi;
+	struct ubi_vol_info vol_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			errmsg("UBI is not present in the system");
+		else
+			sys_errmsg("cannot open libubi");
+		goto out_libubi;
+	}
+
+	err = ubi_probe_node(libubi, args.vol);
+	if (err == 1) {
+		errmsg("\"%s\" is an UBI device node, not an UBI volume node",
+		       args.vol);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI volume node", args.vol);
+		else
+			sys_errmsg("error while probing \"%s\"", args.vol);
+		goto out_libubi;
+	}
+
+	err = ubi_get_vol_info(libubi, args.vol, &vol_info);
+	if (err) {
+		sys_errmsg("cannot get information about UBI volume \"%s\"",
+			   args.vol);
+		goto out_libubi;
+	}
+
+	fd = open(args.vol, O_RDONLY);
+	if (fd == -1) {
+		sys_errmsg("cannot open UBI volume \"%s\"", args.vol);
+		goto out_libubi;
+	}
+
+	err = dump_eraseblock(fd, &vol_info);
+	if (err)
+		goto out_fd;
+
+	close(fd);
+	libubi_close(libubi);
+	return 0;
+
+out_fd:
+	close(fd);
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}