aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorDmitry Pervushin <dpervushin@embeddedalley.com>2009-05-31 10:32:59 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-06-03 10:45:23 -0400
commit2ba3d76a1e29f2ba64fbc762875cf9fb2d4ba2ba (patch)
tree633d48cb740534827b2a764c74e7b423415c0774 /drivers/mtd
parent518ceef0c9ca97023e45ae46aedaefa240c690a6 (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>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/ubi/Kconfig13
-rw-r--r--drivers/mtd/ubi/Makefile2
-rw-r--r--drivers/mtd/ubi/gluebi.c378
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
51config MTD_UBI_GLUEBI 51config 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
62source "drivers/mtd/ubi/Kconfig.debug" 63source "drivers/mtd/ubi/Kconfig.debug"
63endmenu 64endmenu
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
4ubi-y += misc.o 4ubi-y += misc.o
5 5
6ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o 6ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
7ubi-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o 7obj-$(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 */
55struct 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 */
65static LIST_HEAD(gluebi_devices);
66static 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 */
78static 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 */
42static int gluebi_get_device(struct mtd_info *mtd) 96static 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 */
84static void gluebi_put_device(struct mtd_info *mtd) 146static 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; 151 mutex_lock(&devices_mutex);
90 ubi_assert(vol->gluebi_refcount >= 0); 152 gluebi->refcnt -= 1;
91 if (vol->gluebi_refcount == 0) 153 if (gluebi->refcnt == 0)
92 ubi_close_volume(vol->gluebi_desc); 154 ubi_close_volume(gluebi->desc);
155 module_put(THIS_MODULE);
156 mutex_unlock(&devices_mutex);
93} 157}
94 158
95/** 159/**
@@ -107,16 +171,12 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
107 size_t *retlen, unsigned char *buf) 171 size_t *retlen, unsigned char *buf)
108{ 172{
109 int err = 0, lnum, offs, total_read; 173 int err = 0, lnum, offs, total_read;
110 struct ubi_volume *vol; 174 struct gluebi_device *gluebi;
111 struct ubi_device *ubi;
112
113 dbg_gen("read %zd bytes from offset %lld", len, from);
114 175
115 if (len < 0 || from < 0 || from + len > mtd->size) 176 if (len < 0 || from < 0 || from + len > mtd->size)
116 return -EINVAL; 177 return -EINVAL;
117 178
118 vol = container_of(mtd, struct ubi_volume, gluebi_mtd); 179 gluebi = container_of(mtd, struct gluebi_device, mtd);
119 ubi = vol->ubi;
120 180
121 lnum = div_u64_rem(from, mtd->erasesize, &offs); 181 lnum = div_u64_rem(from, mtd->erasesize, &offs);
122 total_read = len; 182 total_read = len;
@@ -126,7 +186,7 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
126 if (to_read > total_read) 186 if (to_read > total_read)
127 to_read = total_read; 187 to_read = total_read;
128 188
129 err = ubi_eba_read_leb(ubi, vol, lnum, buf, offs, to_read, 0); 189 err = ubi_read(gluebi->desc, lnum, buf, offs, to_read);
130 if (err) 190 if (err)
131 break; 191 break;
132 192
@@ -152,21 +212,17 @@ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len,
152 * case of failure. 212 * case of failure.
153 */ 213 */
154static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, 214static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
155 size_t *retlen, const u_char *buf) 215 size_t *retlen, const u_char *buf)
156{ 216{
157 int err = 0, lnum, offs, total_written; 217 int err = 0, lnum, offs, total_written;
158 struct ubi_volume *vol; 218 struct gluebi_device *gluebi;
159 struct ubi_device *ubi;
160
161 dbg_gen("write %zd bytes to offset %lld", len, to);
162 219
163 if (len < 0 || to < 0 || len + to > mtd->size) 220 if (len < 0 || to < 0 || len + to > mtd->size)
164 return -EINVAL; 221 return -EINVAL;
165 222
166 vol = container_of(mtd, struct ubi_volume, gluebi_mtd); 223 gluebi = container_of(mtd, struct gluebi_device, mtd);
167 ubi = vol->ubi;
168 224
169 if (ubi->ro_mode) 225 if (!(mtd->flags & MTD_WRITEABLE))
170 return -EROFS; 226 return -EROFS;
171 227
172 lnum = div_u64_rem(to, mtd->erasesize, &offs); 228 lnum = div_u64_rem(to, mtd->erasesize, &offs);
@@ -181,8 +237,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
181 if (to_write > total_written) 237 if (to_write > total_written)
182 to_write = total_written; 238 to_write = total_written;
183 239
184 err = ubi_eba_write_leb(ubi, vol, lnum, buf, offs, to_write, 240 err = ubi_write(gluebi->desc, lnum, buf, offs, to_write);
185 UBI_UNKNOWN);
186 if (err) 241 if (err)
187 break; 242 break;
188 243
@@ -207,41 +262,36 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len,
207static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) 262static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr)
208{ 263{
209 int err, i, lnum, count; 264 int err, i, lnum, count;
210 struct ubi_volume *vol; 265 struct gluebi_device *gluebi;
211 struct ubi_device *ubi;
212
213 dbg_gen("erase %llu bytes at offset %llu", (unsigned long long)instr->len,
214 (unsigned long long)instr->addr);
215 266
216 if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize) 267 if (instr->addr < 0 || instr->addr > mtd->size - mtd->erasesize)
217 return -EINVAL; 268 return -EINVAL;
218
219 if (instr->len < 0 || instr->addr + instr->len > mtd->size) 269 if (instr->len < 0 || instr->addr + instr->len > mtd->size)
220 return -EINVAL; 270 return -EINVAL;
221
222 if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd)) 271 if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd))
223 return -EINVAL; 272 return -EINVAL;
224 273
225 lnum = mtd_div_by_eb(instr->addr, mtd); 274 lnum = mtd_div_by_eb(instr->addr, mtd);
226 count = mtd_div_by_eb(instr->len, mtd); 275 count = mtd_div_by_eb(instr->len, mtd);
227 276
228 vol = container_of(mtd, struct ubi_volume, gluebi_mtd); 277 gluebi = container_of(mtd, struct gluebi_device, mtd);
229 ubi = vol->ubi;
230 278
231 if (ubi->ro_mode) 279 if (!(mtd->flags & MTD_WRITEABLE))
232 return -EROFS; 280 return -EROFS;
233 281
234 for (i = 0; i < count; i++) { 282 for (i = 0; i < count - 1; i++) {
235 err = ubi_eba_unmap_leb(ubi, vol, lnum + i); 283 err = ubi_leb_unmap(gluebi->desc, lnum + i);
236 if (err) 284 if (err)
237 goto out_err; 285 goto out_err;
238 } 286 }
239
240 /* 287 /*
241 * MTD erase operations are synchronous, so we have to make sure the 288 * MTD erase operations are synchronous, so we have to make sure the
242 * physical eraseblock is wiped out. 289 * physical eraseblock is wiped out.
290 *
291 * Thus, perform leb_erase instead of leb_unmap operation - leb_erase
292 * will wait for the end of operations
243 */ 293 */
244 err = ubi_wl_flush(ubi); 294 err = ubi_leb_erase(gluebi->desc, lnum + i);
245 if (err) 295 if (err)
246 goto out_err; 296 goto out_err;
247 297
@@ -256,28 +306,38 @@ out_err:
256} 306}
257 307
258/** 308/**
259 * ubi_create_gluebi - initialize gluebi for an UBI volume. 309 * gluebi_create - create a gluebi device for an UBI volume.
260 * @ubi: UBI device description object 310 * @di: UBI device description object
261 * @vol: volume description object 311 * @vi: UBI volume description object
262 * 312 *
263 * This function is called when an UBI volume is created in order to create 313 * This function is called when a new UBI volume is created in order to create
264 * corresponding fake MTD device. Returns zero in case of success and a 314 * corresponding fake MTD device. Returns zero in case of success and a
265 * negative error code in case of failure. 315 * negative error code in case of failure.
266 */ 316 */
267int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) 317static int gluebi_create(struct ubi_device_info *di,
318 struct ubi_volume_info *vi)
268{ 319{
269 struct mtd_info *mtd = &vol->gluebi_mtd; 320 struct gluebi_device *gluebi, *g;
321 struct mtd_info *mtd;
270 322
271 mtd->name = kmemdup(vol->name, vol->name_len + 1, GFP_KERNEL); 323 gluebi = kzalloc(sizeof(struct gluebi_device), GFP_KERNEL);
272 if (!mtd->name) 324 if (!gluebi)
273 return -ENOMEM; 325 return -ENOMEM;
274 326
327 mtd = &gluebi->mtd;
328 mtd->name = kmemdup(vi->name, vi->name_len + 1, GFP_KERNEL);
329 if (!mtd->name) {
330 kfree(gluebi);
331 return -ENOMEM;
332 }
333
334 gluebi->vol_id = vi->vol_id;
275 mtd->type = MTD_UBIVOLUME; 335 mtd->type = MTD_UBIVOLUME;
276 if (!ubi->ro_mode) 336 if (!di->ro_mode)
277 mtd->flags = MTD_WRITEABLE; 337 mtd->flags = MTD_WRITEABLE;
278 mtd->writesize = ubi->min_io_size;
279 mtd->owner = THIS_MODULE; 338 mtd->owner = THIS_MODULE;
280 mtd->erasesize = vol->usable_leb_size; 339 mtd->writesize = di->min_io_size;
340 mtd->erasesize = vi->usable_leb_size;
281 mtd->read = gluebi_read; 341 mtd->read = gluebi_read;
282 mtd->write = gluebi_write; 342 mtd->write = gluebi_write;
283 mtd->erase = gluebi_erase; 343 mtd->erase = gluebi_erase;
@@ -285,60 +345,196 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol)
285 mtd->put_device = gluebi_put_device; 345 mtd->put_device = gluebi_put_device;
286 346
287 /* 347 /*
288 * In case of dynamic volume, MTD device size is just volume size. In 348 * In case of dynamic a volume, MTD device size is just volume size. In
289 * case of a static volume the size is equivalent to the amount of data 349 * case of a static volume the size is equivalent to the amount of data
290 * bytes. 350 * bytes.
291 */ 351 */
292 if (vol->vol_type == UBI_DYNAMIC_VOLUME) 352 if (vi->vol_type == UBI_DYNAMIC_VOLUME)
293 mtd->size = (long long)vol->usable_leb_size * vol->reserved_pebs; 353 mtd->size = (unsigned long long)vi->usable_leb_size * vi->size;
294 else 354 else
295 mtd->size = vol->used_bytes; 355 mtd->size = vi->used_bytes;
356
357 /* Just a sanity check - make sure this gluebi device does not exist */
358 mutex_lock(&devices_mutex);
359 g = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
360 if (g)
361 err_msg("gluebi MTD device %d form UBI device %d volume %d "
362 "already exists", g->mtd.index, vi->ubi_num,
363 vi->vol_id);
364 mutex_unlock(&devices_mutex);
296 365
297 if (add_mtd_device(mtd)) { 366 if (add_mtd_device(mtd)) {
298 ubi_err("cannot not add MTD device"); 367 err_msg("cannot add MTD device");
299 kfree(mtd->name); 368 kfree(mtd->name);
369 kfree(gluebi);
300 return -ENFILE; 370 return -ENFILE;
301 } 371 }
302 372
303 dbg_gen("added mtd%d (\"%s\"), size %llu, EB size %u", 373 mutex_lock(&devices_mutex);
304 mtd->index, mtd->name, (unsigned long long)mtd->size, mtd->erasesize); 374 list_add_tail(&gluebi->list, &gluebi_devices);
375 mutex_unlock(&devices_mutex);
305 return 0; 376 return 0;
306} 377}
307 378
308/** 379/**
309 * ubi_destroy_gluebi - close gluebi for an UBI volume. 380 * gluebi_remove - remove a gluebi device.
310 * @vol: volume description object 381 * @vi: UBI volume description object
311 * 382 *
312 * This function is called when an UBI volume is removed in order to remove 383 * This function is called when an UBI volume is removed and it removes
313 * corresponding fake MTD device. Returns zero in case of success and a 384 * corresponding fake MTD device. Returns zero in case of success and a
314 * negative error code in case of failure. 385 * negative error code in case of failure.
315 */ 386 */
316int ubi_destroy_gluebi(struct ubi_volume *vol) 387static int gluebi_remove(struct ubi_volume_info *vi)
317{ 388{
318 int err; 389 int err = 0;
319 struct mtd_info *mtd = &vol->gluebi_mtd; 390 struct mtd_info *mtd;
391 struct gluebi_device *gluebi;
392
393 mutex_lock(&devices_mutex);
394 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
395 if (!gluebi) {
396 err_msg("got remove notification for unknown UBI device %d "
397 "volume %d", vi->ubi_num, vi->vol_id);
398 err = -ENOENT;
399 } else if (gluebi->refcnt)
400 err = -EBUSY;
401 else
402 list_del(&gluebi->list);
403 mutex_unlock(&devices_mutex);
404 if (err)
405 return err;
320 406
321 dbg_gen("remove mtd%d", mtd->index); 407 mtd = &gluebi->mtd;
322 err = del_mtd_device(mtd); 408 err = del_mtd_device(mtd);
323 if (err) 409 if (err) {
410 err_msg("cannot remove fake MTD device %d, UBI device %d, "
411 "volume %d, error %d", mtd->index, gluebi->ubi_num,
412 gluebi->vol_id, err);
413 mutex_lock(&devices_mutex);
414 list_add_tail(&gluebi->list, &gluebi_devices);
415 mutex_unlock(&devices_mutex);
324 return err; 416 return err;
417 }
418
325 kfree(mtd->name); 419 kfree(mtd->name);
420 kfree(gluebi);
326 return 0; 421 return 0;
327} 422}
328 423
329/** 424/**
330 * ubi_gluebi_updated - UBI volume was updated notifier. 425 * gluebi_updated - UBI volume was updated notifier.
331 * @vol: volume description object 426 * @vi: volume info structure
332 * 427 *
333 * This function is called every time an UBI volume is updated. This function 428 * This function is called every time an UBI volume is updated. It does nothing
334 * does nothing if volume @vol is dynamic, and changes MTD device size if the 429 * if te volume @vol is dynamic, and changes MTD device size if the
335 * volume is static. This is needed because static volumes cannot be read past 430 * volume is static. This is needed because static volumes cannot be read past
336 * data they contain. 431 * data they contain. This function returns zero in case of success and a
432 * negative error code in case of error.
433 */
434static int gluebi_updated(struct ubi_volume_info *vi)
435{
436 struct gluebi_device *gluebi;
437
438 mutex_lock(&devices_mutex);
439 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
440 if (!gluebi) {
441 mutex_unlock(&devices_mutex);
442 err_msg("got update notification for unknown UBI device %d "
443 "volume %d", vi->ubi_num, vi->vol_id);
444 return -ENOENT;
445 }
446
447 if (vi->vol_type == UBI_STATIC_VOLUME)
448 gluebi->mtd.size = vi->used_bytes;
449 mutex_unlock(&devices_mutex);
450 return 0;
451}
452
453/**
454 * gluebi_resized - UBI volume was re-sized notifier.
455 * @vi: volume info structure
456 *
457 * This function is called every time an UBI volume is re-size. It changes the
458 * corresponding fake MTD device size. This function returns zero in case of
459 * success and a negative error code in case of error.
460 */
461static int gluebi_resized(struct ubi_volume_info *vi)
462{
463 struct gluebi_device *gluebi;
464
465 mutex_lock(&devices_mutex);
466 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id);
467 if (!gluebi) {
468 mutex_unlock(&devices_mutex);
469 err_msg("got update notification for unknown UBI device %d "
470 "volume %d", vi->ubi_num, vi->vol_id);
471 return -ENOENT;
472 }
473 gluebi->mtd.size = vi->used_bytes;
474 mutex_unlock(&devices_mutex);
475 return 0;
476}
477
478/**
479 * gluebi_notify - UBI notification handler.
480 * @nb: registered notifier block
481 * @l: notification type
482 * @ptr: pointer to the &struct ubi_notification object
337 */ 483 */
338void ubi_gluebi_updated(struct ubi_volume *vol) 484static int gluebi_notify(struct notifier_block *nb, unsigned long l,
485 void *ns_ptr)
339{ 486{
340 struct mtd_info *mtd = &vol->gluebi_mtd; 487 struct ubi_notification *nt = ns_ptr;
488
489 switch (l) {
490 case UBI_VOLUME_ADDED:
491 gluebi_create(&nt->di, &nt->vi);
492 break;
493 case UBI_VOLUME_REMOVED:
494 gluebi_remove(&nt->vi);
495 break;
496 case UBI_VOLUME_RESIZED:
497 gluebi_resized(&nt->vi);
498 break;
499 case UBI_VOLUME_UPDATED:
500 gluebi_updated(&nt->vi);
501 break;
502 default:
503 break;
504 }
505 return NOTIFY_OK;
506}
341 507
342 if (vol->vol_type == UBI_STATIC_VOLUME) 508static struct notifier_block gluebi_notifier = {
343 mtd->size = vol->used_bytes; 509 .notifier_call = gluebi_notify,
510};
511
512static int __init ubi_gluebi_init(void)
513{
514 return ubi_register_volume_notifier(&gluebi_notifier, 0);
344} 515}
516
517static void __exit ubi_gluebi_exit(void)
518{
519 struct gluebi_device *gluebi, *g;
520
521 list_for_each_entry_safe(gluebi, g, &gluebi_devices, list) {
522 int err;
523 struct mtd_info *mtd = &gluebi->mtd;
524
525 err = del_mtd_device(mtd);
526 if (err)
527 err_msg("error %d while removing gluebi MTD device %d, "
528 "UBI device %d, volume %d - ignoring", err,
529 mtd->index, gluebi->ubi_num, gluebi->vol_id);
530 kfree(mtd->name);
531 kfree(gluebi);
532 }
533 ubi_unregister_volume_notifier(&gluebi_notifier);
534}
535
536module_init(ubi_gluebi_init);
537module_exit(ubi_gluebi_exit);
538MODULE_DESCRIPTION("MTD emulation layer over UBI volumes");
539MODULE_AUTHOR("Artem Bityutskiy, Joern Engel");
540MODULE_LICENSE("GPL");