From 9f961b57568960a150cc9781c52824c9093a0514 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 16 Dec 2007 16:59:31 +0200 Subject: 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: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 52 +++++++++++++++++++++++++++++++++++++++---------- drivers/mtd/ubi/cdev.c | 10 ++++++++++ drivers/mtd/ubi/ubi.h | 3 ++- 3 files changed, 54 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index b3efb2fa3c1..3f37b16f877 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -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 @@ -33,6 +38,7 @@ #include #include #include +#include #include #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 '//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, <ree_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,8 +751,11 @@ 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 @@ out_detach: 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); } diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 22c15a388f2..bc900d24cdb 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -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 @@ -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, diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 994233d6e1e..21c028366fd 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -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[]; -- cgit v1.2.3