提交 9f961b57 编写于 作者: A Artem Bityutskiy

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: NArtem Bityutskiy <Artem.Bityutskiy@nokia.com>
上级 16f557ec
...@@ -21,11 +21,16 @@ ...@@ -21,11 +21,16 @@
*/ */
/* /*
* This file includes UBI initialization and building of UBI devices. At the * This file includes UBI initialization and building of UBI devices.
* 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 * When UBI is initialized, it attaches all the MTD devices specified as the
* attach UBI devices by scanning, which will become a bottleneck when flashes * module load parameters or the kernel boot parameters. If MTD devices were
* reach certain large size. Then one may improve UBI and add other methods. * 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> #include <linux/err.h>
...@@ -33,6 +38,7 @@ ...@@ -33,6 +38,7 @@
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/stringify.h> #include <linux/stringify.h>
#include <linux/stat.h> #include <linux/stat.h>
#include <linux/miscdevice.h>
#include <linux/log2.h> #include <linux/log2.h>
#include "ubi.h" #include "ubi.h"
...@@ -70,6 +76,12 @@ struct kmem_cache *ubi_ltree_slab; ...@@ -70,6 +76,12 @@ struct kmem_cache *ubi_ltree_slab;
/* Slab cache for wear-leveling entries */ /* Slab cache for wear-leveling entries */
struct kmem_cache *ubi_wl_entry_slab; 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/' */ /* "Show" method for files in '/<sysfs>/class/ubi/' */
static ssize_t ubi_version_show(struct class *class, char *buf) static ssize_t ubi_version_show(struct class *class, char *buf)
...@@ -701,19 +713,31 @@ static int __init ubi_init(void) ...@@ -701,19 +713,31 @@ static int __init ubi_init(void)
return -EINVAL; return -EINVAL;
} }
/* Create base sysfs directory and sysfs files */
ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); ubi_class = class_create(THIS_MODULE, UBI_NAME_STR);
if (IS_ERR(ubi_class)) if (IS_ERR(ubi_class)) {
return PTR_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); 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; 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", ubi_ltree_slab = kmem_cache_create("ubi_ltree_slab",
sizeof(struct ubi_ltree_entry), 0, sizeof(struct ubi_ltree_entry), 0,
0, &ltree_entry_ctor); 0, &ltree_entry_ctor);
if (!ubi_ltree_slab) if (!ubi_ltree_slab)
goto out_version; goto out_dev_unreg;
ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
sizeof(struct ubi_wl_entry), sizeof(struct ubi_wl_entry),
...@@ -727,8 +751,11 @@ static int __init ubi_init(void) ...@@ -727,8 +751,11 @@ static int __init ubi_init(void)
cond_resched(); cond_resched();
err = attach_mtd_dev(p->name, p->vid_hdr_offs, p->data_offs); 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; goto out_detach;
}
} }
return 0; return 0;
...@@ -739,10 +766,14 @@ static int __init ubi_init(void) ...@@ -739,10 +766,14 @@ static int __init ubi_init(void)
kmem_cache_destroy(ubi_wl_entry_slab); kmem_cache_destroy(ubi_wl_entry_slab);
out_ltree: out_ltree:
kmem_cache_destroy(ubi_ltree_slab); kmem_cache_destroy(ubi_ltree_slab);
out_dev_unreg:
misc_deregister(&ubi_ctrl_cdev);
out_version: out_version:
class_remove_file(ubi_class, &ubi_version); class_remove_file(ubi_class, &ubi_version);
out_class: out_class:
class_destroy(ubi_class); class_destroy(ubi_class);
out:
printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err);
return err; return err;
} }
module_init(ubi_init); module_init(ubi_init);
...@@ -756,6 +787,7 @@ static void __exit ubi_exit(void) ...@@ -756,6 +787,7 @@ static void __exit ubi_exit(void)
detach_mtd_dev(ubi_devices[i]); detach_mtd_dev(ubi_devices[i]);
kmem_cache_destroy(ubi_wl_entry_slab); kmem_cache_destroy(ubi_wl_entry_slab);
kmem_cache_destroy(ubi_ltree_slab); kmem_cache_destroy(ubi_ltree_slab);
misc_deregister(&ubi_ctrl_cdev);
class_remove_file(ubi_class, &ubi_version); class_remove_file(ubi_class, &ubi_version);
class_destroy(ubi_class); class_destroy(ubi_class);
} }
......
...@@ -28,6 +28,11 @@ ...@@ -28,6 +28,11 @@
* *
* Major and minor numbers are assigned dynamically to both UBI and volume * Major and minor numbers are assigned dynamically to both UBI and volume
* character devices. * 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> #include <linux/module.h>
...@@ -693,6 +698,11 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file, ...@@ -693,6 +698,11 @@ static int ubi_cdev_ioctl(struct inode *inode, struct file *file,
return err; return err;
} }
/* UBI control character device operations */
struct file_operations ubi_ctrl_cdev_operations = {
.owner = THIS_MODULE,
};
/* UBI character device operations */ /* UBI character device operations */
struct file_operations ubi_cdev_operations = { struct file_operations ubi_cdev_operations = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
......
...@@ -235,7 +235,7 @@ struct ubi_wl_entry; ...@@ -235,7 +235,7 @@ struct ubi_wl_entry;
/** /**
* struct ubi_device - UBI device description structure * 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 * @cdev: character device object to create character device
* @ubi_num: UBI device number * @ubi_num: UBI device number
* @ubi_name: UBI device name * @ubi_name: UBI device name
...@@ -398,6 +398,7 @@ struct ubi_device { ...@@ -398,6 +398,7 @@ struct ubi_device {
extern struct kmem_cache *ubi_ltree_slab; extern struct kmem_cache *ubi_ltree_slab;
extern struct kmem_cache *ubi_wl_entry_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_cdev_operations;
extern struct file_operations ubi_vol_cdev_operations; extern struct file_operations ubi_vol_cdev_operations;
extern struct ubi_device *ubi_devices[]; extern struct ubi_device *ubi_devices[];
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册