Commit 9d54c8a3 authored by Ezequiel Garcia's avatar Ezequiel Garcia Committed by Artem Bityutskiy

UBI: R/O block driver on top of UBI volumes

This commit introduces read-only block device emulation on top of UBI volumes.

Given UBI takes care of wear leveling and bad block management it's possible
to add a thin layer to enable block device access to UBI volumes.
This allows to use a block-oriented filesystem on a flash device.

The UBI block devices are meant to be used in conjunction with any
regular, block-oriented file system (e.g. ext4), although it's primarily
targeted at read-only file systems, such as squashfs.

Block devices are created upon user request through new ioctls:
UBI_IOCVOLATTBLK to attach and UBI_IOCVOLDETBLK to detach.
Also, a new UBI module parameter is added 'ubi.block'. This parameter is
needed in order to attach a block device on boot-up time, allowing to
mount the rootfs on a ubiblock device.
For instance, you could have these kernel parameters:

  ubi.mtd=5 ubi.block=0,0 root=/dev/ubiblock0_0

Or, if you compile ubi as a module:

  $ modprobe ubi mtd=/dev/mtd5 block=/dev/ubi0_0

Artem: amend commentaries and massage the patch a little bit.
Signed-off-by: default avatarEzequiel Garcia <ezequiel.garcia@free-electrons.com>
Signed-off-by: default avatarArtem Bityutskiy <artem.bityutskiy@linux.intel.com>
parent 5547fec7
......@@ -87,4 +87,19 @@ config MTD_UBI_GLUEBI
work on top of UBI. Do not enable this unless you use legacy
software.
config MTD_UBI_BLOCK
bool "Read-only block devices on top of UBI volumes"
default n
help
This option enables read-only UBI block devices support. UBI block
devices will be layered on top of UBI volumes, which means that the
UBI driver will transparently handle things like bad eraseblocks and
bit-flips. You can put any block-oriented file system on top of UBI
volumes in read-only mode (e.g., ext4), but it is probably most
practical for read-only file systems, like squashfs.
When selected, this feature will be built in the UBI driver.
If in doubt, say "N".
endif # MTD_UBI
......@@ -3,5 +3,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o
ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
ubi-y += misc.o debug.o
ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o
ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o
obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
This diff is collapsed.
......@@ -1298,6 +1298,15 @@ static int __init ubi_init(void)
}
}
err = ubiblock_init();
if (err) {
ubi_err("block: cannot initialize, error %d", err);
/* See comment above re-ubi_is_module(). */
if (ubi_is_module())
goto out_detach;
}
return 0;
out_detach:
......@@ -1326,6 +1335,8 @@ static void __exit ubi_exit(void)
{
int i;
ubiblock_exit();
for (i = 0; i < UBI_MAX_DEVICES; i++)
if (ubi_devices[i]) {
mutex_lock(&ubi_devices_mutex);
......
......@@ -561,6 +561,26 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
break;
}
/* Attach a block device to an UBI volume */
case UBI_IOCVOLATTBLK:
{
struct ubi_volume_info vi;
ubi_get_volume_info(desc, &vi);
err = ubiblock_add(&vi);
break;
}
/* Dettach a block device from an UBI volume */
case UBI_IOCVOLDETBLK:
{
struct ubi_volume_info vi;
ubi_get_volume_info(desc, &vi);
err = ubiblock_del(&vi);
break;
}
default:
err = -ENOTTY;
break;
......
......@@ -864,6 +864,20 @@ int ubi_update_fastmap(struct ubi_device *ubi);
int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
int fm_anchor);
/* block.c */
#ifdef CONFIG_MTD_UBI_BLOCK
int ubiblock_init(void);
void ubiblock_exit(void);
int ubiblock_add(struct ubi_volume_info *vi);
int ubiblock_del(struct ubi_volume_info *vi);
#else
static inline int ubiblock_init(void) { return 0; }
static inline void ubiblock_exit(void) {}
static inline int ubiblock_add(struct ubi_volume_info *vi) { return -ENOTTY; }
static inline int ubiblock_del(struct ubi_volume_info *vi) { return -ENOTTY; }
#endif
/*
* ubi_rb_for_each_entry - walk an RB-tree.
* @rb: a pointer to type 'struct rb_node' to use as a loop counter
......
......@@ -134,6 +134,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 devices on 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.
*/
/*
......@@ -191,6 +198,10 @@
/* Set an UBI volume property */
#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
struct ubi_set_vol_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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment