diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 18:35:38 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-04-04 18:35:38 -0400 |
| commit | 370d2662d569f22ac3d598cd4475617cd910c759 (patch) | |
| tree | 127b1cd120174be71ce74488694a48df6c87571e | |
| parent | d15fee814d8d30bbb4859ef8fef7a1f96327635b (diff) | |
| parent | d56030ac25d383218045c5d87e98e0494d6af3ad (diff) | |
Merge tag 'upstream-3.15-rc1' of git://git.infradead.org/linux-ubifs
Pull ubifs updates from Artem Bityutskiy:
"This pull request includes the 'ubiblock' driver which provides R/O
block access to UBI volumes. It is useful for those who want to use
squashfs on top of raw flash devices. UBI will provide bit-flip
handling and wear-levelling in this case (e.g., if there are other UBI
volumes with R/W UBIFS too).
The driver is actually pretty small and it is part of the UBI kernel
subsystem. Delivered by Ezequiel Garcia, along with a piece of
documentation on the MTD web site and the user-space tool for creating
and removing block devices"
* tag 'upstream-3.15-rc1' of git://git.infradead.org/linux-ubifs:
UBI: block: Remove __initdata from ubiblock_param_ops
UBI: make UBI_IOCVOLCRBLK take a parameter for future usage
UBI: rename block device ioctls
UBI: block: Use ENOSYS as return value when CONFIG_UBIBLOCK=n
UBI: block: Add CONFIG_BLOCK dependency
UBI: block: Use 'u64' for the 64-bit dividend
UBI: block: Mark init-only symbol as __initdata
UBI: block: do not use term "attach"
UBI: R/O block driver on top of UBI volumes
| -rw-r--r-- | drivers/mtd/ubi/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/mtd/ubi/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mtd/ubi/block.c | 647 | ||||
| -rw-r--r-- | drivers/mtd/ubi/build.c | 11 | ||||
| -rw-r--r-- | drivers/mtd/ubi/cdev.c | 20 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 20 | ||||
| -rw-r--r-- | include/uapi/mtd/ubi-user.h | 22 |
7 files changed, 737 insertions, 0 deletions
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 36663af56d89..f0855ce08ed9 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig | |||
| @@ -87,4 +87,20 @@ config MTD_UBI_GLUEBI | |||
| 87 | work on top of UBI. Do not enable this unless you use legacy | 87 | work on top of UBI. Do not enable this unless you use legacy |
| 88 | software. | 88 | software. |
| 89 | 89 | ||
| 90 | config MTD_UBI_BLOCK | ||
| 91 | bool "Read-only block devices on top of UBI volumes" | ||
| 92 | default n | ||
| 93 | depends on BLOCK | ||
| 94 | help | ||
| 95 | This option enables read-only UBI block devices support. UBI block | ||
| 96 | devices will be layered on top of UBI volumes, which means that the | ||
| 97 | UBI driver will transparently handle things like bad eraseblocks and | ||
| 98 | bit-flips. You can put any block-oriented file system on top of UBI | ||
| 99 | volumes in read-only mode (e.g., ext4), but it is probably most | ||
| 100 | practical for read-only file systems, like squashfs. | ||
| 101 | |||
| 102 | When selected, this feature will be built in the UBI driver. | ||
| 103 | |||
| 104 | If in doubt, say "N". | ||
| 105 | |||
| 90 | endif # MTD_UBI | 106 | endif # MTD_UBI |
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile index b46b0c978581..4e3c3d70d8c3 100644 --- a/drivers/mtd/ubi/Makefile +++ b/drivers/mtd/ubi/Makefile | |||
| @@ -3,5 +3,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o | |||
| 3 | ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o | 3 | ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o |
| 4 | ubi-y += misc.o debug.o | 4 | ubi-y += misc.o debug.o |
| 5 | ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o | 5 | ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o |
| 6 | ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o | ||
| 6 | 7 | ||
| 7 | obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o | 8 | obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o |
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c new file mode 100644 index 000000000000..7ff473c871a9 --- /dev/null +++ b/drivers/mtd/ubi/block.c | |||
| @@ -0,0 +1,647 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Ezequiel Garcia | ||
| 3 | * Copyright (c) 2011 Free Electrons | ||
| 4 | * | ||
| 5 | * Driver parameter handling strongly based on drivers/mtd/ubi/build.c | ||
| 6 | * Copyright (c) International Business Machines Corp., 2006 | ||
| 7 | * Copyright (c) Nokia Corporation, 2007 | ||
| 8 | * Authors: Artem Bityutskiy, Frank Haverkamp | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation, version 2. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | ||
| 17 | * the GNU General Public License for more details. | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* | ||
| 21 | * Read-only block devices on top of UBI volumes | ||
| 22 | * | ||
| 23 | * A simple implementation to allow a block device to be layered on top of a | ||
| 24 | * UBI volume. The implementation is provided by creating a static 1-to-1 | ||
| 25 | * mapping between the block device and the UBI volume. | ||
| 26 | * | ||
| 27 | * The addressed byte is obtained from the addressed block sector, which is | ||
| 28 | * mapped linearly into the corresponding LEB: | ||
| 29 | * | ||
| 30 | * LEB number = addressed byte / LEB size | ||
| 31 | * | ||
| 32 | * This feature is compiled in the UBI core, and adds a 'block' parameter | ||
| 33 | * to allow early creation of block devices on top of UBI volumes. Runtime | ||
| 34 | * block creation/removal for UBI volumes is provided through two UBI ioctls: | ||
| 35 | * UBI_IOCVOLCRBLK and UBI_IOCVOLRMBLK. | ||
| 36 | */ | ||
| 37 | |||
| 38 | #include <linux/module.h> | ||
| 39 | #include <linux/init.h> | ||
| 40 | #include <linux/err.h> | ||
| 41 | #include <linux/kernel.h> | ||
| 42 | #include <linux/list.h> | ||
| 43 | #include <linux/mutex.h> | ||
| 44 | #include <linux/slab.h> | ||
| 45 | #include <linux/vmalloc.h> | ||
| 46 | #include <linux/mtd/ubi.h> | ||
| 47 | #include <linux/workqueue.h> | ||
| 48 | #include <linux/blkdev.h> | ||
| 49 | #include <linux/hdreg.h> | ||
| 50 | #include <asm/div64.h> | ||
| 51 | |||
| 52 | #include "ubi-media.h" | ||
| 53 | #include "ubi.h" | ||
| 54 | |||
| 55 | /* Maximum number of supported devices */ | ||
| 56 | #define UBIBLOCK_MAX_DEVICES 32 | ||
| 57 | |||
| 58 | /* Maximum length of the 'block=' parameter */ | ||
| 59 | #define UBIBLOCK_PARAM_LEN 63 | ||
| 60 | |||
| 61 | /* Maximum number of comma-separated items in the 'block=' parameter */ | ||
| 62 | #define UBIBLOCK_PARAM_COUNT 2 | ||
| 63 | |||
| 64 | struct ubiblock_param { | ||
| 65 | int ubi_num; | ||
| 66 | int vol_id; | ||
| 67 | char name[UBIBLOCK_PARAM_LEN+1]; | ||
| 68 | }; | ||
| 69 | |||
| 70 | /* Numbers of elements set in the @ubiblock_param array */ | ||
| 71 | static int ubiblock_devs __initdata; | ||
| 72 | |||
| 73 | /* MTD devices specification parameters */ | ||
| 74 | static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata; | ||
| 75 | |||
| 76 | struct ubiblock { | ||
| 77 | struct ubi_volume_desc *desc; | ||
| 78 | int ubi_num; | ||
| 79 | int vol_id; | ||
| 80 | int refcnt; | ||
| 81 | int leb_size; | ||
| 82 | |||
| 83 | struct gendisk *gd; | ||
| 84 | struct request_queue *rq; | ||
| 85 | |||
| 86 | struct workqueue_struct *wq; | ||
| 87 | struct work_struct work; | ||
| 88 | |||
| 89 | struct mutex dev_mutex; | ||
| 90 | spinlock_t queue_lock; | ||
| 91 | struct list_head list; | ||
| 92 | }; | ||
| 93 | |||
| 94 | /* Linked list of all ubiblock instances */ | ||
| 95 | static LIST_HEAD(ubiblock_devices); | ||
| 96 | static DEFINE_MUTEX(devices_mutex); | ||
| 97 | static int ubiblock_major; | ||
| 98 | |||
| 99 | static int __init ubiblock_set_param(const char *val, | ||
| 100 | const struct kernel_param *kp) | ||
| 101 | { | ||
| 102 | int i, ret; | ||
| 103 | size_t len; | ||
| 104 | struct ubiblock_param *param; | ||
| 105 | char buf[UBIBLOCK_PARAM_LEN]; | ||
| 106 | char *pbuf = &buf[0]; | ||
| 107 | char *tokens[UBIBLOCK_PARAM_COUNT]; | ||
| 108 | |||
| 109 | if (!val) | ||
| 110 | return -EINVAL; | ||
| 111 | |||
| 112 | len = strnlen(val, UBIBLOCK_PARAM_LEN); | ||
| 113 | if (len == 0) { | ||
| 114 | ubi_warn("block: empty 'block=' parameter - ignored\n"); | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | if (len == UBIBLOCK_PARAM_LEN) { | ||
| 119 | ubi_err("block: parameter \"%s\" is too long, max. is %d\n", | ||
| 120 | val, UBIBLOCK_PARAM_LEN); | ||
| 121 | return -EINVAL; | ||
| 122 | } | ||
| 123 | |||
| 124 | strcpy(buf, val); | ||
| 125 | |||
| 126 | /* Get rid of the final newline */ | ||
| 127 | if (buf[len - 1] == '\n') | ||
| 128 | buf[len - 1] = '\0'; | ||
| 129 | |||
| 130 | for (i = 0; i < UBIBLOCK_PARAM_COUNT; i++) | ||
| 131 | tokens[i] = strsep(&pbuf, ","); | ||
| 132 | |||
| 133 | param = &ubiblock_param[ubiblock_devs]; | ||
| 134 | if (tokens[1]) { | ||
| 135 | /* Two parameters: can be 'ubi, vol_id' or 'ubi, vol_name' */ | ||
| 136 | ret = kstrtoint(tokens[0], 10, ¶m->ubi_num); | ||
| 137 | if (ret < 0) | ||
| 138 | return -EINVAL; | ||
| 139 | |||
| 140 | /* Second param can be a number or a name */ | ||
| 141 | ret = kstrtoint(tokens[1], 10, ¶m->vol_id); | ||
| 142 | if (ret < 0) { | ||
| 143 | param->vol_id = -1; | ||
| 144 | strcpy(param->name, tokens[1]); | ||
| 145 | } | ||
| 146 | |||
| 147 | } else { | ||
| 148 | /* One parameter: must be device path */ | ||
| 149 | strcpy(param->name, tokens[0]); | ||
| 150 | param->ubi_num = -1; | ||
| 151 | param->vol_id = -1; | ||
