aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/gluebi.c
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/ubi/gluebi.c
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/ubi/gluebi.c')
-rw-r--r--drivers/mtd/ubi/gluebi.c378
1 files changed, 287 insertions, 91 deletions
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");