📄 build.c
字号:
#ifdef CONFIG_MTD_UBI_DEBUG mutex_init(&ubi->dbg_buf_mutex); ubi->dbg_peb_buf = vmalloc(ubi->peb_size); if (!ubi->dbg_peb_buf) goto out_free;#endif err = attach_by_scanning(ubi); if (err) { dbg_err("failed to attach by scanning, error %d", err); goto out_free; } if (ubi->autoresize_vol_id != -1) { err = autoresize(ubi, ubi->autoresize_vol_id); if (err) goto out_detach; } err = uif_init(ubi); if (err) goto out_detach; ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); if (IS_ERR(ubi->bgt_thread)) { err = PTR_ERR(ubi->bgt_thread); ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name, err); goto out_uif; } ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); ubi_msg("MTD device name: \"%s\"", mtd->name); ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); ubi_msg("number of good PEBs: %d", ubi->good_peb_count); ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); ubi_msg("number of user volumes: %d", ubi->vol_count - UBI_INT_VOL_COUNT); ubi_msg("available PEBs: %d", ubi->avail_pebs); ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs); ubi_msg("number of PEBs reserved for bad PEB handling: %d", ubi->beb_rsvd_pebs); ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); /* Enable the background thread */ if (!DBG_DISABLE_BGT) { ubi->thread_enabled = 1; wake_up_process(ubi->bgt_thread); } ubi_devices[ubi_num] = ubi; return ubi_num;out_uif: uif_close(ubi);out_detach: ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl);out_free: vfree(ubi->peb_buf1); vfree(ubi->peb_buf2);#ifdef CONFIG_MTD_UBI_DEBUG vfree(ubi->dbg_peb_buf);#endif kfree(ubi); return err;}/** * ubi_detach_mtd_dev - detach an MTD device. * @ubi_num: UBI device number to detach from * @anyway: detach MTD even if device reference count is not zero * * This function destroys an UBI device number @ubi_num and detaches the * underlying MTD device. Returns zero in case of success and %-EBUSY if the * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not * exist. * * Note, the invocations of this function has to be serialized by the * @ubi_devices_mutex. */int ubi_detach_mtd_dev(int ubi_num, int anyway){ struct ubi_device *ubi; if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) return -EINVAL; spin_lock(&ubi_devices_lock); ubi = ubi_devices[ubi_num]; if (!ubi) { spin_unlock(&ubi_devices_lock); return -EINVAL; } if (ubi->ref_count) { if (!anyway) { spin_unlock(&ubi_devices_lock); return -EBUSY; } /* This may only happen if there is a bug */ ubi_err("%s reference count %d, destroy anyway", ubi->ubi_name, ubi->ref_count); } ubi_devices[ubi_num] = NULL; spin_unlock(&ubi_devices_lock); ubi_assert(ubi_num == ubi->ubi_num); dbg_msg("detaching mtd%d from ubi%d", ubi->mtd->index, ubi_num); /* * Before freeing anything, we have to stop the background thread to * prevent it from doing anything on this device while we are freeing. */ if (ubi->bgt_thread) kthread_stop(ubi->bgt_thread); uif_close(ubi); ubi_eba_close(ubi); ubi_wl_close(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); vfree(ubi->peb_buf1); vfree(ubi->peb_buf2);#ifdef CONFIG_MTD_UBI_DEBUG vfree(ubi->dbg_peb_buf);#endif ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); kfree(ubi); return 0;}/** * find_mtd_device - open an MTD device by its name or number. * @mtd_dev: name or number of the device * * This function tries to open and MTD device described by @mtd_dev string, * which is first treated as an ASCII number, and if it is not true, it is * treated as MTD device name. Returns MTD device description object in case of * success and a negative error code in case of failure. */static struct mtd_info * __init open_mtd_device(const char *mtd_dev){ struct mtd_info *mtd; int mtd_num; char *endp; mtd_num = simple_strtoul(mtd_dev, &endp, 0); if (*endp != '\0' || mtd_dev == endp) { /* * This does not look like an ASCII integer, probably this is * MTD device name. */ mtd = get_mtd_device_nm(mtd_dev); } else mtd = get_mtd_device(NULL, mtd_num); return mtd;}int __init ubi_init(void){ int err, i, k; /* Ensure that EC and VID headers have correct size */ BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); if (mtd_devs > UBI_MAX_DEVICES) { ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES); return -EINVAL; } /* Create base sysfs directory and sysfs files */ ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); if (IS_ERR(ubi_class)) { err = PTR_ERR(ubi_class); ubi_err("cannot create UBI class"); goto out; } err = class_create_file(ubi_class, &ubi_version); if (err) { ubi_err("cannot create sysfs file"); goto out_class; } err = misc_register(&ubi_ctrl_cdev); if (err) { ubi_err("cannot register device"); goto out_version; }#ifdef UBI_LINUX ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", sizeof(struct ubi_wl_entry), 0, 0, NULL); if (!ubi_wl_entry_slab) goto out_dev_unreg;#endif /* Attach MTD devices */ for (i = 0; i < mtd_devs; i++) { struct mtd_dev_param *p = &mtd_dev_param[i]; struct mtd_info *mtd; cond_resched(); mtd = open_mtd_device(p->name); if (IS_ERR(mtd)) { err = PTR_ERR(mtd); goto out_detach; } mutex_lock(&ubi_devices_mutex); err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, p->vid_hdr_offs); mutex_unlock(&ubi_devices_mutex); if (err < 0) { put_mtd_device(mtd); ubi_err("cannot attach mtd%d", mtd->index); goto out_detach; } } return 0;out_detach: for (k = 0; k < i; k++) if (ubi_devices[k]) { mutex_lock(&ubi_devices_mutex); ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1); mutex_unlock(&ubi_devices_mutex); }#ifdef UBI_LINUX kmem_cache_destroy(ubi_wl_entry_slab);out_dev_unreg:#endif misc_deregister(&ubi_ctrl_cdev);out_version: class_remove_file(ubi_class, &ubi_version);out_class: class_destroy(ubi_class);out: ubi_err("UBI error: cannot initialize UBI, error %d", err); return err;}module_init(ubi_init);void __exit ubi_exit(void){ int i; for (i = 0; i < UBI_MAX_DEVICES; i++) if (ubi_devices[i]) { mutex_lock(&ubi_devices_mutex); ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1); mutex_unlock(&ubi_devices_mutex); } kmem_cache_destroy(ubi_wl_entry_slab); misc_deregister(&ubi_ctrl_cdev); class_remove_file(ubi_class, &ubi_version); class_destroy(ubi_class); mtd_devs = 0;}module_exit(ubi_exit);/** * bytes_str_to_int - convert a string representing number of bytes to an * integer. * @str: the string to convert * * This function returns positive resulting integer in case of success and a * negative error code in case of failure. */static int __init bytes_str_to_int(const char *str){ char *endp; unsigned long result; result = simple_strtoul(str, &endp, 0); if (str == endp || result < 0) { printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", str); return -EINVAL; } switch (*endp) { case 'G': result *= 1024; case 'M': result *= 1024; case 'K': result *= 1024; if (endp[1] == 'i' && endp[2] == 'B') endp += 2; case '\0': break; default: printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", str); return -EINVAL; } return result;}/** * ubi_mtd_param_parse - parse the 'mtd=' UBI parameter. * @val: the parameter value to parse * @kp: not used * * This function returns zero in case of success and a negative error code in * case of error. */int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp){ int i, len; struct mtd_dev_param *p; char buf[MTD_PARAM_LEN_MAX]; char *pbuf = &buf[0]; char *tokens[2] = {NULL, NULL}; if (!val) return -EINVAL; if (mtd_devs == UBI_MAX_DEVICES) { printk(KERN_ERR "UBI error: too many parameters, max. is %d\n", UBI_MAX_DEVICES); return -EINVAL; } len = strnlen(val, MTD_PARAM_LEN_MAX); if (len == MTD_PARAM_LEN_MAX) { printk(KERN_ERR "UBI error: parameter \"%s\" is too long, " "max. is %d\n", val, MTD_PARAM_LEN_MAX); return -EINVAL; } if (len == 0) { printk(KERN_WARNING "UBI warning: empty 'mtd=' parameter - " "ignored\n"); return 0; } strcpy(buf, val); /* Get rid of the final newline */ if (buf[len - 1] == '\n') buf[len - 1] = '\0'; for (i = 0; i < 2; i++) tokens[i] = strsep(&pbuf, ","); if (pbuf) { printk(KERN_ERR "UBI error: too many arguments at \"%s\"\n", val); return -EINVAL; } p = &mtd_dev_param[mtd_devs]; strcpy(&p->name[0], tokens[0]); if (tokens[1]) p->vid_hdr_offs = bytes_str_to_int(tokens[1]); if (p->vid_hdr_offs < 0) return p->vid_hdr_offs; mtd_devs += 1; return 0;}module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: " "mtd=<name|num>[,<vid_hdr_offs>].\n" "Multiple \"mtd\" parameters may be specified.\n" "MTD devices may be specified by their number or name.\n" "Optional \"vid_hdr_offs\" parameter specifies UBI VID " "header position and data starting position to be used " "by UBI.\n" "Example: mtd=content,1984 mtd=4 - attach MTD device" "with name \"content\" using VID header offset 1984, and " "MTD device number 4 with default VID header offset.");MODULE_VERSION(__stringify(UBI_VERSION));MODULE_DESCRIPTION("UBI - Unsorted Block Images");MODULE_AUTHOR("Artem Bityutskiy");MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -