Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Ezequiel Garcia and committed by
Artem Bityutskiy
9d54c8a3 5547fec7

+718
+15
drivers/mtd/ubi/Kconfig
··· 87 87 work on top of UBI. Do not enable this unless you use legacy 88 88 software. 89 89 90 + config MTD_UBI_BLOCK 91 + bool "Read-only block devices on top of UBI volumes" 92 + default n 93 + help 94 + This option enables read-only UBI block devices support. UBI block 95 + devices will be layered on top of UBI volumes, which means that the 96 + UBI driver will transparently handle things like bad eraseblocks and 97 + bit-flips. You can put any block-oriented file system on top of UBI 98 + volumes in read-only mode (e.g., ext4), but it is probably most 99 + practical for read-only file systems, like squashfs. 100 + 101 + When selected, this feature will be built in the UBI driver. 102 + 103 + If in doubt, say "N". 104 + 90 105 endif # MTD_UBI
+1
drivers/mtd/ubi/Makefile
··· 3 3 ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o 4 4 ubi-y += misc.o debug.o 5 5 ubi-$(CONFIG_MTD_UBI_FASTMAP) += fastmap.o 6 + ubi-$(CONFIG_MTD_UBI_BLOCK) += block.o 6 7 7 8 obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+646
drivers/mtd/ubi/block.c
··· 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 new 'block' parameter 33 + * to allow early block device attaching. Runtime block attach/detach for UBI 34 + * volumes is provided through two new UBI ioctls: UBI_IOCVOLATTBLK and 35 + * UBI_IOCVOLDETBLK. 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, &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 + 159 + static const struct kernel_param_ops ubiblock_param_ops = { 160 + .set = ubiblock_set_param, 161 + }; 162 + module_param_cb(block, &ubiblock_param_ops, NULL, 0); 163 + MODULE_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 + 174 + static 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 + 184 + static 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 + 198 + static 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 + loff_t 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 + 231 + static 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 + 262 + static 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 + 290 + static 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 + 304 + static 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 + 337 + out_done: 338 + dev->refcnt++; 339 + mutex_unlock(&dev->dev_mutex); 340 + return 0; 341 + 342 + out_unlock: 343 + mutex_unlock(&dev->dev_mutex); 344 + return ret; 345 + } 346 + 347 + static 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 + 360 + static 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 + 370 + static 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 + 377 + int ubiblock_add(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 + 449 + out_free_queue: 450 + blk_cleanup_queue(dev->rq); 451 + out_put_disk: 452 + put_disk(dev->gd); 453 + out_free_dev: 454 + kfree(dev); 455 + 456 + return ret; 457 + } 458 + 459 + static 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 + 467 + int ubiblock_del(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 + 499 + static 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 'ubiblock_del()'. 507 + */ 508 + mutex_lock(&devices_mutex); 509 + dev = find_dev_nolock(vi->ubi_num, vi->vol_id); 510 + if (!dev) { 511 + mutex_unlock(&devices_mutex); 512 + return; 513 + } 514 + 515 + mutex_lock(&dev->dev_mutex); 516 + disk_capacity = (vi->size * vi->usable_leb_size) >> 9; 517 + set_capacity(dev->gd, disk_capacity); 518 + ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size); 519 + mutex_unlock(&dev->dev_mutex); 520 + mutex_unlock(&devices_mutex); 521 + } 522 + 523 + static int ubiblock_notify(struct notifier_block *nb, 524 + unsigned long notification_type, void *ns_ptr) 525 + { 526 + struct ubi_notification *nt = ns_ptr; 527 + 528 + switch (notification_type) { 529 + case UBI_VOLUME_ADDED: 530 + /* 531 + * We want to enforce explicit block device attaching for 532 + * volumes, so when a volume is added we do nothing. 533 + */ 534 + break; 535 + case UBI_VOLUME_REMOVED: 536 + ubiblock_del(&nt->vi); 537 + break; 538 + case UBI_VOLUME_RESIZED: 539 + ubiblock_resize(&nt->vi); 540 + break; 541 + default: 542 + break; 543 + } 544 + return NOTIFY_OK; 545 + } 546 + 547 + static struct notifier_block ubiblock_notifier = { 548 + .notifier_call = ubiblock_notify, 549 + }; 550 + 551 + static struct ubi_volume_desc * __init 552 + open_volume_desc(const char *name, int ubi_num, int vol_id) 553 + { 554 + if (ubi_num == -1) 555 + /* No ubi num, name must be a vol device path */ 556 + return ubi_open_volume_path(name, UBI_READONLY); 557 + else if (vol_id == -1) 558 + /* No vol_id, must be vol_name */ 559 + return ubi_open_volume_nm(ubi_num, name, UBI_READONLY); 560 + else 561 + return ubi_open_volume(ubi_num, vol_id, UBI_READONLY); 562 + } 563 + 564 + static int __init ubiblock_attach_from_param(void) 565 + { 566 + int i, ret; 567 + struct ubiblock_param *p; 568 + struct ubi_volume_desc *desc; 569 + struct ubi_volume_info vi; 570 + 571 + for (i = 0; i < ubiblock_devs; i++) { 572 + p = &ubiblock_param[i]; 573 + 574 + desc = open_volume_desc(p->name, p->ubi_num, p->vol_id); 575 + if (IS_ERR(desc)) { 576 + ubi_err("block: can't open volume, err=%ld\n", 577 + PTR_ERR(desc)); 578 + ret = PTR_ERR(desc); 579 + break; 580 + } 581 + 582 + ubi_get_volume_info(desc, &vi); 583 + ubi_close_volume(desc); 584 + 585 + ret = ubiblock_add(&vi); 586 + if (ret) { 587 + ubi_err("block: can't add '%s' volume, err=%d\n", 588 + vi.name, ret); 589 + break; 590 + } 591 + } 592 + return ret; 593 + } 594 + 595 + static void ubiblock_detach_all(void) 596 + { 597 + struct ubiblock *next; 598 + struct ubiblock *dev; 599 + 600 + list_for_each_entry_safe(dev, next, &ubiblock_devices, list) { 601 + /* Flush pending work and stop workqueue */ 602 + destroy_workqueue(dev->wq); 603 + /* The module is being forcefully removed */ 604 + WARN_ON(dev->desc); 605 + /* Remove from device list */ 606 + list_del(&dev->list); 607 + ubiblock_cleanup(dev); 608 + kfree(dev); 609 + } 610 + } 611 + 612 + int __init ubiblock_init(void) 613 + { 614 + int ret; 615 + 616 + ubiblock_major = register_blkdev(0, "ubiblock"); 617 + if (ubiblock_major < 0) 618 + return ubiblock_major; 619 + 620 + /* Attach block devices from 'block=' module param */ 621 + ret = ubiblock_attach_from_param(); 622 + if (ret) 623 + goto err_detach; 624 + 625 + /* 626 + * Block devices needs to be attached to volumes explicitly 627 + * upon user request. So we ignore existing volumes. 628 + */ 629 + ret = ubi_register_volume_notifier(&ubiblock_notifier, 1); 630 + if (ret) 631 + goto err_unreg; 632 + return 0; 633 + 634 + err_unreg: 635 + unregister_blkdev(ubiblock_major, "ubiblock"); 636 + err_detach: 637 + ubiblock_detach_all(); 638 + return ret; 639 + } 640 + 641 + void __exit ubiblock_exit(void) 642 + { 643 + ubi_unregister_volume_notifier(&ubiblock_notifier); 644 + ubiblock_detach_all(); 645 + unregister_blkdev(ubiblock_major, "ubiblock"); 646 + }
+11
drivers/mtd/ubi/build.c
··· 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 1310 return 0; 1302 1311 1303 1312 out_detach: ··· 1334 1325 static void __exit ubi_exit(void) 1335 1326 { 1336 1327 int i; 1328 + 1329 + ubiblock_exit(); 1337 1330 1338 1331 for (i = 0; i < UBI_MAX_DEVICES; i++) 1339 1332 if (ubi_devices[i]) {
+20
drivers/mtd/ubi/cdev.c
··· 561 561 break; 562 562 } 563 563 564 + /* Attach a block device to an UBI volume */ 565 + case UBI_IOCVOLATTBLK: 566 + { 567 + struct ubi_volume_info vi; 568 + 569 + ubi_get_volume_info(desc, &vi); 570 + err = ubiblock_add(&vi); 571 + break; 572 + } 573 + 574 + /* Dettach a block device from an UBI volume */ 575 + case UBI_IOCVOLDETBLK: 576 + { 577 + struct ubi_volume_info vi; 578 + 579 + ubi_get_volume_info(desc, &vi); 580 + err = ubiblock_del(&vi); 581 + break; 582 + } 583 + 564 584 default: 565 585 err = -ENOTTY; 566 586 break;
+14
drivers/mtd/ubi/ubi.h
··· 864 864 int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, 865 865 int fm_anchor); 866 866 867 + /* block.c */ 868 + #ifdef CONFIG_MTD_UBI_BLOCK 869 + int ubiblock_init(void); 870 + void ubiblock_exit(void); 871 + int ubiblock_add(struct ubi_volume_info *vi); 872 + int ubiblock_del(struct ubi_volume_info *vi); 873 + #else 874 + static inline int ubiblock_init(void) { return 0; } 875 + static inline void ubiblock_exit(void) {} 876 + static inline int ubiblock_add(struct ubi_volume_info *vi) { return -ENOTTY; } 877 + static inline int ubiblock_del(struct ubi_volume_info *vi) { return -ENOTTY; } 878 + #endif 879 + 880 + 867 881 /* 868 882 * ubi_rb_for_each_entry - walk an RB-tree. 869 883 * @rb: a pointer to type 'struct rb_node' to use as a loop counter
+11
include/uapi/mtd/ubi-user.h
··· 134 134 * used. A pointer to a &struct ubi_set_vol_prop_req object is expected to be 135 135 * passed. The object describes which property should be set, and to which value 136 136 * it should be set. 137 + * 138 + * Block devices on UBI volumes 139 + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 140 + * 141 + * To attach or detach a block device from an UBI volume the %UBI_IOCVOLATTBLK 142 + * and %UBI_IOCVOLDETBLK ioctl commands should be used, respectively. 143 + * These commands take no arguments. 137 144 */ 138 145 139 146 /* ··· 198 191 /* Set an UBI volume property */ 199 192 #define UBI_IOCSETVOLPROP _IOW(UBI_VOL_IOC_MAGIC, 6, \ 200 193 struct ubi_set_vol_prop_req) 194 + /* Attach a block device to an UBI volume */ 195 + #define UBI_IOCVOLATTBLK _IO(UBI_VOL_IOC_MAGIC, 7) 196 + /* Detach a block device from an UBI volume */ 197 + #define UBI_IOCVOLDETBLK _IO(UBI_VOL_IOC_MAGIC, 8) 201 198 202 199 /* Maximum MTD device name length supported by UBI */ 203 200 #define MAX_UBI_MTD_NAME_LEN 127