| From: Ezequiel Garcia |
| Subject: [PATCH] ubi-utils: Add ubiblkvol tool |
| Date: Sat, 18 May 2013 11:31:55 -0300 |
| |
| With the addition of block device access to UBI volumes, we now |
| add a simple userspace tool to access the new ioctls. |
| |
| Since the ioctls have no arguments, usage of this tool is as simple |
| as it gets: |
| |
| $ ubiblkvol --attach /dev/ubi0_0 |
| |
| will make a new device /dev/ubiblock0_0 available, and |
| |
| $ ubiblkvol --detach /dev/ubi0_0 |
| |
| will remove the device. |
| |
| Signed-off-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> |
| --- |
| Makefile | 2 +- |
| include/mtd/ubi-user.h | 11 +++ |
| ubi-utils/.gitignore | 1 + |
| ubi-utils/include/libubi.h | 16 +++++ |
| ubi-utils/libubi.c | 10 +++ |
| ubi-utils/ubiblkvol.c | 176 +++++++++++++++++++++++++++++++++++++++++++++ |
| 6 files changed, 215 insertions(+), 1 deletion(-) |
| create mode 100644 ubi-utils/ubiblkvol.c |
| |
| diff --git a/Makefile b/Makefile |
| index c8d25f2..9ccda38 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 ubiblkvol |
| |
| BINS = $(MTD_BINS) |
| BINS += mkfs.ubifs/mkfs.ubifs |
| diff --git a/include/mtd/ubi-user.h b/include/mtd/ubi-user.h |
| index 1c06d88..922d484 100644 |
| --- a/include/mtd/ubi-user.h |
| +++ b/include/mtd/ubi-user.h |
| @@ -132,6 +132,13 @@ |
| * 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 device access to UBI volumes |
| + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| + * |
| + * To attach or detach a block device from an UBI volume the %UBI_IOCVOLATTBLK |
| + * and %UBI_IOCVOLDETBLK ioctl commands should be used, respectively. |
| + * These commands take no arguments. |
| */ |
| |
| /* |
| @@ -186,6 +193,10 @@ |
| #define UBI_IOCEBISMAP _IOR(UBI_VOL_IOC_MAGIC, 5, int32_t) |
| /* Set an UBI volume property */ |
| #define UBI_IOCSETPROP _IOW(UBI_VOL_IOC_MAGIC, 6, struct ubi_set_prop_req) |
| +/* Attach a block device to an UBI volume */ |
| +#define UBI_IOCVOLATTBLK _IO(UBI_VOL_IOC_MAGIC, 7) |
| +/* Detach a block device from an UBI volume */ |
| +#define UBI_IOCVOLDETBLK _IO(UBI_VOL_IOC_MAGIC, 8) |
| |
| /* Maximum MTD device name length supported by UBI */ |
| #define MAX_UBI_MTD_NAME_LEN 127 |
| diff --git a/ubi-utils/.gitignore b/ubi-utils/.gitignore |
| index c035c97..5c9cbd9 100644 |
| --- a/ubi-utils/.gitignore |
| +++ b/ubi-utils/.gitignore |
| @@ -9,4 +9,5 @@ |
| /ubirmvol |
| /ubiupdatevol |
| /ubirsvol |
| +/ubiblkvol |
| /mtdinfo |
| diff --git a/ubi-utils/include/libubi.h b/ubi-utils/include/libubi.h |
| index 47f40e2..3759aa8 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_add - attach a block device to 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_add(int fd); |
| + |
| +/** |
| + * ubi_vol_block_del - detach 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_del(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..cb631f9 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_add(int fd) |
| +{ |
| + return ioctl(fd, UBI_IOCVOLATTBLK); |
| +} |
| + |
| +int ubi_vol_block_del(int fd) |
| +{ |
| + return ioctl(fd, UBI_IOCVOLDETBLK); |
| +} |
| + |
| int ubi_update_start(libubi_t desc, int fd, long long bytes) |
| { |
| desc = desc; |
| diff --git a/ubi-utils/ubiblkvol.c b/ubi-utils/ubiblkvol.c |
| new file mode 100644 |
| index 0000000..4d023cc |
| --- /dev/null |
| +++ b/ubi-utils/ubiblkvol.c |
| @@ -0,0 +1,176 @@ |
| +/* |
| + * ubiblkvol: |
| + * An utility to attach block devices to UBI volumes. |
| + * |
| + * Copyright (c) Ezequiel Garcia, 2013 |
| + * |
| + * 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. |
| + * |
| + * Usage |
| + * ----- |
| + * Since the ioctls have no arguments, usage of this tool is as simple |
| + * as it gets: |
| + * |
| + * $ ubiblkvol --attach /dev/ubi0_0 |
| + * |
| + * will make a new device /dev/ubiblock0_0 available, and |
| + * |
| + * $ ubiblkvol --detach /dev/ubi0_0 |
| + * |
| + * will remove the device. |
| + */ |
| + |
| +#define PROGRAM_NAME "ubiblkvol" |
| + |
| +#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 attach; |
| +}; |
| + |
| +static struct args args; |
| + |
| +static const char doc[] = PROGRAM_NAME " version " VERSION |
| + " - a tool to add/remove block device interface from UBI volumes."; |
| + |
| +static const char optionsstr[] = |
| +"-a, --attach attach block to volume\n" |
| +"-d, --detach detach block from volume\n" |
| +"-h, --help print help message\n" |
| +"-V, --version print program version"; |
| + |
| +static const char usage[] = |
| +"Usage: " PROGRAM_NAME " [-a,-d] <UBI volume node file name>\n" |
| +"Example: " PROGRAM_NAME " --attach /dev/ubi0_0"; |
| + |
| +static const struct option long_options[] = { |
| + { .name = "attach", .has_arg = 1, .flag = NULL, .val = 'a' }, |
| + { .name = "detach", .has_arg = 1, .flag = NULL, .val = 'd' }, |
| + { .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, "a:d:h?V", long_options, NULL); |
| + if (key == -1) |
| + break; |
| + |
| + switch (key) { |
| + case 'a': |
| + args.attach = 1; |
| + case 'd': |
| + 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"); |
| + else |
| + sys_errmsg("cannot open libubi"); |
| + goto out_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.attach) { |
| + err = ubi_vol_block_add(fd); |
| + if (err) { |
| + sys_errmsg("cannot attach block device"); |
| + goto out_close; |
| + } |
| + } else { |
| + err = ubi_vol_block_del(fd); |
| + if (err) { |
| + sys_errmsg("cannot detach block device"); |
| + goto out_close; |
| + } |
| + } |
| + |
| + close(fd); |
| + libubi_close(libubi); |
| + return 0; |
| + |
| +out_close: |
| + close(fd); |
| +out_libubi: |
| + libubi_close(libubi); |
| + return -1; |
| +} |
| -- |
| 1.8.1.5 |
| |