diff options
| author | Dmitry Pervushin <dpervushin@embeddedalley.com> | 2009-05-31 10:32:59 -0400 |
|---|---|---|
| committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-06-03 10:45:23 -0400 |
| commit | 2ba3d76a1e29f2ba64fbc762875cf9fb2d4ba2ba (patch) | |
| tree | 633d48cb740534827b2a764c74e7b423415c0774 | |
| parent | 518ceef0c9ca97023e45ae46aedaefa240c690a6 (diff) | |
UBI: make gluebi a separate module
[Artem: re-worked the patch: made it release resources when the
module is unloaded, made it do module referencing, made it really
independent on UBI, tested it with the UBI test-suite which can
be found in ubi-2.6.git/tests/ubi-tests, re-named most of the
funcs/variables to get rid of the "ubi" word and make names
consistent.]
Signed-off-by: Dmitry Pervushin <dpervushin@embeddedalley.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
| -rw-r--r-- | drivers/mtd/ubi/Kconfig | 13 | ||||
| -rw-r--r-- | drivers/mtd/ubi/Makefile | 2 | ||||
| -rw-r--r-- | drivers/mtd/ubi/gluebi.c | 378 |
3 files changed, 295 insertions, 98 deletions
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 3f063108e95f..b1cd7a1a2191 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig | |||
| @@ -49,15 +49,16 @@ config MTD_UBI_BEB_RESERVE | |||
| 49 | reserved. Leave the default value if unsure. | 49 | reserved. Leave the default value if unsure. |
| 50 | 50 | ||
| 51 | config MTD_UBI_GLUEBI | 51 | config MTD_UBI_GLUEBI |
| 52 | bool "Emulate MTD devices" | 52 | tristate "MTD devices emulation driver (gluebi)" |
| 53 | default n | 53 | default n |
| 54 | depends on MTD_UBI | 54 | depends on MTD_UBI |
| 55 | help | 55 | help |
| 56 | This option enables MTD devices emulation on top of UBI volumes: for | 56 | This option enables gluebi - an additional driver which emulates MTD |
| 57 | each UBI volumes an MTD device is created, and all I/O to this MTD | 57 | devices on top of UBI volumes: for each UBI volumes an MTD device is |
| 58 | device is redirected to the UBI volume. This is handy to make | 58 | created, and all I/O to this MTD device is redirected to the UBI |
| 59 | MTD-oriented software (like JFFS2) work on top of UBI. Do not enable | 59 | volume. This is handy to make MTD-oriented software (like JFFS2) |
| 60 | this if no legacy software will be used. | 60 | work on top of UBI. Do not enable this unless you use legacy |
| 61 | software. | ||
| 61 | 62 | ||
| 62 | source "drivers/mtd/ubi/Kconfig.debug" | 63 | source "drivers/mtd/ubi/Kconfig.debug" |
| 63 | endmenu | 64 | endmenu |
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile index dd834e04151b..c9302a5452b0 100644 --- a/drivers/mtd/ubi/Makefile +++ b/drivers/mtd/ubi/Makefile | |||
| @@ -4,4 +4,4 @@ ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o | |||
| 4 | ubi-y += misc.o | 4 | ubi-y += misc.o |
| 5 | 5 | ||
| 6 | ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o | 6 | ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o |
| 7 | ubi-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o | 7 | obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o |
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 49cd55ade9c8..95aaac03f938 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
| @@ -19,17 +19,71 @@ | |||
| 19 | */ | 19 | */ |
| 20 | 20 | ||
| 21 | /* | 21 | /* |
| 22 | * This file includes implementation of fake MTD devices for each UBI volume. | 22 | * This is a small driver which implements fake MTD devices on top of UBI |
| 23 | * This sounds strange, but it is in fact quite useful to make MTD-oriented | 23 | * volumes. This sounds strange, but it is in fact quite useful to make |
| 24 | * software (including all the legacy software) to work on top of UBI. | 24 | * MTD-oriented software (including all the legacy software) work on top of |
| 25 | * UBI. | ||
| 25 | * | 26 | * |
| 26 | * Gluebi emulates MTD devices of "MTD_UBIVOLUME" type. Their minimal I/O unit | 27 | * Gluebi emulates MTD devices of "MTD_UBIVOLUME" type. Their minimal I/O unit |
| 27 | * size (mtd->writesize) is equivalent to the UBI minimal I/O unit. The | 28 | * size (@mtd->writesize) is equivalent to the UBI minimal I/O unit. The |
| 28 | * eraseblock size is equivalent to the logical eraseblock size of the volume. | 29 | * eraseblock size is equivalent to the logical eraseblock size of the volume. |
| 29 | */ | 30 | */ |
| 30 | 31 | ||
| 32 | #include <linux/err.h> | ||
| 33 | #include <linux/list.h> | ||
| 34 | #include <linux/sched.h> | ||
| 31 | #include <linux/math64.h> | 35 | #include <linux/math64.h> |
| 32 | #include "ubi.h" | 36 | #include <linux/module.h> |
| 37 | #include <linux/mutex.h> | ||
| 38 | #include <linux/mtd/ubi.h> | ||
| 39 | #include <linux/mtd/mtd.h> | ||
| 40 | #include "ubi-media.h" | ||
| 41 | |||
| 42 | #define err_msg(fmt, ...) \ | ||
| 43 | printk(KERN_DEBUG "gluebi (pid %d): %s: " fmt "\n", \ | ||
| 44 | current->pid, __func__, ##__VA_ARGS__) | ||
| 45 | |||
| 46 | /** | ||
| 47 | * struct gluebi_device - a gluebi device description data structure. | ||
| 48 | * @mtd: emulated MTD device description object | ||
| 49 | * @refcnt: gluebi device reference count | ||
| 50 | * @desc: UBI volume descriptor | ||
| 51 | * @ubi_num: UBI device number this gluebi device works on | ||
| 52 | * @vol_id: ID of UBI volume this gluebi device works on | ||
| 53 | * @list: link in a list of gluebi devices | ||
| 54 | */ | ||
| 55 | struct gluebi_device { | ||
| 56 | struct mtd_info mtd; | ||
| 57 | int refcnt; | ||
| 58 | struct ubi_volume_desc *desc; | ||
| 59 | int ubi_num; | ||
| 60 | int vol_id; | ||
| 61 | struct list_head list; | ||
| 62 | }; | ||
| 63 | |||
| 64 | /* List of all gluebi devices */ | ||
| 65 | static LIST_HEAD(gluebi_devices); | ||
| 66 | static DEFINE_MUTEX(devices_mutex); | ||
| 67 | |||
| 68 | /** | ||
| 69 | * find_gluebi_nolock - find a gluebi device. | ||
| 70 | * @ubi_num: UBI device number | ||
| 71 | * @vol_id: volume ID | ||
| 72 | * | ||
| 73 | * This function seraches for gluebi device corresponding to UBI device | ||
| 74 | * @ubi_num and UBI volume @vol_id. Returns the gluebi device description | ||
| 75 | * object in case of success and %NULL in case of failure. The caller has to | ||
| 76 | * have the &devices_mutex locked. | ||
| 77 | */ | ||
| 78 | static struct gluebi_device *find_gluebi_nolock(int ubi_num, int vol_id) | ||
| 79 | { | ||
| 80 | struct gluebi_device *gluebi; | ||
| 81 | |||
| 82 | list_for_each_entry(gluebi, &gluebi_devices, list) | ||
| 83 | if (gluebi->ubi_num == ubi_num && gluebi->vol_id == vol_id) | ||
| 84 | return gluebi; | ||
| 85 | return NULL; | ||
| 86 | } | ||
| 33 | 87 | ||
| 34 | /** | 88 | /** |
| 35 | * gluebi_get_device - get MTD device reference. | 89 | * gluebi_get_device - get MTD device reference. |
| @@ -41,15 +95,18 @@ | |||
| 41 | */ | 95 | */ |
| 42 | static int gluebi_get_device(struct mtd_info *mtd) | 96 | static int gluebi_get_device(struct mtd_info *mtd) |
| 43 | { | 97 | { |
| 44 | struct ubi_volume *vol; | 98 | struct gluebi_device *gluebi; |
| 99 | int ubi_mode = UBI_READONLY; | ||
| 45 | 100 | ||
| 46 | vol = container_of(mtd, struct ubi_volume, gluebi_mtd); | 101 | if (!try_module_get(THIS_MODULE)) |
| 102 | return -ENODEV; | ||
| 47 | 103 | ||
| 48 | /* | 104 | if (mtd->flags & MTD_WRITEABLE) |
| 49 | * We do not introduce locks for gluebi reference count because the | 105 | ubi_mode = UBI_READWRITE; |
| 50 | * get_device()/put_device() calls are already serialized at MTD. | 106 | |
| 51 | */ | 107 | gluebi = container_of(mtd, struct gluebi_device, mtd); |
| 52 | if (vol->gluebi_refcount > 0) { | 108 | mutex_lock(&devices_mutex); |
| 109 | if (gluebi->refcnt > 0) { | ||
| 53 | /* | 110 | /* |
| 54 | * The MTD device is already referenced and this is just one | 111 | * The MTD device is already referenced and this is just one |
| 55 | * more reference. MTD allows many users to open the same | 112 | * more reference. MTD allows many users to open the same |
| @@ -58,7 +115,8 @@ static int gluebi_get_device(struct mtd_info *mtd) | |||
| 58 | * open the UBI volume again - just increase the reference | 115 | * open the UBI volume again - just increase the reference |
| 59 | * counter and return. | 116 | * counter and return. |
| 60 | */ | 117 | */ |
| 61 | vol->gluebi_refcount += 1; | 118 | gluebi->refcnt += 1; |
| 119 | mutex_unlock(&devices_mutex); | ||
| 62 | return 0; | 120 | return 0; |
| 63 | } | 121 | } |
| 64 | 122 | ||
| @@ -66,11 +124,15 @@ static int gluebi_get_device(struct mtd_info *mtd) | |||
| 66 | * This is the first reference to this UBI volume via the MTD device | 124 | * This is the first reference to this UBI volume via the MTD device |
| 67 | * interface. Open the corresponding volume in read-write mode. | 125 | * interface. Open the corresponding volume in read-write mode. |
| 68 | */ | 126 | */ |
| 69 | vol->gluebi_desc = ubi_open_volume(vol->ubi->ubi_num, vol->vol_id, | 127 | gluebi->desc = ubi_open_volume(gluebi->ubi_num, gluebi->vol_id, |
| 70 | UBI_READWRITE); | 128 | ubi_mode); |
| 71 | if (IS_ERR(vol->gluebi_desc)) | 129 | if (IS_ERR(gluebi->desc)) { |
| 72 | return PTR_ERR(vol->gluebi_desc); | 130 | mutex_unlock(&devices_mutex); |
| 73 | vol->gluebi_refcount += 1; | 131 | module_put(THIS_MODULE); |
| 132 | return PTR_ERR(gluebi->desc); | ||
| 133 | } | ||
| 134 | gluebi->refcnt += 1; | ||
| 135 | mutex_unlock(&devices_mutex); | ||
| 74 | return 0; | 136 | return 0; |
| 75 | } | 137 | } |
| 76 | 138 | ||
| @@ -83,13 +145,15 @@ static int gluebi_get_device(struct mtd_info *mtd) | |||
| 83 | */ | 145 | */ |
| 84 | static void gluebi_put_device(struct mtd_info *mtd) | 146 | static void gluebi_put_device(struct mtd_info *mtd) |
| 85 | { | 147 | { |
| 86 | struct ubi_volume *vol; | 148 | struct gluebi_device *gluebi; |
| 87 | 149 | ||
| 88 | vol = container_of(mtd, struct ubi_volume, gluebi_mtd); | 150 | gluebi = container_of(mtd, struct gluebi_device, mtd); |
| 89 | vol->gluebi_refcount -= 1; | ||
