162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* This file mostly implements UBI kernel API functions */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/module.h> 1162306a36Sopenharmony_ci#include <linux/err.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/namei.h> 1462306a36Sopenharmony_ci#include <linux/fs.h> 1562306a36Sopenharmony_ci#include <asm/div64.h> 1662306a36Sopenharmony_ci#include "ubi.h" 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci/** 1962306a36Sopenharmony_ci * ubi_do_get_device_info - get information about UBI device. 2062306a36Sopenharmony_ci * @ubi: UBI device description object 2162306a36Sopenharmony_ci * @di: the information is stored here 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * This function is the same as 'ubi_get_device_info()', but it assumes the UBI 2462306a36Sopenharmony_ci * device is locked and cannot disappear. 2562306a36Sopenharmony_ci */ 2662306a36Sopenharmony_civoid ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci di->ubi_num = ubi->ubi_num; 2962306a36Sopenharmony_ci di->leb_size = ubi->leb_size; 3062306a36Sopenharmony_ci di->leb_start = ubi->leb_start; 3162306a36Sopenharmony_ci di->min_io_size = ubi->min_io_size; 3262306a36Sopenharmony_ci di->max_write_size = ubi->max_write_size; 3362306a36Sopenharmony_ci di->ro_mode = ubi->ro_mode; 3462306a36Sopenharmony_ci di->cdev = ubi->cdev.dev; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_do_get_device_info); 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci/** 3962306a36Sopenharmony_ci * ubi_get_device_info - get information about UBI device. 4062306a36Sopenharmony_ci * @ubi_num: UBI device number 4162306a36Sopenharmony_ci * @di: the information is stored here 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * This function returns %0 in case of success, %-EINVAL if the UBI device 4462306a36Sopenharmony_ci * number is invalid, and %-ENODEV if there is no such UBI device. 4562306a36Sopenharmony_ci */ 4662306a36Sopenharmony_ciint ubi_get_device_info(int ubi_num, struct ubi_device_info *di) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct ubi_device *ubi; 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 5162306a36Sopenharmony_ci return -EINVAL; 5262306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 5362306a36Sopenharmony_ci if (!ubi) 5462306a36Sopenharmony_ci return -ENODEV; 5562306a36Sopenharmony_ci ubi_do_get_device_info(ubi, di); 5662306a36Sopenharmony_ci ubi_put_device(ubi); 5762306a36Sopenharmony_ci return 0; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_get_device_info); 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/** 6262306a36Sopenharmony_ci * ubi_do_get_volume_info - get information about UBI volume. 6362306a36Sopenharmony_ci * @ubi: UBI device description object 6462306a36Sopenharmony_ci * @vol: volume description object 6562306a36Sopenharmony_ci * @vi: the information is stored here 6662306a36Sopenharmony_ci */ 6762306a36Sopenharmony_civoid ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, 6862306a36Sopenharmony_ci struct ubi_volume_info *vi) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci vi->vol_id = vol->vol_id; 7162306a36Sopenharmony_ci vi->ubi_num = ubi->ubi_num; 7262306a36Sopenharmony_ci vi->size = vol->reserved_pebs; 7362306a36Sopenharmony_ci vi->used_bytes = vol->used_bytes; 7462306a36Sopenharmony_ci vi->vol_type = vol->vol_type; 7562306a36Sopenharmony_ci vi->corrupted = vol->corrupted; 7662306a36Sopenharmony_ci vi->upd_marker = vol->upd_marker; 7762306a36Sopenharmony_ci vi->alignment = vol->alignment; 7862306a36Sopenharmony_ci vi->usable_leb_size = vol->usable_leb_size; 7962306a36Sopenharmony_ci vi->name_len = vol->name_len; 8062306a36Sopenharmony_ci vi->name = vol->name; 8162306a36Sopenharmony_ci vi->cdev = vol->cdev.dev; 8262306a36Sopenharmony_ci vi->dev = &vol->dev; 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci/** 8662306a36Sopenharmony_ci * ubi_get_volume_info - get information about UBI volume. 8762306a36Sopenharmony_ci * @desc: volume descriptor 8862306a36Sopenharmony_ci * @vi: the information is stored here 8962306a36Sopenharmony_ci */ 9062306a36Sopenharmony_civoid ubi_get_volume_info(struct ubi_volume_desc *desc, 9162306a36Sopenharmony_ci struct ubi_volume_info *vi) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci ubi_do_get_volume_info(desc->vol->ubi, desc->vol, vi); 9462306a36Sopenharmony_ci} 9562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_get_volume_info); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/** 9862306a36Sopenharmony_ci * ubi_open_volume - open UBI volume. 9962306a36Sopenharmony_ci * @ubi_num: UBI device number 10062306a36Sopenharmony_ci * @vol_id: volume ID 10162306a36Sopenharmony_ci * @mode: open mode 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * The @mode parameter specifies if the volume should be opened in read-only 10462306a36Sopenharmony_ci * mode, read-write mode, or exclusive mode. The exclusive mode guarantees that 10562306a36Sopenharmony_ci * nobody else will be able to open this volume. UBI allows to have many volume 10662306a36Sopenharmony_ci * readers and one writer at a time. 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * If a static volume is being opened for the first time since boot, it will be 10962306a36Sopenharmony_ci * checked by this function, which means it will be fully read and the CRC 11062306a36Sopenharmony_ci * checksum of each logical eraseblock will be checked. 11162306a36Sopenharmony_ci * 11262306a36Sopenharmony_ci * This function returns volume descriptor in case of success and a negative 11362306a36Sopenharmony_ci * error code in case of failure. 11462306a36Sopenharmony_ci */ 11562306a36Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume(int ubi_num, int vol_id, int mode) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci int err; 11862306a36Sopenharmony_ci struct ubi_volume_desc *desc; 11962306a36Sopenharmony_ci struct ubi_device *ubi; 12062306a36Sopenharmony_ci struct ubi_volume *vol; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci dbg_gen("open device %d, volume %d, mode %d", ubi_num, vol_id, mode); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 12562306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (mode != UBI_READONLY && mode != UBI_READWRITE && 12862306a36Sopenharmony_ci mode != UBI_EXCLUSIVE && mode != UBI_METAONLY) 12962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* 13262306a36Sopenharmony_ci * First of all, we have to get the UBI device to prevent its removal. 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 13562306a36Sopenharmony_ci if (!ubi) 13662306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) { 13962306a36Sopenharmony_ci err = -EINVAL; 14062306a36Sopenharmony_ci goto out_put_ubi; 14162306a36Sopenharmony_ci } 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci desc = kmalloc(sizeof(struct ubi_volume_desc), GFP_KERNEL); 14462306a36Sopenharmony_ci if (!desc) { 14562306a36Sopenharmony_ci err = -ENOMEM; 14662306a36Sopenharmony_ci goto out_put_ubi; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci err = -ENODEV; 15062306a36Sopenharmony_ci if (!try_module_get(THIS_MODULE)) 15162306a36Sopenharmony_ci goto out_free; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci spin_lock(&ubi->volumes_lock); 15462306a36Sopenharmony_ci vol = ubi->volumes[vol_id]; 15562306a36Sopenharmony_ci if (!vol) 15662306a36Sopenharmony_ci goto out_unlock; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci err = -EBUSY; 15962306a36Sopenharmony_ci switch (mode) { 16062306a36Sopenharmony_ci case UBI_READONLY: 16162306a36Sopenharmony_ci if (vol->exclusive) 16262306a36Sopenharmony_ci goto out_unlock; 16362306a36Sopenharmony_ci vol->readers += 1; 16462306a36Sopenharmony_ci break; 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci case UBI_READWRITE: 16762306a36Sopenharmony_ci if (vol->exclusive || vol->writers > 0) 16862306a36Sopenharmony_ci goto out_unlock; 16962306a36Sopenharmony_ci vol->writers += 1; 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci case UBI_EXCLUSIVE: 17362306a36Sopenharmony_ci if (vol->exclusive || vol->writers || vol->readers || 17462306a36Sopenharmony_ci vol->metaonly) 17562306a36Sopenharmony_ci goto out_unlock; 17662306a36Sopenharmony_ci vol->exclusive = 1; 17762306a36Sopenharmony_ci break; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci case UBI_METAONLY: 18062306a36Sopenharmony_ci if (vol->metaonly || vol->exclusive) 18162306a36Sopenharmony_ci goto out_unlock; 18262306a36Sopenharmony_ci vol->metaonly = 1; 18362306a36Sopenharmony_ci break; 18462306a36Sopenharmony_ci } 18562306a36Sopenharmony_ci get_device(&vol->dev); 18662306a36Sopenharmony_ci vol->ref_count += 1; 18762306a36Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci desc->vol = vol; 19062306a36Sopenharmony_ci desc->mode = mode; 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_ci mutex_lock(&ubi->ckvol_mutex); 19362306a36Sopenharmony_ci if (!vol->checked && !vol->skip_check) { 19462306a36Sopenharmony_ci /* This is the first open - check the volume */ 19562306a36Sopenharmony_ci err = ubi_check_volume(ubi, vol_id); 19662306a36Sopenharmony_ci if (err < 0) { 19762306a36Sopenharmony_ci mutex_unlock(&ubi->ckvol_mutex); 19862306a36Sopenharmony_ci ubi_close_volume(desc); 19962306a36Sopenharmony_ci return ERR_PTR(err); 20062306a36Sopenharmony_ci } 20162306a36Sopenharmony_ci if (err == 1) { 20262306a36Sopenharmony_ci ubi_warn(ubi, "volume %d on UBI device %d is corrupted", 20362306a36Sopenharmony_ci vol_id, ubi->ubi_num); 20462306a36Sopenharmony_ci vol->corrupted = 1; 20562306a36Sopenharmony_ci } 20662306a36Sopenharmony_ci vol->checked = 1; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci mutex_unlock(&ubi->ckvol_mutex); 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci return desc; 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ciout_unlock: 21362306a36Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 21462306a36Sopenharmony_ci module_put(THIS_MODULE); 21562306a36Sopenharmony_ciout_free: 21662306a36Sopenharmony_ci kfree(desc); 21762306a36Sopenharmony_ciout_put_ubi: 21862306a36Sopenharmony_ci ubi_err(ubi, "cannot open device %d, volume %d, error %d", 21962306a36Sopenharmony_ci ubi_num, vol_id, err); 22062306a36Sopenharmony_ci ubi_put_device(ubi); 22162306a36Sopenharmony_ci return ERR_PTR(err); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/** 22662306a36Sopenharmony_ci * ubi_open_volume_nm - open UBI volume by name. 22762306a36Sopenharmony_ci * @ubi_num: UBI device number 22862306a36Sopenharmony_ci * @name: volume name 22962306a36Sopenharmony_ci * @mode: open mode 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * This function is similar to 'ubi_open_volume()', but opens a volume by name. 23262306a36Sopenharmony_ci */ 23362306a36Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume_nm(int ubi_num, const char *name, 23462306a36Sopenharmony_ci int mode) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci int i, vol_id = -1, len; 23762306a36Sopenharmony_ci struct ubi_device *ubi; 23862306a36Sopenharmony_ci struct ubi_volume_desc *ret; 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci dbg_gen("open device %d, volume %s, mode %d", ubi_num, name, mode); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci if (!name) 24362306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci len = strnlen(name, UBI_VOL_NAME_MAX + 1); 24662306a36Sopenharmony_ci if (len > UBI_VOL_NAME_MAX) 24762306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 25062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 25362306a36Sopenharmony_ci if (!ubi) 25462306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci spin_lock(&ubi->volumes_lock); 25762306a36Sopenharmony_ci /* Walk all volumes of this UBI device */ 25862306a36Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) { 25962306a36Sopenharmony_ci struct ubi_volume *vol = ubi->volumes[i]; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci if (vol && len == vol->name_len && !strcmp(name, vol->name)) { 26262306a36Sopenharmony_ci vol_id = i; 26362306a36Sopenharmony_ci break; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci if (vol_id >= 0) 26962306a36Sopenharmony_ci ret = ubi_open_volume(ubi_num, vol_id, mode); 27062306a36Sopenharmony_ci else 27162306a36Sopenharmony_ci ret = ERR_PTR(-ENODEV); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci /* 27462306a36Sopenharmony_ci * We should put the UBI device even in case of success, because 27562306a36Sopenharmony_ci * 'ubi_open_volume()' took a reference as well. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci ubi_put_device(ubi); 27862306a36Sopenharmony_ci return ret; 27962306a36Sopenharmony_ci} 28062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume_nm); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/** 28362306a36Sopenharmony_ci * ubi_open_volume_path - open UBI volume by its character device node path. 28462306a36Sopenharmony_ci * @pathname: volume character device node path 28562306a36Sopenharmony_ci * @mode: open mode 28662306a36Sopenharmony_ci * 28762306a36Sopenharmony_ci * This function is similar to 'ubi_open_volume()', but opens a volume the path 28862306a36Sopenharmony_ci * to its character device node. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_cistruct ubi_volume_desc *ubi_open_volume_path(const char *pathname, int mode) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci int error, ubi_num, vol_id; 29362306a36Sopenharmony_ci struct path path; 29462306a36Sopenharmony_ci struct kstat stat; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci dbg_gen("open volume %s, mode %d", pathname, mode); 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci if (!pathname || !*pathname) 29962306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci error = kern_path(pathname, LOOKUP_FOLLOW, &path); 30262306a36Sopenharmony_ci if (error) 30362306a36Sopenharmony_ci return ERR_PTR(error); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci error = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); 30662306a36Sopenharmony_ci path_put(&path); 30762306a36Sopenharmony_ci if (error) 30862306a36Sopenharmony_ci return ERR_PTR(error); 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_ci if (!S_ISCHR(stat.mode)) 31162306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci ubi_num = ubi_major2num(MAJOR(stat.rdev)); 31462306a36Sopenharmony_ci vol_id = MINOR(stat.rdev) - 1; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (vol_id >= 0 && ubi_num >= 0) 31762306a36Sopenharmony_ci return ubi_open_volume(ubi_num, vol_id, mode); 31862306a36Sopenharmony_ci return ERR_PTR(-ENODEV); 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_open_volume_path); 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci/** 32362306a36Sopenharmony_ci * ubi_close_volume - close UBI volume. 32462306a36Sopenharmony_ci * @desc: volume descriptor 32562306a36Sopenharmony_ci */ 32662306a36Sopenharmony_civoid ubi_close_volume(struct ubi_volume_desc *desc) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 32962306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci dbg_gen("close device %d, volume %d, mode %d", 33262306a36Sopenharmony_ci ubi->ubi_num, vol->vol_id, desc->mode); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci spin_lock(&ubi->volumes_lock); 33562306a36Sopenharmony_ci switch (desc->mode) { 33662306a36Sopenharmony_ci case UBI_READONLY: 33762306a36Sopenharmony_ci vol->readers -= 1; 33862306a36Sopenharmony_ci break; 33962306a36Sopenharmony_ci case UBI_READWRITE: 34062306a36Sopenharmony_ci vol->writers -= 1; 34162306a36Sopenharmony_ci break; 34262306a36Sopenharmony_ci case UBI_EXCLUSIVE: 34362306a36Sopenharmony_ci vol->exclusive = 0; 34462306a36Sopenharmony_ci break; 34562306a36Sopenharmony_ci case UBI_METAONLY: 34662306a36Sopenharmony_ci vol->metaonly = 0; 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci vol->ref_count -= 1; 35062306a36Sopenharmony_ci spin_unlock(&ubi->volumes_lock); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci kfree(desc); 35362306a36Sopenharmony_ci put_device(&vol->dev); 35462306a36Sopenharmony_ci ubi_put_device(ubi); 35562306a36Sopenharmony_ci module_put(THIS_MODULE); 35662306a36Sopenharmony_ci} 35762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_close_volume); 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci/** 36062306a36Sopenharmony_ci * leb_read_sanity_check - does sanity checks on read requests. 36162306a36Sopenharmony_ci * @desc: volume descriptor 36262306a36Sopenharmony_ci * @lnum: logical eraseblock number to read from 36362306a36Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 36462306a36Sopenharmony_ci * @len: how many bytes to read 36562306a36Sopenharmony_ci * 36662306a36Sopenharmony_ci * This function is used by ubi_leb_read() and ubi_leb_read_sg() 36762306a36Sopenharmony_ci * to perform sanity checks. 36862306a36Sopenharmony_ci */ 36962306a36Sopenharmony_cistatic int leb_read_sanity_check(struct ubi_volume_desc *desc, int lnum, 37062306a36Sopenharmony_ci int offset, int len) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 37362306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 37462306a36Sopenharmony_ci int vol_id = vol->vol_id; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots || lnum < 0 || 37762306a36Sopenharmony_ci lnum >= vol->used_ebs || offset < 0 || len < 0 || 37862306a36Sopenharmony_ci offset + len > vol->usable_leb_size) 37962306a36Sopenharmony_ci return -EINVAL; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci if (vol->vol_type == UBI_STATIC_VOLUME) { 38262306a36Sopenharmony_ci if (vol->used_ebs == 0) 38362306a36Sopenharmony_ci /* Empty static UBI volume */ 38462306a36Sopenharmony_ci return 0; 38562306a36Sopenharmony_ci if (lnum == vol->used_ebs - 1 && 38662306a36Sopenharmony_ci offset + len > vol->last_eb_bytes) 38762306a36Sopenharmony_ci return -EINVAL; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if (vol->upd_marker) 39162306a36Sopenharmony_ci return -EBADF; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return 0; 39462306a36Sopenharmony_ci} 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci/** 39762306a36Sopenharmony_ci * ubi_leb_read - read data. 39862306a36Sopenharmony_ci * @desc: volume descriptor 39962306a36Sopenharmony_ci * @lnum: logical eraseblock number to read from 40062306a36Sopenharmony_ci * @buf: buffer where to store the read data 40162306a36Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 40262306a36Sopenharmony_ci * @len: how many bytes to read 40362306a36Sopenharmony_ci * @check: whether UBI has to check the read data's CRC or not. 40462306a36Sopenharmony_ci * 40562306a36Sopenharmony_ci * This function reads data from offset @offset of logical eraseblock @lnum and 40662306a36Sopenharmony_ci * stores the data at @buf. When reading from static volumes, @check specifies 40762306a36Sopenharmony_ci * whether the data has to be checked or not. If yes, the whole logical 40862306a36Sopenharmony_ci * eraseblock will be read and its CRC checksum will be checked (i.e., the CRC 40962306a36Sopenharmony_ci * checksum is per-eraseblock). So checking may substantially slow down the 41062306a36Sopenharmony_ci * read speed. The @check argument is ignored for dynamic volumes. 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * In case of success, this function returns zero. In case of failure, this 41362306a36Sopenharmony_ci * function returns a negative error code. 41462306a36Sopenharmony_ci * 41562306a36Sopenharmony_ci * %-EBADMSG error code is returned: 41662306a36Sopenharmony_ci * o for both static and dynamic volumes if MTD driver has detected a data 41762306a36Sopenharmony_ci * integrity problem (unrecoverable ECC checksum mismatch in case of NAND); 41862306a36Sopenharmony_ci * o for static volumes in case of data CRC mismatch. 41962306a36Sopenharmony_ci * 42062306a36Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 42162306a36Sopenharmony_ci * returns immediately with %-EBADF error code. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ciint ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, 42462306a36Sopenharmony_ci int len, int check) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 42762306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 42862306a36Sopenharmony_ci int err, vol_id = vol->vol_id; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci err = leb_read_sanity_check(desc, lnum, offset, len); 43362306a36Sopenharmony_ci if (err < 0) 43462306a36Sopenharmony_ci return err; 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci if (len == 0) 43762306a36Sopenharmony_ci return 0; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); 44062306a36Sopenharmony_ci if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { 44162306a36Sopenharmony_ci ubi_warn(ubi, "mark volume %d as corrupted", vol_id); 44262306a36Sopenharmony_ci vol->corrupted = 1; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci return err; 44662306a36Sopenharmony_ci} 44762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_read); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci/** 45162306a36Sopenharmony_ci * ubi_leb_read_sg - read data into a scatter gather list. 45262306a36Sopenharmony_ci * @desc: volume descriptor 45362306a36Sopenharmony_ci * @lnum: logical eraseblock number to read from 45462306a36Sopenharmony_ci * @sgl: UBI scatter gather list to store the read data 45562306a36Sopenharmony_ci * @offset: offset within the logical eraseblock to read from 45662306a36Sopenharmony_ci * @len: how many bytes to read 45762306a36Sopenharmony_ci * @check: whether UBI has to check the read data's CRC or not. 45862306a36Sopenharmony_ci * 45962306a36Sopenharmony_ci * This function works exactly like ubi_leb_read_sg(). But instead of 46062306a36Sopenharmony_ci * storing the read data into a buffer it writes to an UBI scatter gather 46162306a36Sopenharmony_ci * list. 46262306a36Sopenharmony_ci */ 46362306a36Sopenharmony_ciint ubi_leb_read_sg(struct ubi_volume_desc *desc, int lnum, struct ubi_sgl *sgl, 46462306a36Sopenharmony_ci int offset, int len, int check) 46562306a36Sopenharmony_ci{ 46662306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 46762306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 46862306a36Sopenharmony_ci int err, vol_id = vol->vol_id; 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci dbg_gen("read %d bytes from LEB %d:%d:%d", len, vol_id, lnum, offset); 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci err = leb_read_sanity_check(desc, lnum, offset, len); 47362306a36Sopenharmony_ci if (err < 0) 47462306a36Sopenharmony_ci return err; 47562306a36Sopenharmony_ci 47662306a36Sopenharmony_ci if (len == 0) 47762306a36Sopenharmony_ci return 0; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci err = ubi_eba_read_leb_sg(ubi, vol, sgl, lnum, offset, len, check); 48062306a36Sopenharmony_ci if (err && mtd_is_eccerr(err) && vol->vol_type == UBI_STATIC_VOLUME) { 48162306a36Sopenharmony_ci ubi_warn(ubi, "mark volume %d as corrupted", vol_id); 48262306a36Sopenharmony_ci vol->corrupted = 1; 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci 48562306a36Sopenharmony_ci return err; 48662306a36Sopenharmony_ci} 48762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_read_sg); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci/** 49062306a36Sopenharmony_ci * ubi_leb_write - write data. 49162306a36Sopenharmony_ci * @desc: volume descriptor 49262306a36Sopenharmony_ci * @lnum: logical eraseblock number to write to 49362306a36Sopenharmony_ci * @buf: data to write 49462306a36Sopenharmony_ci * @offset: offset within the logical eraseblock where to write 49562306a36Sopenharmony_ci * @len: how many bytes to write 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * This function writes @len bytes of data from @buf to offset @offset of 49862306a36Sopenharmony_ci * logical eraseblock @lnum. 49962306a36Sopenharmony_ci * 50062306a36Sopenharmony_ci * This function takes care of physical eraseblock write failures. If write to 50162306a36Sopenharmony_ci * the physical eraseblock write operation fails, the logical eraseblock is 50262306a36Sopenharmony_ci * re-mapped to another physical eraseblock, the data is recovered, and the 50362306a36Sopenharmony_ci * write finishes. UBI has a pool of reserved physical eraseblocks for this. 50462306a36Sopenharmony_ci * 50562306a36Sopenharmony_ci * If all the data were successfully written, zero is returned. If an error 50662306a36Sopenharmony_ci * occurred and UBI has not been able to recover from it, this function returns 50762306a36Sopenharmony_ci * a negative error code. Note, in case of an error, it is possible that 50862306a36Sopenharmony_ci * something was still written to the flash media, but that may be some 50962306a36Sopenharmony_ci * garbage. 51062306a36Sopenharmony_ci * 51162306a36Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 51262306a36Sopenharmony_ci * returns immediately with %-EBADF code. 51362306a36Sopenharmony_ci */ 51462306a36Sopenharmony_ciint ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, 51562306a36Sopenharmony_ci int offset, int len) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 51862306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 51962306a36Sopenharmony_ci int vol_id = vol->vol_id; 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci dbg_gen("write %d bytes to LEB %d:%d:%d", len, vol_id, lnum, offset); 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) 52462306a36Sopenharmony_ci return -EINVAL; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 52762306a36Sopenharmony_ci return -EROFS; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum) || offset < 0 || len < 0 || 53062306a36Sopenharmony_ci offset + len > vol->usable_leb_size || 53162306a36Sopenharmony_ci offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1)) 53262306a36Sopenharmony_ci return -EINVAL; 53362306a36Sopenharmony_ci 53462306a36Sopenharmony_ci if (vol->upd_marker) 53562306a36Sopenharmony_ci return -EBADF; 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci if (len == 0) 53862306a36Sopenharmony_ci return 0; 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len); 54162306a36Sopenharmony_ci} 54262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_write); 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci/* 54562306a36Sopenharmony_ci * ubi_leb_change - change logical eraseblock atomically. 54662306a36Sopenharmony_ci * @desc: volume descriptor 54762306a36Sopenharmony_ci * @lnum: logical eraseblock number to change 54862306a36Sopenharmony_ci * @buf: data to write 54962306a36Sopenharmony_ci * @len: how many bytes to write 55062306a36Sopenharmony_ci * 55162306a36Sopenharmony_ci * This function changes the contents of a logical eraseblock atomically. @buf 55262306a36Sopenharmony_ci * has to contain new logical eraseblock data, and @len - the length of the 55362306a36Sopenharmony_ci * data, which has to be aligned. The length may be shorter than the logical 55462306a36Sopenharmony_ci * eraseblock size, ant the logical eraseblock may be appended to more times 55562306a36Sopenharmony_ci * later on. This function guarantees that in case of an unclean reboot the old 55662306a36Sopenharmony_ci * contents is preserved. Returns zero in case of success and a negative error 55762306a36Sopenharmony_ci * code in case of failure. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ciint ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, 56062306a36Sopenharmony_ci int len) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 56362306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 56462306a36Sopenharmony_ci int vol_id = vol->vol_id; 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci dbg_gen("atomically write %d bytes to LEB %d:%d", len, vol_id, lnum); 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci if (vol_id < 0 || vol_id >= ubi->vtbl_slots) 56962306a36Sopenharmony_ci return -EINVAL; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 57262306a36Sopenharmony_ci return -EROFS; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum) || len < 0 || 57562306a36Sopenharmony_ci len > vol->usable_leb_size || len & (ubi->min_io_size - 1)) 57662306a36Sopenharmony_ci return -EINVAL; 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci if (vol->upd_marker) 57962306a36Sopenharmony_ci return -EBADF; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci if (len == 0) 58262306a36Sopenharmony_ci return 0; 58362306a36Sopenharmony_ci 58462306a36Sopenharmony_ci return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len); 58562306a36Sopenharmony_ci} 58662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_change); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci/** 58962306a36Sopenharmony_ci * ubi_leb_erase - erase logical eraseblock. 59062306a36Sopenharmony_ci * @desc: volume descriptor 59162306a36Sopenharmony_ci * @lnum: logical eraseblock number 59262306a36Sopenharmony_ci * 59362306a36Sopenharmony_ci * This function un-maps logical eraseblock @lnum and synchronously erases the 59462306a36Sopenharmony_ci * correspondent physical eraseblock. Returns zero in case of success and a 59562306a36Sopenharmony_ci * negative error code in case of failure. 59662306a36Sopenharmony_ci * 59762306a36Sopenharmony_ci * If the volume is damaged because of an interrupted update this function just 59862306a36Sopenharmony_ci * returns immediately with %-EBADF code. 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ciint ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) 60162306a36Sopenharmony_ci{ 60262306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 60362306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 60462306a36Sopenharmony_ci int err; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci dbg_gen("erase LEB %d:%d", vol->vol_id, lnum); 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 60962306a36Sopenharmony_ci return -EROFS; 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 61262306a36Sopenharmony_ci return -EINVAL; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci if (vol->upd_marker) 61562306a36Sopenharmony_ci return -EBADF; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci err = ubi_eba_unmap_leb(ubi, vol, lnum); 61862306a36Sopenharmony_ci if (err) 61962306a36Sopenharmony_ci return err; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci return ubi_wl_flush(ubi, vol->vol_id, lnum); 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_erase); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci/** 62662306a36Sopenharmony_ci * ubi_leb_unmap - un-map logical eraseblock. 62762306a36Sopenharmony_ci * @desc: volume descriptor 62862306a36Sopenharmony_ci * @lnum: logical eraseblock number 62962306a36Sopenharmony_ci * 63062306a36Sopenharmony_ci * This function un-maps logical eraseblock @lnum and schedules the 63162306a36Sopenharmony_ci * corresponding physical eraseblock for erasure, so that it will eventually be 63262306a36Sopenharmony_ci * physically erased in background. This operation is much faster than the 63362306a36Sopenharmony_ci * erase operation. 63462306a36Sopenharmony_ci * 63562306a36Sopenharmony_ci * Unlike erase, the un-map operation does not guarantee that the logical 63662306a36Sopenharmony_ci * eraseblock will contain all 0xFF bytes when UBI is initialized again. For 63762306a36Sopenharmony_ci * example, if several logical eraseblocks are un-mapped, and an unclean reboot 63862306a36Sopenharmony_ci * happens after this, the logical eraseblocks will not necessarily be 63962306a36Sopenharmony_ci * un-mapped again when this MTD device is attached. They may actually be 64062306a36Sopenharmony_ci * mapped to the same physical eraseblocks again. So, this function has to be 64162306a36Sopenharmony_ci * used with care. 64262306a36Sopenharmony_ci * 64362306a36Sopenharmony_ci * In other words, when un-mapping a logical eraseblock, UBI does not store 64462306a36Sopenharmony_ci * any information about this on the flash media, it just marks the logical 64562306a36Sopenharmony_ci * eraseblock as "un-mapped" in RAM. If UBI is detached before the physical 64662306a36Sopenharmony_ci * eraseblock is physically erased, it will be mapped again to the same logical 64762306a36Sopenharmony_ci * eraseblock when the MTD device is attached again. 64862306a36Sopenharmony_ci * 64962306a36Sopenharmony_ci * The main and obvious use-case of this function is when the contents of a 65062306a36Sopenharmony_ci * logical eraseblock has to be re-written. Then it is much more efficient to 65162306a36Sopenharmony_ci * first un-map it, then write new data, rather than first erase it, then write 65262306a36Sopenharmony_ci * new data. Note, once new data has been written to the logical eraseblock, 65362306a36Sopenharmony_ci * UBI guarantees that the old contents has gone forever. In other words, if an 65462306a36Sopenharmony_ci * unclean reboot happens after the logical eraseblock has been un-mapped and 65562306a36Sopenharmony_ci * then written to, it will contain the last written data. 65662306a36Sopenharmony_ci * 65762306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in 65862306a36Sopenharmony_ci * case of failure. If the volume is damaged because of an interrupted update 65962306a36Sopenharmony_ci * this function just returns immediately with %-EBADF code. 66062306a36Sopenharmony_ci */ 66162306a36Sopenharmony_ciint ubi_leb_unmap(struct ubi_volume_desc *desc, int lnum) 66262306a36Sopenharmony_ci{ 66362306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 66462306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 66962306a36Sopenharmony_ci return -EROFS; 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 67262306a36Sopenharmony_ci return -EINVAL; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (vol->upd_marker) 67562306a36Sopenharmony_ci return -EBADF; 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci return ubi_eba_unmap_leb(ubi, vol, lnum); 67862306a36Sopenharmony_ci} 67962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_unmap); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci/** 68262306a36Sopenharmony_ci * ubi_leb_map - map logical eraseblock to a physical eraseblock. 68362306a36Sopenharmony_ci * @desc: volume descriptor 68462306a36Sopenharmony_ci * @lnum: logical eraseblock number 68562306a36Sopenharmony_ci * 68662306a36Sopenharmony_ci * This function maps an un-mapped logical eraseblock @lnum to a physical 68762306a36Sopenharmony_ci * eraseblock. This means, that after a successful invocation of this 68862306a36Sopenharmony_ci * function the logical eraseblock @lnum will be empty (contain only %0xFF 68962306a36Sopenharmony_ci * bytes) and be mapped to a physical eraseblock, even if an unclean reboot 69062306a36Sopenharmony_ci * happens. 69162306a36Sopenharmony_ci * 69262306a36Sopenharmony_ci * This function returns zero in case of success, %-EBADF if the volume is 69362306a36Sopenharmony_ci * damaged because of an interrupted update, %-EBADMSG if the logical 69462306a36Sopenharmony_ci * eraseblock is already mapped, and other negative error codes in case of 69562306a36Sopenharmony_ci * other failures. 69662306a36Sopenharmony_ci */ 69762306a36Sopenharmony_ciint ubi_leb_map(struct ubi_volume_desc *desc, int lnum) 69862306a36Sopenharmony_ci{ 69962306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 70062306a36Sopenharmony_ci struct ubi_device *ubi = vol->ubi; 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_ci dbg_gen("map LEB %d:%d", vol->vol_id, lnum); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) 70562306a36Sopenharmony_ci return -EROFS; 70662306a36Sopenharmony_ci 70762306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 70862306a36Sopenharmony_ci return -EINVAL; 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_ci if (vol->upd_marker) 71162306a36Sopenharmony_ci return -EBADF; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci if (ubi_eba_is_mapped(vol, lnum)) 71462306a36Sopenharmony_ci return -EBADMSG; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_leb_map); 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci/** 72162306a36Sopenharmony_ci * ubi_is_mapped - check if logical eraseblock is mapped. 72262306a36Sopenharmony_ci * @desc: volume descriptor 72362306a36Sopenharmony_ci * @lnum: logical eraseblock number 72462306a36Sopenharmony_ci * 72562306a36Sopenharmony_ci * This function checks if logical eraseblock @lnum is mapped to a physical 72662306a36Sopenharmony_ci * eraseblock. If a logical eraseblock is un-mapped, this does not necessarily 72762306a36Sopenharmony_ci * mean it will still be un-mapped after the UBI device is re-attached. The 72862306a36Sopenharmony_ci * logical eraseblock may become mapped to the physical eraseblock it was last 72962306a36Sopenharmony_ci * mapped to. 73062306a36Sopenharmony_ci * 73162306a36Sopenharmony_ci * This function returns %1 if the LEB is mapped, %0 if not, and a negative 73262306a36Sopenharmony_ci * error code in case of failure. If the volume is damaged because of an 73362306a36Sopenharmony_ci * interrupted update this function just returns immediately with %-EBADF error 73462306a36Sopenharmony_ci * code. 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_ciint ubi_is_mapped(struct ubi_volume_desc *desc, int lnum) 73762306a36Sopenharmony_ci{ 73862306a36Sopenharmony_ci struct ubi_volume *vol = desc->vol; 73962306a36Sopenharmony_ci 74062306a36Sopenharmony_ci dbg_gen("test LEB %d:%d", vol->vol_id, lnum); 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci if (!ubi_leb_valid(vol, lnum)) 74362306a36Sopenharmony_ci return -EINVAL; 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci if (vol->upd_marker) 74662306a36Sopenharmony_ci return -EBADF; 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci return ubi_eba_is_mapped(vol, lnum); 74962306a36Sopenharmony_ci} 75062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_is_mapped); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci/** 75362306a36Sopenharmony_ci * ubi_sync - synchronize UBI device buffers. 75462306a36Sopenharmony_ci * @ubi_num: UBI device to synchronize 75562306a36Sopenharmony_ci * 75662306a36Sopenharmony_ci * The underlying MTD device may cache data in hardware or in software. This 75762306a36Sopenharmony_ci * function ensures the caches are flushed. Returns zero in case of success and 75862306a36Sopenharmony_ci * a negative error code in case of failure. 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_ciint ubi_sync(int ubi_num) 76162306a36Sopenharmony_ci{ 76262306a36Sopenharmony_ci struct ubi_device *ubi; 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 76562306a36Sopenharmony_ci if (!ubi) 76662306a36Sopenharmony_ci return -ENODEV; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci mtd_sync(ubi->mtd); 76962306a36Sopenharmony_ci ubi_put_device(ubi); 77062306a36Sopenharmony_ci return 0; 77162306a36Sopenharmony_ci} 77262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_sync); 77362306a36Sopenharmony_ci 77462306a36Sopenharmony_ci/** 77562306a36Sopenharmony_ci * ubi_flush - flush UBI work queue. 77662306a36Sopenharmony_ci * @ubi_num: UBI device to flush work queue 77762306a36Sopenharmony_ci * @vol_id: volume id to flush for 77862306a36Sopenharmony_ci * @lnum: logical eraseblock number to flush for 77962306a36Sopenharmony_ci * 78062306a36Sopenharmony_ci * This function executes all pending works for a particular volume id / logical 78162306a36Sopenharmony_ci * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as 78262306a36Sopenharmony_ci * a wildcard for all of the corresponding volume numbers or logical 78362306a36Sopenharmony_ci * eraseblock numbers. It returns zero in case of success and a negative error 78462306a36Sopenharmony_ci * code in case of failure. 78562306a36Sopenharmony_ci */ 78662306a36Sopenharmony_ciint ubi_flush(int ubi_num, int vol_id, int lnum) 78762306a36Sopenharmony_ci{ 78862306a36Sopenharmony_ci struct ubi_device *ubi; 78962306a36Sopenharmony_ci int err = 0; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 79262306a36Sopenharmony_ci if (!ubi) 79362306a36Sopenharmony_ci return -ENODEV; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci err = ubi_wl_flush(ubi, vol_id, lnum); 79662306a36Sopenharmony_ci ubi_put_device(ubi); 79762306a36Sopenharmony_ci return err; 79862306a36Sopenharmony_ci} 79962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_flush); 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_ciBLOCKING_NOTIFIER_HEAD(ubi_notifiers); 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci/** 80462306a36Sopenharmony_ci * ubi_register_volume_notifier - register a volume notifier. 80562306a36Sopenharmony_ci * @nb: the notifier description object 80662306a36Sopenharmony_ci * @ignore_existing: if non-zero, do not send "added" notification for all 80762306a36Sopenharmony_ci * already existing volumes 80862306a36Sopenharmony_ci * 80962306a36Sopenharmony_ci * This function registers a volume notifier, which means that 81062306a36Sopenharmony_ci * 'nb->notifier_call()' will be invoked when an UBI volume is created, 81162306a36Sopenharmony_ci * removed, re-sized, re-named, or updated. The first argument of the function 81262306a36Sopenharmony_ci * is the notification type. The second argument is pointer to a 81362306a36Sopenharmony_ci * &struct ubi_notification object which describes the notification event. 81462306a36Sopenharmony_ci * Using UBI API from the volume notifier is prohibited. 81562306a36Sopenharmony_ci * 81662306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code 81762306a36Sopenharmony_ci * in case of failure. 81862306a36Sopenharmony_ci */ 81962306a36Sopenharmony_ciint ubi_register_volume_notifier(struct notifier_block *nb, 82062306a36Sopenharmony_ci int ignore_existing) 82162306a36Sopenharmony_ci{ 82262306a36Sopenharmony_ci int err; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci err = blocking_notifier_chain_register(&ubi_notifiers, nb); 82562306a36Sopenharmony_ci if (err != 0) 82662306a36Sopenharmony_ci return err; 82762306a36Sopenharmony_ci if (ignore_existing) 82862306a36Sopenharmony_ci return 0; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* 83162306a36Sopenharmony_ci * We are going to walk all UBI devices and all volumes, and 83262306a36Sopenharmony_ci * notify the user about existing volumes by the %UBI_VOLUME_ADDED 83362306a36Sopenharmony_ci * event. We have to lock the @ubi_devices_mutex to make sure UBI 83462306a36Sopenharmony_ci * devices do not disappear. 83562306a36Sopenharmony_ci */ 83662306a36Sopenharmony_ci mutex_lock(&ubi_devices_mutex); 83762306a36Sopenharmony_ci ubi_enumerate_volumes(nb); 83862306a36Sopenharmony_ci mutex_unlock(&ubi_devices_mutex); 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci return err; 84162306a36Sopenharmony_ci} 84262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_register_volume_notifier); 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci/** 84562306a36Sopenharmony_ci * ubi_unregister_volume_notifier - unregister the volume notifier. 84662306a36Sopenharmony_ci * @nb: the notifier description object 84762306a36Sopenharmony_ci * 84862306a36Sopenharmony_ci * This function unregisters volume notifier @nm and returns zero in case of 84962306a36Sopenharmony_ci * success and a negative error code in case of failure. 85062306a36Sopenharmony_ci */ 85162306a36Sopenharmony_ciint ubi_unregister_volume_notifier(struct notifier_block *nb) 85262306a36Sopenharmony_ci{ 85362306a36Sopenharmony_ci return blocking_notifier_chain_unregister(&ubi_notifiers, nb); 85462306a36Sopenharmony_ci} 85562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(ubi_unregister_volume_notifier); 856