Patchwork [v2] ubi-utils: Add ubiblock tool

login
register
mail settings
Submitter Ezequiel Garcia
Date March 14, 2014, 2:25 p.m.
Message ID <1394807124-25916-1-git-send-email-ezequiel.garcia@free-electrons.com>
Download mbox | patch
Permalink /patch/330331/
State New
Headers show

Comments

Ezequiel Garcia - March 14, 2014, 2:25 p.m.
With the addition of block device access to UBI volumes, we now
add a simple userspace tool to access the new ioctls.

Usage of this tool is as simple as it gets:

  $ ubiblock --create /dev/ubi0_0

will create a new block device /dev/ubiblock0_0, and

  $ ubiblock --remove /dev/ubi0_0

will remove the device.

Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
---
Changes from previous attempts:

 * Rename the tool to ubiblock, as per Artem's suggestion.

 * Renamed the ubiblock parameters, s/attach/create, s/detach/remove.

 * Update new ioctls name and parameter.

 * Take advantage of ENOTTY and ENOSYS to report a proper error
   message; ENOTTY will be typically be obtained on old kernels
   where the UBI block ioctl's haven't been introduced.
   ENOSYS, on the other side, will happen when UBI is supported
   but not enabled in the running kernel (iow, not present).

 Makefile                   |   2 +-
 include/mtd/ubi-user.h     |  22 ++++++
 ubi-utils/.gitignore       |   1 +
 ubi-utils/include/libubi.h |  16 ++++
 ubi-utils/libubi.c         |  10 +++
 ubi-utils/ubiblock.c       | 181 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 231 insertions(+), 1 deletion(-)
 create mode 100644 ubi-utils/ubiblock.c
Ezequiel Garcia - March 21, 2014, 6:09 p.m.
On Mar 14, Ezequiel Garcia wrote:
> With the addition of block device access to UBI volumes, we now
> add a simple userspace tool to access the new ioctls.
> 
> Usage of this tool is as simple as it gets:
> 
>   $ ubiblock --create /dev/ubi0_0
> 
> will create a new block device /dev/ubiblock0_0, and
> 
>   $ ubiblock --remove /dev/ubi0_0
> 
> will remove the device.
> 
> Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com>
> ---

Ping?

I'm wondering how's the release cycle for this. Is it possible
to make a release more or less soon, so this new ubiblock tool
is available?
Artem Bityutskiy - March 25, 2014, 7:52 a.m.
On Fri, 2014-03-14 at 11:25 -0300, Ezequiel Garcia wrote:
> With the addition of block device access to UBI volumes, we now
> add a simple userspace tool to access the new ioctls.
> 
> Usage of this tool is as simple as it gets:
> 
>   $ ubiblock --create /dev/ubi0_0
> 
> will create a new block device /dev/ubiblock0_0, and

Pushed to mtd-utils, thanks!
Artem Bityutskiy - March 25, 2014, 8:08 a.m.
On Tue, 2014-03-25 at 09:52 +0200, Artem Bityutskiy wrote:
> On Fri, 2014-03-14 at 11:25 -0300, Ezequiel Garcia wrote:
> > With the addition of block device access to UBI volumes, we now
> > add a simple userspace tool to access the new ioctls.
> > 
> > Usage of this tool is as simple as it gets:
> > 
> >   $ ubiblock --create /dev/ubi0_0
> > 
> > will create a new block device /dev/ubiblock0_0, and
> 
> Pushed to mtd-utils, thanks!

Actually, I did not, push fails.

The root-cause, AFAICS, is that when Brian pushes there, files and
directories in .git/objects/ get created without "write" group
permissions. So I cannot create new objects.

I _think_ this is because of Brian's umask. If Brian could set it to
'002', that would not happen.

Brian or David, would you please fix-up the permissions and add g+w? Is
there a way to force g+w, I wonder? I am not aware of such...
Artem Bityutskiy - March 25, 2014, 8:14 a.m.
On Tue, 2014-03-25 at 10:08 +0200, Artem Bityutskiy wrote:
> On Tue, 2014-03-25 at 09:52 +0200, Artem Bityutskiy wrote:
> > On Fri, 2014-03-14 at 11:25 -0300, Ezequiel Garcia wrote:
> > > With the addition of block device access to UBI volumes, we now
> > > add a simple userspace tool to access the new ioctls.
> > > 
> > > Usage of this tool is as simple as it gets:
> > > 
> > >   $ ubiblock --create /dev/ubi0_0
> > > 
> > > will create a new block device /dev/ubiblock0_0, and
> > 
> > Pushed to mtd-utils, thanks!
> 
> Actually, I did not, push fails.
> 
> The root-cause, AFAICS, is that when Brian pushes there, files and
> directories in .git/objects/ get created without "write" group
> permissions. So I cannot create new objects.
> 
> I _think_ this is because of Brian's umask. If Brian could set it to
> '002', that would not happen.
> 
> Brian or David, would you please fix-up the permissions and add g+w? Is
> there a way to force g+w, I wonder? I am not aware of such...

There are many discussions on the topic, actually, e.g.:

http://serverfault.com/questions/26954/how-do-i-share-a-git-repository-with-multiple-users-on-a-machine
http://stackoverflow.com/questions/6448242/git-push-error-insufficient-permission-for-adding-an-object-to-repository-datab
Ezequiel Garcia - March 29, 2014, 8:24 p.m.
On Mar 25, Artem Bityutskiy wrote:
> On Fri, 2014-03-14 at 11:25 -0300, Ezequiel Garcia wrote:
> > With the addition of block device access to UBI volumes, we now
> > add a simple userspace tool to access the new ioctls.
> > 
> > Usage of this tool is as simple as it gets:
> > 
> >   $ ubiblock --create /dev/ubi0_0
> > 
> > will create a new block device /dev/ubiblock0_0, and
> 
> Pushed to mtd-utils, thanks!
> 

Thanks! Do you think it would be appropriate to do a new release, so
the new tool is included?
Artem Bityutskiy - March 31, 2014, 9:45 a.m.
On Sat, 2014-03-29 at 17:24 -0300, Ezequiel Garcia wrote:
> On Mar 25, Artem Bityutskiy wrote:
> > On Fri, 2014-03-14 at 11:25 -0300, Ezequiel Garcia wrote:
> > > With the addition of block device access to UBI volumes, we now
> > > add a simple userspace tool to access the new ioctls.
> > > 
> > > Usage of this tool is as simple as it gets:
> > > 
> > >   $ ubiblock --create /dev/ubi0_0
> > > 
> > > will create a new block device /dev/ubiblock0_0, and
> > 
> > Pushed to mtd-utils, thanks!
> > 
> 
> Thanks! Do you think it would be appropriate to do a new release, so
> the new tool is included?

Yeah, probably. Let's check if Brian has anything in mind and then I can
make a release.
Brian Norris - March 31, 2014, 5:13 p.m.
On Mon, Mar 31, 2014 at 12:45:34PM +0300, Artem Bityutskiy wrote:
> On Sat, 2014-03-29 at 17:24 -0300, Ezequiel Garcia wrote:
> > Thanks! Do you think it would be appropriate to do a new release, so
> > the new tool is included?
> 
> Yeah, probably. Let's check if Brian has anything in mind and then I can
> make a release.

Other than the trivial ubiformat patch I just sent, no objections here.
A release is probably a good idea.

(NB: I just upgraded my rootfs mtd-utils to the latest git HEAD a week
or two ago; I suppose a release tag would have been better!)

Brian
Ezequiel Garcia - April 5, 2014, 8:33 p.m.
Hello Artem, Richard:

On Mar 14, Ezequiel Garcia wrote:
> With the addition of block device access to UBI volumes, we now
> add a simple userspace tool to access the new ioctls.
> 
> Usage of this tool is as simple as it gets:
> 
>   $ ubiblock --create /dev/ubi0_0
> 
> will create a new block device /dev/ubiblock0_0, and
> 
>   $ ubiblock --remove /dev/ubi0_0
> 

After using this for something else than silly tests, I've found this
usage is actually a bit braindead :-)

The user will probably want to create a block device based on the volume's
name or ID, and not just the node path. In particular, using the name is
probably the most useful case, given the atomic ubi volume rename feature.

Therefore, I'd like to see this fixed, but I'm not entirely sure what's the
best approach. Here are my ideas so far to identify a volume:

  * Follow the convention of ubirmvol:

    ubiblock --create /dev/ubi0_0 (like we have now)
    ubiblock --create <UBI device node file name>
	     [-n <volume id>] [--vol_id=<volume id>]
             [-N <volume name>] [--name=<volume name>]

  * Implement something matching the mount command usage. For example,

    ubiblock --create /dev/ubi0_0 (like we have now)
    ubiblock --create ubi0:name
    ubiblock --create ubi0_0

  * All of them?

To be honest, I don't have any preference.
Artem Bityutskiy - April 7, 2014, 11:33 a.m.
On Sat, 2014-04-05 at 17:33 -0300, Ezequiel Garcia wrote:
> Hello Artem, Richard:
> 
> On Mar 14, Ezequiel Garcia wrote:
> > With the addition of block device access to UBI volumes, we now
> > add a simple userspace tool to access the new ioctls.
> > 
> > Usage of this tool is as simple as it gets:
> > 
> >   $ ubiblock --create /dev/ubi0_0
> > 
> > will create a new block device /dev/ubiblock0_0, and
> > 
> >   $ ubiblock --remove /dev/ubi0_0
> > 
> 
> After using this for something else than silly tests, I've found this
> usage is actually a bit braindead :-)
> 
> The user will probably want to create a block device based on the volume's
> name or ID, and not just the node path. In particular, using the name is
> probably the most useful case, given the atomic ubi volume rename feature.
> 
> Therefore, I'd like to see this fixed, but I'm not entirely sure what's the
> best approach. Here are my ideas so far to identify a volume:
> 
>   * Follow the convention of ubirmvol:
> 
>     ubiblock --create /dev/ubi0_0 (like we have now)
>     ubiblock --create <UBI device node file name>
> 	     [-n <volume id>] [--vol_id=<volume id>]
>              [-N <volume name>] [--name=<volume name>]
> 
>   * Implement something matching the mount command usage. For example,
> 
>     ubiblock --create /dev/ubi0_0 (like we have now)
>     ubiblock --create ubi0:name
>     ubiblock --create ubi0_0
> 
>   * All of them?
> 
> To be honest, I don't have any preference.

Oh, and I released your tool before I read this e-mail.

Well, this means that your new changes need to be compatible. Sorry for
this. Sure, go ahead with the improvements. I also do not have
preferences. Try to be consistent with other tools, change them too if
necessary, implement what makes sense and useful.
Ezequiel Garcia - April 7, 2014, 11:48 a.m.
On Apr 07, Artem Bityutskiy wrote:
> On Sat, 2014-04-05 at 17:33 -0300, Ezequiel Garcia wrote:
> > Hello Artem, Richard:
> > 
> > On Mar 14, Ezequiel Garcia wrote:
> > > With the addition of block device access to UBI volumes, we now
> > > add a simple userspace tool to access the new ioctls.
> > > 
> > > Usage of this tool is as simple as it gets:
> > > 
> > >   $ ubiblock --create /dev/ubi0_0
> > > 
> > > will create a new block device /dev/ubiblock0_0, and
> > > 
> > >   $ ubiblock --remove /dev/ubi0_0
> > > 
> > 
> > After using this for something else than silly tests, I've found this
> > usage is actually a bit braindead :-)
> > 
> > The user will probably want to create a block device based on the volume's
> > name or ID, and not just the node path. In particular, using the name is
> > probably the most useful case, given the atomic ubi volume rename feature.
> > 
> > Therefore, I'd like to see this fixed, but I'm not entirely sure what's the
> > best approach. Here are my ideas so far to identify a volume:
> > 
> >   * Follow the convention of ubirmvol:
> > 
> >     ubiblock --create /dev/ubi0_0 (like we have now)
> >     ubiblock --create <UBI device node file name>
> > 	     [-n <volume id>] [--vol_id=<volume id>]
> >              [-N <volume name>] [--name=<volume name>]
> > 
> >   * Implement something matching the mount command usage. For example,
> > 
> >     ubiblock --create /dev/ubi0_0 (like we have now)
> >     ubiblock --create ubi0:name
> >     ubiblock --create ubi0_0
> > 
> >   * All of them?
> > 
> > To be honest, I don't have any preference.
> 
> Oh, and I released your tool before I read this e-mail.
> 

Oh, no problem. It's my fault for not giving enough thought to this.

> Well, this means that your new changes need to be compatible. Sorry for
> this. Sure, go ahead with the improvements. I also do not have
> preferences. Try to be consistent with other tools, change them too if
> necessary, implement what makes sense and useful.
> 

Right then. I'll cook a patch, hopefully today!

Patch

diff --git a/Makefile b/Makefile
index 4ff8a49..d316a3d 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@  MTD_BINS = \
 	sumtool jffs2reader
 UBI_BINS = \
 	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
+	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol ubiblock
 
 BINS = $(MTD_BINS)
 BINS += mkfs.ubifs/mkfs.ubifs
diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h
index 1c06d88..2b50dad 100644
--- a/include/mtd/ubi-user.h
+++ b/include/mtd/ubi-user.h
@@ -132,6 +132,16 @@ 
  * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be
  * passed. The object describes which property should be set, and to which value
  * it should be set.
+ *
+ * Block devices on UBI volumes
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * To create a R/O block device on top of an UBI volume the %UBI_IOCVOLCRBLK
+ * should be used. A pointer to a &struct ubi_blkcreate_req object is expected
+ * to be passed, which is not used and reserved for future usage.
+ *
+ * Conversely, to remove a block device the %UBI_IOCVOLRMBLK should be used,
+ * which takes no arguments.
  */
 
 /*
@@ -186,6 +196,10 @@ 
 /* Set an UBI volume property */
 #define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
 			       struct ubi_set_vol_prop_req)
+/* Create a R/O block device on top of an UBI volume */
+#define UBI_IOCVOLCRBLK _IOW(UBI_VOL_IOC_MAGIC, 7, struct ubi_blkcreate_req)
+/* Remove the R/O block device */
+#define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8)
 
 /* Maximum MTD device name length supported by UBI */
 #define MAX_UBI_MTD_NAME_LEN 127
@@ -415,4 +429,12 @@  struct ubi_set_vol_prop_req {
 	uint64_t value;
 }  __attribute__((packed));
 
+/**
+ * struct ubi_blkcreate_req - a data structure used in block creation requests.
+ * @padding: reserved for future, not used, has to be zeroed
+ */
+struct ubi_blkcreate_req {
+	int8_t  padding[128];
+}  __attribute__((packed));
+
 #endif /* __UBI_USER_H__ */
diff --git a/ubi-utils/.gitignore b/ubi-utils/.gitignore
index c035c97..19653a8 100644
--- a/ubi-utils/.gitignore
+++ b/ubi-utils/.gitignore
@@ -9,4 +9,5 @@ 
 /ubirmvol
 /ubiupdatevol
 /ubirsvol
+/ubiblock
 /mtdinfo
diff --git a/ubi-utils/include/libubi.h b/ubi-utils/include/libubi.h
index 47f40e2..4d6a7ee 100644
--- a/ubi-utils/include/libubi.h
+++ b/ubi-utils/include/libubi.h
@@ -400,6 +400,22 @@  int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
 			 struct ubi_vol_info *info);
 
 /**
+ * ubi_vol_block_create - create a block device on top of an UBI volume.
+ * @fd: volume character device file descriptor
+ *
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int ubi_vol_block_create(int fd);
+
+/**
+ * ubi_vol_block_remove - remove a block device from an UBI volume.
+ * @fd: volume character device file descriptor
+ *
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+int ubi_vol_block_remove(int fd);
+
+/**
  * ubi_update_start - start UBI volume update.
  * @desc: UBI library descriptor
  * @fd: volume character device file descriptor
diff --git a/ubi-utils/libubi.c b/ubi-utils/libubi.c
index a7463e8..598191e 100644
--- a/ubi-utils/libubi.c
+++ b/ubi-utils/libubi.c
@@ -1109,6 +1109,16 @@  int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
 	return ret;
 }
 
+int ubi_vol_block_create(int fd)
+{
+	return ioctl(fd, UBI_IOCVOLCRBLK);
+}
+
+int ubi_vol_block_remove(int fd)
+{
+	return ioctl(fd, UBI_IOCVOLRMBLK);
+}
+
 int ubi_update_start(libubi_t desc, int fd, long long bytes)
 {
 	desc = desc;
diff --git a/ubi-utils/ubiblock.c b/ubi-utils/ubiblock.c
new file mode 100644
index 0000000..bdbd931
--- /dev/null
+++ b/ubi-utils/ubiblock.c
@@ -0,0 +1,181 @@ 
+/*
+ * ubiblock:
+ *   An utility to create/remove block devices to UBI volumes.
+ *
+ * Copyright (c) Ezequiel Garcia, 2014
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Usage
+ * -----
+ * Since the ioctls have no arguments, usage of this tool is as simple
+ * as it gets:
+ *
+ *   $ ubiblock --create /dev/ubi0_0
+ *
+ * will make a new device /dev/ubiblock0_0 available, and
+ *
+ *   $ ubiblock --remove /dev/ubi0_0
+ *
+ * will remove the device.
+ */
+
+#define PROGRAM_NAME    "ubiblock"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <libubi.h>
+#include "common.h"
+
+struct args {
+	const char *node;
+	int create;
+};
+
+static struct args args;
+
+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";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " [-c,-r] <UBI volume node file name>\n"
+"Example: " PROGRAM_NAME " --create /dev/ubi0_0";
+
+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 = "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[])
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "c:r:h?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'c':
+			args.create = 1;
+		case 'r':
+			args.node = optarg;
+			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);
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (!args.node)
+		return errmsg("invalid arguments (use -h for help)");
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err, fd;
+	libubi_t libubi;
+
+	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");
+		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;
+	}
+
+	fd = open(args.node, O_RDWR);
+	if (fd == -1) {
+		sys_errmsg("cannot open UBI volume \"%s\"", args.node);
+		goto out_libubi;
+	}
+
+	if (args.create) {
+		err = ubi_vol_block_create(fd);
+		if (err) {
+			if (errno == ENOSYS)
+				errmsg("UBI block is not present in the system");
+			if (errno == ENOTTY)
+				errmsg("UBI block not supported (check your kernel version)");
+			sys_errmsg("cannot create block device");
+			goto out_close;
+		}
+	} else {
+		err = ubi_vol_block_remove(fd);
+		if (err) {
+			if (errno == ENOSYS)
+				errmsg("UBI block is not present in the system");
+			if (errno == ENOTTY)
+				errmsg("UBI block not supported (check your kernel version)");
+			sys_errmsg("cannot remove block device");
+			goto out_close;
+		}
+	}
+
+	close(fd);
+	libubi_close(libubi);
+	return 0;
+
+out_close:
+	close(fd);
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}