// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) International Business Machines Corp., 2006 * * Author: Artem Bityutskiy (Битюцкий Артём), Joern Engel */ /* * This is a small driver which implements fake MTD devices on top of UBI * volumes. This sounds strange, but it is in fact quite useful to make * MTD-oriented software (including all the legacy software) work on top of * UBI. * * Gluebi emulates MTD devices of "MTD_UBIVOLUME" type. Their minimal I/O unit * size (@mtd->writesize) is equivalent to the UBI minimal I/O unit. The * eraseblock size is equivalent to the logical eraseblock size of the volume. */ #include <linux/err.h> #include <linux/list.h> #include <linux/slab.h> #include <linux/sched.h> #include <linux/math64.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/mtd/ubi.h> #include <linux/mtd/mtd.h> #include "ubi-media.h" #define err_msg(fmt, ...) … /** * struct gluebi_device - a gluebi device description data structure. * @mtd: emulated MTD device description object * @refcnt: gluebi device reference count * @desc: UBI volume descriptor * @ubi_num: UBI device number this gluebi device works on * @vol_id: ID of UBI volume this gluebi device works on * @list: link in a list of gluebi devices */ struct gluebi_device { … }; /* List of all gluebi devices */ static LIST_HEAD(gluebi_devices); static DEFINE_MUTEX(devices_mutex); /** * find_gluebi_nolock - find a gluebi device. * @ubi_num: UBI device number * @vol_id: volume ID * * This function seraches for gluebi device corresponding to UBI device * @ubi_num and UBI volume @vol_id. Returns the gluebi device description * object in case of success and %NULL in case of failure. The caller has to * have the &devices_mutex locked. */ static struct gluebi_device *find_gluebi_nolock(int ubi_num, int vol_id) { … } /** * gluebi_get_device - get MTD device reference. * @mtd: the MTD device description object * * This function is called every time the MTD device is being opened and * implements the MTD get_device() operation. Returns zero in case of success * and a negative error code in case of failure. */ static int gluebi_get_device(struct mtd_info *mtd) { … } /** * gluebi_put_device - put MTD device reference. * @mtd: the MTD device description object * * This function is called every time the MTD device is being put. Returns * zero in case of success and a negative error code in case of failure. */ static void gluebi_put_device(struct mtd_info *mtd) { … } /** * gluebi_read - read operation of emulated MTD devices. * @mtd: MTD device description object * @from: absolute offset from where to read * @len: how many bytes to read * @retlen: count of read bytes is returned here * @buf: buffer to store the read data * * This function returns zero in case of success and a negative error code in * case of failure. */ static int gluebi_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, unsigned char *buf) { … } /** * gluebi_write - write operation of emulated MTD devices. * @mtd: MTD device description object * @to: absolute offset where to write * @len: how many bytes to write * @retlen: count of written bytes is returned here * @buf: buffer with data to write * * This function returns zero in case of success and a negative error code in * case of failure. */ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf) { … } /** * gluebi_erase - erase operation of emulated MTD devices. * @mtd: the MTD device description object * @instr: the erase operation description * * This function calls the erase callback when finishes. Returns zero in case * of success and a negative error code in case of failure. */ static int gluebi_erase(struct mtd_info *mtd, struct erase_info *instr) { … } /** * gluebi_create - create a gluebi device for an UBI volume. * @di: UBI device description object * @vi: UBI volume description object * * This function is called when a new UBI volume is created in order to create * corresponding fake MTD device. Returns zero in case of success and a * negative error code in case of failure. */ static int gluebi_create(struct ubi_device_info *di, struct ubi_volume_info *vi) { … } /** * gluebi_remove - remove a gluebi device. * @vi: UBI volume description object * * This function is called when an UBI volume is removed and it removes * corresponding fake MTD device. Returns zero in case of success and a * negative error code in case of failure. */ static int gluebi_remove(struct ubi_volume_info *vi) { … } /** * gluebi_updated - UBI volume was updated notifier. * @vi: volume info structure * * This function is called every time an UBI volume is updated. It does nothing * if te volume @vol is dynamic, and changes MTD device size if the * volume is static. This is needed because static volumes cannot be read past * data they contain. This function returns zero in case of success and a * negative error code in case of error. */ static int gluebi_updated(struct ubi_volume_info *vi) { … } /** * gluebi_resized - UBI volume was re-sized notifier. * @vi: volume info structure * * This function is called every time an UBI volume is re-size. It changes the * corresponding fake MTD device size. This function returns zero in case of * success and a negative error code in case of error. */ static int gluebi_resized(struct ubi_volume_info *vi) { … } /** * gluebi_notify - UBI notification handler. * @nb: registered notifier block * @l: notification type * @ns_ptr: pointer to the &struct ubi_notification object */ static int gluebi_notify(struct notifier_block *nb, unsigned long l, void *ns_ptr) { … } static struct notifier_block gluebi_notifier = …; static int __init ubi_gluebi_init(void) { … } static void __exit ubi_gluebi_exit(void) { … } module_init(…) …; module_exit(ubi_gluebi_exit); MODULE_DESCRIPTION(…) …; MODULE_AUTHOR(…) …; MODULE_LICENSE(…) …;