18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* This file mostly implements UBI kernel API functions */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/module.h> 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <linux/namei.h> 148c2ecf20Sopenharmony_ci#include <linux/fs.h> 158c2ecf20Sopenharmony_ci#include <asm/div64.h> 168c2ecf20Sopenharmony_ci#include "ubi.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci/** 198c2ecf20Sopenharmony_ci * ubi_do_get_device_info - get information about UBI device. 208c2ecf20Sopenharmony_ci * @ubi: UBI device description object 218c2ecf20Sopenharmony_ci * @di: the information is stored here 228c2ecf20Sopenharmony_ci * 238c2ecf20Sopenharmony_ci * This function is the same as 'ubi_get_device_info()', but it assumes the UBI 248c2ecf20Sopenharmony_ci * device is locked and cannot disappear. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_civoid ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci di->ubi_num = ubi->ubi_num; 298c2ecf20Sopenharmony_ci di->leb_size = ubi->leb_size; 308c2ecf20Sopenharmony_ci di->leb_start = ubi->leb_start; 318c2ecf20Sopenharmony_ci di->min_io_size = ubi->min_io_size; 328c2ecf20Sopenharmony_ci di->max_write_size = ubi->max_write_size; 338c2ecf20Sopenharmony_ci di->ro_mode = ubi->ro_mode; 348c2ecf20Sopenharmony_ci di->cdev = ubi->cdev.dev; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_do_get_device_info); 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci/** 398c2ecf20Sopenharmony_ci * ubi_get_device_info - get information about UBI device. 408c2ecf20Sopenharmony_ci * @ubi_num: UBI device number 418c2ecf20Sopenharmony_ci * @di: the information is stored here 428c2ecf20Sopenharmony_ci * 438c2ecf20Sopenharmony_ci * This function returns %0 in case of success, %-EINVAL if the UBI device 448c2ecf20Sopenharmony_ci * number is invalid, and %-ENODEV if there is no such UBI device. 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_ciint ubi_get_device_info(int ubi_num, struct ubi_device_info *di) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct ubi_device *ubi; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 518c2ecf20Sopenharmony_ci return -EINVAL; 528c2ecf20Sopenharmony_ci ubi = ubi_get_device(ubi_num); 538c2ecf20Sopenharmony_ci if (!ubi) 548c2ecf20Sopenharmony_ci return -ENODEV; 558c2ecf20Sopenharmony_ci ubi_do_get_device_info(ubi, di); 568c2ecf20Sopenharmony_ci ubi_put_device(ubi); 578c2ecf20Sopenharmony_ci return 0; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_get_device_info); 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/** 628c2ecf20Sopenharmony_ci * ubi_do_get_volume_info - get information about UBI volume. 638c2ecf20Sopenharmony_ci * @ubi: UBI device description object 648c2ecf20Sopenharmony_ci * @vol: volume description object 658c2ecf20Sopenharmony_ci * @vi: the information is stored here 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_civoid ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, 688c2ecf20Sopenharmony_ci struct ubi_volume_info *vi) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci vi->vol_id = vol->vol_id; 718c2ecf20Sopenharmony_ci vi->ubi_num = ubi->ubi_num; 728c2ecf20Sopenharmony_ci vi->size = vol->reserved_pebs; 738c2ecf20Sopenharmony_ci vi->used_bytes = vol->used_bytes; 748c2ecf20Sopenharmony_ci vi->vol_type = vol->vol_type; 758c2ecf20Sopenharmony_ci vi->corrupted = vol->corrupted; 768c2ecf20Sopenharmony_ci vi->upd_marker = vol->upd_marker; 778c2ecf20Sopenharmony_ci vi->alignment = vol->alignment; 788c2ecf20Sopenharmony_ci vi->usable_leb_size = vol->usable_leb_size; 798c2ecf20Sopenharmony_ci vi->name_len = vol->name_len; 808c2ecf20Sopenharmony_ci vi->name = vol->name; 818c2ecf20Sopenharmony_ci vi->cdev = vol->cdev.dev; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/** 858c2ecf20Sopenharmony_ci * ubi_get_volume_info - get information about UBI volume. 868c2ecf20Sopenharmony_ci * @desc: volume descriptor 878c2ecf20Sopenharmony_ci * @vi: the information is stored here 888c2ecf20Sopenharmony_ci */ 898c2ecf20Sopenharmony_civoid ubi_get_volume_info(struct ubi_volume_desc *desc, 908c2ecf20Sopenharmony_ci struct ubi_volume_info *vi) 918c2ecf20Sopenharmony_ci{ 928c2ecf20Sopenharmony_ci ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi); 938c2ecf20Sopenharmony_ci} 948c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_get_volume_info); 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci/** 978c2ecf20Sopenharmony_ci * ubi_open_volume - open UBI volume. 988c2ecf20Sopenharmony_ci * @ubi_num: UBI device number 998c2ecf20Sopenharmony_ci * @vol_id: volume ID 1008c2ecf20Sopenharmony_ci * @mode: open mode 1018c2ecf20Sopenharmony_ci * 1028c2ecf20Sopenharmony_ci * The @mode parameter specifies if the volume should be opened in read-only 1038c2ecf20Sopenharmony_ci * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that 1048c2ecf20Sopenharmony_ci * nobody else will be able to open this volume. UBI allows to have many volume 1058c2ecf20Sopenharmony_ci * readers and one writer at a time. 1068c2ecf20Sopenharmony_ci * 1078c2ecf20Sopenharmony_ci * If a static volume is being opened for the first time since boot, it will be 1088c2ecf20Sopenharmony_ci * checked by this function, which means it will be fully read and the CRC 1098c2ecf20Sopenharmony_ci * checksum of each logical eraseblock will be checked. 1108c2ecf20Sopenharmony_ci * 1118c2ecf20Sopenharmony_ci * This function returns volume descriptor in case of success and a negative 1128c2ecf20Sopenharmony_ci * error code in case of failure. 1138c2ecf20Sopenharmony_ci */ 1148c2ecf20Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci int err; 1178c2ecf20Sopenharmony_ci struct ubi_volume_desc *desc; 1188c2ecf20Sopenharmony_ci struct ubi_device *ubi; 1198c2ecf20Sopenharmony_ci struct ubi_volume *vol; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode); 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 1248c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci if (mode != UBI_READONLY && mode != UBI_READWRITE && 1278c2ecf20Sopenharmony_ci mode != UBI_EXCLUSIVE && mode != UBI_METAONLY) 1288c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* 1318c2ecf20Sopenharmony_ci * First of all, we have to get the UBI device to prevent its removal. 1328c2ecf20Sopenharmony_ci */ 1338c2ecf20Sopenharmony_ci ubi = ubi_get_device(ubi_num); 1348c2ecf20Sopenharmony_ci if (!ubi) 1358c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { 1388c2ecf20Sopenharmony_ci err = -EINVAL; 1398c2ecf20Sopenharmony_ci goto out_put_ubi; 1408c2ecf20Sopenharmony_ci } 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); 1438c2ecf20Sopenharmony_ci if (!desc) { 1448c2ecf20Sopenharmony_ci err = -ENOMEM; 1458c2ecf20Sopenharmony_ci goto out_put_ubi; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci err = -ENODEV; 1498c2ecf20Sopenharmony_ci if (!try_module_get(THIS_MODULE)) 1508c2ecf20Sopenharmony_ci goto out_free; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci spin_lock(&ubi->volumes_lock); 1538c2ecf20Sopenharmony_ci vol = ubi->volumes[vol_id]; 1548c2ecf20Sopenharmony_ci if (!vol) 1558c2ecf20Sopenharmony_ci goto out_unlock; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci err = -EBUSY; 1588c2ecf20Sopenharmony_ci switch (mode) { 1598c2ecf20Sopenharmony_ci case UBI_READONLY: 1608c2ecf20Sopenharmony_ci if (vol->exclusive) 1618c2ecf20Sopenharmony_ci goto out_unlock; 1628c2ecf20Sopenharmony_ci vol->readers += 1; 1638c2ecf20Sopenharmony_ci break; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci case UBI_READWRITE: 1668c2ecf20Sopenharmony_ci if (vol->exclusive || vol->writers > 0) 1678c2ecf20Sopenharmony_ci goto out_unlock; 1688c2ecf20Sopenharmony_ci vol->writers += 1; 1698c2ecf20Sopenharmony_ci break; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci case UBI_EXCLUSIVE: 1728c2ecf20Sopenharmony_ci if (vol->exclusive || vol->writers || vol->readers || 1738c2ecf20Sopenharmony_ci vol->metaonly) 1748c2ecf20Sopenharmony_ci goto out_unlock; 1758c2ecf20Sopenharmony_ci vol->exclusive = 1; 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci case UBI_METAONLY: 1798c2ecf20Sopenharmony_ci if (vol->metaonly || vol->exclusive) 1808c2ecf20Sopenharmony_ci goto out_unlock; 1818c2ecf20Sopenharmony_ci vol->metaonly = 1; 1828c2ecf20Sopenharmony_ci break; 1838c2ecf20Sopenharmony_ci } 1848c2ecf20Sopenharmony_ci get_device(&vol->dev); 1858c2ecf20Sopenharmony_ci vol->ref_count += 1; 1868c2ecf20Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci desc->vol = vol; 1898c2ecf20Sopenharmony_ci desc->mode = mode; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci mutex_lock(&ubi->ckvol_mutex); 1928c2ecf20Sopenharmony_ci if (!vol->checked && !vol->skip_check) { 1938c2ecf20Sopenharmony_ci /* This is the first open - check the volume */ 1948c2ecf20Sopenharmony_ci err = ubi_check_volume(ubi, vol_id); 1958c2ecf20Sopenharmony_ci if (err < 0) { 1968c2ecf20Sopenharmony_ci mutex_unlock(&ubi->ckvol_mutex); 1978c2ecf20Sopenharmony_ci ubi_close_volume(desc); 1988c2ecf20Sopenharmony_ci return ERR_PTR(err); 1998c2ecf20Sopenharmony_ci } 2008c2ecf20Sopenharmony_ci if (err == 1) { 2018c2ecf20Sopenharmony_ci ubi_warn(ubi, "volume %d on UBI device %d is corrupted", 2028c2ecf20Sopenharmony_ci vol_id, ubi->ubi_num); 2038c2ecf20Sopenharmony_ci vol->corrupted = 1; 2048c2ecf20Sopenharmony_ci } 2058c2ecf20Sopenharmony_ci vol->checked = 1; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci mutex_unlock(&ubi->ckvol_mutex); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return desc; 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ciout_unlock: 2128c2ecf20Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 2138c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 2148c2ecf20Sopenharmony_ciout_free: 2158c2ecf20Sopenharmony_ci kfree(desc); 2168c2ecf20Sopenharmony_ciout_put_ubi: 2178c2ecf20Sopenharmony_ci ubi_err(ubi, "cannot open device %d, volume %d, error %d", 2188c2ecf20Sopenharmony_ci ubi_num, vol_id, err); 2198c2ecf20Sopenharmony_ci ubi_put_device(ubi); 2208c2ecf20Sopenharmony_ci return ERR_PTR(err); 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume); 2238c2ecf20Sopenharmony_ci 2248c2ecf20Sopenharmony_ci/** 2258c2ecf20Sopenharmony_ci * ubi_open_volume_nm - open UBI volume by name. 2268c2ecf20Sopenharmony_ci * @ubi_num: UBI device number 2278c2ecf20Sopenharmony_ci * @name: volume name 2288c2ecf20Sopenharmony_ci * @mode: open mode 2298c2ecf20Sopenharmony_ci * 2308c2ecf20Sopenharmony_ci * This function is similar to 'ubi_open_volume()', but opens a volume by name. 2318c2ecf20Sopenharmony_ci */ 2328c2ecf20Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, 2338c2ecf20Sopenharmony_ci int mode) 2348c2ecf20Sopenharmony_ci{ 2358c2ecf20Sopenharmony_ci int i, vol_id = -1, len; 2368c2ecf20Sopenharmony_ci struct ubi_device *ubi; 2378c2ecf20Sopenharmony_ci struct ubi_volume_desc *ret; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci if (!name) 2428c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci len = strnlen(name, UBI_VOL_NAME_MAX + 1); 2458c2ecf20Sopenharmony_ci if (len > UBI_VOL_NAME_MAX) 2468c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 2498c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci ubi = ubi_get_device(ubi_num); 2528c2ecf20Sopenharmony_ci if (!ubi) 2538c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci spin_lock(&ubi->volumes_lock); 2568c2ecf20Sopenharmony_ci /* Walk all volumes of this UBI device */ 2578c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) { 2588c2ecf20Sopenharmony_ci struct ubi_volume *vol = ubi->volumes[i]; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci if (vol && len == vol->name_len && !strcmp(name, vol->name)) { 2618c2ecf20Sopenharmony_ci vol_id = i; 2628c2ecf20Sopenharmony_ci break; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (vol_id >= 0) 2688c2ecf20Sopenharmony_ci ret = ubi_open_volume(ubi_num, vol_id, mode); 2698c2ecf20Sopenharmony_ci else 2708c2ecf20Sopenharmony_ci ret = ERR_PTR(-ENODEV); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* 2738c2ecf20Sopenharmony_ci * We should put the UBI device even in case of success, because 2748c2ecf20Sopenharmony_ci * 'ubi_open_volume()' took a reference as well. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci ubi_put_device(ubi); 2778c2ecf20Sopenharmony_ci return ret; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume_nm); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci/** 2828c2ecf20Sopenharmony_ci * ubi_open_volume_path - open UBI volume by its character device node path. 2838c2ecf20Sopenharmony_ci * @pathname: volume character device node path 2848c2ecf20Sopenharmony_ci * @mode: open mode 2858c2ecf20Sopenharmony_ci * 2868c2ecf20Sopenharmony_ci * This function is similar to 'ubi_open_volume()', but opens a volume the path 2878c2ecf20Sopenharmony_ci * to its character device node. 2888c2ecf20Sopenharmony_ci */ 2898c2ecf20Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) 2908c2ecf20Sopenharmony_ci{ 2918c2ecf20Sopenharmony_ci int error, ubi_num, vol_id; 2928c2ecf20Sopenharmony_ci struct path path; 2938c2ecf20Sopenharmony_ci struct kstat stat; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci dbg_gen("open volume %s, mode %d", pathname, mode); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (!pathname || !*pathname) 2988c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ci error = kern_path(pathname, LOOKUP_FOLLOW, &path); 3018c2ecf20Sopenharmony_ci if (error) 3028c2ecf20Sopenharmony_ci return ERR_PTR(error); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); 3058c2ecf20Sopenharmony_ci path_put(&path); 3068c2ecf20Sopenharmony_ci if (error) 3078c2ecf20Sopenharmony_ci return ERR_PTR(error); 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (!S_ISCHR(stat.mode)) 3108c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci ubi_num = ubi_major2num(MAJOR(stat.rdev)); 3138c2ecf20Sopenharmony_ci vol_id = MINOR(stat.rdev) - 1; 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci if (vol_id >= 0 && ubi_num >= 0) 3168c2ecf20Sopenharmony_ci return ubi_open_volume(ubi_num, vol_id, mode); 3178c2ecf20Sopenharmony_ci return ERR_PTR(-ENODEV); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume_path); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci/** 3228c2ecf20Sopenharmony_ci * ubi_close_volume - close UBI volume. 3238c2ecf20Sopenharmony_ci * @desc: volume descriptor 3248c2ecf20Sopenharmony_ci */ 3258c2ecf20Sopenharmony_civoid ubi_close_volume(struct ubi_volume_desc *desc) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 3288c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci dbg_gen("close device %d, volume %d, mode %d", 3318c2ecf20Sopenharmony_ci ubi->ubi_num, vol->vol_id, desc->mode); 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_ci spin_lock(&ubi->volumes_lock); 3348c2ecf20Sopenharmony_ci switch (desc->mode) { 3358c2ecf20Sopenharmony_ci case UBI_READONLY: 3368c2ecf20Sopenharmony_ci vol->readers -= 1; 3378c2ecf20Sopenharmony_ci break; 3388c2ecf20Sopenharmony_ci case UBI_READWRITE: 3398c2ecf20Sopenharmony_ci vol->writers -= 1; 3408c2ecf20Sopenharmony_ci break; 3418c2ecf20Sopenharmony_ci case UBI_EXCLUSIVE: 3428c2ecf20Sopenharmony_ci vol->exclusive = 0; 3438c2ecf20Sopenharmony_ci break; 3448c2ecf20Sopenharmony_ci case UBI_METAONLY: 3458c2ecf20Sopenharmony_ci vol->metaonly = 0; 3468c2ecf20Sopenharmony_ci break; 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci vol->ref_count -= 1; 3498c2ecf20Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci kfree(desc); 3528c2ecf20Sopenharmony_ci put_device(&vol->dev); 3538c2ecf20Sopenharmony_ci ubi_put_device(ubi); 3548c2ecf20Sopenharmony_ci module_put(THIS_MODULE); 3558c2ecf20Sopenharmony_ci} 3568c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_close_volume); 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci/** 3598c2ecf20Sopenharmony_ci * leb_read_sanity_check - does sanity checks on read requests. 3608c2ecf20Sopenharmony_ci * @desc: volume descriptor 3618c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to read from 3628c2ecf20Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 3638c2ecf20Sopenharmony_ci * @len: how many bytes to read 3648c2ecf20Sopenharmony_ci * 3658c2ecf20Sopenharmony_ci * This function is used by ubi_leb_read() and ubi_leb_read_sg() 3668c2ecf20Sopenharmony_ci * to perform sanity checks. 3678c2ecf20Sopenharmony_ci */ 3688c2ecf20Sopenharmony_cistatic int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum, 3698c2ecf20Sopenharmony_ci int offset, int len) 3708c2ecf20Sopenharmony_ci{ 3718c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 3728c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 3738c2ecf20Sopenharmony_ci int vol_id = vol->vol_id; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || 3768c2ecf20Sopenharmony_ci lnum >= vol->used_ebs || offset < 0 || len < 0 || 3778c2ecf20Sopenharmony_ci offset + len > vol->usable_leb_size) 3788c2ecf20Sopenharmony_ci return -EINVAL; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (vol->vol_type == UBI_STATIC_VOLUME) { 3818c2ecf20Sopenharmony_ci if (vol->used_ebs == 0) 3828c2ecf20Sopenharmony_ci /* Empty static UBI volume */ 3838c2ecf20Sopenharmony_ci return 0; 3848c2ecf20Sopenharmony_ci if (lnum == vol->used_ebs - 1 && 3858c2ecf20Sopenharmony_ci offset + len > vol->last_eb_bytes) 3868c2ecf20Sopenharmony_ci return -EINVAL; 3878c2ecf20Sopenharmony_ci } 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci if (vol->upd_marker) 3908c2ecf20Sopenharmony_ci return -EBADF; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci return 0; 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci/** 3968c2ecf20Sopenharmony_ci * ubi_leb_read - read data. 3978c2ecf20Sopenharmony_ci * @desc: volume descriptor 3988c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to read from 3998c2ecf20Sopenharmony_ci * @buf: buffer where to store the read data 4008c2ecf20Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 4018c2ecf20Sopenharmony_ci * @len: how many bytes to read 4028c2ecf20Sopenharmony_ci * @check: whether UBI has to check the read data's CRC or not. 4038c2ecf20Sopenharmony_ci * 4048c2ecf20Sopenharmony_ci * This function reads data from offset @offset of logical eraseblock @lnum and 4058c2ecf20Sopenharmony_ci * stores the data at @buf. When reading from static volumes, @check specifies 4068c2ecf20Sopenharmony_ci * whether the data has to be checked or not. If yes, the whole logical 4078c2ecf20Sopenharmony_ci * eraseblock will be read and its CRC checksum will be checked (i.e., the CRC 4088c2ecf20Sopenharmony_ci * checksum is per-eraseblock). So checking may substantially slow down the 4098c2ecf20Sopenharmony_ci * read speed. The @check argument is ignored for dynamic volumes. 4108c2ecf20Sopenharmony_ci * 4118c2ecf20Sopenharmony_ci * In case of success, this function returns zero. In case of failure, this 4128c2ecf20Sopenharmony_ci * function returns a negative error code. 4138c2ecf20Sopenharmony_ci * 4148c2ecf20Sopenharmony_ci * %-EBADMSG error code is returned: 4158c2ecf20Sopenharmony_ci * o for both static and dynamic volumes if MTD driver has detected a data 4168c2ecf20Sopenharmony_ci * integrity problem (unrecoverable ECC checksum mismatch in case of NAND); 4178c2ecf20Sopenharmony_ci * o for static volumes in case of data CRC mismatch. 4188c2ecf20Sopenharmony_ci * 4198c2ecf20Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 4208c2ecf20Sopenharmony_ci * returns immediately with %-EBADF error code. 4218c2ecf20Sopenharmony_ci */ 4228c2ecf20Sopenharmony_ciint ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, 4238c2ecf20Sopenharmony_ci int len, int check) 4248c2ecf20Sopenharmony_ci{ 4258c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 4268c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 4278c2ecf20Sopenharmony_ci int err, vol_id = vol->vol_id; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci err = leb_read_sanity_check(desc, lnum, offset, len); 4328c2ecf20Sopenharmony_ci if (err < 0) 4338c2ecf20Sopenharmony_ci return err; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci if (len == 0) 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); 4398c2ecf20Sopenharmony_ci if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { 4408c2ecf20Sopenharmony_ci ubi_warn(ubi, "mark volume %d as corrupted", vol_id); 4418c2ecf20Sopenharmony_ci vol->corrupted = 1; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci return err; 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_read); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ci/** 4508c2ecf20Sopenharmony_ci * ubi_leb_read_sg - read data into a scatter gather list. 4518c2ecf20Sopenharmony_ci * @desc: volume descriptor 4528c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to read from 4538c2ecf20Sopenharmony_ci * @buf: buffer where to store the read data 4548c2ecf20Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 4558c2ecf20Sopenharmony_ci * @len: how many bytes to read 4568c2ecf20Sopenharmony_ci * @check: whether UBI has to check the read data's CRC or not. 4578c2ecf20Sopenharmony_ci * 4588c2ecf20Sopenharmony_ci * This function works exactly like ubi_leb_read_sg(). But instead of 4598c2ecf20Sopenharmony_ci * storing the read data into a buffer it writes to an UBI scatter gather 4608c2ecf20Sopenharmony_ci * list. 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_ciint ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl, 4638c2ecf20Sopenharmony_ci int offset, int len, int check) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 4668c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 4678c2ecf20Sopenharmony_ci int err, vol_id = vol->vol_id; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci err = leb_read_sanity_check(desc, lnum, offset, len); 4728c2ecf20Sopenharmony_ci if (err < 0) 4738c2ecf20Sopenharmony_ci return err; 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_ci if (len == 0) 4768c2ecf20Sopenharmony_ci return 0; 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_ci err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check); 4798c2ecf20Sopenharmony_ci if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { 4808c2ecf20Sopenharmony_ci ubi_warn(ubi, "mark volume %d as corrupted", vol_id); 4818c2ecf20Sopenharmony_ci vol->corrupted = 1; 4828c2ecf20Sopenharmony_ci } 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci return err; 4858c2ecf20Sopenharmony_ci} 4868c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_read_sg); 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci/** 4898c2ecf20Sopenharmony_ci * ubi_leb_write - write data. 4908c2ecf20Sopenharmony_ci * @desc: volume descriptor 4918c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to write to 4928c2ecf20Sopenharmony_ci * @buf: data to write 4938c2ecf20Sopenharmony_ci * @offset: offset within the logical eraseblock where to write 4948c2ecf20Sopenharmony_ci * @len: how many bytes to write 4958c2ecf20Sopenharmony_ci * 4968c2ecf20Sopenharmony_ci * This function writes @len bytes of data from @buf to offset @offset of 4978c2ecf20Sopenharmony_ci * logical eraseblock @lnum. 4988c2ecf20Sopenharmony_ci * 4998c2ecf20Sopenharmony_ci * This function takes care of physical eraseblock write failures. If write to 5008c2ecf20Sopenharmony_ci * the physical eraseblock write operation fails, the logical eraseblock is 5018c2ecf20Sopenharmony_ci * re-mapped to another physical eraseblock, the data is recovered, and the 5028c2ecf20Sopenharmony_ci * write finishes. UBI has a pool of reserved physical eraseblocks for this. 5038c2ecf20Sopenharmony_ci * 5048c2ecf20Sopenharmony_ci * If all the data were successfully written, zero is returned. If an error 5058c2ecf20Sopenharmony_ci * occurred and UBI has not been able to recover from it, this function returns 5068c2ecf20Sopenharmony_ci * a negative error code. Note, in case of an error, it is possible that 5078c2ecf20Sopenharmony_ci * something was still written to the flash media, but that may be some 5088c2ecf20Sopenharmony_ci * garbage. 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 5118c2ecf20Sopenharmony_ci * returns immediately with %-EBADF code. 5128c2ecf20Sopenharmony_ci */ 5138c2ecf20Sopenharmony_ciint ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, 5148c2ecf20Sopenharmony_ci int offset, int len) 5158c2ecf20Sopenharmony_ci{ 5168c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 5178c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 5188c2ecf20Sopenharmony_ci int vol_id = vol->vol_id; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) 5238c2ecf20Sopenharmony_ci return -EINVAL; 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 5268c2ecf20Sopenharmony_ci return -EROFS; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum) || offset < 0 || len < 0 || 5298c2ecf20Sopenharmony_ci offset + len > vol->usable_leb_size || 5308c2ecf20Sopenharmony_ci offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1)) 5318c2ecf20Sopenharmony_ci return -EINVAL; 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci if (vol->upd_marker) 5348c2ecf20Sopenharmony_ci return -EBADF; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci if (len == 0) 5378c2ecf20Sopenharmony_ci return 0; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len); 5408c2ecf20Sopenharmony_ci} 5418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_write); 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci/* 5448c2ecf20Sopenharmony_ci * ubi_leb_change - change logical eraseblock atomically. 5458c2ecf20Sopenharmony_ci * @desc: volume descriptor 5468c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to change 5478c2ecf20Sopenharmony_ci * @buf: data to write 5488c2ecf20Sopenharmony_ci * @len: how many bytes to write 5498c2ecf20Sopenharmony_ci * 5508c2ecf20Sopenharmony_ci * This function changes the contents of a logical eraseblock atomically. @buf 5518c2ecf20Sopenharmony_ci * has to contain new logical eraseblock data, and @len - the length of the 5528c2ecf20Sopenharmony_ci * data, which has to be aligned. The length may be shorter than the logical 5538c2ecf20Sopenharmony_ci * eraseblock size, ant the logical eraseblock may be appended to more times 5548c2ecf20Sopenharmony_ci * later on. This function guarantees that in case of an unclean reboot the old 5558c2ecf20Sopenharmony_ci * contents is preserved. Returns zero in case of success and a negative error 5568c2ecf20Sopenharmony_ci * code in case of failure. 5578c2ecf20Sopenharmony_ci */ 5588c2ecf20Sopenharmony_ciint ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, 5598c2ecf20Sopenharmony_ci int len) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 5628c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 5638c2ecf20Sopenharmony_ci int vol_id = vol->vol_id; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) 5688c2ecf20Sopenharmony_ci return -EINVAL; 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 5718c2ecf20Sopenharmony_ci return -EROFS; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum) || len < 0 || 5748c2ecf20Sopenharmony_ci len > vol->usable_leb_size || len & (ubi->min_io_size - 1)) 5758c2ecf20Sopenharmony_ci return -EINVAL; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if (vol->upd_marker) 5788c2ecf20Sopenharmony_ci return -EBADF; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci if (len == 0) 5818c2ecf20Sopenharmony_ci return 0; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len); 5848c2ecf20Sopenharmony_ci} 5858c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_change); 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci/** 5888c2ecf20Sopenharmony_ci * ubi_leb_erase - erase logical eraseblock. 5898c2ecf20Sopenharmony_ci * @desc: volume descriptor 5908c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number 5918c2ecf20Sopenharmony_ci * 5928c2ecf20Sopenharmony_ci * This function un-maps logical eraseblock @lnum and synchronously erases the 5938c2ecf20Sopenharmony_ci * correspondent physical eraseblock. Returns zero in case of success and a 5948c2ecf20Sopenharmony_ci * negative error code in case of failure. 5958c2ecf20Sopenharmony_ci * 5968c2ecf20Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 5978c2ecf20Sopenharmony_ci * returns immediately with %-EBADF code. 5988c2ecf20Sopenharmony_ci */ 5998c2ecf20Sopenharmony_ciint ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) 6008c2ecf20Sopenharmony_ci{ 6018c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 6028c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 6038c2ecf20Sopenharmony_ci int err; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 6088c2ecf20Sopenharmony_ci return -EROFS; 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 6118c2ecf20Sopenharmony_ci return -EINVAL; 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_ci if (vol->upd_marker) 6148c2ecf20Sopenharmony_ci return -EBADF; 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci err = ubi_eba_unmap_leb(ubi, vol, lnum); 6178c2ecf20Sopenharmony_ci if (err) 6188c2ecf20Sopenharmony_ci return err; 6198c2ecf20Sopenharmony_ci 6208c2ecf20Sopenharmony_ci return ubi_wl_flush(ubi, vol->vol_id, lnum); 6218c2ecf20Sopenharmony_ci} 6228c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_erase); 6238c2ecf20Sopenharmony_ci 6248c2ecf20Sopenharmony_ci/** 6258c2ecf20Sopenharmony_ci * ubi_leb_unmap - un-map logical eraseblock. 6268c2ecf20Sopenharmony_ci * @desc: volume descriptor 6278c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number 6288c2ecf20Sopenharmony_ci * 6298c2ecf20Sopenharmony_ci * This function un-maps logical eraseblock @lnum and schedules the 6308c2ecf20Sopenharmony_ci * corresponding physical eraseblock for erasure, so that it will eventually be 6318c2ecf20Sopenharmony_ci * physically erased in background. This operation is much faster than the 6328c2ecf20Sopenharmony_ci * erase operation. 6338c2ecf20Sopenharmony_ci * 6348c2ecf20Sopenharmony_ci * Unlike erase, the un-map operation does not guarantee that the logical 6358c2ecf20Sopenharmony_ci * eraseblock will contain all 0xFF bytes when UBI is initialized again. For 6368c2ecf20Sopenharmony_ci * example, if several logical eraseblocks are un-mapped, and an unclean reboot 6378c2ecf20Sopenharmony_ci * happens after this, the logical eraseblocks will not necessarily be 6388c2ecf20Sopenharmony_ci * un-mapped again when this MTD device is attached. They may actually be 6398c2ecf20Sopenharmony_ci * mapped to the same physical eraseblocks again. So, this function has to be 6408c2ecf20Sopenharmony_ci * used with care. 6418c2ecf20Sopenharmony_ci * 6428c2ecf20Sopenharmony_ci * In other words, when un-mapping a logical eraseblock, UBI does not store 6438c2ecf20Sopenharmony_ci * any information about this on the flash media, it just marks the logical 6448c2ecf20Sopenharmony_ci * eraseblock as "un-mapped" in RAM. If UBI is detached before the physical 6458c2ecf20Sopenharmony_ci * eraseblock is physically erased, it will be mapped again to the same logical 6468c2ecf20Sopenharmony_ci * eraseblock when the MTD device is attached again. 6478c2ecf20Sopenharmony_ci * 6488c2ecf20Sopenharmony_ci * The main and obvious use-case of this function is when the contents of a 6498c2ecf20Sopenharmony_ci * logical eraseblock has to be re-written. Then it is much more efficient to 6508c2ecf20Sopenharmony_ci * first un-map it, then write new data, rather than first erase it, then write 6518c2ecf20Sopenharmony_ci * new data. Note, once new data has been written to the logical eraseblock, 6528c2ecf20Sopenharmony_ci * UBI guarantees that the old contents has gone forever. In other words, if an 6538c2ecf20Sopenharmony_ci * unclean reboot happens after the logical eraseblock has been un-mapped and 6548c2ecf20Sopenharmony_ci * then written to, it will contain the last written data. 6558c2ecf20Sopenharmony_ci * 6568c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in 6578c2ecf20Sopenharmony_ci * case of failure. If the volume is damaged because of an interrupted update 6588c2ecf20Sopenharmony_ci * this function just returns immediately with %-EBADF code. 6598c2ecf20Sopenharmony_ci */ 6608c2ecf20Sopenharmony_ciint ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) 6618c2ecf20Sopenharmony_ci{ 6628c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 6638c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 6688c2ecf20Sopenharmony_ci return -EROFS; 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 6718c2ecf20Sopenharmony_ci return -EINVAL; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (vol->upd_marker) 6748c2ecf20Sopenharmony_ci return -EBADF; 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci return ubi_eba_unmap_leb(ubi, vol, lnum); 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_unmap); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci/** 6818c2ecf20Sopenharmony_ci * ubi_leb_map - map logical eraseblock to a physical eraseblock. 6828c2ecf20Sopenharmony_ci * @desc: volume descriptor 6838c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number 6848c2ecf20Sopenharmony_ci * 6858c2ecf20Sopenharmony_ci * This function maps an un-mapped logical eraseblock @lnum to a physical 6868c2ecf20Sopenharmony_ci * eraseblock. This means, that after a successful invocation of this 6878c2ecf20Sopenharmony_ci * function the logical eraseblock @lnum will be empty (contain only %0xFF 6888c2ecf20Sopenharmony_ci * bytes) and be mapped to a physical eraseblock, even if an unclean reboot 6898c2ecf20Sopenharmony_ci * happens. 6908c2ecf20Sopenharmony_ci * 6918c2ecf20Sopenharmony_ci * This function returns zero in case of success, %-EBADF if the volume is 6928c2ecf20Sopenharmony_ci * damaged because of an interrupted update, %-EBADMSG if the logical 6938c2ecf20Sopenharmony_ci * eraseblock is already mapped, and other negative error codes in case of 6948c2ecf20Sopenharmony_ci * other failures. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_ciint ubi_leb_map(struct ubi_volume_desc *desc, int lnum) 6978c2ecf20Sopenharmony_ci{ 6988c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 6998c2ecf20Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_ci dbg_gen("map LEB %d:%d", vol->vol_id, lnum); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 7048c2ecf20Sopenharmony_ci return -EROFS; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 7078c2ecf20Sopenharmony_ci return -EINVAL; 7088c2ecf20Sopenharmony_ci 7098c2ecf20Sopenharmony_ci if (vol->upd_marker) 7108c2ecf20Sopenharmony_ci return -EBADF; 7118c2ecf20Sopenharmony_ci 7128c2ecf20Sopenharmony_ci if (ubi_eba_is_mapped(vol, lnum)) 7138c2ecf20Sopenharmony_ci return -EBADMSG; 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); 7168c2ecf20Sopenharmony_ci} 7178c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_map); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci/** 7208c2ecf20Sopenharmony_ci * ubi_is_mapped - check if logical eraseblock is mapped. 7218c2ecf20Sopenharmony_ci * @desc: volume descriptor 7228c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number 7238c2ecf20Sopenharmony_ci * 7248c2ecf20Sopenharmony_ci * This function checks if logical eraseblock @lnum is mapped to a physical 7258c2ecf20Sopenharmony_ci * eraseblock. If a logical eraseblock is un-mapped, this does not necessarily 7268c2ecf20Sopenharmony_ci * mean it will still be un-mapped after the UBI device is re-attached. The 7278c2ecf20Sopenharmony_ci * logical eraseblock may become mapped to the physical eraseblock it was last 7288c2ecf20Sopenharmony_ci * mapped to. 7298c2ecf20Sopenharmony_ci * 7308c2ecf20Sopenharmony_ci * This function returns %1 if the LEB is mapped, %0 if not, and a negative 7318c2ecf20Sopenharmony_ci * error code in case of failure. If the volume is damaged because of an 7328c2ecf20Sopenharmony_ci * interrupted update this function just returns immediately with %-EBADF error 7338c2ecf20Sopenharmony_ci * code. 7348c2ecf20Sopenharmony_ci */ 7358c2ecf20Sopenharmony_ciint ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) 7368c2ecf20Sopenharmony_ci{ 7378c2ecf20Sopenharmony_ci struct ubi_volume *vol = desc->vol; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci dbg_gen("test LEB %d:%d", vol->vol_id, lnum); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 7428c2ecf20Sopenharmony_ci return -EINVAL; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci if (vol->upd_marker) 7458c2ecf20Sopenharmony_ci return -EBADF; 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci return ubi_eba_is_mapped(vol, lnum); 7488c2ecf20Sopenharmony_ci} 7498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_is_mapped); 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci/** 7528c2ecf20Sopenharmony_ci * ubi_sync - synchronize UBI device buffers. 7538c2ecf20Sopenharmony_ci * @ubi_num: UBI device to synchronize 7548c2ecf20Sopenharmony_ci * 7558c2ecf20Sopenharmony_ci * The underlying MTD device may cache data in hardware or in software. This 7568c2ecf20Sopenharmony_ci * function ensures the caches are flushed. Returns zero in case of success and 7578c2ecf20Sopenharmony_ci * a negative error code in case of failure. 7588c2ecf20Sopenharmony_ci */ 7598c2ecf20Sopenharmony_ciint ubi_sync(int ubi_num) 7608c2ecf20Sopenharmony_ci{ 7618c2ecf20Sopenharmony_ci struct ubi_device *ubi; 7628c2ecf20Sopenharmony_ci 7638c2ecf20Sopenharmony_ci ubi = ubi_get_device(ubi_num); 7648c2ecf20Sopenharmony_ci if (!ubi) 7658c2ecf20Sopenharmony_ci return -ENODEV; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci mtd_sync(ubi->mtd); 7688c2ecf20Sopenharmony_ci ubi_put_device(ubi); 7698c2ecf20Sopenharmony_ci return 0; 7708c2ecf20Sopenharmony_ci} 7718c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_sync); 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_ci/** 7748c2ecf20Sopenharmony_ci * ubi_flush - flush UBI work queue. 7758c2ecf20Sopenharmony_ci * @ubi_num: UBI device to flush work queue 7768c2ecf20Sopenharmony_ci * @vol_id: volume id to flush for 7778c2ecf20Sopenharmony_ci * @lnum: logical eraseblock number to flush for 7788c2ecf20Sopenharmony_ci * 7798c2ecf20Sopenharmony_ci * This function executes all pending works for a particular volume id / logical 7808c2ecf20Sopenharmony_ci * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as 7818c2ecf20Sopenharmony_ci * a wildcard for all of the corresponding volume numbers or logical 7828c2ecf20Sopenharmony_ci * eraseblock numbers. It returns zero in case of success and a negative error 7838c2ecf20Sopenharmony_ci * code in case of failure. 7848c2ecf20Sopenharmony_ci */ 7858c2ecf20Sopenharmony_ciint ubi_flush(int ubi_num, int vol_id, int lnum) 7868c2ecf20Sopenharmony_ci{ 7878c2ecf20Sopenharmony_ci struct ubi_device *ubi; 7888c2ecf20Sopenharmony_ci int err = 0; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ubi = ubi_get_device(ubi_num); 7918c2ecf20Sopenharmony_ci if (!ubi) 7928c2ecf20Sopenharmony_ci return -ENODEV; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci err = ubi_wl_flush(ubi, vol_id, lnum); 7958c2ecf20Sopenharmony_ci ubi_put_device(ubi); 7968c2ecf20Sopenharmony_ci return err; 7978c2ecf20Sopenharmony_ci} 7988c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_flush); 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ciBLOCKING_NOTIFIER_HEAD(ubi_notifiers); 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci/** 8038c2ecf20Sopenharmony_ci * ubi_register_volume_notifier - register a volume notifier. 8048c2ecf20Sopenharmony_ci * @nb: the notifier description object 8058c2ecf20Sopenharmony_ci * @ignore_existing: if non-zero, do not send "added" notification for all 8068c2ecf20Sopenharmony_ci * already existing volumes 8078c2ecf20Sopenharmony_ci * 8088c2ecf20Sopenharmony_ci * This function registers a volume notifier, which means that 8098c2ecf20Sopenharmony_ci * 'nb->notifier_call()' will be invoked when an UBI volume is created, 8108c2ecf20Sopenharmony_ci * removed, re-sized, re-named, or updated. The first argument of the function 8118c2ecf20Sopenharmony_ci * is the notification type. The second argument is pointer to a 8128c2ecf20Sopenharmony_ci * &struct ubi_notification object which describes the notification event. 8138c2ecf20Sopenharmony_ci * Using UBI API from the volume notifier is prohibited. 8148c2ecf20Sopenharmony_ci * 8158c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code 8168c2ecf20Sopenharmony_ci * in case of failure. 8178c2ecf20Sopenharmony_ci */ 8188c2ecf20Sopenharmony_ciint ubi_register_volume_notifier(struct notifier_block *nb, 8198c2ecf20Sopenharmony_ci int ignore_existing) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci int err; 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci err = blocking_notifier_chain_register(&ubi_notifiers, nb); 8248c2ecf20Sopenharmony_ci if (err != 0) 8258c2ecf20Sopenharmony_ci return err; 8268c2ecf20Sopenharmony_ci if (ignore_existing) 8278c2ecf20Sopenharmony_ci return 0; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci /* 8308c2ecf20Sopenharmony_ci * We are going to walk all UBI devices and all volumes, and 8318c2ecf20Sopenharmony_ci * notify the user about existing volumes by the %UBI_VOLUME_ADDED 8328c2ecf20Sopenharmony_ci * event. We have to lock the @ubi_devices_mutex to make sure UBI 8338c2ecf20Sopenharmony_ci * devices do not disappear. 8348c2ecf20Sopenharmony_ci */ 8358c2ecf20Sopenharmony_ci mutex_lock(&ubi_devices_mutex); 8368c2ecf20Sopenharmony_ci ubi_enumerate_volumes(nb); 8378c2ecf20Sopenharmony_ci mutex_unlock(&ubi_devices_mutex); 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_ci return err; 8408c2ecf20Sopenharmony_ci} 8418c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_register_volume_notifier); 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci/** 8448c2ecf20Sopenharmony_ci * ubi_unregister_volume_notifier - unregister the volume notifier. 8458c2ecf20Sopenharmony_ci * @nb: the notifier description object 8468c2ecf20Sopenharmony_ci * 8478c2ecf20Sopenharmony_ci * This function unregisters volume notifier @nm and returns zero in case of 8488c2ecf20Sopenharmony_ci * success and a negative error code in case of failure. 8498c2ecf20Sopenharmony_ci */ 8508c2ecf20Sopenharmony_ciint ubi_unregister_volume_notifier(struct notifier_block *nb) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci return blocking_notifier_chain_unregister(&ubi_notifiers, nb); 8538c2ecf20Sopenharmony_ci} 8548c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier); 855