Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9f961b57 authored by Artem Bityutskiy's avatar Artem Bityutskiy
Browse files

UBI: add UBI control device



This patch is a preparation to make UBI devices dynamic. It
adds an UBI control device which has dynamically allocated
major number and registers itself as "ubi_ctrl". It does not
do anything so far. The idea is that this device will allow
to attach/detach MTD devices from userspace.

This is symilar to what the Linux device mapper has.

The next things to do are:
* Fix UBI, because it now assumes UBI devices cannot go away
* Implement control device ioctls which will attach/detach MTD
  devices

Signed-off-by: default avatarArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
parent 16f557ec
Loading
Loading
Loading
Loading
+42 −10
Original line number Diff line number Diff line
@@ -21,11 +21,16 @@
 */

/*
 * This file includes UBI initialization and building of UBI devices. At the
 * moment UBI devices may only be added while UBI is initialized, but dynamic
 * device add/remove functionality is planned. Also, at the moment we only
 * attach UBI devices by scanning, which will become a bottleneck when flashes
 * reach certain large size. Then one may improve UBI and add other methods.
 * This file includes UBI initialization and building of UBI devices.
 *
 * When UBI is initialized, it attaches all the MTD devices specified as the
 * module load parameters or the kernel boot parameters. If MTD devices were
 * specified, UBI does not attach any MTD device, but it is possible to do
 * later using the "UBI control device".
 *
 * At the moment we only attach UBI devices by scanning, which will become a
 * bottleneck when flashes reach certain large size. Then one may improve UBI
 * and add other methods, although it does not seem to be easy to do.
 */

#include <linux/err.h>
@@ -33,6 +38,7 @@
#include <linux/moduleparam.h>
#include <linux/stringify.h>
#include <linux/stat.h>
#include <linux/miscdevice.h>
#include <linux/log2.h>
#include "ubi.h"

@@ -70,6 +76,12 @@ struct kmem_cache *ubi_ltree_slab;
/* Slab cache for wear-leveling entries */
struct kmem_cache *ubi_wl_entry_slab;

/* UBI control character device */
static struct miscdevice ubi_ctrl_cdev = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = "ubi_ctrl",
	.fops = &ubi_ctrl_cdev_operations,
};

/* "Show" method for files in '/<sysfs>/class/ubi/' */
static ssize_t ubi_version_show(struct class *class, char *buf)
@@ -701,19 +713,31 @@ static int __init ubi_init(void)
		return -EINVAL;
	}

	/* Create base sysfs directory and sysfs files */
	ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
	if (IS_ERR(ubi_class))
		return PTR_ERR(ubi_class);
	if (IS_ERR(ubi_class)) {
		err = PTR_ERR(ubi_class);
		printk(KERN_ERR "UBI error: cannot create UBI class\n");
		goto out;
	}

	err = class_create_file(ubi_class, &ubi_version);
	if (err)
	if (err) {
		printk(KERN_ERR "UBI error: cannot create sysfs file\n");
		goto out_class;
	}

	err = misc_register(&ubi_ctrl_cdev);
	if (err) {
		printk(KERN_ERR "UBI error: cannot register device\n");
		goto out_version;
	}

	ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab",
					   sizeof(struct ubi_ltree_entry), 0,
					   0, &ltree_entry_ctor);
	if (!ubi_ltree_slab)
		goto out_version;
		goto out_dev_unreg;

	ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
						sizeof(struct ubi_wl_entry),
@@ -727,9 +751,12 @@ static int __init ubi_init(void)

		cond_resched();
		err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs);
		if (err)
		if (err) {
			printk(KERN_ERR "UBI error: cannot attach %s\n",
			       p->name);
			goto out_detach;
		}
	}

	return 0;

@@ -739,10 +766,14 @@ static int __init ubi_init(void)
	kmem_cache_destroy(ubi_wl_entry_slab);
out_ltree:
	kmem_cache_destroy(ubi_ltree_slab);
out_dev_unreg:
	misc_deregister(&ubi_ctrl_cdev);
out_version:
	class_remove_file(ubi_class, &ubi_version);
out_class:
	class_destroy(ubi_class);
out:
	printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
	return err;
}
module_init(ubi_init);
@@ -756,6 +787,7 @@ static void __exit ubi_exit(void)
			detach_mtd_dev(ubi_devices[i]);
	kmem_cache_destroy(ubi_wl_entry_slab);
	kmem_cache_destroy(ubi_ltree_slab);
	misc_deregister(&ubi_ctrl_cdev);
	class_remove_file(ubi_class, &ubi_version);
	class_destroy(ubi_class);
}
+10 −0
Original line number Diff line number Diff line
@@ -28,6 +28,11 @@
 *
 * Major and minor numbers are assigned dynamically to both UBI and volume
 * character devices.
 *
 * Well, there is the third kind of character devices - the UBI control
 * character device, which allows to manipulate by UBI devices - create and
 * delete them. In other words, it is used for attaching and detaching MTD
 * devices.
 */

#include <linux/module.h>
@@ -693,6 +698,11 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
	return err;
}

/* UBI control character device operations */
struct file_operations ubi_ctrl_cdev_operations = {
	.owner = THIS_MODULE,
};

/* UBI character device operations */
struct file_operations ubi_cdev_operations = {
	.owner = THIS_MODULE,
+2 −1
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ struct ubi_wl_entry;

/**
 * struct ubi_device - UBI device description structure
 * @dev: class device object to use the the Linux device model
 * @dev: UBI device object to use the the Linux device model
 * @cdev: character device object to create character device
 * @ubi_num: UBI device number
 * @ubi_name: UBI device name
@@ -398,6 +398,7 @@ struct ubi_device {

extern struct kmem_cache *ubi_ltree_slab;
extern struct kmem_cache *ubi_wl_entry_slab;
extern struct file_operations ubi_ctrl_cdev_operations;
extern struct file_operations ubi_cdev_operations;
extern struct file_operations ubi_vol_cdev_operations;
extern struct ubi_device *ubi_devices[];