diff options
| author | Steffen Sledz <sledz@dresearch.de> | 2009-04-24 16:06:58 +0200 |
|---|---|---|
| committer | Steffen Sledz <sledz@dresearch.de> | 2009-04-24 16:06:58 +0200 |
| commit | f39b6e0d805fc55cd7bcc6edd03f81bd2441301a (patch) | |
| tree | 9dd7eb4bfe0fffad9a44c89291c8f9203cf1232f /recipes | |
| parent | d03984dc6ef1414c1983361229434b97606ff42d (diff) | |
linux-2.6.24: make ubifs available for all machines
Diffstat (limited to 'recipes')
| -rw-r--r-- | recipes/linux/linux-2.6.24/hipox/hipox-ubifs.patch | 43970 | ||||
| -rw-r--r-- | recipes/linux/linux-2.6.24/ubifs-v2.6.24.patch | 45442 | ||||
| -rw-r--r-- | recipes/linux/linux_2.6.24.bb | 3 |
3 files changed, 45447 insertions, 43968 deletions
diff --git a/recipes/linux/linux-2.6.24/hipox/hipox-ubifs.patch b/recipes/linux/linux-2.6.24/hipox/hipox-ubifs.patch index 2aef97d4eb..670f22518c 100644 --- a/recipes/linux/linux-2.6.24/hipox/hipox-ubifs.patch +++ b/recipes/linux/linux-2.6.24/hipox/hipox-ubifs.patch @@ -1,43974 +1,10 @@ -diff -Nurd linux-2.6.24.orig/crypto/Kconfig linux-2.6.24/crypto/Kconfig ---- linux-2.6.24.orig/crypto/Kconfig 2009-04-17 09:45:12.000000000 +0200 -+++ linux-2.6.24/crypto/Kconfig 2009-04-17 09:49:26.000000000 +0200 -@@ -502,6 +502,14 @@ - Authenc: Combined mode wrapper for IPsec. - This is required for IPSec. - -+config CRYPTO_LZO -+ tristate "LZO compression algorithm" -+ select CRYPTO_ALGAPI -+ select LZO_COMPRESS -+ select LZO_DECOMPRESS -+ help -+ This is the LZO algorithm. -+ - source "drivers/crypto/Kconfig" - - endif # if CRYPTO -diff -Nurd linux-2.6.24.orig/crypto/Makefile linux-2.6.24/crypto/Makefile ---- linux-2.6.24.orig/crypto/Makefile 2009-04-17 09:45:12.000000000 +0200 -+++ linux-2.6.24/crypto/Makefile 2009-04-17 09:49:26.000000000 +0200 -@@ -51,6 +51,7 @@ - obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o - obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o - obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o -+obj-$(CONFIG_CRYPTO_LZO) += lzo.o - obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o - - obj-$(CONFIG_CRYPTO_TEST) += tcrypt.o -diff -Nurd linux-2.6.24.orig/crypto/lzo.c linux-2.6.24/crypto/lzo.c ---- linux-2.6.24.orig/crypto/lzo.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.24/crypto/lzo.c 2009-04-17 09:49:26.000000000 +0200 -@@ -0,0 +1,106 @@ -+/* -+ * Cryptographic API. -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published by -+ * the Free Software Foundation. -+ * -+ * This program is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -+ * more details. -+ * -+ * You should have received a copy of the GNU General Public License along with -+ * this program; if not, write to the Free Software Foundation, Inc., 51 -+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#include <linux/init.h> -+#include <linux/module.h> -+#include <linux/crypto.h> -+#include <linux/vmalloc.h> -+#include <linux/lzo.h> -+ -+struct lzo_ctx { -+ void *lzo_comp_mem; -+}; -+ -+static int lzo_init(struct crypto_tfm *tfm) -+{ -+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ ctx->lzo_comp_mem = vmalloc(LZO1X_MEM_COMPRESS); -+ if (!ctx->lzo_comp_mem) -+ return -ENOMEM; -+ -+ return 0; -+} -+ -+static void lzo_exit(struct crypto_tfm *tfm) -+{ -+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -+ -+ vfree(ctx->lzo_comp_mem); -+} -+ -+static int lzo_compress(struct crypto_tfm *tfm, const u8 *src, -+ unsigned int slen, u8 *dst, unsigned int *dlen) -+{ -+ struct lzo_ctx *ctx = crypto_tfm_ctx(tfm); -+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ -+ int err; -+ -+ err = lzo1x_1_compress(src, slen, dst, &tmp_len, ctx->lzo_comp_mem); -+ -+ if (err != LZO_E_OK) -+ return -EINVAL; -+ -+ *dlen = tmp_len; -+ return 0; -+} -+ -+static int lzo_decompress(struct crypto_tfm *tfm, const u8 *src, -+ unsigned int slen, u8 *dst, unsigned int *dlen) -+{ -+ int err; -+ size_t tmp_len = *dlen; /* size_t(ulong) <-> uint on 64 bit */ -+ -+ err = lzo1x_decompress_safe(src, slen, dst, &tmp_len); -+ -+ if (err != LZO_E_OK) -+ return -EINVAL; -+ -+ *dlen = tmp_len; -+ return 0; -+ -+} -+ -+static struct crypto_alg alg = { -+ .cra_name = "lzo", -+ .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, -+ .cra_ctxsize = sizeof(struct lzo_ctx), -+ .cra_module = THIS_MODULE, -+ .cra_list = LIST_HEAD_INIT(alg.cra_list), -+ .cra_init = lzo_init, -+ .cra_exit = lzo_exit, -+ .cra_u = { .compress = { -+ .coa_compress = lzo_compress, -+ .coa_decompress = lzo_decompress } } -+}; -+ -+static int __init init(void) -+{ -+ return crypto_register_alg(&alg); -+} -+ -+static void __exit fini(void) -+{ -+ crypto_unregister_alg(&alg); -+} -+ -+module_init(init); -+module_exit(fini); -+ -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LZO Compression Algorithm"); -diff -Nurd linux-2.6.24.orig/drivers/mtd/ubi/Kconfig linux-2.6.24/drivers/mtd/ubi/Kconfig ---- linux-2.6.24.orig/drivers/mtd/ubi/Kconfig 2009-04-17 09:45:11.000000000 +0200 -+++ linux-2.6.24/drivers/mtd/ubi/Kconfig 2009-04-17 09:49:26.000000000 +0200 -@@ -24,8 +24,13 @@ - erase counter value and the lowest erase counter value of eraseblocks - of UBI devices. When this threshold is exceeded, UBI starts performing - wear leveling by means of moving data from eraseblock with low erase -- counter to eraseblocks with high erase counter. Leave the default -- value if unsure. -+ counter to eraseblocks with high erase counter. -+ -+ The default value should be OK for SLC NAND flashes, NOR flashes and -+ other flashes which have eraseblock life-cycle 100000 or more. -+ However, in case of MLC NAND flashes which typically have eraseblock -+ life-cycle less then 10000, the threshold should be lessened (e.g., -+ to 128 or 256, although it does not have to be power of 2). - - config MTD_UBI_BEB_RESERVE - int "Percentage of reserved eraseblocks for bad eraseblocks handling" -diff -Nurd linux-2.6.24.orig/drivers/mtd/ubi/build.c linux-2.6.24/drivers/mtd/ubi/build.c ---- linux-2.6.24.orig/drivers/mtd/ubi/build.c 2009-04-17 09:45:11.000000000 +0200 -+++ linux-2.6.24/drivers/mtd/ubi/build.c 2009-04-17 09:49:26.000000000 +0200 -@@ -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,7 +38,9 @@ - #include <linux/moduleparam.h> - #include <linux/stringify.h> - #include <linux/stat.h> -+#include <linux/miscdevice.h> - #include <linux/log2.h> -+#include <linux/kthread.h> - #include "ubi.h" - - /* Maximum length of the 'mtd=' parameter */ -@@ -43,29 +50,39 @@ - * struct mtd_dev_param - MTD device parameter description data structure. - * @name: MTD device name or number string - * @vid_hdr_offs: VID header offset -- * @data_offs: data offset - */ --struct mtd_dev_param --{ -+struct mtd_dev_param { - char name[MTD_PARAM_LEN_MAX]; - int vid_hdr_offs; -- int data_offs; - }; - - /* Numbers of elements set in the @mtd_dev_param array */ --static int mtd_devs = 0; -+static int mtd_devs; - - /* MTD devices specification parameters */ - static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; - --/* Number of UBI devices in system */ --int ubi_devices_cnt; -+/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ -+struct class *ubi_class; -+ -+/* 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, -+}; - - /* All UBI devices in system */ --struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; -+static struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; - --/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ --struct class *ubi_class; -+/* Serializes UBI devices creations and removals */ -+DEFINE_MUTEX(ubi_devices_mutex); -+ -+/* Protects @ubi_devices and @ubi->ref_count */ -+static DEFINE_SPINLOCK(ubi_devices_lock); - - /* "Show" method for files in '/<sysfs>/class/ubi/' */ - static ssize_t ubi_version_show(struct class *class, char *buf) -@@ -101,42 +118,157 @@ - __ATTR(min_io_size, S_IRUGO, dev_attribute_show, NULL); - static struct device_attribute dev_bgt_enabled = - __ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL); -+static struct device_attribute dev_mtd_num = -+ __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); -+ -+/** -+ * ubi_get_device - get UBI device. -+ * @ubi_num: UBI device number -+ * -+ * This function returns UBI device description object for UBI device number -+ * @ubi_num, or %NULL if the device does not exist. This function increases the -+ * device reference count to prevent removal of the device. In other words, the -+ * device cannot be removed if its reference count is not zero. -+ */ -+struct ubi_device *ubi_get_device(int ubi_num) -+{ -+ struct ubi_device *ubi; -+ -+ spin_lock(&ubi_devices_lock); -+ ubi = ubi_devices[ubi_num]; -+ if (ubi) { -+ ubi_assert(ubi->ref_count >= 0); -+ ubi->ref_count += 1; -+ get_device(&ubi->dev); -+ } -+ spin_unlock(&ubi_devices_lock); -+ -+ return ubi; -+} -+ -+/** -+ * ubi_put_device - drop an UBI device reference. -+ * @ubi: UBI device description object -+ */ -+void ubi_put_device(struct ubi_device *ubi) -+{ -+ spin_lock(&ubi_devices_lock); -+ ubi->ref_count -= 1; -+ put_device(&ubi->dev); -+ spin_unlock(&ubi_devices_lock); -+} -+ -+/** -+ * ubi_get_by_major - get UBI device by character device major number. -+ * @major: major number -+ * -+ * This function is similar to 'ubi_get_device()', but it searches the device -+ * by its major number. -+ */ -+struct ubi_device *ubi_get_by_major(int major) -+{ -+ int i; -+ struct ubi_device *ubi; -+ -+ spin_lock(&ubi_devices_lock); -+ for (i = 0; i < UBI_MAX_DEVICES; i++) { -+ ubi = ubi_devices[i]; -+ if (ubi && MAJOR(ubi->cdev.dev) == major) { -+ ubi_assert(ubi->ref_count >= 0); -+ ubi->ref_count += 1; -+ get_device(&ubi->dev); -+ spin_unlock(&ubi_devices_lock); -+ return ubi; -+ } -+ } -+ spin_unlock(&ubi_devices_lock); -+ -+ return NULL; -+} -+ -+/** -+ * ubi_major2num - get UBI device number by character device major number. -+ * @major: major number -+ * -+ * This function searches UBI device number object by its major number. If UBI -+ * device was not found, this function returns -ENODEV, otherwise the UBI device -+ * number is returned. -+ */ -+int ubi_major2num(int major) -+{ -+ int i, ubi_num = -ENODEV; -+ -+ spin_lock(&ubi_devices_lock); -+ for (i = 0; i < UBI_MAX_DEVICES; i++) { -+ struct ubi_device *ubi = ubi_devices[i]; -+ -+ if (ubi && MAJOR(ubi->cdev.dev) == major) { -+ ubi_num = ubi->ubi_num; -+ break; -+ } -+ } -+ spin_unlock(&ubi_devices_lock); -+ -+ return ubi_num; -+} - - /* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */ - static ssize_t dev_attribute_show(struct device *dev, - struct device_attribute *attr, char *buf) - { -- const struct ubi_device *ubi; -+ ssize_t ret; -+ struct ubi_device *ubi; - -+ /* -+ * The below code looks weird, but it actually makes sense. We get the -+ * UBI device reference from the contained 'struct ubi_device'. But it -+ * is unclear if the device was removed or not yet. Indeed, if the -+ * device was removed before we increased its reference count, -+ * 'ubi_get_device()' will return -ENODEV and we fail. -+ * -+ * Remember, 'struct ubi_device' is freed in the release function, so -+ * we still can use 'ubi->ubi_num'. -+ */ - ubi = container_of(dev, struct ubi_device, dev); -+ ubi = ubi_get_device(ubi->ubi_num); -+ if (!ubi) -+ return -ENODEV; -+ - if (attr == &dev_eraseblock_size) -- return sprintf(buf, "%d\n", ubi->leb_size); -+ ret = sprintf(buf, "%d\n", ubi->leb_size); - else if (attr == &dev_avail_eraseblocks) -- return sprintf(buf, "%d\n", ubi->avail_pebs); -+ ret = sprintf(buf, "%d\n", ubi->avail_pebs); - else if (attr == &dev_total_eraseblocks) -- return sprintf(buf, "%d\n", ubi->good_peb_count); -+ ret = sprintf(buf, "%d\n", ubi->good_peb_count); - else if (attr == &dev_volumes_count) -- return sprintf(buf, "%d\n", ubi->vol_count); -+ ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT); - else if (attr == &dev_max_ec) -- return sprintf(buf, "%d\n", ubi->max_ec); -+ ret = sprintf(buf, "%d\n", ubi->max_ec); - else if (attr == &dev_reserved_for_bad) -- return sprintf(buf, "%d\n", ubi->beb_rsvd_pebs); -+ ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs); - else if (attr == &dev_bad_peb_count) -- return sprintf(buf, "%d\n", ubi->bad_peb_count); -+ ret = sprintf(buf, "%d\n", ubi->bad_peb_count); - else if (attr == &dev_max_vol_count) -- return sprintf(buf, "%d\n", ubi->vtbl_slots); -+ ret = sprintf(buf, "%d\n", ubi->vtbl_slots); - else if (attr == &dev_min_io_size) -- return sprintf(buf, "%d\n", ubi->min_io_size); -+ ret = sprintf(buf, "%d\n", ubi->min_io_size); - else if (attr == &dev_bgt_enabled) -- return sprintf(buf, "%d\n", ubi->thread_enabled); -+ ret = sprintf(buf, "%d\n", ubi->thread_enabled); -+ else if (attr == &dev_mtd_num) -+ ret = sprintf(buf, "%d\n", ubi->mtd->index); - else -- BUG(); -+ ret = -EINVAL; - -- return 0; -+ ubi_put_device(ubi); -+ return ret; - } - --/* Fake "release" method for UBI devices */ --static void dev_release(struct device *dev) { } -+static void dev_release(struct device *dev) -+{ -+ struct ubi_device *ubi = container_of(dev, struct ubi_device, dev); -+ -+ kfree(ubi); -+} - - /** - * ubi_sysfs_init - initialize sysfs for an UBI device. -@@ -150,68 +282,44 @@ - int err; - - ubi->dev.release = dev_release; -- ubi->dev.devt = MKDEV(ubi->major, 0); -+ ubi->dev.devt = ubi->cdev.dev; - ubi->dev.class = ubi_class; - sprintf(&ubi->dev.bus_id[0], UBI_NAME_STR"%d", ubi->ubi_num); - err = device_register(&ubi->dev); - if (err) -- goto out; -+ return err; - - err = device_create_file(&ubi->dev, &dev_eraseblock_size); - if (err) -- goto out_unregister; -+ return err; - err = device_create_file(&ubi->dev, &dev_avail_eraseblocks); - if (err) -- goto out_eraseblock_size; -+ return err; - err = device_create_file(&ubi->dev, &dev_total_eraseblocks); - if (err) -- goto out_avail_eraseblocks; -+ return err; - err = device_create_file(&ubi->dev, &dev_volumes_count); - if (err) -- goto out_total_eraseblocks; -+ return err; - err = device_create_file(&ubi->dev, &dev_max_ec); - if (err) -- goto out_volumes_count; -+ return err; - err = device_create_file(&ubi->dev, &dev_reserved_for_bad); - if (err) -- goto out_volumes_max_ec; -+ return err; - err = device_create_file(&ubi->dev, &dev_bad_peb_count); - if (err) -- goto out_reserved_for_bad; -+ return err; - err = device_create_file(&ubi->dev, &dev_max_vol_count); - if (err) -- goto out_bad_peb_count; -+ return err; - err = device_create_file(&ubi->dev, &dev_min_io_size); - if (err) -- goto out_max_vol_count; -+ return err; - err = device_create_file(&ubi->dev, &dev_bgt_enabled); - if (err) -- goto out_min_io_size; -- -- return 0; -- --out_min_io_size: -- device_remove_file(&ubi->dev, &dev_min_io_size); --out_max_vol_count: -- device_remove_file(&ubi->dev, &dev_max_vol_count); --out_bad_peb_count: -- device_remove_file(&ubi->dev, &dev_bad_peb_count); --out_reserved_for_bad: -- device_remove_file(&ubi->dev, &dev_reserved_for_bad); --out_volumes_max_ec: -- device_remove_file(&ubi->dev, &dev_max_ec); --out_volumes_count: -- device_remove_file(&ubi->dev, &dev_volumes_count); --out_total_eraseblocks: -- device_remove_file(&ubi->dev, &dev_total_eraseblocks); --out_avail_eraseblocks: -- device_remove_file(&ubi->dev, &dev_avail_eraseblocks); --out_eraseblock_size: -- device_remove_file(&ubi->dev, &dev_eraseblock_size); --out_unregister: -- device_unregister(&ubi->dev); --out: -- ubi_err("failed to initialize sysfs for %s", ubi->ubi_name); -+ return err; -+ err = device_create_file(&ubi->dev, &dev_mtd_num); - return err; - } - -@@ -221,6 +329,7 @@ - */ - static void ubi_sysfs_close(struct ubi_device *ubi) - { -+ device_remove_file(&ubi->dev, &dev_mtd_num); - device_remove_file(&ubi->dev, &dev_bgt_enabled); - device_remove_file(&ubi->dev, &dev_min_io_size); - device_remove_file(&ubi->dev, &dev_max_vol_count); -@@ -244,7 +353,26 @@ - - for (i = 0; i < ubi->vtbl_slots; i++) - if (ubi->volumes[i]) -- ubi_free_volume(ubi, i); -+ ubi_free_volume(ubi, ubi->volumes[i]); -+} -+ -+/** -+ * free_user_volumes - free all user volumes. -+ * @ubi: UBI device description object -+ * -+ * Normally the volumes are freed at the release function of the volume device -+ * objects. However, on error paths the volumes have to be freed before the -+ * device objects have been initialized. -+ */ -+static void free_user_volumes(struct ubi_device *ubi) -+{ -+ int i; -+ -+ for (i = 0; i < ubi->vtbl_slots; i++) -+ if (ubi->volumes[i]) { -+ kfree(ubi->volumes[i]->eba_tbl); -+ kfree(ubi->volumes[i]); -+ } - } - - /** -@@ -252,16 +380,13 @@ - * @ubi: UBI device description object - * - * This function returns zero in case of success and a negative error code in -- * case of failure. -+ * case of failure. Note, this function destroys all volumes if it failes. - */ - static int uif_init(struct ubi_device *ubi) - { - int i, err; - dev_t dev; - -- mutex_init(&ubi->vtbl_mutex); -- spin_lock_init(&ubi->volumes_lock); -- - sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); - - /* -@@ -278,52 +403,72 @@ - return err; - } - -+ ubi_assert(MINOR(dev) == 0); - cdev_init(&ubi->cdev, &ubi_cdev_operations); -- ubi->major = MAJOR(dev); -- dbg_msg("%s major is %u", ubi->ubi_name, ubi->major); -+ dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev)); - ubi->cdev.owner = THIS_MODULE; - -- dev = MKDEV(ubi->major, 0); - err = cdev_add(&ubi->cdev, dev, 1); - if (err) { -- ubi_err("cannot add character device %s", ubi->ubi_name); -+ ubi_err("cannot add character device"); - goto out_unreg; - } - - err = ubi_sysfs_init(ubi); - if (err) -- goto out_cdev; -+ goto out_sysfs; - - for (i = 0; i < ubi->vtbl_slots; i++) - if (ubi->volumes[i]) { -- err = ubi_add_volume(ubi, i); -- if (err) -+ err = ubi_add_volume(ubi, ubi->volumes[i]); -+ if (err) { -+ ubi_err("cannot add volume %d", i); - goto out_volumes; -+ } - } - - return 0; - - out_volumes: - kill_volumes(ubi); -+out_sysfs: - ubi_sysfs_close(ubi); --out_cdev: - cdev_del(&ubi->cdev); - out_unreg: -- unregister_chrdev_region(MKDEV(ubi->major, 0), -- ubi->vtbl_slots + 1); -+ unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); -+ ubi_err("cannot initialize UBI %s, error %d", ubi->ubi_name, err); - return err; - } - - /** - * uif_close - close user interfaces for an UBI device. - * @ubi: UBI device description object -+ * -+ * Note, since this function un-registers UBI volume device objects (@vol->dev), -+ * the memory allocated voe the volumes is freed as well (in the release -+ * function). - */ - static void uif_close(struct ubi_device *ubi) - { - kill_volumes(ubi); - ubi_sysfs_close(ubi); - cdev_del(&ubi->cdev); -- unregister_chrdev_region(MKDEV(ubi->major, 0), ubi->vtbl_slots + 1); -+ unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); -+} -+ -+/** -+ * free_internal_volumes - free internal volumes. -+ * @ubi: UBI device description object -+ */ -+static void free_internal_volumes(struct ubi_device *ubi) -+{ -+ int i; -+ -+ for (i = ubi->vtbl_slots; -+ i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { -+ kfree(ubi->volumes[i]->eba_tbl); -+ kfree(ubi->volumes[i]); -+ } - } - - /** -@@ -370,6 +515,7 @@ - out_wl: - ubi_wl_close(ubi); - out_vtbl: -+ free_internal_volumes(ubi); - vfree(ubi->vtbl); - out_si: - ubi_scan_destroy_si(si); -@@ -377,16 +523,16 @@ - } - - /** -- * io_init - initialize I/O unit for a given UBI device. -+ * io_init - initialize I/O sub-system for a given UBI device. - * @ubi: UBI device description object - * - * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are - * assumed: - * o EC header is always at offset zero - this cannot be changed; - * o VID header starts just after the EC header at the closest address -- * aligned to @io->@hdrs_min_io_size; -+ * aligned to @io->hdrs_min_io_size; - * o data starts just after the VID header at the closest address aligned to -- * @io->@min_io_size -+ * @io->min_io_size - * - * This function returns zero in case of success and a negative error code in - * case of failure. -@@ -407,6 +553,9 @@ - return -EINVAL; - } - -+ if (ubi->vid_hdr_offset < 0) -+ return -EINVAL; -+ - /* - * Note, in this implementation we support MTD devices with 0x7FFFFFFF - * physical eraseblocks maximum. -@@ -422,9 +571,14 @@ - ubi->min_io_size = ubi->mtd->writesize; - ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; - -- /* Make sure minimal I/O unit is power of 2 */ -+ /* -+ * Make sure minimal I/O unit is power of 2. Note, there is no -+ * fundamental reason for this assumption. It is just an optimization -+ * which allows us to avoid costly division operations. -+ */ - if (!is_power_of_2(ubi->min_io_size)) { -- ubi_err("bad min. I/O unit"); -+ ubi_err("min. I/O unit (%d) is not power of 2", -+ ubi->min_io_size); - return -EINVAL; - } - -@@ -453,10 +607,8 @@ - } - - /* Similar for the data offset */ -- if (ubi->leb_start == 0) { -- ubi->leb_start = ubi->vid_hdr_offset + ubi->vid_hdr_alsize; -- ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); -- } -+ ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; -+ ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); - - dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); - dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset); -@@ -474,7 +626,7 @@ - if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || - ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || - ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || -- ubi->leb_start % ubi->min_io_size) { -+ ubi->leb_start & (ubi->min_io_size - 1)) { - ubi_err("bad VID header (%d) or data offsets (%d)", - ubi->vid_hdr_offset, ubi->leb_start); - return -EINVAL; -@@ -499,8 +651,16 @@ - ubi->ro_mode = 1; - } - -- dbg_msg("leb_size %d", ubi->leb_size); -- dbg_msg("ro_mode %d", ubi->ro_mode); -+ ubi_msg("physical eraseblock size: %d bytes (%d KiB)", -+ ubi->peb_size, ubi->peb_size >> 10); -+ ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); -+ ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); -+ if (ubi->hdrs_min_io_size != ubi->min_io_size) -+ ubi_msg("sub-page size: %d", -+ ubi->hdrs_min_io_size); -+ ubi_msg("VID header offset: %d (aligned %d)", -+ ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); -+ ubi_msg("data offset: %d", ubi->leb_start); - - /* - * Note, ideally, we have to initialize ubi->bad_peb_count here. But -@@ -514,89 +674,162 @@ - } - - /** -- * attach_mtd_dev - attach an MTD device. -- * @mtd_dev: MTD device name or number string -- * @vid_hdr_offset: VID header offset -- * @data_offset: data offset -+ * autoresize - re-size the volume which has the "auto-resize" flag set. -+ * @ubi: UBI device description object -+ * @vol_id: ID of the volume to re-size - * -- * This function attaches an MTD device to UBI. It first treats @mtd_dev as the -- * MTD device name, and tries to open it by this name. If it is unable to open, -- * it tries to convert @mtd_dev to an integer and open the MTD device by its -- * number. Returns zero in case of success and a negative error code in case of -- * failure. -+ * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in -+ * the volume table to the largest possible size. See comments in ubi-header.h -+ * for more description of the flag. Returns zero in case of success and a -+ * negative error code in case of failure. - */ --static int attach_mtd_dev(const char *mtd_dev, int vid_hdr_offset, -- int data_offset) -+static int autoresize(struct ubi_device *ubi, int vol_id) - { -- struct ubi_device *ubi; -- struct mtd_info *mtd; -- int i, err; -+ struct ubi_volume_desc desc; -+ struct ubi_volume *vol = ubi->volumes[vol_id]; -+ int err, old_reserved_pebs = vol->reserved_pebs; - -- mtd = get_mtd_device_nm(mtd_dev); -- if (IS_ERR(mtd)) { -- int mtd_num; -- char *endp; -+ /* -+ * Clear the auto-resize flag in the volume in-memory copy of the -+ * volume table, and 'ubi_resize_volume()' will propagate this change -+ * to the flash. -+ */ -+ ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; - -- if (PTR_ERR(mtd) != -ENODEV) -- return PTR_ERR(mtd); -+ if (ubi->avail_pebs == 0) { -+ struct ubi_vtbl_record vtbl_rec; - - /* -- * Probably this is not MTD device name but MTD device number - -- * check this out. -+ * No available PEBs to re-size the volume, clear the flag on -+ * flash and exit. - */ -- mtd_num = simple_strtoul(mtd_dev, &endp, 0); -- if (*endp != '\0' || mtd_dev == endp) { -- ubi_err("incorrect MTD device: \"%s\"", mtd_dev); -- return -ENODEV; -+ memcpy(&vtbl_rec, &ubi->vtbl[vol_id], -+ sizeof(struct ubi_vtbl_record)); -+ err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); -+ if (err) -+ ubi_err("cannot clean auto-resize flag for volume %d", -+ vol_id); -+ } else { -+ desc.vol = vol; -+ err = ubi_resize_volume(&desc, -+ old_reserved_pebs + ubi->avail_pebs); -+ if (err) -+ ubi_err("cannot auto-resize volume %d", vol_id); -+ } -+ -+ if (err) -+ return err; -+ -+ ubi_msg("volume %d (\"%s\") re-sized from %d to %d LEBs", vol_id, -+ vol->name, old_reserved_pebs, vol->reserved_pebs); -+ return 0; -+} -+ -+/** -+ * ubi_attach_mtd_dev - attach an MTD device. -+ * @mtd: MTD device description object -+ * @ubi_num: number to assign to the new UBI device -+ * @vid_hdr_offset: VID header offset -+ * -+ * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number -+ * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in -+ * which case this function finds a vacant device number and assigns it -+ * automatically. Returns the new UBI device number in case of success and a -+ * negative error code in case of failure. -+ * -+ * Note, the invocations of this function has to be serialized by the -+ * @ubi_devices_mutex. -+ */ -+int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) -+{ -+ struct ubi_device *ubi; -+ int i, err, do_free = 1; -+ -+ /* -+ * Check if we already have the same MTD device attached. -+ * -+ * Note, this function assumes that UBI devices creations and deletions -+ * are serialized, so it does not take the &ubi_devices_lock. -+ */ -+ for (i = 0; i < UBI_MAX_DEVICES; i++) { -+ ubi = ubi_devices[i]; -+ if (ubi && mtd->index == ubi->mtd->index) { -+ dbg_err("mtd%d is already attached to ubi%d", -+ mtd->index, i); -+ return -EEXIST; - } -+ } - -- mtd = get_mtd_device(NULL, mtd_num); -- if (IS_ERR(mtd)) -- return PTR_ERR(mtd); -+ /* -+ * Make sure this MTD device is not emulated on top of an UBI volume -+ * already. Well, generally this recursion works fine, but there are -+ * different problems like the UBI module takes a reference to itself -+ * by attaching (and thus, opening) the emulated MTD device. This -+ * results in inability to unload the module. And in general it makes -+ * no sense to attach emulated MTD devices, so we prohibit this. -+ */ -+ if (mtd->type == MTD_UBIVOLUME) { -+ ubi_err("refuse attaching mtd%d - it is already emulated on " -+ "top of UBI", mtd->index); -+ return -EINVAL; - } - -- /* Check if we already have the same MTD device attached */ -- for (i = 0; i < ubi_devices_cnt; i++) -- if (ubi_devices[i]->mtd->index == mtd->index) { -- ubi_err("mtd%d is already attached to ubi%d", -- mtd->index, i); -- err = -EINVAL; -- goto out_mtd; -+ if (ubi_num == UBI_DEV_NUM_AUTO) { -+ /* Search for an empty slot in the @ubi_devices array */ -+ for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) -+ if (!ubi_devices[ubi_num]) -+ break; -+ if (ubi_num == UBI_MAX_DEVICES) { -+ dbg_err("only %d UBI devices may be created", -+ UBI_MAX_DEVICES); -+ return -ENFILE; - } -+ } else { -+ if (ubi_num >= UBI_MAX_DEVICES) -+ return -EINVAL; - -- ubi = ubi_devices[ubi_devices_cnt] = kzalloc(sizeof(struct ubi_device), -- GFP_KERNEL); -- if (!ubi) { -- err = -ENOMEM; -- goto out_mtd; -+ /* Make sure ubi_num is not busy */ -+ if (ubi_devices[ubi_num]) { -+ dbg_err("ubi%d already exists", ubi_num); -+ return -EEXIST; -+ } - } - -- ubi->ubi_num = ubi_devices_cnt; -+ ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); -+ if (!ubi) -+ return -ENOMEM; -+ - ubi->mtd = mtd; -+ ubi->ubi_num = ubi_num; -+ ubi->vid_hdr_offset = vid_hdr_offset; -+ ubi->autoresize_vol_id = -1; - -- dbg_msg("attaching mtd%d to ubi%d: VID header offset %d data offset %d", -- ubi->mtd->index, ubi_devices_cnt, vid_hdr_offset, data_offset); -+ mutex_init(&ubi->buf_mutex); -+ mutex_init(&ubi->ckvol_mutex); -+ mutex_init(&ubi->mult_mutex); -+ mutex_init(&ubi->volumes_mutex); -+ spin_lock_init(&ubi->volumes_lock); -+ -+ ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); - -- ubi->vid_hdr_offset = vid_hdr_offset; -- ubi->leb_start = data_offset; - err = io_init(ubi); - if (err) - goto out_free; - -- mutex_init(&ubi->buf_mutex); -+ err = -ENOMEM; - ubi->peb_buf1 = vmalloc(ubi->peb_size); - if (!ubi->peb_buf1) - goto out_free; - - ubi->peb_buf2 = vmalloc(ubi->peb_size); - if (!ubi->peb_buf2) -- goto out_free; -+ goto out_free; - - #ifdef CONFIG_MTD_UBI_DEBUG - mutex_init(&ubi->dbg_buf_mutex); - ubi->dbg_peb_buf = vmalloc(ubi->peb_size); - if (!ubi->dbg_peb_buf) -- goto out_free; -+ goto out_free; - #endif - - err = attach_by_scanning(ubi); -@@ -605,22 +838,29 @@ - goto out_free; - } - -+ if (ubi->autoresize_vol_id != -1) { -+ err = autoresize(ubi, ubi->autoresize_vol_id); -+ if (err) -+ goto out_detach; -+ } -+ - err = uif_init(ubi); - if (err) -- goto out_detach; -+ goto out_nofree; - -- ubi_msg("attached mtd%d to ubi%d", ubi->mtd->index, ubi_devices_cnt); -- ubi_msg("MTD device name: \"%s\"", ubi->mtd->name); -+ ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); -+ if (IS_ERR(ubi->bgt_thread)) { -+ err = PTR_ERR(ubi->bgt_thread); -+ ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name, -+ err); -+ goto out_uif; -+ } -+ -+ ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); -+ ubi_msg("MTD device name: \"%s\"", mtd->name); - ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); -- ubi_msg("physical eraseblock size: %d bytes (%d KiB)", -- ubi->peb_size, ubi->peb_size >> 10); -- ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); - ubi_msg("number of good PEBs: %d", ubi->good_peb_count); - ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); -- ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); -- ubi_msg("VID header offset: %d (aligned %d)", -- ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); -- ubi_msg("data offset: %d", ubi->leb_start); - ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); - ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); - ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); -@@ -632,18 +872,22 @@ - ubi->beb_rsvd_pebs); - ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); - -- /* Enable the background thread */ -- if (!DBG_DISABLE_BGT) { -+ if (!DBG_DISABLE_BGT) - ubi->thread_enabled = 1; -- wake_up_process(ubi->bgt_thread); -- } -+ wake_up_process(ubi->bgt_thread); - -- ubi_devices_cnt += 1; -- return 0; -+ ubi_devices[ubi_num] = ubi; -+ return ubi_num; - -+out_uif: -+ uif_close(ubi); -+out_nofree: -+ do_free = 0; - out_detach: -- ubi_eba_close(ubi); - ubi_wl_close(ubi); -+ if (do_free) -+ free_user_volumes(ubi); -+ free_internal_volumes(ubi); - vfree(ubi->vtbl); - out_free: - vfree(ubi->peb_buf1); -@@ -652,24 +896,67 @@ - vfree(ubi->dbg_peb_buf); - #endif - kfree(ubi); --out_mtd: -- put_mtd_device(mtd); -- ubi_devices[ubi_devices_cnt] = NULL; - return err; - } - - /** -- * detach_mtd_dev - detach an MTD device. -- * @ubi: UBI device description object -+ * ubi_detach_mtd_dev - detach an MTD device. -+ * @ubi_num: UBI device number to detach from -+ * @anyway: detach MTD even if device reference count is not zero -+ * -+ * This function destroys an UBI device number @ubi_num and detaches the -+ * underlying MTD device. Returns zero in case of success and %-EBUSY if the -+ * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not -+ * exist. -+ * -+ * Note, the invocations of this function has to be serialized by the -+ * @ubi_devices_mutex. - */ --static void detach_mtd_dev(struct ubi_device *ubi) -+int ubi_detach_mtd_dev(int ubi_num, int anyway) - { -- int ubi_num = ubi->ubi_num, mtd_num = ubi->mtd->index; -+ struct ubi_de |
