18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 48c2ecf20Sopenharmony_ci * Copyright (c) Nokia Corporation, 2006, 2007 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём) 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci/* 108c2ecf20Sopenharmony_ci * This file includes volume table manipulation code. The volume table is an 118c2ecf20Sopenharmony_ci * on-flash table containing volume meta-data like name, number of reserved 128c2ecf20Sopenharmony_ci * physical eraseblocks, type, etc. The volume table is stored in the so-called 138c2ecf20Sopenharmony_ci * "layout volume". 148c2ecf20Sopenharmony_ci * 158c2ecf20Sopenharmony_ci * The layout volume is an internal volume which is organized as follows. It 168c2ecf20Sopenharmony_ci * consists of two logical eraseblocks - LEB 0 and LEB 1. Each logical 178c2ecf20Sopenharmony_ci * eraseblock stores one volume table copy, i.e. LEB 0 and LEB 1 duplicate each 188c2ecf20Sopenharmony_ci * other. This redundancy guarantees robustness to unclean reboots. The volume 198c2ecf20Sopenharmony_ci * table is basically an array of volume table records. Each record contains 208c2ecf20Sopenharmony_ci * full information about the volume and protected by a CRC checksum. Note, 218c2ecf20Sopenharmony_ci * nowadays we use the atomic LEB change operation when updating the volume 228c2ecf20Sopenharmony_ci * table, so we do not really need 2 LEBs anymore, but we preserve the older 238c2ecf20Sopenharmony_ci * design for the backward compatibility reasons. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * When the volume table is changed, it is first changed in RAM. Then LEB 0 is 268c2ecf20Sopenharmony_ci * erased, and the updated volume table is written back to LEB 0. Then same for 278c2ecf20Sopenharmony_ci * LEB 1. This scheme guarantees recoverability from unclean reboots. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * In this UBI implementation the on-flash volume table does not contain any 308c2ecf20Sopenharmony_ci * information about how much data static volumes contain. 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * But it would still be beneficial to store this information in the volume 338c2ecf20Sopenharmony_ci * table. For example, suppose we have a static volume X, and all its physical 348c2ecf20Sopenharmony_ci * eraseblocks became bad for some reasons. Suppose we are attaching the 358c2ecf20Sopenharmony_ci * corresponding MTD device, for some reason we find no logical eraseblocks 368c2ecf20Sopenharmony_ci * corresponding to the volume X. According to the volume table volume X does 378c2ecf20Sopenharmony_ci * exist. So we don't know whether it is just empty or all its physical 388c2ecf20Sopenharmony_ci * eraseblocks went bad. So we cannot alarm the user properly. 398c2ecf20Sopenharmony_ci * 408c2ecf20Sopenharmony_ci * The volume table also stores so-called "update marker", which is used for 418c2ecf20Sopenharmony_ci * volume updates. Before updating the volume, the update marker is set, and 428c2ecf20Sopenharmony_ci * after the update operation is finished, the update marker is cleared. So if 438c2ecf20Sopenharmony_ci * the update operation was interrupted (e.g. by an unclean reboot) - the 448c2ecf20Sopenharmony_ci * update marker is still there and we know that the volume's contents is 458c2ecf20Sopenharmony_ci * damaged. 468c2ecf20Sopenharmony_ci */ 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#include <linux/crc32.h> 498c2ecf20Sopenharmony_ci#include <linux/err.h> 508c2ecf20Sopenharmony_ci#include <linux/slab.h> 518c2ecf20Sopenharmony_ci#include <asm/div64.h> 528c2ecf20Sopenharmony_ci#include "ubi.h" 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic void self_vtbl_check(const struct ubi_device *ubi); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Empty volume table record */ 578c2ecf20Sopenharmony_cistatic struct ubi_vtbl_record empty_vtbl_record; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/** 608c2ecf20Sopenharmony_ci * ubi_update_layout_vol - helper for updatting layout volumes on flash 618c2ecf20Sopenharmony_ci * @ubi: UBI device description object 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_cistatic int ubi_update_layout_vol(struct ubi_device *ubi) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct ubi_volume *layout_vol; 668c2ecf20Sopenharmony_ci int i, err; 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)]; 698c2ecf20Sopenharmony_ci for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { 708c2ecf20Sopenharmony_ci err = ubi_eba_atomic_leb_change(ubi, layout_vol, i, ubi->vtbl, 718c2ecf20Sopenharmony_ci ubi->vtbl_size); 728c2ecf20Sopenharmony_ci if (err) 738c2ecf20Sopenharmony_ci return err; 748c2ecf20Sopenharmony_ci } 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return 0; 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/** 808c2ecf20Sopenharmony_ci * ubi_change_vtbl_record - change volume table record. 818c2ecf20Sopenharmony_ci * @ubi: UBI device description object 828c2ecf20Sopenharmony_ci * @idx: table index to change 838c2ecf20Sopenharmony_ci * @vtbl_rec: new volume table record 848c2ecf20Sopenharmony_ci * 858c2ecf20Sopenharmony_ci * This function changes volume table record @idx. If @vtbl_rec is %NULL, empty 868c2ecf20Sopenharmony_ci * volume table record is written. The caller does not have to calculate CRC of 878c2ecf20Sopenharmony_ci * the record as it is done by this function. Returns zero in case of success 888c2ecf20Sopenharmony_ci * and a negative error code in case of failure. 898c2ecf20Sopenharmony_ci */ 908c2ecf20Sopenharmony_ciint ubi_change_vtbl_record(struct ubi_device *ubi, int idx, 918c2ecf20Sopenharmony_ci struct ubi_vtbl_record *vtbl_rec) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci int err; 948c2ecf20Sopenharmony_ci uint32_t crc; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci ubi_assert(idx >= 0 && idx < ubi->vtbl_slots); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci if (!vtbl_rec) 998c2ecf20Sopenharmony_ci vtbl_rec = &empty_vtbl_record; 1008c2ecf20Sopenharmony_ci else { 1018c2ecf20Sopenharmony_ci crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC); 1028c2ecf20Sopenharmony_ci vtbl_rec->crc = cpu_to_be32(crc); 1038c2ecf20Sopenharmony_ci } 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record)); 1068c2ecf20Sopenharmony_ci err = ubi_update_layout_vol(ubi); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci self_vtbl_check(ubi); 1098c2ecf20Sopenharmony_ci return err ? err : 0; 1108c2ecf20Sopenharmony_ci} 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/** 1138c2ecf20Sopenharmony_ci * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table. 1148c2ecf20Sopenharmony_ci * @ubi: UBI device description object 1158c2ecf20Sopenharmony_ci * @rename_list: list of &struct ubi_rename_entry objects 1168c2ecf20Sopenharmony_ci * 1178c2ecf20Sopenharmony_ci * This function re-names multiple volumes specified in @req in the volume 1188c2ecf20Sopenharmony_ci * table. Returns zero in case of success and a negative error code in case of 1198c2ecf20Sopenharmony_ci * failure. 1208c2ecf20Sopenharmony_ci */ 1218c2ecf20Sopenharmony_ciint ubi_vtbl_rename_volumes(struct ubi_device *ubi, 1228c2ecf20Sopenharmony_ci struct list_head *rename_list) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct ubi_rename_entry *re; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci list_for_each_entry(re, rename_list, list) { 1278c2ecf20Sopenharmony_ci uint32_t crc; 1288c2ecf20Sopenharmony_ci struct ubi_volume *vol = re->desc->vol; 1298c2ecf20Sopenharmony_ci struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id]; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci if (re->remove) { 1328c2ecf20Sopenharmony_ci memcpy(vtbl_rec, &empty_vtbl_record, 1338c2ecf20Sopenharmony_ci sizeof(struct ubi_vtbl_record)); 1348c2ecf20Sopenharmony_ci continue; 1358c2ecf20Sopenharmony_ci } 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci vtbl_rec->name_len = cpu_to_be16(re->new_name_len); 1388c2ecf20Sopenharmony_ci memcpy(vtbl_rec->name, re->new_name, re->new_name_len); 1398c2ecf20Sopenharmony_ci memset(vtbl_rec->name + re->new_name_len, 0, 1408c2ecf20Sopenharmony_ci UBI_VOL_NAME_MAX + 1 - re->new_name_len); 1418c2ecf20Sopenharmony_ci crc = crc32(UBI_CRC32_INIT, vtbl_rec, 1428c2ecf20Sopenharmony_ci UBI_VTBL_RECORD_SIZE_CRC); 1438c2ecf20Sopenharmony_ci vtbl_rec->crc = cpu_to_be32(crc); 1448c2ecf20Sopenharmony_ci } 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci return ubi_update_layout_vol(ubi); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/** 1508c2ecf20Sopenharmony_ci * vtbl_check - check if volume table is not corrupted and sensible. 1518c2ecf20Sopenharmony_ci * @ubi: UBI device description object 1528c2ecf20Sopenharmony_ci * @vtbl: volume table 1538c2ecf20Sopenharmony_ci * 1548c2ecf20Sopenharmony_ci * This function returns zero if @vtbl is all right, %1 if CRC is incorrect, 1558c2ecf20Sopenharmony_ci * and %-EINVAL if it contains inconsistent data. 1568c2ecf20Sopenharmony_ci */ 1578c2ecf20Sopenharmony_cistatic int vtbl_check(const struct ubi_device *ubi, 1588c2ecf20Sopenharmony_ci const struct ubi_vtbl_record *vtbl) 1598c2ecf20Sopenharmony_ci{ 1608c2ecf20Sopenharmony_ci int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len; 1618c2ecf20Sopenharmony_ci int upd_marker, err; 1628c2ecf20Sopenharmony_ci uint32_t crc; 1638c2ecf20Sopenharmony_ci const char *name; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) { 1668c2ecf20Sopenharmony_ci cond_resched(); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); 1698c2ecf20Sopenharmony_ci alignment = be32_to_cpu(vtbl[i].alignment); 1708c2ecf20Sopenharmony_ci data_pad = be32_to_cpu(vtbl[i].data_pad); 1718c2ecf20Sopenharmony_ci upd_marker = vtbl[i].upd_marker; 1728c2ecf20Sopenharmony_ci vol_type = vtbl[i].vol_type; 1738c2ecf20Sopenharmony_ci name_len = be16_to_cpu(vtbl[i].name_len); 1748c2ecf20Sopenharmony_ci name = &vtbl[i].name[0]; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC); 1778c2ecf20Sopenharmony_ci if (be32_to_cpu(vtbl[i].crc) != crc) { 1788c2ecf20Sopenharmony_ci ubi_err(ubi, "bad CRC at record %u: %#08x, not %#08x", 1798c2ecf20Sopenharmony_ci i, crc, be32_to_cpu(vtbl[i].crc)); 1808c2ecf20Sopenharmony_ci ubi_dump_vtbl_record(&vtbl[i], i); 1818c2ecf20Sopenharmony_ci return 1; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if (reserved_pebs == 0) { 1858c2ecf20Sopenharmony_ci if (memcmp(&vtbl[i], &empty_vtbl_record, 1868c2ecf20Sopenharmony_ci UBI_VTBL_RECORD_SIZE)) { 1878c2ecf20Sopenharmony_ci err = 2; 1888c2ecf20Sopenharmony_ci goto bad; 1898c2ecf20Sopenharmony_ci } 1908c2ecf20Sopenharmony_ci continue; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 || 1948c2ecf20Sopenharmony_ci name_len < 0) { 1958c2ecf20Sopenharmony_ci err = 3; 1968c2ecf20Sopenharmony_ci goto bad; 1978c2ecf20Sopenharmony_ci } 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci if (alignment > ubi->leb_size || alignment == 0) { 2008c2ecf20Sopenharmony_ci err = 4; 2018c2ecf20Sopenharmony_ci goto bad; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci n = alignment & (ubi->min_io_size - 1); 2058c2ecf20Sopenharmony_ci if (alignment != 1 && n) { 2068c2ecf20Sopenharmony_ci err = 5; 2078c2ecf20Sopenharmony_ci goto bad; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci n = ubi->leb_size % alignment; 2118c2ecf20Sopenharmony_ci if (data_pad != n) { 2128c2ecf20Sopenharmony_ci ubi_err(ubi, "bad data_pad, has to be %d", n); 2138c2ecf20Sopenharmony_ci err = 6; 2148c2ecf20Sopenharmony_ci goto bad; 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { 2188c2ecf20Sopenharmony_ci err = 7; 2198c2ecf20Sopenharmony_ci goto bad; 2208c2ecf20Sopenharmony_ci } 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci if (upd_marker != 0 && upd_marker != 1) { 2238c2ecf20Sopenharmony_ci err = 8; 2248c2ecf20Sopenharmony_ci goto bad; 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if (reserved_pebs > ubi->good_peb_count) { 2288c2ecf20Sopenharmony_ci ubi_err(ubi, "too large reserved_pebs %d, good PEBs %d", 2298c2ecf20Sopenharmony_ci reserved_pebs, ubi->good_peb_count); 2308c2ecf20Sopenharmony_ci err = 9; 2318c2ecf20Sopenharmony_ci goto bad; 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (name_len > UBI_VOL_NAME_MAX) { 2358c2ecf20Sopenharmony_ci err = 10; 2368c2ecf20Sopenharmony_ci goto bad; 2378c2ecf20Sopenharmony_ci } 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (name[0] == '\0') { 2408c2ecf20Sopenharmony_ci err = 11; 2418c2ecf20Sopenharmony_ci goto bad; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci if (name_len != strnlen(name, name_len + 1)) { 2458c2ecf20Sopenharmony_ci err = 12; 2468c2ecf20Sopenharmony_ci goto bad; 2478c2ecf20Sopenharmony_ci } 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Checks that all names are unique */ 2518c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots - 1; i++) { 2528c2ecf20Sopenharmony_ci for (n = i + 1; n < ubi->vtbl_slots; n++) { 2538c2ecf20Sopenharmony_ci int len1 = be16_to_cpu(vtbl[i].name_len); 2548c2ecf20Sopenharmony_ci int len2 = be16_to_cpu(vtbl[n].name_len); 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci if (len1 > 0 && len1 == len2 && 2578c2ecf20Sopenharmony_ci !strncmp(vtbl[i].name, vtbl[n].name, len1)) { 2588c2ecf20Sopenharmony_ci ubi_err(ubi, "volumes %d and %d have the same name \"%s\"", 2598c2ecf20Sopenharmony_ci i, n, vtbl[i].name); 2608c2ecf20Sopenharmony_ci ubi_dump_vtbl_record(&vtbl[i], i); 2618c2ecf20Sopenharmony_ci ubi_dump_vtbl_record(&vtbl[n], n); 2628c2ecf20Sopenharmony_ci return -EINVAL; 2638c2ecf20Sopenharmony_ci } 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cibad: 2708c2ecf20Sopenharmony_ci ubi_err(ubi, "volume table check failed: record %d, error %d", i, err); 2718c2ecf20Sopenharmony_ci ubi_dump_vtbl_record(&vtbl[i], i); 2728c2ecf20Sopenharmony_ci return -EINVAL; 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci/** 2768c2ecf20Sopenharmony_ci * create_vtbl - create a copy of volume table. 2778c2ecf20Sopenharmony_ci * @ubi: UBI device description object 2788c2ecf20Sopenharmony_ci * @ai: attaching information 2798c2ecf20Sopenharmony_ci * @copy: number of the volume table copy 2808c2ecf20Sopenharmony_ci * @vtbl: contents of the volume table 2818c2ecf20Sopenharmony_ci * 2828c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in 2838c2ecf20Sopenharmony_ci * case of failure. 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_cistatic int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, 2868c2ecf20Sopenharmony_ci int copy, void *vtbl) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci int err, tries = 0; 2898c2ecf20Sopenharmony_ci struct ubi_vid_io_buf *vidb; 2908c2ecf20Sopenharmony_ci struct ubi_vid_hdr *vid_hdr; 2918c2ecf20Sopenharmony_ci struct ubi_ainf_peb *new_aeb; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci dbg_gen("create volume table (copy #%d)", copy + 1); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); 2968c2ecf20Sopenharmony_ci if (!vidb) 2978c2ecf20Sopenharmony_ci return -ENOMEM; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci vid_hdr = ubi_get_vid_hdr(vidb); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ciretry: 3028c2ecf20Sopenharmony_ci new_aeb = ubi_early_get_peb(ubi, ai); 3038c2ecf20Sopenharmony_ci if (IS_ERR(new_aeb)) { 3048c2ecf20Sopenharmony_ci err = PTR_ERR(new_aeb); 3058c2ecf20Sopenharmony_ci goto out_free; 3068c2ecf20Sopenharmony_ci } 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci vid_hdr->vol_type = UBI_LAYOUT_VOLUME_TYPE; 3098c2ecf20Sopenharmony_ci vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID); 3108c2ecf20Sopenharmony_ci vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT; 3118c2ecf20Sopenharmony_ci vid_hdr->data_size = vid_hdr->used_ebs = 3128c2ecf20Sopenharmony_ci vid_hdr->data_pad = cpu_to_be32(0); 3138c2ecf20Sopenharmony_ci vid_hdr->lnum = cpu_to_be32(copy); 3148c2ecf20Sopenharmony_ci vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum); 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci /* The EC header is already there, write the VID header */ 3178c2ecf20Sopenharmony_ci err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vidb); 3188c2ecf20Sopenharmony_ci if (err) 3198c2ecf20Sopenharmony_ci goto write_error; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci /* Write the layout volume contents */ 3228c2ecf20Sopenharmony_ci err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size); 3238c2ecf20Sopenharmony_ci if (err) 3248c2ecf20Sopenharmony_ci goto write_error; 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci /* 3278c2ecf20Sopenharmony_ci * And add it to the attaching information. Don't delete the old version 3288c2ecf20Sopenharmony_ci * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'. 3298c2ecf20Sopenharmony_ci */ 3308c2ecf20Sopenharmony_ci err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); 3318c2ecf20Sopenharmony_ci ubi_free_aeb(ai, new_aeb); 3328c2ecf20Sopenharmony_ci ubi_free_vid_buf(vidb); 3338c2ecf20Sopenharmony_ci return err; 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ciwrite_error: 3368c2ecf20Sopenharmony_ci if (err == -EIO && ++tries <= 5) { 3378c2ecf20Sopenharmony_ci /* 3388c2ecf20Sopenharmony_ci * Probably this physical eraseblock went bad, try to pick 3398c2ecf20Sopenharmony_ci * another one. 3408c2ecf20Sopenharmony_ci */ 3418c2ecf20Sopenharmony_ci list_add(&new_aeb->u.list, &ai->erase); 3428c2ecf20Sopenharmony_ci goto retry; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci ubi_free_aeb(ai, new_aeb); 3458c2ecf20Sopenharmony_ciout_free: 3468c2ecf20Sopenharmony_ci ubi_free_vid_buf(vidb); 3478c2ecf20Sopenharmony_ci return err; 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci/** 3528c2ecf20Sopenharmony_ci * process_lvol - process the layout volume. 3538c2ecf20Sopenharmony_ci * @ubi: UBI device description object 3548c2ecf20Sopenharmony_ci * @ai: attaching information 3558c2ecf20Sopenharmony_ci * @av: layout volume attaching information 3568c2ecf20Sopenharmony_ci * 3578c2ecf20Sopenharmony_ci * This function is responsible for reading the layout volume, ensuring it is 3588c2ecf20Sopenharmony_ci * not corrupted, and recovering from corruptions if needed. Returns volume 3598c2ecf20Sopenharmony_ci * table in case of success and a negative error code in case of failure. 3608c2ecf20Sopenharmony_ci */ 3618c2ecf20Sopenharmony_cistatic struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, 3628c2ecf20Sopenharmony_ci struct ubi_attach_info *ai, 3638c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av) 3648c2ecf20Sopenharmony_ci{ 3658c2ecf20Sopenharmony_ci int err; 3668c2ecf20Sopenharmony_ci struct rb_node *rb; 3678c2ecf20Sopenharmony_ci struct ubi_ainf_peb *aeb; 3688c2ecf20Sopenharmony_ci struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL }; 3698c2ecf20Sopenharmony_ci int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1}; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci /* 3728c2ecf20Sopenharmony_ci * UBI goes through the following steps when it changes the layout 3738c2ecf20Sopenharmony_ci * volume: 3748c2ecf20Sopenharmony_ci * a. erase LEB 0; 3758c2ecf20Sopenharmony_ci * b. write new data to LEB 0; 3768c2ecf20Sopenharmony_ci * c. erase LEB 1; 3778c2ecf20Sopenharmony_ci * d. write new data to LEB 1. 3788c2ecf20Sopenharmony_ci * 3798c2ecf20Sopenharmony_ci * Before the change, both LEBs contain the same data. 3808c2ecf20Sopenharmony_ci * 3818c2ecf20Sopenharmony_ci * Due to unclean reboots, the contents of LEB 0 may be lost, but there 3828c2ecf20Sopenharmony_ci * should LEB 1. So it is OK if LEB 0 is corrupted while LEB 1 is not. 3838c2ecf20Sopenharmony_ci * Similarly, LEB 1 may be lost, but there should be LEB 0. And 3848c2ecf20Sopenharmony_ci * finally, unclean reboots may result in a situation when neither LEB 3858c2ecf20Sopenharmony_ci * 0 nor LEB 1 are corrupted, but they are different. In this case, LEB 3868c2ecf20Sopenharmony_ci * 0 contains more recent information. 3878c2ecf20Sopenharmony_ci * 3888c2ecf20Sopenharmony_ci * So the plan is to first check LEB 0. Then 3898c2ecf20Sopenharmony_ci * a. if LEB 0 is OK, it must be containing the most recent data; then 3908c2ecf20Sopenharmony_ci * we compare it with LEB 1, and if they are different, we copy LEB 3918c2ecf20Sopenharmony_ci * 0 to LEB 1; 3928c2ecf20Sopenharmony_ci * b. if LEB 0 is corrupted, but LEB 1 has to be OK, and we copy LEB 1 3938c2ecf20Sopenharmony_ci * to LEB 0. 3948c2ecf20Sopenharmony_ci */ 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci dbg_gen("check layout volume"); 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci /* Read both LEB 0 and LEB 1 into memory */ 3998c2ecf20Sopenharmony_ci ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) { 4008c2ecf20Sopenharmony_ci leb[aeb->lnum] = vzalloc(ubi->vtbl_size); 4018c2ecf20Sopenharmony_ci if (!leb[aeb->lnum]) { 4028c2ecf20Sopenharmony_ci err = -ENOMEM; 4038c2ecf20Sopenharmony_ci goto out_free; 4048c2ecf20Sopenharmony_ci } 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0, 4078c2ecf20Sopenharmony_ci ubi->vtbl_size); 4088c2ecf20Sopenharmony_ci if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) 4098c2ecf20Sopenharmony_ci /* 4108c2ecf20Sopenharmony_ci * Scrub the PEB later. Note, -EBADMSG indicates an 4118c2ecf20Sopenharmony_ci * uncorrectable ECC error, but we have our own CRC and 4128c2ecf20Sopenharmony_ci * the data will be checked later. If the data is OK, 4138c2ecf20Sopenharmony_ci * the PEB will be scrubbed (because we set 4148c2ecf20Sopenharmony_ci * aeb->scrub). If the data is not OK, the contents of 4158c2ecf20Sopenharmony_ci * the PEB will be recovered from the second copy, and 4168c2ecf20Sopenharmony_ci * aeb->scrub will be cleared in 4178c2ecf20Sopenharmony_ci * 'ubi_add_to_av()'. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_ci aeb->scrub = 1; 4208c2ecf20Sopenharmony_ci else if (err) 4218c2ecf20Sopenharmony_ci goto out_free; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci err = -EINVAL; 4258c2ecf20Sopenharmony_ci if (leb[0]) { 4268c2ecf20Sopenharmony_ci leb_corrupted[0] = vtbl_check(ubi, leb[0]); 4278c2ecf20Sopenharmony_ci if (leb_corrupted[0] < 0) 4288c2ecf20Sopenharmony_ci goto out_free; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci if (!leb_corrupted[0]) { 4328c2ecf20Sopenharmony_ci /* LEB 0 is OK */ 4338c2ecf20Sopenharmony_ci if (leb[1]) 4348c2ecf20Sopenharmony_ci leb_corrupted[1] = memcmp(leb[0], leb[1], 4358c2ecf20Sopenharmony_ci ubi->vtbl_size); 4368c2ecf20Sopenharmony_ci if (leb_corrupted[1]) { 4378c2ecf20Sopenharmony_ci ubi_warn(ubi, "volume table copy #2 is corrupted"); 4388c2ecf20Sopenharmony_ci err = create_vtbl(ubi, ai, 1, leb[0]); 4398c2ecf20Sopenharmony_ci if (err) 4408c2ecf20Sopenharmony_ci goto out_free; 4418c2ecf20Sopenharmony_ci ubi_msg(ubi, "volume table was restored"); 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci /* Both LEB 1 and LEB 2 are OK and consistent */ 4458c2ecf20Sopenharmony_ci vfree(leb[1]); 4468c2ecf20Sopenharmony_ci return leb[0]; 4478c2ecf20Sopenharmony_ci } else { 4488c2ecf20Sopenharmony_ci /* LEB 0 is corrupted or does not exist */ 4498c2ecf20Sopenharmony_ci if (leb[1]) { 4508c2ecf20Sopenharmony_ci leb_corrupted[1] = vtbl_check(ubi, leb[1]); 4518c2ecf20Sopenharmony_ci if (leb_corrupted[1] < 0) 4528c2ecf20Sopenharmony_ci goto out_free; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci if (leb_corrupted[1]) { 4558c2ecf20Sopenharmony_ci /* Both LEB 0 and LEB 1 are corrupted */ 4568c2ecf20Sopenharmony_ci ubi_err(ubi, "both volume tables are corrupted"); 4578c2ecf20Sopenharmony_ci goto out_free; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci ubi_warn(ubi, "volume table copy #1 is corrupted"); 4618c2ecf20Sopenharmony_ci err = create_vtbl(ubi, ai, 0, leb[1]); 4628c2ecf20Sopenharmony_ci if (err) 4638c2ecf20Sopenharmony_ci goto out_free; 4648c2ecf20Sopenharmony_ci ubi_msg(ubi, "volume table was restored"); 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ci vfree(leb[0]); 4678c2ecf20Sopenharmony_ci return leb[1]; 4688c2ecf20Sopenharmony_ci } 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ciout_free: 4718c2ecf20Sopenharmony_ci vfree(leb[0]); 4728c2ecf20Sopenharmony_ci vfree(leb[1]); 4738c2ecf20Sopenharmony_ci return ERR_PTR(err); 4748c2ecf20Sopenharmony_ci} 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ci/** 4778c2ecf20Sopenharmony_ci * create_empty_lvol - create empty layout volume. 4788c2ecf20Sopenharmony_ci * @ubi: UBI device description object 4798c2ecf20Sopenharmony_ci * @ai: attaching information 4808c2ecf20Sopenharmony_ci * 4818c2ecf20Sopenharmony_ci * This function returns volume table contents in case of success and a 4828c2ecf20Sopenharmony_ci * negative error code in case of failure. 4838c2ecf20Sopenharmony_ci */ 4848c2ecf20Sopenharmony_cistatic struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, 4858c2ecf20Sopenharmony_ci struct ubi_attach_info *ai) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci int i; 4888c2ecf20Sopenharmony_ci struct ubi_vtbl_record *vtbl; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci vtbl = vzalloc(ubi->vtbl_size); 4918c2ecf20Sopenharmony_ci if (!vtbl) 4928c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4938c2ecf20Sopenharmony_ci 4948c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) 4958c2ecf20Sopenharmony_ci memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE); 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { 4988c2ecf20Sopenharmony_ci int err; 4998c2ecf20Sopenharmony_ci 5008c2ecf20Sopenharmony_ci err = create_vtbl(ubi, ai, i, vtbl); 5018c2ecf20Sopenharmony_ci if (err) { 5028c2ecf20Sopenharmony_ci vfree(vtbl); 5038c2ecf20Sopenharmony_ci return ERR_PTR(err); 5048c2ecf20Sopenharmony_ci } 5058c2ecf20Sopenharmony_ci } 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci return vtbl; 5088c2ecf20Sopenharmony_ci} 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci/** 5118c2ecf20Sopenharmony_ci * init_volumes - initialize volume information for existing volumes. 5128c2ecf20Sopenharmony_ci * @ubi: UBI device description object 5138c2ecf20Sopenharmony_ci * @ai: scanning information 5148c2ecf20Sopenharmony_ci * @vtbl: volume table 5158c2ecf20Sopenharmony_ci * 5168c2ecf20Sopenharmony_ci * This function allocates volume description objects for existing volumes. 5178c2ecf20Sopenharmony_ci * Returns zero in case of success and a negative error code in case of 5188c2ecf20Sopenharmony_ci * failure. 5198c2ecf20Sopenharmony_ci */ 5208c2ecf20Sopenharmony_cistatic int init_volumes(struct ubi_device *ubi, 5218c2ecf20Sopenharmony_ci const struct ubi_attach_info *ai, 5228c2ecf20Sopenharmony_ci const struct ubi_vtbl_record *vtbl) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci int i, err, reserved_pebs = 0; 5258c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 5268c2ecf20Sopenharmony_ci struct ubi_volume *vol; 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) { 5298c2ecf20Sopenharmony_ci cond_resched(); 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_ci if (be32_to_cpu(vtbl[i].reserved_pebs) == 0) 5328c2ecf20Sopenharmony_ci continue; /* Empty record */ 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); 5358c2ecf20Sopenharmony_ci if (!vol) 5368c2ecf20Sopenharmony_ci return -ENOMEM; 5378c2ecf20Sopenharmony_ci 5388c2ecf20Sopenharmony_ci vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs); 5398c2ecf20Sopenharmony_ci vol->alignment = be32_to_cpu(vtbl[i].alignment); 5408c2ecf20Sopenharmony_ci vol->data_pad = be32_to_cpu(vtbl[i].data_pad); 5418c2ecf20Sopenharmony_ci vol->upd_marker = vtbl[i].upd_marker; 5428c2ecf20Sopenharmony_ci vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ? 5438c2ecf20Sopenharmony_ci UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; 5448c2ecf20Sopenharmony_ci vol->name_len = be16_to_cpu(vtbl[i].name_len); 5458c2ecf20Sopenharmony_ci vol->usable_leb_size = ubi->leb_size - vol->data_pad; 5468c2ecf20Sopenharmony_ci memcpy(vol->name, vtbl[i].name, vol->name_len); 5478c2ecf20Sopenharmony_ci vol->name[vol->name_len] = '\0'; 5488c2ecf20Sopenharmony_ci vol->vol_id = i; 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (vtbl[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG) 5518c2ecf20Sopenharmony_ci vol->skip_check = 1; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) { 5548c2ecf20Sopenharmony_ci /* Auto re-size flag may be set only for one volume */ 5558c2ecf20Sopenharmony_ci if (ubi->autoresize_vol_id != -1) { 5568c2ecf20Sopenharmony_ci ubi_err(ubi, "more than one auto-resize volume (%d and %d)", 5578c2ecf20Sopenharmony_ci ubi->autoresize_vol_id, i); 5588c2ecf20Sopenharmony_ci kfree(vol); 5598c2ecf20Sopenharmony_ci return -EINVAL; 5608c2ecf20Sopenharmony_ci } 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci ubi->autoresize_vol_id = i; 5638c2ecf20Sopenharmony_ci } 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci ubi_assert(!ubi->volumes[i]); 5668c2ecf20Sopenharmony_ci ubi->volumes[i] = vol; 5678c2ecf20Sopenharmony_ci ubi->vol_count += 1; 5688c2ecf20Sopenharmony_ci vol->ubi = ubi; 5698c2ecf20Sopenharmony_ci reserved_pebs += vol->reserved_pebs; 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci /* 5728c2ecf20Sopenharmony_ci * We use ubi->peb_count and not vol->reserved_pebs because 5738c2ecf20Sopenharmony_ci * we want to keep the code simple. Otherwise we'd have to 5748c2ecf20Sopenharmony_ci * resize/check the bitmap upon volume resize too. 5758c2ecf20Sopenharmony_ci * Allocating a few bytes more does not hurt. 5768c2ecf20Sopenharmony_ci */ 5778c2ecf20Sopenharmony_ci err = ubi_fastmap_init_checkmap(vol, ubi->peb_count); 5788c2ecf20Sopenharmony_ci if (err) 5798c2ecf20Sopenharmony_ci return err; 5808c2ecf20Sopenharmony_ci 5818c2ecf20Sopenharmony_ci /* 5828c2ecf20Sopenharmony_ci * In case of dynamic volume UBI knows nothing about how many 5838c2ecf20Sopenharmony_ci * data is stored there. So assume the whole volume is used. 5848c2ecf20Sopenharmony_ci */ 5858c2ecf20Sopenharmony_ci if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 5868c2ecf20Sopenharmony_ci vol->used_ebs = vol->reserved_pebs; 5878c2ecf20Sopenharmony_ci vol->last_eb_bytes = vol->usable_leb_size; 5888c2ecf20Sopenharmony_ci vol->used_bytes = 5898c2ecf20Sopenharmony_ci (long long)vol->used_ebs * vol->usable_leb_size; 5908c2ecf20Sopenharmony_ci continue; 5918c2ecf20Sopenharmony_ci } 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_ci /* Static volumes only */ 5948c2ecf20Sopenharmony_ci av = ubi_find_av(ai, i); 5958c2ecf20Sopenharmony_ci if (!av || !av->leb_count) { 5968c2ecf20Sopenharmony_ci /* 5978c2ecf20Sopenharmony_ci * No eraseblocks belonging to this volume found. We 5988c2ecf20Sopenharmony_ci * don't actually know whether this static volume is 5998c2ecf20Sopenharmony_ci * completely corrupted or just contains no data. And 6008c2ecf20Sopenharmony_ci * we cannot know this as long as data size is not 6018c2ecf20Sopenharmony_ci * stored on flash. So we just assume the volume is 6028c2ecf20Sopenharmony_ci * empty. FIXME: this should be handled. 6038c2ecf20Sopenharmony_ci */ 6048c2ecf20Sopenharmony_ci continue; 6058c2ecf20Sopenharmony_ci } 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci if (av->leb_count != av->used_ebs) { 6088c2ecf20Sopenharmony_ci /* 6098c2ecf20Sopenharmony_ci * We found a static volume which misses several 6108c2ecf20Sopenharmony_ci * eraseblocks. Treat it as corrupted. 6118c2ecf20Sopenharmony_ci */ 6128c2ecf20Sopenharmony_ci ubi_warn(ubi, "static volume %d misses %d LEBs - corrupted", 6138c2ecf20Sopenharmony_ci av->vol_id, av->used_ebs - av->leb_count); 6148c2ecf20Sopenharmony_ci vol->corrupted = 1; 6158c2ecf20Sopenharmony_ci continue; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci vol->used_ebs = av->used_ebs; 6198c2ecf20Sopenharmony_ci vol->used_bytes = 6208c2ecf20Sopenharmony_ci (long long)(vol->used_ebs - 1) * vol->usable_leb_size; 6218c2ecf20Sopenharmony_ci vol->used_bytes += av->last_data_size; 6228c2ecf20Sopenharmony_ci vol->last_eb_bytes = av->last_data_size; 6238c2ecf20Sopenharmony_ci } 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci /* And add the layout volume */ 6268c2ecf20Sopenharmony_ci vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); 6278c2ecf20Sopenharmony_ci if (!vol) 6288c2ecf20Sopenharmony_ci return -ENOMEM; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci vol->reserved_pebs = UBI_LAYOUT_VOLUME_EBS; 6318c2ecf20Sopenharmony_ci vol->alignment = UBI_LAYOUT_VOLUME_ALIGN; 6328c2ecf20Sopenharmony_ci vol->vol_type = UBI_DYNAMIC_VOLUME; 6338c2ecf20Sopenharmony_ci vol->name_len = sizeof(UBI_LAYOUT_VOLUME_NAME) - 1; 6348c2ecf20Sopenharmony_ci memcpy(vol->name, UBI_LAYOUT_VOLUME_NAME, vol->name_len + 1); 6358c2ecf20Sopenharmony_ci vol->usable_leb_size = ubi->leb_size; 6368c2ecf20Sopenharmony_ci vol->used_ebs = vol->reserved_pebs; 6378c2ecf20Sopenharmony_ci vol->last_eb_bytes = vol->reserved_pebs; 6388c2ecf20Sopenharmony_ci vol->used_bytes = 6398c2ecf20Sopenharmony_ci (long long)vol->used_ebs * (ubi->leb_size - vol->data_pad); 6408c2ecf20Sopenharmony_ci vol->vol_id = UBI_LAYOUT_VOLUME_ID; 6418c2ecf20Sopenharmony_ci vol->ref_count = 1; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci ubi_assert(!ubi->volumes[i]); 6448c2ecf20Sopenharmony_ci ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol; 6458c2ecf20Sopenharmony_ci reserved_pebs += vol->reserved_pebs; 6468c2ecf20Sopenharmony_ci ubi->vol_count += 1; 6478c2ecf20Sopenharmony_ci vol->ubi = ubi; 6488c2ecf20Sopenharmony_ci err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS); 6498c2ecf20Sopenharmony_ci if (err) 6508c2ecf20Sopenharmony_ci return err; 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (reserved_pebs > ubi->avail_pebs) { 6538c2ecf20Sopenharmony_ci ubi_err(ubi, "not enough PEBs, required %d, available %d", 6548c2ecf20Sopenharmony_ci reserved_pebs, ubi->avail_pebs); 6558c2ecf20Sopenharmony_ci if (ubi->corr_peb_count) 6568c2ecf20Sopenharmony_ci ubi_err(ubi, "%d PEBs are corrupted and not used", 6578c2ecf20Sopenharmony_ci ubi->corr_peb_count); 6588c2ecf20Sopenharmony_ci return -ENOSPC; 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci ubi->rsvd_pebs += reserved_pebs; 6618c2ecf20Sopenharmony_ci ubi->avail_pebs -= reserved_pebs; 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci return 0; 6648c2ecf20Sopenharmony_ci} 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci/** 6678c2ecf20Sopenharmony_ci * check_av - check volume attaching information. 6688c2ecf20Sopenharmony_ci * @vol: UBI volume description object 6698c2ecf20Sopenharmony_ci * @av: volume attaching information 6708c2ecf20Sopenharmony_ci * 6718c2ecf20Sopenharmony_ci * This function returns zero if the volume attaching information is consistent 6728c2ecf20Sopenharmony_ci * to the data read from the volume tabla, and %-EINVAL if not. 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_cistatic int check_av(const struct ubi_volume *vol, 6758c2ecf20Sopenharmony_ci const struct ubi_ainf_volume *av) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci int err; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci if (av->highest_lnum >= vol->reserved_pebs) { 6808c2ecf20Sopenharmony_ci err = 1; 6818c2ecf20Sopenharmony_ci goto bad; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ci if (av->leb_count > vol->reserved_pebs) { 6848c2ecf20Sopenharmony_ci err = 2; 6858c2ecf20Sopenharmony_ci goto bad; 6868c2ecf20Sopenharmony_ci } 6878c2ecf20Sopenharmony_ci if (av->vol_type != vol->vol_type) { 6888c2ecf20Sopenharmony_ci err = 3; 6898c2ecf20Sopenharmony_ci goto bad; 6908c2ecf20Sopenharmony_ci } 6918c2ecf20Sopenharmony_ci if (av->used_ebs > vol->reserved_pebs) { 6928c2ecf20Sopenharmony_ci err = 4; 6938c2ecf20Sopenharmony_ci goto bad; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci if (av->data_pad != vol->data_pad) { 6968c2ecf20Sopenharmony_ci err = 5; 6978c2ecf20Sopenharmony_ci goto bad; 6988c2ecf20Sopenharmony_ci } 6998c2ecf20Sopenharmony_ci return 0; 7008c2ecf20Sopenharmony_ci 7018c2ecf20Sopenharmony_cibad: 7028c2ecf20Sopenharmony_ci ubi_err(vol->ubi, "bad attaching information, error %d", err); 7038c2ecf20Sopenharmony_ci ubi_dump_av(av); 7048c2ecf20Sopenharmony_ci ubi_dump_vol_info(vol); 7058c2ecf20Sopenharmony_ci return -EINVAL; 7068c2ecf20Sopenharmony_ci} 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci/** 7098c2ecf20Sopenharmony_ci * check_attaching_info - check that attaching information. 7108c2ecf20Sopenharmony_ci * @ubi: UBI device description object 7118c2ecf20Sopenharmony_ci * @ai: attaching information 7128c2ecf20Sopenharmony_ci * 7138c2ecf20Sopenharmony_ci * Even though we protect on-flash data by CRC checksums, we still don't trust 7148c2ecf20Sopenharmony_ci * the media. This function ensures that attaching information is consistent to 7158c2ecf20Sopenharmony_ci * the information read from the volume table. Returns zero if the attaching 7168c2ecf20Sopenharmony_ci * information is OK and %-EINVAL if it is not. 7178c2ecf20Sopenharmony_ci */ 7188c2ecf20Sopenharmony_cistatic int check_attaching_info(const struct ubi_device *ubi, 7198c2ecf20Sopenharmony_ci struct ubi_attach_info *ai) 7208c2ecf20Sopenharmony_ci{ 7218c2ecf20Sopenharmony_ci int err, i; 7228c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 7238c2ecf20Sopenharmony_ci struct ubi_volume *vol; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) { 7268c2ecf20Sopenharmony_ci ubi_err(ubi, "found %d volumes while attaching, maximum is %d + %d", 7278c2ecf20Sopenharmony_ci ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots); 7288c2ecf20Sopenharmony_ci return -EINVAL; 7298c2ecf20Sopenharmony_ci } 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && 7328c2ecf20Sopenharmony_ci ai->highest_vol_id < UBI_INTERNAL_VOL_START) { 7338c2ecf20Sopenharmony_ci ubi_err(ubi, "too large volume ID %d found", 7348c2ecf20Sopenharmony_ci ai->highest_vol_id); 7358c2ecf20Sopenharmony_ci return -EINVAL; 7368c2ecf20Sopenharmony_ci } 7378c2ecf20Sopenharmony_ci 7388c2ecf20Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { 7398c2ecf20Sopenharmony_ci cond_resched(); 7408c2ecf20Sopenharmony_ci 7418c2ecf20Sopenharmony_ci av = ubi_find_av(ai, i); 7428c2ecf20Sopenharmony_ci vol = ubi->volumes[i]; 7438c2ecf20Sopenharmony_ci if (!vol) { 7448c2ecf20Sopenharmony_ci if (av) 7458c2ecf20Sopenharmony_ci ubi_remove_av(ai, av); 7468c2ecf20Sopenharmony_ci continue; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci if (vol->reserved_pebs == 0) { 7508c2ecf20Sopenharmony_ci ubi_assert(i < ubi->vtbl_slots); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci if (!av) 7538c2ecf20Sopenharmony_ci continue; 7548c2ecf20Sopenharmony_ci 7558c2ecf20Sopenharmony_ci /* 7568c2ecf20Sopenharmony_ci * During attaching we found a volume which does not 7578c2ecf20Sopenharmony_ci * exist according to the information in the volume 7588c2ecf20Sopenharmony_ci * table. This must have happened due to an unclean 7598c2ecf20Sopenharmony_ci * reboot while the volume was being removed. Discard 7608c2ecf20Sopenharmony_ci * these eraseblocks. 7618c2ecf20Sopenharmony_ci */ 7628c2ecf20Sopenharmony_ci ubi_msg(ubi, "finish volume %d removal", av->vol_id); 7638c2ecf20Sopenharmony_ci ubi_remove_av(ai, av); 7648c2ecf20Sopenharmony_ci } else if (av) { 7658c2ecf20Sopenharmony_ci err = check_av(vol, av); 7668c2ecf20Sopenharmony_ci if (err) 7678c2ecf20Sopenharmony_ci return err; 7688c2ecf20Sopenharmony_ci } 7698c2ecf20Sopenharmony_ci } 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci return 0; 7728c2ecf20Sopenharmony_ci} 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci/** 7758c2ecf20Sopenharmony_ci * ubi_read_volume_table - read the volume table. 7768c2ecf20Sopenharmony_ci * @ubi: UBI device description object 7778c2ecf20Sopenharmony_ci * @ai: attaching information 7788c2ecf20Sopenharmony_ci * 7798c2ecf20Sopenharmony_ci * This function reads volume table, checks it, recover from errors if needed, 7808c2ecf20Sopenharmony_ci * or creates it if needed. Returns zero in case of success and a negative 7818c2ecf20Sopenharmony_ci * error code in case of failure. 7828c2ecf20Sopenharmony_ci */ 7838c2ecf20Sopenharmony_ciint ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) 7848c2ecf20Sopenharmony_ci{ 7858c2ecf20Sopenharmony_ci int err; 7868c2ecf20Sopenharmony_ci struct ubi_ainf_volume *av; 7878c2ecf20Sopenharmony_ci 7888c2ecf20Sopenharmony_ci empty_vtbl_record.crc = cpu_to_be32(0xf116c36b); 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci /* 7918c2ecf20Sopenharmony_ci * The number of supported volumes is limited by the eraseblock size 7928c2ecf20Sopenharmony_ci * and by the UBI_MAX_VOLUMES constant. 7938c2ecf20Sopenharmony_ci */ 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if (ubi->leb_size < UBI_VTBL_RECORD_SIZE) { 7968c2ecf20Sopenharmony_ci ubi_err(ubi, "LEB size too small for a volume record"); 7978c2ecf20Sopenharmony_ci return -EINVAL; 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE; 8018c2ecf20Sopenharmony_ci if (ubi->vtbl_slots > UBI_MAX_VOLUMES) 8028c2ecf20Sopenharmony_ci ubi->vtbl_slots = UBI_MAX_VOLUMES; 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; 8058c2ecf20Sopenharmony_ci ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID); 8088c2ecf20Sopenharmony_ci if (!av) { 8098c2ecf20Sopenharmony_ci /* 8108c2ecf20Sopenharmony_ci * No logical eraseblocks belonging to the layout volume were 8118c2ecf20Sopenharmony_ci * found. This could mean that the flash is just empty. In 8128c2ecf20Sopenharmony_ci * this case we create empty layout volume. 8138c2ecf20Sopenharmony_ci * 8148c2ecf20Sopenharmony_ci * But if flash is not empty this must be a corruption or the 8158c2ecf20Sopenharmony_ci * MTD device just contains garbage. 8168c2ecf20Sopenharmony_ci */ 8178c2ecf20Sopenharmony_ci if (ai->is_empty) { 8188c2ecf20Sopenharmony_ci ubi->vtbl = create_empty_lvol(ubi, ai); 8198c2ecf20Sopenharmony_ci if (IS_ERR(ubi->vtbl)) 8208c2ecf20Sopenharmony_ci return PTR_ERR(ubi->vtbl); 8218c2ecf20Sopenharmony_ci } else { 8228c2ecf20Sopenharmony_ci ubi_err(ubi, "the layout volume was not found"); 8238c2ecf20Sopenharmony_ci return -EINVAL; 8248c2ecf20Sopenharmony_ci } 8258c2ecf20Sopenharmony_ci } else { 8268c2ecf20Sopenharmony_ci if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) { 8278c2ecf20Sopenharmony_ci /* This must not happen with proper UBI images */ 8288c2ecf20Sopenharmony_ci ubi_err(ubi, "too many LEBs (%d) in layout volume", 8298c2ecf20Sopenharmony_ci av->leb_count); 8308c2ecf20Sopenharmony_ci return -EINVAL; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci 8338c2ecf20Sopenharmony_ci ubi->vtbl = process_lvol(ubi, ai, av); 8348c2ecf20Sopenharmony_ci if (IS_ERR(ubi->vtbl)) 8358c2ecf20Sopenharmony_ci return PTR_ERR(ubi->vtbl); 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* 8418c2ecf20Sopenharmony_ci * The layout volume is OK, initialize the corresponding in-RAM data 8428c2ecf20Sopenharmony_ci * structures. 8438c2ecf20Sopenharmony_ci */ 8448c2ecf20Sopenharmony_ci err = init_volumes(ubi, ai, ubi->vtbl); 8458c2ecf20Sopenharmony_ci if (err) 8468c2ecf20Sopenharmony_ci goto out_free; 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci /* 8498c2ecf20Sopenharmony_ci * Make sure that the attaching information is consistent to the 8508c2ecf20Sopenharmony_ci * information stored in the volume table. 8518c2ecf20Sopenharmony_ci */ 8528c2ecf20Sopenharmony_ci err = check_attaching_info(ubi, ai); 8538c2ecf20Sopenharmony_ci if (err) 8548c2ecf20Sopenharmony_ci goto out_free; 8558c2ecf20Sopenharmony_ci 8568c2ecf20Sopenharmony_ci return 0; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ciout_free: 8598c2ecf20Sopenharmony_ci vfree(ubi->vtbl); 8608c2ecf20Sopenharmony_ci ubi_free_all_volumes(ubi); 8618c2ecf20Sopenharmony_ci return err; 8628c2ecf20Sopenharmony_ci} 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci/** 8658c2ecf20Sopenharmony_ci * self_vtbl_check - check volume table. 8668c2ecf20Sopenharmony_ci * @ubi: UBI device description object 8678c2ecf20Sopenharmony_ci */ 8688c2ecf20Sopenharmony_cistatic void self_vtbl_check(const struct ubi_device *ubi) 8698c2ecf20Sopenharmony_ci{ 8708c2ecf20Sopenharmony_ci if (!ubi_dbg_chk_gen(ubi)) 8718c2ecf20Sopenharmony_ci return; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci if (vtbl_check(ubi, ubi->vtbl)) { 8748c2ecf20Sopenharmony_ci ubi_err(ubi, "self-check failed"); 8758c2ecf20Sopenharmony_ci BUG(); 8768c2ecf20Sopenharmony_ci } 8778c2ecf20Sopenharmony_ci} 878