Lines Matching +full:ubi +full:- +full:volume +full:-
1 // SPDX-License-Identifier: GPL-2.0-or-later
9 * This is a small driver which implements fake MTD devices on top of UBI
11 * MTD-oriented software (including all the legacy software) work on top of
12 * UBI.
15 * size (@mtd->writesize) is equivalent to the UBI minimal I/O unit. The
16 * eraseblock size is equivalent to the logical eraseblock size of the volume.
26 #include <linux/mtd/ubi.h>
28 #include "ubi-media.h"
32 current->pid, __func__, ##__VA_ARGS__)
35 * struct gluebi_device - a gluebi device description data structure.
38 * @desc: UBI volume descriptor
39 * @ubi_num: UBI device number this gluebi device works on
40 * @vol_id: ID of UBI volume this gluebi device works on
57 * find_gluebi_nolock - find a gluebi device.
58 * @ubi_num: UBI device number
59 * @vol_id: volume ID
61 * This function seraches for gluebi device corresponding to UBI device
62 * @ubi_num and UBI volume @vol_id. Returns the gluebi device description
71 if (gluebi->ubi_num == ubi_num && gluebi->vol_id == vol_id) in find_gluebi_nolock()
77 * gluebi_get_device - get MTD device reference.
89 if (mtd->flags & MTD_WRITEABLE) in gluebi_get_device()
94 if (gluebi->refcnt > 0) { in gluebi_get_device()
98 * volume simultaneously and do not distinguish between in gluebi_get_device()
99 * readers/writers/exclusive/meta openers as UBI does. So we do in gluebi_get_device()
100 * not open the UBI volume again - just increase the reference in gluebi_get_device()
103 gluebi->refcnt += 1; in gluebi_get_device()
109 * This is the first reference to this UBI volume via the MTD device in gluebi_get_device()
110 * interface. Open the corresponding volume in read-write mode. in gluebi_get_device()
112 gluebi->desc = ubi_open_volume(gluebi->ubi_num, gluebi->vol_id, in gluebi_get_device()
114 if (IS_ERR(gluebi->desc)) { in gluebi_get_device()
116 return PTR_ERR(gluebi->desc); in gluebi_get_device()
118 gluebi->refcnt += 1; in gluebi_get_device()
124 * gluebi_put_device - put MTD device reference.
136 gluebi->refcnt -= 1; in gluebi_put_device()
137 if (gluebi->refcnt == 0) in gluebi_put_device()
138 ubi_close_volume(gluebi->desc); in gluebi_put_device()
143 * gluebi_read - read operation of emulated MTD devices.
160 lnum = div_u64_rem(from, mtd->erasesize, &offs); in gluebi_read()
163 size_t to_read = mtd->erasesize - offs; in gluebi_read()
168 err = ubi_read(gluebi->desc, lnum, buf, offs, to_read); in gluebi_read()
174 bytes_left -= to_read; in gluebi_read()
178 *retlen = len - bytes_left; in gluebi_read()
183 * gluebi_write - write operation of emulated MTD devices.
200 lnum = div_u64_rem(to, mtd->erasesize, &offs); in gluebi_write()
202 if (len % mtd->writesize || offs % mtd->writesize) in gluebi_write()
203 return -EINVAL; in gluebi_write()
207 size_t to_write = mtd->erasesize - offs; in gluebi_write()
212 err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write); in gluebi_write()
218 bytes_left -= to_write; in gluebi_write()
222 *retlen = len - bytes_left; in gluebi_write()
227 * gluebi_erase - erase operation of emulated MTD devices.
239 if (mtd_mod_by_ws(instr->addr, mtd) || mtd_mod_by_ws(instr->len, mtd)) in gluebi_erase()
240 return -EINVAL; in gluebi_erase()
242 lnum = mtd_div_by_eb(instr->addr, mtd); in gluebi_erase()
243 count = mtd_div_by_eb(instr->len, mtd); in gluebi_erase()
246 for (i = 0; i < count - 1; i++) { in gluebi_erase()
247 err = ubi_leb_unmap(gluebi->desc, lnum + i); in gluebi_erase()
255 * Thus, perform leb_erase instead of leb_unmap operation - leb_erase in gluebi_erase()
258 err = ubi_leb_erase(gluebi->desc, lnum + i); in gluebi_erase()
265 instr->fail_addr = (long long)lnum * mtd->erasesize; in gluebi_erase()
270 * gluebi_create - create a gluebi device for an UBI volume.
271 * @di: UBI device description object
272 * @vi: UBI volume description object
274 * This function is called when a new UBI volume is created in order to create
286 return -ENOMEM; in gluebi_create()
288 mtd = &gluebi->mtd; in gluebi_create()
289 mtd->name = kmemdup(vi->name, vi->name_len + 1, GFP_KERNEL); in gluebi_create()
290 if (!mtd->name) { in gluebi_create()
292 return -ENOMEM; in gluebi_create()
295 gluebi->vol_id = vi->vol_id; in gluebi_create()
296 gluebi->ubi_num = vi->ubi_num; in gluebi_create()
297 mtd->type = MTD_UBIVOLUME; in gluebi_create()
298 if (!di->ro_mode) in gluebi_create()
299 mtd->flags = MTD_WRITEABLE; in gluebi_create()
300 mtd->owner = THIS_MODULE; in gluebi_create()
301 mtd->writesize = di->min_io_size; in gluebi_create()
302 mtd->erasesize = vi->usable_leb_size; in gluebi_create()
303 mtd->_read = gluebi_read; in gluebi_create()
304 mtd->_write = gluebi_write; in gluebi_create()
305 mtd->_erase = gluebi_erase; in gluebi_create()
306 mtd->_get_device = gluebi_get_device; in gluebi_create()
307 mtd->_put_device = gluebi_put_device; in gluebi_create()
310 * In case of dynamic a volume, MTD device size is just volume size. In in gluebi_create()
311 * case of a static volume the size is equivalent to the amount of data in gluebi_create()
314 if (vi->vol_type == UBI_DYNAMIC_VOLUME) in gluebi_create()
315 mtd->size = (unsigned long long)vi->usable_leb_size * vi->size; in gluebi_create()
317 mtd->size = vi->used_bytes; in gluebi_create()
319 /* Just a sanity check - make sure this gluebi device does not exist */ in gluebi_create()
321 g = find_gluebi_nolock(vi->ubi_num, vi->vol_id); in gluebi_create()
323 err_msg("gluebi MTD device %d form UBI device %d volume %d already exists", in gluebi_create()
324 g->mtd.index, vi->ubi_num, vi->vol_id); in gluebi_create()
329 kfree(mtd->name); in gluebi_create()
331 return -ENFILE; in gluebi_create()
335 list_add_tail(&gluebi->list, &gluebi_devices); in gluebi_create()
341 * gluebi_remove - remove a gluebi device.
342 * @vi: UBI volume description object
344 * This function is called when an UBI volume is removed and it removes
355 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id); in gluebi_remove()
357 err_msg("got remove notification for unknown UBI device %d volume %d", in gluebi_remove()
358 vi->ubi_num, vi->vol_id); in gluebi_remove()
359 err = -ENOENT; in gluebi_remove()
360 } else if (gluebi->refcnt) in gluebi_remove()
361 err = -EBUSY; in gluebi_remove()
363 list_del(&gluebi->list); in gluebi_remove()
368 mtd = &gluebi->mtd; in gluebi_remove()
371 err_msg("cannot remove fake MTD device %d, UBI device %d, volume %d, error %d", in gluebi_remove()
372 mtd->index, gluebi->ubi_num, gluebi->vol_id, err); in gluebi_remove()
374 list_add_tail(&gluebi->list, &gluebi_devices); in gluebi_remove()
379 kfree(mtd->name); in gluebi_remove()
385 * gluebi_updated - UBI volume was updated notifier.
386 * @vi: volume info structure
388 * This function is called every time an UBI volume is updated. It does nothing
389 * if te volume @vol is dynamic, and changes MTD device size if the
390 * volume is static. This is needed because static volumes cannot be read past
399 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id); in gluebi_updated()
402 err_msg("got update notification for unknown UBI device %d volume %d", in gluebi_updated()
403 vi->ubi_num, vi->vol_id); in gluebi_updated()
404 return -ENOENT; in gluebi_updated()
407 if (vi->vol_type == UBI_STATIC_VOLUME) in gluebi_updated()
408 gluebi->mtd.size = vi->used_bytes; in gluebi_updated()
414 * gluebi_resized - UBI volume was re-sized notifier.
415 * @vi: volume info structure
417 * This function is called every time an UBI volume is re-size. It changes the
426 gluebi = find_gluebi_nolock(vi->ubi_num, vi->vol_id); in gluebi_resized()
429 err_msg("got update notification for unknown UBI device %d volume %d", in gluebi_resized()
430 vi->ubi_num, vi->vol_id); in gluebi_resized()
431 return -ENOENT; in gluebi_resized()
433 gluebi->mtd.size = vi->used_bytes; in gluebi_resized()
439 * gluebi_notify - UBI notification handler.
451 gluebi_create(&nt->di, &nt->vi); in gluebi_notify()
454 gluebi_remove(&nt->vi); in gluebi_notify()
457 gluebi_resized(&nt->vi); in gluebi_notify()
460 gluebi_updated(&nt->vi); in gluebi_notify()
483 struct mtd_info *mtd = &gluebi->mtd; in ubi_gluebi_exit()
487 err_msg("error %d while removing gluebi MTD device %d, UBI device %d, volume %d - ignoring", in ubi_gluebi_exit()
488 err, mtd->index, gluebi->ubi_num, in ubi_gluebi_exit()
489 gluebi->vol_id); in ubi_gluebi_exit()
490 kfree(mtd->name); in ubi_gluebi_exit()
498 MODULE_DESCRIPTION("MTD emulation layer over UBI volumes");