aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 18:35:38 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-04 18:35:38 -0400
commit370d2662d569f22ac3d598cd4475617cd910c759 (patch)
tree127b1cd120174be71ce74488694a48df6c87571e
parentd15fee814d8d30bbb4859ef8fef7a1f96327635b (diff)
parentd56030ac25d383218045c5d87e98e0494d6af3ad (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/Kconfig16
-rw-r--r--drivers/mtd/ubi/Makefile1
-rw-r--r--drivers/mtd/ubi/block.c647
-rw-r--r--drivers/mtd/ubi/build.c11
-rw-r--r--drivers/mtd/ubi/cdev.c20
-rw-r--r--drivers/mtd/ubi/ubi.h20
-rw-r--r--include/uapi/mtd/ubi-user.h22
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
90config 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
90endif # MTD_UBI 106endif # 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
3ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o 3ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o
4ubi-y += misc.o debug.o 4ubi-y += misc.o debug.o
5ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o 5ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o
6ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o
6 7
7obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o 8obj-$(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
64struct 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 */
71static int ubiblock_devs __initdata;
72
73/* MTD devices specification parameters */
74static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
75
76struct 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 */
95static LIST_HEAD(ubiblock_devices);
96static DEFINE_MUTEX(devices_mutex);
97static int ubiblock_major;
98
99static 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, &param->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, &param->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;