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;
152 }
153
154 ubiblock_devs++;
155
156 return 0;
157}
158
159static struct kernel_param_ops ubiblock_param_ops = {
160 .set = ubiblock_set_param,
161};
162module_param_cb(block, &ubiblock_param_ops, NULL, 0);
163MODULE_PARM_DESC(block, "Attach block devices to UBI volumes. Parameter format: block=<path|dev,num|dev,name>.\n"
164 "Multiple \"block\" parameters may be specified.\n"
165 "UBI volumes may be specified by their number, name, or path to the device node.\n"
166 "Examples\n"
167 "Using the UBI volume path:\n"
168 "ubi.block=/dev/ubi0_0\n"
169 "Using the UBI device, and the volume name:\n"
170 "ubi.block=0,rootfs\n"
171 "Using both UBI device number and UBI volume number:\n"
172 "ubi.block=0,0\n");
173
174static struct ubiblock *find_dev_nolock(int ubi_num, int vol_id)
175{
176 struct ubiblock *dev;
177
178 list_for_each_entry(dev, &ubiblock_devices, list)
179 if (dev->ubi_num == ubi_num && dev->vol_id == vol_id)
180 return dev;
181 return NULL;
182}
183
184static int ubiblock_read_to_buf(struct ubiblock *dev, char *buffer,
185 int leb, int offset, int len)
186{
187 int ret;
188
189 ret = ubi_read(dev->desc, leb, buffer, offset, len);
190 if (ret) {
191 ubi_err("%s ubi_read error %d",
192 dev->gd->disk_name, ret);
193 return ret;
194 }
195 return 0;
196}
197
198static int ubiblock_read(struct ubiblock *dev, char *buffer,
199 sector_t sec, int len)
200{
201 int ret, leb, offset;
202 int bytes_left = len;
203 int to_read = len;
204 u64 pos = sec << 9;
205
206 /* Get LEB:offset address to read from */
207 offset = do_div(pos, dev->leb_size);
208 leb = pos;
209
210 while (bytes_left) {
211 /*
212 * We can only read one LEB at a time. Therefore if the read
213 * length is larger than one LEB size, we split the operation.
214 */
215 if (offset + to_read > dev->leb_size)
216 to_read = dev->leb_size - offset;
217
218 ret = ubiblock_read_to_buf(dev, buffer, leb, offset, to_read);
219 if (ret)
220 return ret;
221
222 buffer += to_read;
223 bytes_left -= to_read;
224 to_read = bytes_left;
225 leb += 1;
226 offset = 0;
227 }
228 return 0;
229}
230
231static int do_ubiblock_request(struct ubiblock *dev, struct request *req)
232{
233 int len, ret;
234 sector_t sec;
235
236 if (req->cmd_type != REQ_TYPE_FS)
237 return -EIO;
238
239 if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
240 get_capacity(req->rq_disk))
241 return -EIO;
242
243 if (rq_data_dir(req) != READ)
244 return -ENOSYS; /* Write not implemented */
245
246 sec = blk_rq_pos(req);
247 len = blk_rq_cur_bytes(req);
248
249 /*
250 * Let's prevent the device from being removed while we're doing I/O
251 * work. Notice that this means we serialize all the I/O operations,
252 * but it's probably of no impact given the NAND core serializes
253 * flash access anyway.
254 */
255 mutex_lock(&dev->dev_mutex);
256 ret = ubiblock_read(dev, req->buffer, sec, len);
257 mutex_unlock(&dev->dev_mutex);
258
259 return ret;
260}
261
262static void ubiblock_do_work(struct work_struct *work)
263{
264 struct ubiblock *dev =
265 container_of(work, struct ubiblock, work);
266 struct request_queue *rq = dev->rq;
267 struct request *req;
268 int res;
269
270 spin_lock_irq(rq->queue_lock);
271
272 req = blk_fetch_request(rq);
273 while (req) {
274
275 spin_unlock_irq(rq->queue_lock);
276 res = do_ubiblock_request(dev, req);
277 spin_lock_irq(rq->queue_lock);
278
279 /*
280 * If we're done with this request,
281 * we need to fetch a new one
282 */
283 if (!__blk_end_request_cur(req, res))
284 req = blk_fetch_request(rq);
285 }
286
287 spin_unlock_irq(rq->queue_lock);
288}
289
290static void ubiblock_request(struct request_queue *rq)
291{
292 struct ubiblock *dev;
293 struct request *req;
294
295 dev = rq->queuedata;
296
297 if (!dev)
298 while ((req = blk_fetch_request(rq)) != NULL)
299 __blk_end_request_all(req, -ENODEV);
300 else
301 queue_work(dev->wq, &dev->work);
302}
303
304static int ubiblock_open(struct block_device *bdev, fmode_t mode)
305{
306 struct ubiblock *dev = bdev->bd_disk->private_data;
307 int ret;
308
309 mutex_lock(&dev->dev_mutex);
310 if (dev->refcnt > 0) {
311 /*
312 * The volume is already open, just increase the reference
313 * counter.
314 */
315 goto out_done;
316 }
317
318 /*
319 * We want users to be aware they should only mount us as read-only.
320 * It's just a paranoid check, as write requests will get rejected
321 * in any case.
322 */
323 if (mode & FMODE_WRITE) {
324 ret = -EPERM;
325 goto out_unlock;
326 }
327
328 dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY);
329 if (IS_ERR(dev->desc)) {
330 ubi_err("%s failed to open ubi volume %d_%d",
331 dev->gd->disk_name, dev->ubi_num, dev->vol_id);
332 ret = PTR_ERR(dev->desc);
333 dev->desc = NULL;
334 goto out_unlock;
335 }
336
337out_done:
338 dev->refcnt++;
339 mutex_unlock(&dev->dev_mutex);
340 return 0;
341
342out_unlock:
343 mutex_unlock(&dev->dev_mutex);
344 return ret;
345}
346
347static void ubiblock_release(struct gendisk *gd, fmode_t mode)
348{
349 struct ubiblock *dev = gd->private_data;
350
351 mutex_lock(&dev->dev_mutex);
352 dev->refcnt--;
353 if (dev->refcnt == 0) {
354 ubi_close_volume(dev->desc);
355 dev->desc = NULL;
356 }
357 mutex_unlock(&dev->dev_mutex);
358}
359
360static int ubiblock_getgeo(struct block_device *bdev, struct hd_geometry *geo)
361{
362 /* Some tools might require this information */
363 geo->heads = 1;
364 geo->cylinders = 1;
365 geo->sectors = get_capacity(bdev->bd_disk);
366 geo->start = 0;
367 return 0;
368}
369
370static const struct block_device_operations ubiblock_ops = {
371 .owner = THIS_MODULE,
372 .open = ubiblock_open,
373 .release = ubiblock_release,
374 .getgeo = ubiblock_getgeo,
375};
376
377int ubiblock_create(struct ubi_volume_info *vi)
378{
379 struct ubiblock *dev;
380 struct gendisk *gd;
381 int disk_capacity;
382 int ret;
383
384 /* Check that the volume isn't already handled */
385 mutex_lock(&devices_mutex);
386 if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
387 mutex_unlock(&devices_mutex);
388 return -EEXIST;
389 }
390 mutex_unlock(&devices_mutex);
391
392 dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
393 if (!dev)
394 return -ENOMEM;
395
396 mutex_init(&dev->dev_mutex);
397
398 dev->ubi_num = vi->ubi_num;
399 dev->vol_id = vi->vol_id;
400 dev->leb_size = vi->usable_leb_size;
401
402 /* Initialize the gendisk of this ubiblock device */
403 gd = alloc_disk(1);
404 if (!gd) {
405 ubi_err("block: alloc_disk failed");
406 ret = -ENODEV;
407 goto out_free_dev;
408 }
409
410 gd->fops = &ubiblock_ops;
411 gd->major = ubiblock_major;
412 gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
413 gd->private_data = dev;
414 sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
415 disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
416 set_capacity(gd, disk_capacity);
417 dev->gd = gd;
418
419 spin_lock_init(&dev->queue_lock);
420 dev->rq = blk_init_queue(ubiblock_request, &dev->queue_lock);
421 if (!dev->rq) {
422 ubi_err("block: blk_init_queue failed");
423 ret = -ENODEV;
424 goto out_put_disk;
425 }
426
427 dev->rq->queuedata = dev;
428 dev->gd->queue = dev->rq;
429
430 /*
431 * Create one workqueue per volume (per registered block device).
432 * Rembember workqueues are cheap, they're not threads.
433 */
434 dev->wq = alloc_workqueue(gd->disk_name, 0, 0);
435 if (!dev->wq)
436 goto out_free_queue;
437 INIT_WORK(&dev->work, ubiblock_do_work);
438
439 mutex_lock(&devices_mutex);
440 list_add_tail(&dev->list, &ubiblock_devices);
441 mutex_unlock(&devices_mutex);
442
443 /* Must be the last step: anyone can call file ops from now on */
444 add_disk(dev->gd);
445 ubi_msg("%s created from ubi%d:%d(%s)",
446 dev->gd->disk_name, dev->ubi_num, dev->vol_id, vi->name);
447 return 0;
448
449out_free_queue:
450 blk_cleanup_queue(dev->rq);
451out_put_disk:
452 put_disk(dev->gd);
453out_free_dev:
454 kfree(dev);
455
456 return ret;
457}
458
459static void ubiblock_cleanup(struct ubiblock *dev)
460{
461 del_gendisk(dev->gd);
462 blk_cleanup_queue(dev->rq);
463 ubi_msg("%s released", dev->gd->disk_name);
464 put_disk(dev->gd);
465}
466
467int ubiblock_remove(struct ubi_volume_info *vi)
468{
469 struct ubiblock *dev;
470
471 mutex_lock(&devices_mutex);
472 dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
473 if (!dev) {
474 mutex_unlock(&devices_mutex);
475 return -ENODEV;
476 }
477
478 /* Found a device, let's lock it so we can check if it's busy */
479 mutex_lock(&dev->dev_mutex);
480 if (dev->refcnt > 0) {
481 mutex_unlock(&dev->dev_mutex);
482 mutex_unlock(&devices_mutex);
483 return -EBUSY;
484 }
485
486 /* Remove from device list */
487 list_del(&dev->list);
488 mutex_unlock(&devices_mutex);
489
490 /* Flush pending work and stop this workqueue */
491 destroy_workqueue(dev->wq);
492
493 ubiblock_cleanup(dev);
494 mutex_unlock(&dev->dev_mutex);
495 kfree(dev);
496 return 0;
497}
498
499static void ubiblock_resize(struct ubi_volume_info *vi)
500{
501 struct ubiblock *dev;
502 int disk_capacity;
503
504 /*
505 * Need to lock the device list until we stop using the device,
506 * otherwise the device struct might get released in
507 * 'ubiblock_remove()'.
508 */
509 mutex_lock(&devices_mutex);
510 dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
511 if (!dev) {
512 mutex_unlock(&devices_mutex);
513 return;
514 }
515
516 mutex_lock(&dev->dev_mutex);
517 disk_capacity = (vi->size * vi->usable_leb_size) >> 9;
518 set_capacity(dev->gd, disk_capacity);
519 ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size);
520 mutex_unlock(&dev->dev_mutex);
521 mutex_unlock(&devices_mutex);
522}
523
524static int ubiblock_notify(struct notifier_block *nb,
525 unsigned long notification_type, void *ns_ptr)
526{
527 struct ubi_notification *nt = ns_ptr;
528
529 switch (notification_type) {
530 case UBI_VOLUME_ADDED:
531 /*
532 * We want to enforce explicit block device creation for
533 * volumes, so when a volume is added we do nothing.
534 */
535 break;
536 case UBI_VOLUME_REMOVED:
537 ubiblock_remove(&nt->vi);
538 break;
539 case UBI_VOLUME_RESIZED:
540 ubiblock_resize(&nt->vi);
541 break;
542 default:
543 break;
544 }
545 return NOTIFY_OK;
546}
547
548static struct notifier_block ubiblock_notifier = {
549 .notifier_call = ubiblock_notify,
550};
551
552static struct ubi_volume_desc * __init
553open_volume_desc(const char *name, int ubi_num, int vol_id)
554{
555 if (ubi_num == -1)
556 /* No ubi num, name must be a vol device path */
557 return ubi_open_volume_path(name, UBI_READONLY);
558 else if (vol_id == -1)
559 /* No vol_id, must be vol_name */
560 return ubi_open_volume_nm(ubi_num, name, UBI_READONLY);
561 else
562 return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
563}
564
565static int __init ubiblock_create_from_param(void)
566{
567 int i, ret;
568 struct ubiblock_param *p;
569 struct ubi_volume_desc *desc;
570 struct ubi_volume_info vi;
571
572 for (i = 0; i < ubiblock_devs; i++) {
573 p = &ubiblock_param[i];
574
575 desc = open_volume_desc(p->name, p->ubi_num, p->vol_id);
576 if (IS_ERR(desc)) {
577 ubi_err("block: can't open volume, err=%ld\n",
578 PTR_ERR(desc));
579 ret = PTR_ERR(desc);
580 break;
581 }
582
583 ubi_get_volume_info(desc, &vi);
584 ubi_close_volume(desc);
585
586 ret = ubiblock_create(&vi);
587 if (ret) {
588 ubi_err("block: can't add '%s' volume, err=%d\n",
589 vi.name, ret);
590 break;
591 }
592 }
593 return ret;
594}
595
596static void ubiblock_remove_all(void)
597{
598 struct ubiblock *next;
599 struct ubiblock *dev;
600
601 list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
602 /* Flush pending work and stop workqueue */
603 destroy_workqueue(dev->wq);
604 /* The module is being forcefully removed */
605 WARN_ON(dev->desc);
606 /* Remove from device list */
607 list_del(&dev->list);
608 ubiblock_cleanup(dev);
609 kfree(dev);
610 }
611}
612
613int __init ubiblock_init(void)
614{
615 int ret;
616
617 ubiblock_major = register_blkdev(0, "ubiblock");
618 if (ubiblock_major < 0)
619 return ubiblock_major;
620
621 /* Attach block devices from 'block=' module param */
622 ret = ubiblock_create_from_param();
623 if (ret)
624 goto err_remove;
625
626 /*
627 * Block devices are only created upon user requests, so we ignore
628 * existing volumes.
629 */
630 ret = ubi_register_volume_notifier(&ubiblock_notifier, 1);
631 if (ret)
632 goto err_unreg;
633 return 0;
634
635err_unreg:
636 unregister_blkdev(ubiblock_major, "ubiblock");
637err_remove:
638 ubiblock_remove_all();
639 return ret;
640}
641
642void __exit ubiblock_exit(void)
643{
644 ubi_unregister_volume_notifier(&ubiblock_notifier);
645 ubiblock_remove_all();
646 unregister_blkdev(ubiblock_major, "ubiblock");
647}
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 57deae961429..6e30a3c280d0 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -1298,6 +1298,15 @@ static int __init ubi_init(void)
1298 } 1298 }
1299 } 1299 }
1300 1300
1301 err = ubiblock_init();
1302 if (err) {
1303 ubi_err("block: cannot initialize, error %d", err);
1304
1305 /* See comment above re-ubi_is_module(). */
1306 if (ubi_is_module())
1307 goto out_detach;
1308 }
1309
1301 return 0; 1310 return 0;
1302 1311
1303out_detach: 1312out_detach:
@@ -1326,6 +1335,8 @@ static void __exit ubi_exit(void)
1326{ 1335{
1327 int i; 1336 int i;
1328 1337
1338 ubiblock_exit();
1339
1329 for (i = 0; i < UBI_MAX_DEVICES; i++) 1340 for (i = 0; i < UBI_MAX_DEVICES; i++)
1330 if (ubi_devices[i]) { 1341 if (ubi_devices[i]) {
1331 mutex_lock(&ubi_devices_mutex); 1342 mutex_lock(&ubi_devices_mutex);
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 8ca49f2043e4..f54562a5998e 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -561,6 +561,26 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd,
561 break; 561 break;
562 } 562 }
563 563
564 /* Create a R/O block device on top of the UBI volume */
565 case UBI_IOCVOLCRBLK:
566 {
567 struct ubi_volume_info vi;
568
569 ubi_get_volume_info(desc, &vi);
570 err = ubiblock_create(&vi);
571 break;
572 }
573
574 /* Remove the R/O block device */
575 case UBI_IOCVOLRMBLK:
576 {
577 struct ubi_volume_info vi;
578
579 ubi_get_volume_info(desc, &vi);
580 err = ubiblock_remove(&vi);
581 break;
582 }
583
564 default: 584 default:
565 err = -ENOTTY; 585 err = -ENOTTY;
566 break; 586 break;
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8ea6297a208f..0ba8b0a28838 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -864,6 +864,26 @@ int ubi_update_fastmap(struct ubi_device *ubi);
864int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, 864int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
865 int fm_anchor); 865 int fm_anchor);
866 866
867/* block.c */
868#ifdef CONFIG_MTD_UBI_BLOCK
869int ubiblock_init(void);
870void ubiblock_exit(void);
871int ubiblock_create(struct ubi_volume_info *vi);
872int ubiblock_remove(struct ubi_volume_info *vi);
873#else
874static inline int ubiblock_init(void) { return 0; }
875static inline void ubiblock_exit(void) {}
876static inline int ubiblock_create(struct ubi_volume_info *vi)
877{
878 return -ENOSYS;
879}
880static inline int ubiblock_remove(struct ubi_volume_info *vi)
881{
882 return -ENOSYS;
883}
884#endif
885
886
867/* 887/*
868 * ubi_rb_for_each_entry - walk an RB-tree. 888 * ubi_rb_for_each_entry - walk an RB-tree.
869 * @rb: a pointer to type 'struct rb_node' to use as a loop counter 889 * @rb: a pointer to type 'struct rb_node' to use as a loop counter
diff --git a/include/uapi/mtd/ubi-user.h b/include/uapi/mtd/ubi-user.h
index 723c324590c1..1927b0d78a99 100644
--- a/include/uapi/mtd/ubi-user.h
+++ b/include/uapi/mtd/ubi-user.h
@@ -134,6 +134,16 @@
134 * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be 134 * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be
135 * passed. The object describes which property should be set, and to which value 135 * passed. The object describes which property should be set, and to which value
136 * it should be set. 136 * it should be set.
137 *
138 * Block devices on UBI volumes
139 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
140 *
141 * To create a R/O block device on top of an UBI volume the %UBI_IOCVOLCRBLK
142 * should be used. A pointer to a &struct ubi_blkcreate_req object is expected
143 * to be passed, which is not used and reserved for future usage.
144 *
145 * Conversely, to remove a block device the %UBI_IOCVOLRMBLK should be used,
146 * which takes no arguments.
137 */ 147 */
138 148
139/* 149/*
@@ -191,6 +201,10 @@
191/* Set an UBI volume property */ 201/* Set an UBI volume property */
192#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \ 202#define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \
193 struct ubi_set_vol_prop_req) 203 struct ubi_set_vol_prop_req)
204/* Create a R/O block device on top of an UBI volume */
205#define UBI_IOCVOLCRBLK _IOW(UBI_VOL_IOC_MAGIC, 7, struct ubi_blkcreate_req)
206/* Remove the R/O block device */
207#define UBI_IOCVOLRMBLK _IO(UBI_VOL_IOC_MAGIC, 8)
194 208
195/* Maximum MTD device name length supported by UBI */ 209/* Maximum MTD device name length supported by UBI */
196#define MAX_UBI_MTD_NAME_LEN 127 210#define MAX_UBI_MTD_NAME_LEN 127
@@ -420,4 +434,12 @@ struct ubi_set_vol_prop_req {
420 __u64 value; 434 __u64 value;
421} __packed; 435} __packed;
422 436
437/**
438 * struct ubi_blkcreate_req - a data structure used in block creation requests.
439 * @padding: reserved for future, not used, has to be zeroed
440 */
441struct ubi_blkcreate_req {
442 __s8 padding[128];
443} __packed;
444
423#endif /* __UBI_USER_H__ */ 445#endif /* __UBI_USER_H__ */