Lines Matching +full:2 +full:- +full:layered

1 // SPDX-License-Identifier: GPL-2.0-only
13 * Read-only block devices on top of UBI volumes
15 * A simple implementation to allow a block device to be layered on top of a
16 * UBI volume. The implementation is provided by creating a static 1-to-1
39 #include <linux/blk-mq.h>
45 #include "ubi-media.h"
54 /* Maximum number of comma-separated items in the 'block=' parameter */
55 #define UBIBLOCK_PARAM_COUNT 2
106 return -EINVAL; in ubiblock_set_param()
110 pr_warn("UBI: block: empty 'block=' parameter - ignored\n"); in ubiblock_set_param()
117 return -EINVAL; in ubiblock_set_param()
123 if (buf[len - 1] == '\n') in ubiblock_set_param()
124 buf[len - 1] = '\0'; in ubiblock_set_param()
132 ret = kstrtoint(tokens[0], 10, &param->ubi_num); in ubiblock_set_param()
134 return -EINVAL; in ubiblock_set_param()
137 ret = kstrtoint(tokens[1], 10, &param->vol_id); in ubiblock_set_param()
139 param->vol_id = -1; in ubiblock_set_param()
140 strcpy(param->name, tokens[1]); in ubiblock_set_param()
145 strcpy(param->name, tokens[0]); in ubiblock_set_param()
146 param->ubi_num = -1; in ubiblock_set_param()
147 param->vol_id = -1; in ubiblock_set_param()
175 if (dev->ubi_num == ubi_num && dev->vol_id == vol_id) in find_dev_nolock()
183 struct ubiblock *dev = req->q->queuedata; in ubiblock_read()
188 int offset = do_div(pos, dev->leb_size); in ubiblock_read()
201 ubi_sgl_init(&pdu->usgl); in ubiblock_read()
202 blk_rq_map_sg(req->q, req, pdu->usgl.sg); in ubiblock_read()
209 if (offset + to_read > dev->leb_size) in ubiblock_read()
210 to_read = dev->leb_size - offset; in ubiblock_read()
212 ret = ubi_read_sg(dev->desc, leb, &pdu->usgl, offset, to_read); in ubiblock_read()
216 bytes_left -= to_read; in ubiblock_read()
232 struct ubiblock *dev = disk->private_data; in ubiblock_open()
235 mutex_lock(&dev->dev_mutex); in ubiblock_open()
236 if (dev->refcnt > 0) { in ubiblock_open()
245 * We want users to be aware they should only mount us as read-only. in ubiblock_open()
250 ret = -EROFS; in ubiblock_open()
253 dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY); in ubiblock_open()
254 if (IS_ERR(dev->desc)) { in ubiblock_open()
255 dev_err(disk_to_dev(dev->gd), "failed to open ubi volume %d_%d", in ubiblock_open()
256 dev->ubi_num, dev->vol_id); in ubiblock_open()
257 ret = PTR_ERR(dev->desc); in ubiblock_open()
258 dev->desc = NULL; in ubiblock_open()
263 dev->refcnt++; in ubiblock_open()
264 mutex_unlock(&dev->dev_mutex); in ubiblock_open()
268 mutex_unlock(&dev->dev_mutex); in ubiblock_open()
274 struct ubiblock *dev = gd->private_data; in ubiblock_release()
276 mutex_lock(&dev->dev_mutex); in ubiblock_release()
277 dev->refcnt--; in ubiblock_release()
278 if (dev->refcnt == 0) { in ubiblock_release()
279 ubi_close_volume(dev->desc); in ubiblock_release()
280 dev->desc = NULL; in ubiblock_release()
282 mutex_unlock(&dev->dev_mutex); in ubiblock_release()
288 geo->heads = 1; in ubiblock_getgeo()
289 geo->cylinders = 1; in ubiblock_getgeo()
290 geo->sectors = get_capacity(bdev->bd_disk); in ubiblock_getgeo()
291 geo->start = 0; in ubiblock_getgeo()
305 switch (req_op(bd->rq)) { in ubiblock_queue_rq()
307 return ubiblock_read(bd->rq); in ubiblock_queue_rq()
319 sg_init_table(pdu->usgl.sg, UBI_MAX_SG_COUNT); in ubiblock_init_request()
330 u64 size = vi->used_bytes >> 9; in calc_disk_capacity()
332 if (vi->used_bytes % 512) { in calc_disk_capacity()
333 if (vi->vol_type == UBI_DYNAMIC_VOLUME) in calc_disk_capacity()
335 vi->used_bytes - (size << 9)); in calc_disk_capacity()
338 vi->used_bytes - (size << 9)); in calc_disk_capacity()
342 return -EFBIG; in calc_disk_capacity()
366 if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { in ubiblock_create()
367 ret = -EEXIST; in ubiblock_create()
373 ret = -ENOMEM; in ubiblock_create()
377 mutex_init(&dev->dev_mutex); in ubiblock_create()
379 dev->ubi_num = vi->ubi_num; in ubiblock_create()
380 dev->vol_id = vi->vol_id; in ubiblock_create()
381 dev->leb_size = vi->usable_leb_size; in ubiblock_create()
383 dev->tag_set.ops = &ubiblock_mq_ops; in ubiblock_create()
384 dev->tag_set.queue_depth = 64; in ubiblock_create()
385 dev->tag_set.numa_node = NUMA_NO_NODE; in ubiblock_create()
386 dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING; in ubiblock_create()
387 dev->tag_set.cmd_size = sizeof(struct ubiblock_pdu); in ubiblock_create()
388 dev->tag_set.driver_data = dev; in ubiblock_create()
389 dev->tag_set.nr_hw_queues = 1; in ubiblock_create()
391 ret = blk_mq_alloc_tag_set(&dev->tag_set); in ubiblock_create()
394 dev->ubi_num, dev->vol_id); in ubiblock_create()
400 gd = blk_mq_alloc_disk(&dev->tag_set, &lim, dev); in ubiblock_create()
406 gd->fops = &ubiblock_ops; in ubiblock_create()
407 gd->major = ubiblock_major; in ubiblock_create()
408 gd->minors = 1; in ubiblock_create()
409 gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); in ubiblock_create()
410 if (gd->first_minor < 0) { in ubiblock_create()
412 dev->ubi_num, dev->vol_id); in ubiblock_create()
413 ret = -ENODEV; in ubiblock_create()
416 gd->flags |= GENHD_FL_NO_PART; in ubiblock_create()
417 gd->private_data = dev; in ubiblock_create()
418 sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); in ubiblock_create()
420 dev->gd = gd; in ubiblock_create()
422 dev->rq = gd->queue; in ubiblock_create()
424 list_add_tail(&dev->list, &ubiblock_devices); in ubiblock_create()
427 ret = device_add_disk(vi->dev, dev->gd, NULL); in ubiblock_create()
431 dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", in ubiblock_create()
432 dev->ubi_num, dev->vol_id, vi->name); in ubiblock_create()
437 list_del(&dev->list); in ubiblock_create()
438 idr_remove(&ubiblock_minor_idr, gd->first_minor); in ubiblock_create()
442 blk_mq_free_tag_set(&dev->tag_set); in ubiblock_create()
453 int id = dev->gd->first_minor; in ubiblock_cleanup()
456 del_gendisk(dev->gd); in ubiblock_cleanup()
458 dev_info(disk_to_dev(dev->gd), "released"); in ubiblock_cleanup()
459 put_disk(dev->gd); in ubiblock_cleanup()
460 blk_mq_free_tag_set(&dev->tag_set); in ubiblock_cleanup()
470 dev = find_dev_nolock(vi->ubi_num, vi->vol_id); in ubiblock_remove()
472 ret = -ENODEV; in ubiblock_remove()
477 mutex_lock(&dev->dev_mutex); in ubiblock_remove()
478 if (dev->refcnt > 0) { in ubiblock_remove()
479 ret = -EBUSY; in ubiblock_remove()
484 list_del(&dev->list); in ubiblock_remove()
486 mutex_unlock(&dev->dev_mutex); in ubiblock_remove()
493 mutex_unlock(&dev->dev_mutex); in ubiblock_remove()
511 dev = find_dev_nolock(vi->ubi_num, vi->vol_id); in ubiblock_resize()
514 return -ENODEV; in ubiblock_resize()
520 if (ret == -EFBIG) { in ubiblock_resize()
521 dev_warn(disk_to_dev(dev->gd), in ubiblock_resize()
523 vi->size); in ubiblock_resize()
528 mutex_lock(&dev->dev_mutex); in ubiblock_resize()
530 if (get_capacity(dev->gd) != disk_capacity) { in ubiblock_resize()
531 set_capacity(dev->gd, disk_capacity); in ubiblock_resize()
532 dev_info(disk_to_dev(dev->gd), "resized to %lld bytes", in ubiblock_resize()
533 vi->used_bytes); in ubiblock_resize()
535 mutex_unlock(&dev->dev_mutex); in ubiblock_resize()
545 if (ubi_num == -1) { in match_volume_desc()
548 if (err || vi->ubi_num != cur_ubi_num || vi->vol_id != cur_vol_id) in match_volume_desc()
554 if (vol_id == -1) { in match_volume_desc()
556 if (vi->ubi_num != ubi_num) in match_volume_desc()
560 if (len < 1 || vi->name_len != len) in match_volume_desc()
563 if (strcmp(name, vi->name)) in match_volume_desc()
569 if (vi->ubi_num != ubi_num) in match_volume_desc()
572 if (vi->vol_id != vol_id) in match_volume_desc()
591 if (!match_volume_desc(vi, p->name, p->ubi_num, p->vol_id)) in ubiblock_create_from_param()
598 vi->name, p->ubi_num, p->vol_id, ret); in ubiblock_create_from_param()
611 ubiblock_create_from_param(&nt->vi); in ubiblock_notify()
614 ubiblock_remove(&nt->vi); in ubiblock_notify()
617 ubiblock_resize(&nt->vi); in ubiblock_notify()
624 if (nt->vi.vol_type == UBI_STATIC_VOLUME) in ubiblock_notify()
625 ubiblock_resize(&nt->vi); in ubiblock_notify()
645 WARN_ON(dev->desc); in ubiblock_remove_all()
647 list_del(&dev->list); in ubiblock_remove_all()