mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
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: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
This commit is contained in:
committed by
Artem Bityutskiy
parent
5547fec74a
commit
9d54c8a33e
@@ -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
|
||||
|
||||
646
drivers/mtd/ubi/block.c
Normal file
646
drivers/mtd/ubi/block.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user