* [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
@ 2014-04-10 14:43 Ezequiel Garcia
2014-04-14 10:42 ` Artem Bityutskiy
0 siblings, 1 reply; 6+ messages in thread
From: Ezequiel Garcia @ 2014-04-10 14:43 UTC (permalink / raw)
To: linux-mtd; +Cc: Richard Weinberger, Ezequiel Garcia, Artem Bityutskiy
In addition to the previous bevahior, this commit adds support for
ubiblock to identify a UBI volume based on the volume name or ID.
For example, the following command invocations are possible:
$ ubiblock --create=/dev/ubi0_0 - create from UBI volume node
$ ubiblock -r /dev/ubi0_0 - remove from UBI volume node
$ ubiblock -c /dev/ubi0 -n 99 - create from UBI volume 99 from UBI device
$ ubiblock -r /dev/ubi0 -N my_vol - remove from UBI volume named "my_vol" from UBI device
The implementation assume there's device node file named as "/dev/ubi${%d}_${%d}",
where the first integer is the UBI device number, and the second is the
UBI volume ID. This device is not strictly required to exist for a given volume,
so the implementation is a "best-effort".
For this reason, the open_volume_by_id is implemented here instead of adding
it to libubi.
Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
ubi-utils/ubiblock.c | 165 +++++++++++++++++++++++++++++++++++++++++----------
1 file changed, 133 insertions(+), 32 deletions(-)
diff --git a/ubi-utils/ubiblock.c b/ubi-utils/ubiblock.c
index 1e12be8..a599576 100644
--- a/ubi-utils/ubiblock.c
+++ b/ubi-utils/ubiblock.c
@@ -34,49 +34,118 @@
#include <libubi.h>
#include "common.h"
+enum operation {
+ UBIBLOCK_NONE,
+ UBIBLOCK_CREATE,
+ UBIBLOCK_REMOVE,
+};
+
struct args {
+ int vol_id;
const char *node;
- int create;
+ const char *name;
+ enum operation op;
};
-static struct args args;
+static struct args args = {
+ .op = UBIBLOCK_NONE,
+ .vol_id = -1,
+};
static const char doc[] = PROGRAM_NAME " version " VERSION
" - a tool to create/remove block device interface from UBI volumes.";
static const char optionsstr[] =
-"-c, --create create block on top of a volume\n"
-"-r, --remove remove block from volume\n"
-"-h, --help print help message\n"
-"-V, --version print program version";
+"-c, --create=<UBI device/volume node> create block on top of a volume\n"
+"-r, --remove=<UBI device/volume node> remove block from volume\n"
+"-n, --vol_id=<volume id> volume ID\n"
+"-N, --name=<volume name> volume name\n"
+"-h, --help print help message\n"
+"-V, --version print program version";
static const char usage[] =
-"Usage: " PROGRAM_NAME " [-c,-r] <UBI volume node file name>\n"
-"Example: " PROGRAM_NAME " --create /dev/ubi0_0";
+"Usage: " PROGRAM_NAME " [-c,-r] <UBI device or UBI volume node file name>\n"
+" [-n <volume id>] [--vol_id=<volume id>]\n"
+" [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n"
+"Example: " PROGRAM_NAME " --create=/dev/ubi0_0 - create from UBI volume node\n"
+" " PROGRAM_NAME " -c /dev/ubi0 -n 1 - create from UBI volume 1 from UBI device\n"
+" " PROGRAM_NAME " -r /dev/ubi0 -N my_vol - remove from UBI volume named \"my_vol\" from UBI device";
static const struct option long_options[] = {
{ .name = "create", .has_arg = 1, .flag = NULL, .val = 'c' },
{ .name = "remove", .has_arg = 1, .flag = NULL, .val = 'r' },
+ { .name = "vol_id", .has_arg = 1, .flag = NULL, .val = 'n' },
+ { .name = "name", .has_arg = 1, .flag = NULL, .val = 'N' },
{ .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
{ NULL, 0, NULL, 0}
};
-static int parse_opt(int argc, char * const argv[])
+static int param_sanity_check(libubi_t libubi)
+{
+ int err;
+
+ if (args.op == UBIBLOCK_NONE) {
+ errmsg("please, specify a creation or removal operation");
+ return -1;
+ }
+
+ err = ubi_probe_node(libubi, args.node);
+ if (err == 2) {
+ /* UBI volume node, don't need volume ID or name */
+ return 0;
+ } else if (err == 1) {
+ /* UBI device node, we need volume ID or name */
+ ;
+ } else if (err < 0) {
+ if (errno == ENODEV)
+ errmsg("\"%s\" is not an UBI device node", args.node);
+ else
+ errmsg("error while probing \"%s\"", args.node);
+ return -1;
+ }
+
+ if (args.vol_id == -1 && !args.name) {
+ errmsg("please, specify either volume ID or volume name");
+ return -1;
+ }
+
+ if (args.vol_id != -1 && args.name) {
+ errmsg("please, specify either volume ID or volume name, not both");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int parse_opt(libubi_t libubi, int argc, char * const argv[])
{
while (1) {
- int key;
+ int key, error = 0;
- key = getopt_long(argc, argv, "c:r:h?V", long_options, NULL);
+ key = getopt_long(argc, argv, "n:N:c:r:h?V", long_options, NULL);
if (key == -1)
break;
switch (key) {
case 'c':
- args.create = 1;
+ args.op = UBIBLOCK_CREATE;
+ args.node = optarg;
+ break;
case 'r':
+ args.op = UBIBLOCK_REMOVE;
args.node = optarg;
break;
+ case 'n':
+ args.vol_id = simple_strtoul(optarg, &error);
+ if (error || args.vol_id < 0) {
+ errmsg("bad volume ID: " "\"%s\"", optarg);
+ return -1;
+ }
+ break;
+ case 'N':
+ args.name = optarg;
+ break;
case 'h':
case '?':
printf("%s\n\n", doc);
@@ -94,20 +163,52 @@ static int parse_opt(int argc, char * const argv[])
}
}
- if (!args.node)
- return errmsg("invalid arguments (use -h for help)");
-
+ if (param_sanity_check(libubi))
+ return -1;
return 0;
}
-int main(int argc, char * const argv[])
+static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
{
+ char file[256];
+ struct ubi_dev_info dev_info;
int err, fd;
- libubi_t libubi;
- err = parse_opt(argc, argv);
+ err = ubi_get_dev_info(desc, node, &dev_info);
if (err)
+ return errmsg("cannot get information about UBI device \"%s\"", node);
+
+ sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
+ fd = open(file, mode);
+ if (fd == -1)
+ errmsg("Failed to open '%s' volume device", file);
+ return fd;
+}
+
+static int ubi_open_volume_by_name(libubi_t desc, const char *node, const char *name, int mode)
+{
+ struct ubi_dev_info dev_info;
+ struct ubi_vol_info vol_info;
+ int err;
+
+ err = ubi_get_dev_info(desc, node, &dev_info);
+ if (err) {
+ errmsg("cannot get information about UBI device \"%s\"", node);
+ return -1;
+ }
+
+ err = ubi_get_vol_info1_nm(desc, dev_info.dev_num, name, &vol_info);
+ if (err) {
+ errmsg("cannot find UBI volume \"%s\"", name);
return -1;
+ }
+ return ubi_open_volume_by_id(desc, node, vol_info.vol_id, mode);
+}
+
+int main(int argc, char * const argv[])
+{
+ int err, fd;
+ libubi_t libubi;
libubi = libubi_open();
if (!libubi) {
@@ -116,26 +217,26 @@ int main(int argc, char * const argv[])
return sys_errmsg("cannot open libubi");
}
- err = ubi_probe_node(libubi, args.node);
- if (err == 1) {
- errmsg("\"%s\" is an UBI device node, not an UBI volume node",
- args.node);
- goto out_libubi;
- } else if (err < 0) {
- if (errno == ENODEV)
- errmsg("\"%s\" is not an UBI volume node", args.node);
- else
- sys_errmsg("error while probing \"%s\"", args.node);
- goto out_libubi;
+ err = parse_opt(libubi, argc, argv);
+ if (err)
+ return -1;
+
+ if (args.name) {
+ fd = ubi_open_volume_by_name(libubi, args.node, args.name, O_RDWR);
+ } else if (args.vol_id != -1) {
+ fd = ubi_open_volume_by_id(libubi, args.node, args.vol_id, O_RDWR);
+ } else {
+ fd = open(args.node, O_RDWR);
+ if (fd == -1)
+ errmsg("Failed to open '%s' volume device", args.node);
}
- fd = open(args.node, O_RDWR);
if (fd == -1) {
- sys_errmsg("cannot open UBI volume \"%s\"", args.node);
+ sys_errmsg("cannot open UBI volume device");
goto out_libubi;
}
- if (args.create) {
+ if (args.op == UBIBLOCK_CREATE) {
err = ubi_vol_block_create(fd);
if (err) {
if (errno == ENOSYS)
--
1.9.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
2014-04-10 14:43 [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing Ezequiel Garcia
@ 2014-04-14 10:42 ` Artem Bityutskiy
2014-04-14 18:45 ` Ezequiel Garcia
2014-07-21 20:53 ` Ezequiel Garcia
0 siblings, 2 replies; 6+ messages in thread
From: Artem Bityutskiy @ 2014-04-14 10:42 UTC (permalink / raw)
To: Ezequiel Garcia; +Cc: Richard Weinberger, linux-mtd
On Thu, 2014-04-10 at 11:43 -0300, Ezequiel Garcia wrote:
> +static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
> {
> + char file[256];
> + struct ubi_dev_info dev_info;
> int err, fd;
> - libubi_t libubi;
>
> - err = parse_opt(argc, argv);
> + err = ubi_get_dev_info(desc, node, &dev_info);
> if (err)
> + return errmsg("cannot get information about UBI device \"%s\"", node);
> +
> + sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
Device node names may ve anything. Please, do not rely on the "/dev/ubi%
d_%d" naming scheme in the tool.
I think device node can be found out by scanning "/dev" and looking at
the device node major/minor numbers. This is more work of course.
However, libubi does exactly the same assumption about UBI volume names
as you do, so if you move this function to libubi, I think it will be
good enough. At least if someone wants to change this in the future,
then it will only require changing the library, but not its users.
> + fd = open(file, mode);
> + if (fd == -1)
> + errmsg("Failed to open '%s' volume device", file);
> + return fd;
> +}
> +
--
Best Regards,
Artem Bityutskiy
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
2014-04-14 10:42 ` Artem Bityutskiy
@ 2014-04-14 18:45 ` Ezequiel Garcia
2014-07-21 20:53 ` Ezequiel Garcia
1 sibling, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2014-04-14 18:45 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: Richard Weinberger, linux-mtd
On Apr 14, Artem Bityutskiy wrote:
> On Thu, 2014-04-10 at 11:43 -0300, Ezequiel Garcia wrote:
> > +static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
> > {
> > + char file[256];
> > + struct ubi_dev_info dev_info;
> > int err, fd;
> > - libubi_t libubi;
> >
> > - err = parse_opt(argc, argv);
> > + err = ubi_get_dev_info(desc, node, &dev_info);
> > if (err)
> > + return errmsg("cannot get information about UBI device \"%s\"", node);
> > +
> > + sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
>
> Device node names may ve anything. Please, do not rely on the "/dev/ubi%
> d_%d" naming scheme in the tool.
>
Yeah, I know this sucks.
> I think device node can be found out by scanning "/dev" and looking at
> the device node major/minor numbers. This is more work of course.
>
Ah, that's a good idea. Let me give it a try.
> However, libubi does exactly the same assumption about UBI volume names
> as you do, so if you move this function to libubi, I think it will be
> good enough. At least if someone wants to change this in the future,
> then it will only require changing the library, but not its users.
>
OK, I will.
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
2014-04-14 10:42 ` Artem Bityutskiy
2014-04-14 18:45 ` Ezequiel Garcia
@ 2014-07-21 20:53 ` Ezequiel Garcia
2014-07-28 16:31 ` Artem Bityutskiy
1 sibling, 1 reply; 6+ messages in thread
From: Ezequiel Garcia @ 2014-07-21 20:53 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: Richard Weinberger, linux-mtd, Guido Martínez
Sorry for the delay on this one.
On 14 Apr 01:42 PM, Artem Bityutskiy wrote:
> On Thu, 2014-04-10 at 11:43 -0300, Ezequiel Garcia wrote:
> > +static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
> > {
> > + char file[256];
> > + struct ubi_dev_info dev_info;
> > int err, fd;
> > - libubi_t libubi;
> >
> > - err = parse_opt(argc, argv);
> > + err = ubi_get_dev_info(desc, node, &dev_info);
> > if (err)
> > + return errmsg("cannot get information about UBI device \"%s\"", node);
> > +
> > + sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
>
> Device node names may ve anything. Please, do not rely on the "/dev/ubi%
> d_%d" naming scheme in the tool.
>
> I think device node can be found out by scanning "/dev" and looking at
> the device node major/minor numbers. This is more work of course.
>
Yeah, but the UBI major is allocated dynamically so we can't rely on that.
We would have to call an ioctl on each /dev device, which seems like a bit
heavy to me.
How about scanning out the sysfs and associate a name to the UBI device
and volume ID?
# ls -la /sys/class/ubi/
total 0
drwxr-xr-x 2 root root 0 Jul 21 20:23 .
drwxr-xr-x 37 root root 0 Jul 21 20:23 ..
lrwxrwxrwx 1 root root 0 Jul 21 20:23 ubi0 -> ../../devices/virtual/ubi/ubi0
lrwxrwxrwx 1 root root 0 Jul 21 20:23 ubi0_0 -> ../../devices/virtual/ubi/ubi0/ubi0_0
lrwxrwxrwx 1 root root 0 Jul 21 20:23 ubi0_1 -> ../../devices/virtual/ubi/ubi0/ubi0_1
lrwxrwxrwx 1 root root 0 Jul 21 20:23 ubi0_2 -> ../../devices/virtual/ubi/ubi0/ubi0_2
lrwxrwxrwx 1 root root 0 Jul 21 20:23 ubi0_3 -> ../../devices/virtual/ubi/ubi0/ubi0_3
Each /sys/class/ubiX_Y/name file can be related to the UBI device ${X},
and UBI volume ID ${Y}.
Based in this idea, we could make some ubifindvol tool that can find
an UBI volume ID from the UBI name.
> However, libubi does exactly the same assumption about UBI volume names
> as you do, so if you move this function to libubi, I think it will be
> good enough. At least if someone wants to change this in the future,
> then it will only require changing the library, but not its users.
>
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
2014-07-21 20:53 ` Ezequiel Garcia
@ 2014-07-28 16:31 ` Artem Bityutskiy
2014-07-30 14:22 ` Ezequiel Garcia
0 siblings, 1 reply; 6+ messages in thread
From: Artem Bityutskiy @ 2014-07-28 16:31 UTC (permalink / raw)
To: Ezequiel Garcia; +Cc: Richard Weinberger, linux-mtd, Guido Martínez
On Mon, 2014-07-21 at 17:53 -0300, Ezequiel Garcia wrote:
> Sorry for the delay on this one.
>
> On 14 Apr 01:42 PM, Artem Bityutskiy wrote:
> > On Thu, 2014-04-10 at 11:43 -0300, Ezequiel Garcia wrote:
> > > +static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
> > > {
> > > + char file[256];
> > > + struct ubi_dev_info dev_info;
> > > int err, fd;
> > > - libubi_t libubi;
> > >
> > > - err = parse_opt(argc, argv);
> > > + err = ubi_get_dev_info(desc, node, &dev_info);
> > > if (err)
> > > + return errmsg("cannot get information about UBI device \"%s\"", node);
> > > +
> > > + sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
> >
> > Device node names may ve anything. Please, do not rely on the "/dev/ubi%
> > d_%d" naming scheme in the tool.
> >
> > I think device node can be found out by scanning "/dev" and looking at
> > the device node major/minor numbers. This is more work of course.
> >
>
> Yeah, but the UBI major is allocated dynamically so we can't rely on that.
> We would have to call an ioctl on each /dev device, which seems like a bit
> heavy to me.
>
> How about scanning out the sysfs and associate a name to the UBI device
> and volume ID?
What I meant is that you have these:
/sys/class/ubi/ubiX/dev
and these
/sys/class/ubi/ubiX/ubiX_Y/dev
containing the "major:minor" pairs.
For for any X:Y you can find major:minor. Then you scan "/dev" and find
the device nodes, if they exist. If they do not exist, you may ask the
user to create a device node with these major:minor in your error
message.
--
Best Regards,
Artem Bityutskiy
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing
2014-07-28 16:31 ` Artem Bityutskiy
@ 2014-07-30 14:22 ` Ezequiel Garcia
0 siblings, 0 replies; 6+ messages in thread
From: Ezequiel Garcia @ 2014-07-30 14:22 UTC (permalink / raw)
To: Artem Bityutskiy; +Cc: Richard Weinberger, linux-mtd, Guido Martínez
On 28 Jul 07:31 PM, Artem Bityutskiy wrote:
> On Mon, 2014-07-21 at 17:53 -0300, Ezequiel Garcia wrote:
> > Sorry for the delay on this one.
> >
> > On 14 Apr 01:42 PM, Artem Bityutskiy wrote:
> > > On Thu, 2014-04-10 at 11:43 -0300, Ezequiel Garcia wrote:
> > > > +static int ubi_open_volume_by_id(libubi_t desc, const char *node, int vol_id, int mode)
> > > > {
> > > > + char file[256];
> > > > + struct ubi_dev_info dev_info;
> > > > int err, fd;
> > > > - libubi_t libubi;
> > > >
> > > > - err = parse_opt(argc, argv);
> > > > + err = ubi_get_dev_info(desc, node, &dev_info);
> > > > if (err)
> > > > + return errmsg("cannot get information about UBI device \"%s\"", node);
> > > > +
> > > > + sprintf(file, "/dev/ubi%d_%d", dev_info.dev_num, vol_id);
> > >
> > > Device node names may ve anything. Please, do not rely on the "/dev/ubi%
> > > d_%d" naming scheme in the tool.
> > >
> > > I think device node can be found out by scanning "/dev" and looking at
> > > the device node major/minor numbers. This is more work of course.
> > >
> >
> > Yeah, but the UBI major is allocated dynamically so we can't rely on that.
> > We would have to call an ioctl on each /dev device, which seems like a bit
> > heavy to me.
> >
> > How about scanning out the sysfs and associate a name to the UBI device
> > and volume ID?
>
> What I meant is that you have these:
>
> /sys/class/ubi/ubiX/dev
>
> and these
>
> /sys/class/ubi/ubiX/ubiX_Y/dev
>
> containing the "major:minor" pairs.
>
> For for any X:Y you can find major:minor. Then you scan "/dev" and find
> the device nodes, if they exist. If they do not exist, you may ask the
> user to create a device node with these major:minor in your error
> message.
>
Right. That sounds a nice solution. I'll implement something upstreamable
as time permits.
Thanks!
--
Ezequiel García, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-07-30 14:24 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-04-10 14:43 [PATCH] ubiblock: Support UBI volume name or volume ID parameter passing Ezequiel Garcia
2014-04-14 10:42 ` Artem Bityutskiy
2014-04-14 18:45 ` Ezequiel Garcia
2014-07-21 20:53 ` Ezequiel Garcia
2014-07-28 16:31 ` Artem Bityutskiy
2014-07-30 14:22 ` Ezequiel Garcia
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox