eba.c revision 3261ebd7d4194ff30d0eae7ba8d937dcccf7235d
1801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/* 2801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Copyright (c) International Business Machines Corp., 2006 3801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 4801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This program is free software; you can redistribute it and/or modify 5801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * it under the terms of the GNU General Public License as published by 6801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * the Free Software Foundation; either version 2 of the License, or 7801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * (at your option) any later version. 8801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 9801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This program is distributed in the hope that it will be useful, 10801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * but WITHOUT ANY WARRANTY; without even the implied warranty of 11801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * the GNU General Public License for more details. 13801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 14801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * You should have received a copy of the GNU General Public License 15801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * along with this program; if not, write to the Free Software 16801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 18801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Author: Artem Bityutskiy (Битюцкий Артём) 19801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 20801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 21801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/* 22801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The UBI Eraseblock Association (EBA) unit. 23801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 24801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This unit is responsible for I/O to/from logical eraseblock. 25801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 26801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Although in this implementation the EBA table is fully kept and managed in 27801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * RAM, which assumes poor scalability, it might be (partially) maintained on 28801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * flash in future implementations. 29801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 30801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The EBA unit implements per-logical eraseblock locking. Before accessing a 31801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * logical eraseblock it is locked for reading or writing. The per-logical 32801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * eraseblock locking is implemented by means of the lock tree. The lock tree 33801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * is an RB-tree which refers all the currently locked logical eraseblocks. The 34801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * lock tree elements are &struct ltree_entry objects. They are indexed by 35801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * (@vol_id, @lnum) pairs. 36801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 37801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * EBA also maintains the global sequence counter which is incremented each 38801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * time a logical eraseblock is mapped to a physical eraseblock and it is 39801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * stored in the volume identifier header. This means that each VID header has 40801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * a unique sequence number. The sequence number is only increased an we assume 41801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 64 bits is enough to never overflow. 42801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 43801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 44801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy#include <linux/slab.h> 45801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy#include <linux/crc32.h> 46801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy#include <linux/err.h> 47801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy#include "ubi.h" 48801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 49801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 50801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * struct ltree_entry - an entry in the lock tree. 51801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @rb: links RB-tree nodes 52801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID of the locked logical eraseblock 53801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: locked logical eraseblock number 54801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @users: how many tasks are using this logical eraseblock or wait for it 55801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @mutex: read/write mutex to implement read/write access serialization to 56801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * the (@vol_id, @lnum) logical eraseblock 57801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 58801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * When a logical eraseblock is being locked - corresponding &struct ltree_entry 59801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * object is inserted to the lock tree (@ubi->ltree). 60801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 61801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystruct ltree_entry { 62801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct rb_node rb; 63801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int vol_id; 64801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int lnum; 65801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int users; 66801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct rw_semaphore mutex; 67801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy}; 68801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 69801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/* Slab cache for lock-tree entries */ 70801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic struct kmem_cache *ltree_slab; 71801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 72801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 73801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * next_sqnum - get next sequence number. 74801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 75801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 76801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function returns next sequence number to use, which is just the current 77801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * global sequence counter value. It also increases the global sequence 78801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * counter. 79801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 80801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic unsigned long long next_sqnum(struct ubi_device *ubi) 81801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 82801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy unsigned long long sqnum; 83801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 84801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock(&ubi->ltree_lock); 85801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy sqnum = ubi->global_sqnum++; 86801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->ltree_lock); 87801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 88801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return sqnum; 89801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 90801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 91801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 92801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_get_compat - get compatibility flags of a volume. 93801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 94801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 95801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 96801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function returns compatibility flags for an internal volume. User 97801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * volumes have no compatibility flags, so %0 is returned. 98801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 99801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic int ubi_get_compat(const struct ubi_device *ubi, int vol_id) 100801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 101801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vol_id == UBI_LAYOUT_VOL_ID) 102801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return UBI_LAYOUT_VOLUME_COMPAT; 103801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 104801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 105801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 106801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 107801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ltree_lookup - look up the lock tree. 108801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 109801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 110801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 111801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 112801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function returns a pointer to the corresponding &struct ltree_entry 113801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * object if the logical eraseblock is locked and %NULL if it is not. 114801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi->ltree_lock has to be locked. 115801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 116801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic struct ltree_entry *ltree_lookup(struct ubi_device *ubi, int vol_id, 117801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int lnum) 118801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 119801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct rb_node *p; 120801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 121801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = ubi->ltree.rb_node; 122801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy while (p) { 123801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le; 124801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 125801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = rb_entry(p, struct ltree_entry, rb); 126801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 127801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vol_id < le->vol_id) 128801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = p->rb_left; 129801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else if (vol_id > le->vol_id) 130801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = p->rb_right; 131801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else { 132801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (lnum < le->lnum) 133801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = p->rb_left; 134801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else if (lnum > le->lnum) 135801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = p->rb_right; 136801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else 137801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return le; 138801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 139801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 140801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 141801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return NULL; 142801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 143801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 144801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 145801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ltree_add_entry - add new entry to the lock tree. 146801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 147801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 148801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 149801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 150801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function adds new entry for logical eraseblock (@vol_id, @lnum) to the 151801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * lock tree. If such entry is already there, its usage counter is increased. 152801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Returns pointer to the lock tree entry or %-ENOMEM if memory allocation 153801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * failed. 154801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 155801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic struct ltree_entry *ltree_add_entry(struct ubi_device *ubi, int vol_id, 156801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int lnum) 157801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 158801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le, *le1, *le_free; 159801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 160801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = kmem_cache_alloc(ltree_slab, GFP_KERNEL); 161801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!le) 162801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return ERR_PTR(-ENOMEM); 163801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 164801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->vol_id = vol_id; 165801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->lnum = lnum; 166801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 167801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock(&ubi->ltree_lock); 168801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le1 = ltree_lookup(ubi, vol_id, lnum); 169801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 170801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (le1) { 171801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 172801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This logical eraseblock is already locked. The newly 173801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * allocated lock entry is not needed. 174801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 175801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le_free = le; 176801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = le1; 177801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else { 178801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct rb_node **p, *parent = NULL; 179801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 180801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 181801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * No lock entry, add the newly allocated one to the 182801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi->ltree RB-tree. 183801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 184801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le_free = NULL; 185801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 186801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = &ubi->ltree.rb_node; 187801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy while (*p) { 188801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy parent = *p; 189801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le1 = rb_entry(parent, struct ltree_entry, rb); 190801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 191801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vol_id < le1->vol_id) 192801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = &(*p)->rb_left; 193801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else if (vol_id > le1->vol_id) 194801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = &(*p)->rb_right; 195801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else { 196801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(lnum != le1->lnum); 197801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (lnum < le1->lnum) 198801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = &(*p)->rb_left; 199801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else 200801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy p = &(*p)->rb_right; 201801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 202801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 203801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 204801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy rb_link_node(&le->rb, parent, p); 205801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy rb_insert_color(&le->rb, &ubi->ltree); 206801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 207801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->users += 1; 208801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->ltree_lock); 209801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 210801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (le_free) 211801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kmem_cache_free(ltree_slab, le_free); 212801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 213801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return le; 214801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 215801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 216801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 217801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * leb_read_lock - lock logical eraseblock for reading. 218801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 219801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 220801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 221801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 222801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function locks a logical eraseblock for reading. Returns zero in case 223801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * of success and a negative error code in case of failure. 224801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 225801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic int leb_read_lock(struct ubi_device *ubi, int vol_id, int lnum) 226801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 227801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le; 228801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 229801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = ltree_add_entry(ubi, vol_id, lnum); 230801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (IS_ERR(le)) 231801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return PTR_ERR(le); 232801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy down_read(&le->mutex); 233801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 234801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 235801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 236801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 237801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * leb_read_unlock - unlock logical eraseblock. 238801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 239801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 240801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 241801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 242801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic void leb_read_unlock(struct ubi_device *ubi, int vol_id, int lnum) 243801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 244801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int free = 0; 245801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le; 246801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 247801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock(&ubi->ltree_lock); 248801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = ltree_lookup(ubi, vol_id, lnum); 249801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->users -= 1; 250801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(le->users >= 0); 251801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (le->users == 0) { 252801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy rb_erase(&le->rb, &ubi->ltree); 253801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy free = 1; 254801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 255801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->ltree_lock); 256801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 257801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy up_read(&le->mutex); 258801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (free) 259801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kmem_cache_free(ltree_slab, le); 260801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 261801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 262801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 263801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * leb_write_lock - lock logical eraseblock for writing. 264801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 265801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 266801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 267801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 268801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function locks a logical eraseblock for writing. Returns zero in case 269801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * of success and a negative error code in case of failure. 270801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 271801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic int leb_write_lock(struct ubi_device *ubi, int vol_id, int lnum) 272801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 273801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le; 274801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 275801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = ltree_add_entry(ubi, vol_id, lnum); 276801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (IS_ERR(le)) 277801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return PTR_ERR(le); 278801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy down_write(&le->mutex); 279801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 280801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 281801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 282801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 283801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * leb_write_unlock - unlock logical eraseblock. 284801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 285801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 286801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 287801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 288801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic void leb_write_unlock(struct ubi_device *ubi, int vol_id, int lnum) 289801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 290801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int free; 291801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le; 292801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 293801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock(&ubi->ltree_lock); 294801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le = ltree_lookup(ubi, vol_id, lnum); 295801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->users -= 1; 296801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(le->users >= 0); 297801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (le->users == 0) { 298801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy rb_erase(&le->rb, &ubi->ltree); 299801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy free = 1; 300801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else 301801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy free = 0; 302801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->ltree_lock); 303801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 304801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy up_write(&le->mutex); 305801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (free) 306801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kmem_cache_free(ltree_slab, le); 307801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 308801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 309801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 310801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_unmap_leb - un-map logical eraseblock. 311801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 312801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 313801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 314801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 315801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function un-maps logical eraseblock @lnum and schedules corresponding 316801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * physical eraseblock for erasure. Returns zero in case of success and a 317801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * negative error code in case of failure. 318801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 319801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_unmap_leb(struct ubi_device *ubi, int vol_id, int lnum) 320801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 321801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int idx = vol_id2idx(ubi, vol_id), err, pnum; 322801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 323801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 324801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->ro_mode) 325801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -EROFS; 326801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 327801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_write_lock(ubi, vol_id, lnum); 328801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 329801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 330801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 331801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = vol->eba_tbl[lnum]; 332801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum < 0) 333801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* This logical eraseblock is already unmapped */ 334801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 335801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 336801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum); 337801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 338801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; 339801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_put_peb(ubi, pnum, 0); 340801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 341801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_unlock: 342801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 343801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 344801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 345801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 346801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 347801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_read_leb - read data. 348801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 349801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 350801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 351801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @buf: buffer to store the read data 352801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @offset: offset from where to read 353801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @len: how many bytes to read 354801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @check: data CRC check flag 355801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 356801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * If the logical eraseblock @lnum is unmapped, @buf is filled with 0xFF 357801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * bytes. The @check flag only makes sense for static volumes and forces 358801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * eraseblock data CRC checking. 359801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 360801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * In case of success this function returns zero. In case of a static volume, 361801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * if data CRC mismatches - %-EBADMSG is returned. %-EBADMSG may also be 362801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * returned for any volume type if an ECC error was detected by the MTD device 363801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * driver. Other negative error cored may be returned in case of other errors. 364801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 365801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_read_leb(struct ubi_device *ubi, int vol_id, int lnum, void *buf, 366801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int offset, int len, int check) 367801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 368801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int err, pnum, scrub = 0, idx = vol_id2idx(ubi, vol_id); 369801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr; 370801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 371a6343afb6e16b65b9f0b264f94f8207212e7e3aeJeff Garzik uint32_t uninitialized_var(crc); 372801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 373801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_read_lock(ubi, vol_id, lnum); 374801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 375801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 376801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 377801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = vol->eba_tbl[lnum]; 378801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum < 0) { 379801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 380801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The logical eraseblock is not mapped, fill the whole buffer 381801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * with 0xFF bytes. The exception is static volumes for which 382801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * it is an error to read unmapped logical eraseblocks. 383801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 384801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("read %d bytes from offset %d of LEB %d:%d (unmapped)", 385801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, offset, vol_id, lnum); 386801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_read_unlock(ubi, vol_id, lnum); 387801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(vol->vol_type != UBI_STATIC_VOLUME); 388801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy memset(buf, 0xFF, len); 389801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 390801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 391801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 392801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("read %d bytes from offset %d of LEB %d:%d, PEB %d", 393801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, offset, vol_id, lnum, pnum); 394801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 395801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vol->vol_type == UBI_DYNAMIC_VOLUME) 396801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy check = 0; 397801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 398801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyretry: 399801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (check) { 400801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr = ubi_zalloc_vid_hdr(ubi); 401801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vid_hdr) { 402801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -ENOMEM; 403801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 404801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 405801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 406801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1); 407801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err && err != UBI_IO_BITFLIPS) { 408801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err > 0) { 409801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 410801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The header is either absent or corrupted. 411801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The former case means there is a bug - 412801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * switch to read-only mode just in case. 413801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The latter case means a real corruption - we 414801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * may try to recover data. FIXME: but this is 415801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * not implemented. 416801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 417801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err == UBI_IO_BAD_VID_HDR) { 418801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("bad VID header at PEB %d, LEB" 419801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy "%d:%d", pnum, vol_id, lnum); 420801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -EBADMSG; 421801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else 422801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 423801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 424801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_free; 425801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else if (err == UBI_IO_BITFLIPS) 426801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy scrub = 1; 427801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 4283261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig ubi_assert(lnum < be32_to_cpu(vid_hdr->used_ebs)); 4293261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig ubi_assert(len == be32_to_cpu(vid_hdr->data_size)); 430801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 4313261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig crc = be32_to_cpu(vid_hdr->data_crc); 432801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 433801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 434801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 435801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_data(ubi, buf, pnum, offset, len); 436801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 437801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err == UBI_IO_BITFLIPS) { 438801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy scrub = 1; 439801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = 0; 440801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else if (err == -EBADMSG) { 441801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vol->vol_type == UBI_DYNAMIC_VOLUME) 442801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 443801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy scrub = 1; 444801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!check) { 445801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("force data checking"); 446801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy check = 1; 447801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto retry; 448801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 449801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else 450801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 451801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 452801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 453801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (check) { 4542ab934b8afa89b9b3e71b7fb66470a19772f5012Jeff Garzik uint32_t crc1 = crc32(UBI_CRC32_INIT, buf, len); 455801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (crc1 != crc) { 456801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("CRC error: calculated %#08x, must be %#08x", 457801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy crc1, crc); 458801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -EBADMSG; 459801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 460801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 461801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 462801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 463801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (scrub) 464801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_scrub_peb(ubi, pnum); 465801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 466801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_read_unlock(ubi, vol_id, lnum); 467801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 468801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 469801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_free: 470801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 471801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_unlock: 472801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_read_unlock(ubi, vol_id, lnum); 473801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 474801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 475801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 476801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 477801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * recover_peb - recover from write failure. 478801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 479801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @pnum: the physical eraseblock to recover 480801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 481801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 482801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @buf: data which was not written because of the write failure 483801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @offset: offset of the failed write 484801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @len: how many bytes should have been written 485801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 486801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function is called in case of a write failure and moves all good data 487801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * from the potentially bad physical eraseblock to a good physical eraseblock. 488801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function also writes the data which was not written due to the failure. 489801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Returns new physical eraseblock number in case of success, and a negative 490801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * error code in case of failure. 491801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 492801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, 493801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy const void *buf, int offset, int len) 494801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 495801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int err, idx = vol_id2idx(ubi, vol_id), new_pnum, data_size, tries = 0; 496801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 497801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr; 498801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy unsigned char *new_buf; 499801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 500801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr = ubi_zalloc_vid_hdr(ubi); 501801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vid_hdr) { 502801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 503801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 504801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 505801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyretry: 506801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); 507801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (new_pnum < 0) { 508801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 509801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return new_pnum; 510801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 511801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 512801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("recover PEB %d, move data to PEB %d", pnum, new_pnum); 513801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 514801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1); 515801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err && err != UBI_IO_BITFLIPS) { 516801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err > 0) 517801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -EIO; 518801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_put; 519801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 520801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 5213261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 522801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_vid_hdr(ubi, new_pnum, vid_hdr); 523801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 524801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 525801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 526801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy data_size = offset + len; 52792ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy new_buf = vmalloc(data_size); 528801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!new_buf) { 529801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -ENOMEM; 530801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_put; 531801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 532801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy memset(new_buf + offset, 0xFF, len); 533801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 534801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* Read everything before the area where the write failure happened */ 535801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (offset > 0) { 536801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_data(ubi, new_buf, pnum, 0, offset); 537801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err && err != UBI_IO_BITFLIPS) { 53892ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(new_buf); 539801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_put; 540801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 541801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 542801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 543801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy memcpy(new_buf + offset, buf, len); 544801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 545801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, new_buf, new_pnum, 0, data_size); 546801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 54792ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(new_buf); 548801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 549801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 550801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 55192ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(new_buf); 552801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 553801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 554801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = new_pnum; 555801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_wl_put_peb(ubi, pnum, 1); 556801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 557801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("data was successfully recovered"); 558801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 559801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 560801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_put: 561801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_wl_put_peb(ubi, new_pnum, 1); 562801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 563801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 564801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 565801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiywrite_error: 566801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 567801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Bad luck? This physical eraseblock is bad too? Crud. Let's try to 568801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * get another one. 569801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 570801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write to PEB %d", new_pnum); 571801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_wl_put_peb(ubi, new_pnum, 1); 572801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (++tries > UBI_IO_RETRIES) { 573801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 574801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 575801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 576801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("try again"); 577801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto retry; 578801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 579801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 580801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 581801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_write_leb - write data to dynamic volume. 582801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 583801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 584801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 585801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @buf: the data to write 586801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @offset: offset within the logical eraseblock where to write 587801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @len: how many bytes to write 588801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @dtype: data type 589801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 590801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function writes data to logical eraseblock @lnum of a dynamic volume 591801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id. Returns zero in case of success and a negative error code in case 592801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * of failure. In case of error, it is possible that something was still 593801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * written to the flash media, but may be some garbage. 594801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 595801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_write_leb(struct ubi_device *ubi, int vol_id, int lnum, 596801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy const void *buf, int offset, int len, int dtype) 597801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 598801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int idx = vol_id2idx(ubi, vol_id), err, pnum, tries = 0; 599801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 600801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr; 601801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 602801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->ro_mode) 603801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -EROFS; 604801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 605801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_write_lock(ubi, vol_id, lnum); 606801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 607801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 608801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 609801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = vol->eba_tbl[lnum]; 610801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum >= 0) { 611801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("write %d bytes at offset %d of LEB %d:%d, PEB %d", 612801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, offset, vol_id, lnum, pnum); 613801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 614801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, buf, pnum, offset, len); 615801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 616801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write data to PEB %d", pnum); 617801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err == -EIO && ubi->bad_allowed) 618801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = recover_peb(ubi, pnum, vol_id, lnum, buf, offset, len); 619801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 620801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 621801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 622801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 623801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 624801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 625801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 626801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 627801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * The logical eraseblock is not mapped. We have to get a free physical 628801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * eraseblock and write the volume identifier header there first. 629801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 630801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr = ubi_zalloc_vid_hdr(ubi); 631801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vid_hdr) { 632801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 633801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 634801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 635801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 636801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->vol_type = UBI_VID_DYNAMIC; 6373261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 6383261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->vol_id = cpu_to_be32(vol_id); 6393261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->lnum = cpu_to_be32(lnum); 640801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->compat = ubi_get_compat(ubi, vol_id); 6413261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_pad = cpu_to_be32(vol->data_pad); 642801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 643801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyretry: 644801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = ubi_wl_get_peb(ubi, dtype); 645801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum < 0) { 646801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 647801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 648801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return pnum; 649801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 650801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 651801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("write VID hdr and %d bytes at offset %d of LEB %d:%d, PEB %d", 652801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, offset, vol_id, lnum, pnum); 653801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 654801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); 655801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 656801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write VID header to LEB %d:%d, PEB %d", 657801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol_id, lnum, pnum); 658801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 659801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 660801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 661801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, buf, pnum, offset, len); 662801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 663801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write %d bytes at offset %d of LEB %d:%d, " 664801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy "PEB %d", len, offset, vol_id, lnum, pnum); 665801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 666801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 667801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 668801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = pnum; 669801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 670801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 671801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 672801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 673801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 674801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiywrite_error: 675801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err != -EIO || !ubi->bad_allowed) { 676801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 677801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 678801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 679801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 680801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 681801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 682801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 683801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Fortunately, this is the first write operation to this physical 684801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * eraseblock, so just put it and request a new one. We assume that if 685801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * this physical eraseblock went bad, the erase code will handle that. 686801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 687801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_put_peb(ubi, pnum, 1); 688801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err || ++tries > UBI_IO_RETRIES) { 689801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 690801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 691801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 692801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 693801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 694801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 6953261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 696801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("try another PEB"); 697801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto retry; 698801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 699801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 700801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 701801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_write_leb_st - write data to static volume. 702801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 703801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 704801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 705801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @buf: data to write 706801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @len: how many bytes to write 707801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @dtype: data type 708801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @used_ebs: how many logical eraseblocks will this volume contain 709801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 710801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function writes data to logical eraseblock @lnum of static volume 711801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id. The @used_ebs argument should contain total number of logical 712801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * eraseblock in this static volume. 713801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 714801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * When writing to the last logical eraseblock, the @len argument doesn't have 715801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * to be aligned to the minimal I/O unit size. Instead, it has to be equivalent 716801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * to the real data size, although the @buf buffer has to contain the 717801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * alignment. In all other cases, @len has to be aligned. 718801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 719801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * It is prohibited to write more then once to logical eraseblocks of static 720801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * volumes. This function returns zero in case of success and a negative error 721801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * code in case of failure. 722801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 723801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_write_leb_st(struct ubi_device *ubi, int vol_id, int lnum, 724801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy const void *buf, int len, int dtype, int used_ebs) 725801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 726801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int err, pnum, tries = 0, data_size = len; 727801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int idx = vol_id2idx(ubi, vol_id); 728801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 729801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr; 730801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy uint32_t crc; 731801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 732801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->ro_mode) 733801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -EROFS; 734801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 735801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (lnum == used_ebs - 1) 736801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* If this is the last LEB @len may be unaligned */ 737801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len = ALIGN(data_size, ubi->min_io_size); 738801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy else 739801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(len % ubi->min_io_size == 0); 740801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 741801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr = ubi_zalloc_vid_hdr(ubi); 742801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vid_hdr) 743801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 744801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 745801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_write_lock(ubi, vol_id, lnum); 746801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 747801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 748801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 749801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 750801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 7513261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 7523261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->vol_id = cpu_to_be32(vol_id); 7533261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->lnum = cpu_to_be32(lnum); 754801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->compat = ubi_get_compat(ubi, vol_id); 7553261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_pad = cpu_to_be32(vol->data_pad); 756801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 757801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy crc = crc32(UBI_CRC32_INIT, buf, data_size); 758801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->vol_type = UBI_VID_STATIC; 7593261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_size = cpu_to_be32(data_size); 7603261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->used_ebs = cpu_to_be32(used_ebs); 7613261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_crc = cpu_to_be32(crc); 762801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 763801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyretry: 764801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = ubi_wl_get_peb(ubi, dtype); 765801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum < 0) { 766801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 767801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 768801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return pnum; 769801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 770801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 771801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("write VID hdr and %d bytes at LEB %d:%d, PEB %d, used_ebs %d", 772801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, vol_id, lnum, pnum, used_ebs); 773801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 774801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); 775801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 776801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write VID header to LEB %d:%d, PEB %d", 777801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol_id, lnum, pnum); 778801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 779801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 780801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 781801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, buf, pnum, 0, len); 782801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 783801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write %d bytes of data to PEB %d", 784801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, pnum); 785801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 786801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 787801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 788801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(vol->eba_tbl[lnum] < 0); 789801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = pnum; 790801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 791801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 792801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 793801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 794801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 795801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiywrite_error: 796801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err != -EIO || !ubi->bad_allowed) { 797801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 798801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This flash device does not admit of bad eraseblocks or 799801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * something nasty and unexpected happened. Switch to read-only 800801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * mode just in case. 801801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 802801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 803801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 804801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 805801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 806801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 807801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 808801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_put_peb(ubi, pnum, 1); 809801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err || ++tries > UBI_IO_RETRIES) { 810801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 811801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 812801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 813801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 814801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 815801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 8163261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 817801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("try another PEB"); 818801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto retry; 819801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 820801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 821801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/* 822801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_atomic_leb_change - change logical eraseblock atomically. 823801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 824801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vol_id: volume ID 825801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @lnum: logical eraseblock number 826801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @buf: data to write 827801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @len: how many bytes to write 828801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @dtype: data type 829801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 830801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function changes the contents of a logical eraseblock atomically. @buf 831801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * has to contain new logical eraseblock data, and @len - the length of the 832801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * data, which has to be aligned. This function guarantees that in case of an 833801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * unclean reboot the old contents is preserved. Returns zero in case of 834801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * success and a negative error code in case of failure. 835801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 836801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_atomic_leb_change(struct ubi_device *ubi, int vol_id, int lnum, 837801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy const void *buf, int len, int dtype) 838801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 839801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int err, pnum, tries = 0, idx = vol_id2idx(ubi, vol_id); 840801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol = ubi->volumes[idx]; 841801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr; 842801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy uint32_t crc; 843801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 844801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->ro_mode) 845801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -EROFS; 846801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 847801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr = ubi_zalloc_vid_hdr(ubi); 848801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vid_hdr) 849801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 850801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 851801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_write_lock(ubi, vol_id, lnum); 852801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 853801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 854801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 855801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 856801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 8573261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 8583261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->vol_id = cpu_to_be32(vol_id); 8593261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->lnum = cpu_to_be32(lnum); 860801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->compat = ubi_get_compat(ubi, vol_id); 8613261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_pad = cpu_to_be32(vol->data_pad); 862801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 863801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy crc = crc32(UBI_CRC32_INIT, buf, len); 864801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->vol_type = UBI_VID_STATIC; 8653261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_size = cpu_to_be32(len); 866801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->copy_flag = 1; 8673261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_crc = cpu_to_be32(crc); 868801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 869801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyretry: 870801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = ubi_wl_get_peb(ubi, dtype); 871801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum < 0) { 872801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 873801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 874801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return pnum; 875801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 876801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 877801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("change LEB %d:%d, PEB %d, write VID hdr to PEB %d", 878801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol_id, lnum, vol->eba_tbl[lnum], pnum); 879801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 880801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); 881801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 882801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write VID header to LEB %d:%d, PEB %d", 883801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol_id, lnum, pnum); 884801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 885801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 886801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 887801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, buf, pnum, 0, len); 888801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 889801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("failed to write %d bytes of data to PEB %d", 890801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy len, pnum); 891801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto write_error; 892801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 893801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 894801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 1); 895801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 896801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 897801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 898801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 899801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 900801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 901801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = pnum; 902801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 903801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 904801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 905801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 906801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiywrite_error: 907801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err != -EIO || !ubi->bad_allowed) { 908801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 909801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This flash device does not admit of bad eraseblocks or 910801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * something nasty and unexpected happened. Switch to read-only 911801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * mode just in case. 912801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 913801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 914801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 915801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 916801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 917801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 918801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 919801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_wl_put_peb(ubi, pnum, 1); 920801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err || ++tries > UBI_IO_RETRIES) { 921801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_ro_mode(ubi); 922801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 923801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_free_vid_hdr(ubi, vid_hdr); 924801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 925801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 926801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 9273261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 928801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_msg("try another PEB"); 929801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto retry; 930801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 931801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 932801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 933801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ltree_entry_ctor - lock tree entries slab cache constructor. 934801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @obj: the lock-tree entry to construct 935801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @cache: the lock tree entry slab cache 936801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @flags: constructor flags 937801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 938801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiystatic void ltree_entry_ctor(void *obj, struct kmem_cache *cache, 939801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy unsigned long flags) 940801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 941801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ltree_entry *le = obj; 942801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 943801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy le->users = 0; 944801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy init_rwsem(&le->mutex); 945801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 946801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 947801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 948801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_copy_leb - copy logical eraseblock. 949801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 950801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @from: physical eraseblock number from where to copy 951801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @to: physical eraseblock number where to copy 952801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vid_hdr: VID header of the @from physical eraseblock 953801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 954801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function copies logical eraseblock from physical eraseblock @from to 955801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * physical eraseblock @to. The @vid_hdr buffer may be changed by this 956801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * function. Returns zero in case of success, %UBI_IO_BITFLIPS if the operation 957801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * was canceled because bit-flips were detected at the target PEB, and a 958801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * negative error code in case of failure. 959801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 960801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, 961801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_vid_hdr *vid_hdr) 962801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 963801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int err, vol_id, lnum, data_size, aldata_size, pnum, idx; 964801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol; 965801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy uint32_t crc; 966801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy void *buf, *buf1 = NULL; 967801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 9683261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vol_id = be32_to_cpu(vid_hdr->vol_id); 9693261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig lnum = be32_to_cpu(vid_hdr->lnum); 970801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 971801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("copy LEB %d:%d, PEB %d to PEB %d", vol_id, lnum, from, to); 972801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 973801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vid_hdr->vol_type == UBI_VID_STATIC) { 9743261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig data_size = be32_to_cpu(vid_hdr->data_size); 975801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy aldata_size = ALIGN(data_size, ubi->min_io_size); 976801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else 977801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy data_size = aldata_size = 9783261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig ubi->leb_size - be32_to_cpu(vid_hdr->data_pad); 979801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 98092ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy buf = vmalloc(aldata_size); 981801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!buf) 982801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 983801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 984801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 985801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * We do not want anybody to write to this logical eraseblock while we 986801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * are moving it, so we lock it. 987801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 988801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = leb_write_lock(ubi, vol_id, lnum); 989801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 99092ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(buf); 991801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 992801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 993801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 994801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 995801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * But the logical eraseblock might have been put by this time. 996801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Cancel if it is true. 997801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 998801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy idx = vol_id2idx(ubi, vol_id); 999801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1000801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 1001801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * We may race with volume deletion/re-size, so we have to hold 1002801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi->volumes_lock. 1003801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1004801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock(&ubi->volumes_lock); 1005801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol = ubi->volumes[idx]; 1006801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vol) { 1007801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("volume %d was removed meanwhile", vol_id); 1008801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->volumes_lock); 1009801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1010801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1011801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1012801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy pnum = vol->eba_tbl[lnum]; 1013801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (pnum != from) { 1014801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("LEB %d:%d is no longer mapped to PEB %d, mapped to " 1015801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy "PEB %d, cancel", vol_id, lnum, from, pnum); 1016801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->volumes_lock); 1017801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1018801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1019801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_unlock(&ubi->volumes_lock); 1020801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1021801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* OK, now the LEB is locked and we can safely start moving it */ 1022801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1023801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("read %d bytes of data", aldata_size); 1024801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_data(ubi, buf, from, 0, aldata_size); 1025801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err && err != UBI_IO_BITFLIPS) { 1026801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("error %d while reading data from PEB %d", 1027801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err, from); 1028801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1029801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1030801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1031801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 1032801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * Now we have got to calculate how much data we have to to copy. In 1033801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * case of a static volume it is fairly easy - the VID header contains 1034801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * the data size. In case of a dynamic volume it is more difficult - we 1035801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * have to read the contents, cut 0xFF bytes from the end and copy only 1036801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * the first part. We must do this to avoid writing 0xFF bytes as it 1037801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * may have some side-effects. And not only this. It is important not 1038801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * to include those 0xFFs to CRC because later the they may be filled 1039801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * by data. 1040801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1041801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (vid_hdr->vol_type == UBI_VID_DYNAMIC) 1042801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy aldata_size = data_size = 1043801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_calc_data_len(ubi, buf, data_size); 1044801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1045801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1046801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy crc = crc32(UBI_CRC32_INIT, buf, data_size); 1047801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1048801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1049801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 1050801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * It may turn out to me that the whole @from physical eraseblock 1051801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * contains only 0xFF bytes. Then we have to only write the VID header 1052801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * and do not write any data. This also means we should not set 1053801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @vid_hdr->copy_flag, @vid_hdr->data_size, and @vid_hdr->data_crc. 1054801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1055801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (data_size > 0) { 1056801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vid_hdr->copy_flag = 1; 10573261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_size = cpu_to_be32(data_size); 10583261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->data_crc = cpu_to_be32(crc); 1059801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 10603261ebd7d4194ff30d0eae7ba8d937dcccf7235dChristoph Hellwig vid_hdr->sqnum = cpu_to_be64(next_sqnum(ubi)); 1061801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1062801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_vid_hdr(ubi, to, vid_hdr); 1063801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 1064801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1065801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1066801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1067801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1068801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* Read the VID header back and check if it was written correctly */ 1069801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); 1070801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 1071801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err != UBI_IO_BITFLIPS) 1072801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("cannot read VID header back from PEB %d", to); 1073801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1074801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1075801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1076801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (data_size > 0) { 1077801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_write_data(ubi, buf, to, 0, aldata_size); 1078801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) 1079801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1080801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1081801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 1082801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * We've written the data and are going to read it back to make 1083801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * sure it was written correctly. 1084801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 108592ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy buf1 = vmalloc(aldata_size); 1086801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!buf1) { 1087801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -ENOMEM; 1088801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1089801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1090801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1091801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1092801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1093801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = ubi_io_read_data(ubi, buf1, to, 0, aldata_size); 1094801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err) { 1095801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (err != UBI_IO_BITFLIPS) 1096801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("cannot read data back from PEB %d", 1097801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy to); 1098801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1099801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1100801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1101801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1102801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1103801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (memcmp(buf, buf1, aldata_size)) { 1104801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("read data back from PEB %d - it is different", 1105801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy to); 1106801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_unlock; 1107801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1108801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1109801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1110801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_assert(vol->eba_tbl[lnum] == from); 1111801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[lnum] = to; 1112801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1113801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 111492ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(buf); 111592ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(buf1); 1116801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1117801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 1118801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1119801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_unlock: 1120801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy leb_write_unlock(ubi, vol_id, lnum); 112192ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(buf); 112292ad8f37509a7d9d5dd6e0092211b092a7ca7fb1Artem Bityutskiy vfree(buf1); 1123801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 1124801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 1125801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1126801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 1127801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_init_scan - initialize the EBA unit using scanning information. 1128801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 1129801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @si: scanning information 1130801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * 1131801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This function returns zero in case of success and a negative error code in 1132801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * case of failure. 1133801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1134801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyint ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) 1135801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 1136801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int i, j, err, num_volumes; 1137801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_scan_volume *sv; 1138801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_volume *vol; 1139801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct ubi_scan_leb *seb; 1140801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy struct rb_node *rb; 1141801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1142801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("initialize EBA unit"); 1143801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1144801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy spin_lock_init(&ubi->ltree_lock); 1145801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->ltree = RB_ROOT; 1146801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1147801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi_devices_cnt == 0) { 1148801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ltree_slab = kmem_cache_create("ubi_ltree_slab", 1149801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy sizeof(struct ltree_entry), 0, 1150801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 0, <ree_entry_ctor, NULL); 1151801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!ltree_slab) 1152801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return -ENOMEM; 1153801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1154801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1155801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->global_sqnum = si->max_sqnum + 1; 1156801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; 1157801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1158801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy for (i = 0; i < num_volumes; i++) { 1159801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol = ubi->volumes[i]; 1160801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vol) 1161801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy continue; 1162801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1163801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy cond_resched(); 1164801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1165801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl = kmalloc(vol->reserved_pebs * sizeof(int), 1166801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy GFP_KERNEL); 1167801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!vol->eba_tbl) { 1168801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy err = -ENOMEM; 1169801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy goto out_free; 1170801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1171801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1172801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy for (j = 0; j < vol->reserved_pebs; j++) 1173801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[j] = UBI_LEB_UNMAPPED; 1174801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1175801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i)); 1176801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!sv) 1177801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy continue; 1178801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1179801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { 1180801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (seb->lnum >= vol->reserved_pebs) 1181801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* 1182801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * This may happen in case of an unclean reboot 1183801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * during re-size. 1184801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1185801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_scan_move_to_list(sv, seb, &si->erase); 1186801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy vol->eba_tbl[seb->lnum] = seb->pnum; 1187801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1188801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1189801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1190801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->bad_allowed) { 1191801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_calculate_reserved(ubi); 1192801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1193801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi->avail_pebs < ubi->beb_rsvd_level) { 1194801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy /* No enough free physical eraseblocks */ 1195801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->beb_rsvd_pebs = ubi->avail_pebs; 1196801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi_warn("cannot reserve enough PEBs for bad PEB " 1197801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy "handling, reserved %d, need %d", 1198801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); 1199801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } else 1200801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->beb_rsvd_pebs = ubi->beb_rsvd_level; 1201801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1202801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->avail_pebs -= ubi->beb_rsvd_pebs; 1203801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy ubi->rsvd_pebs += ubi->beb_rsvd_pebs; 1204801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1205801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1206801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("EBA unit is initialized"); 1207801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return 0; 1208801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1209801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyout_free: 1210801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy for (i = 0; i < num_volumes; i++) { 1211801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!ubi->volumes[i]) 1212801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy continue; 1213801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kfree(ubi->volumes[i]->eba_tbl); 1214801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1215801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi_devices_cnt == 0) 1216801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kmem_cache_destroy(ltree_slab); 1217801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy return err; 1218801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 1219801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1220801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy/** 1221801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * ubi_eba_close - close EBA unit. 1222801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy * @ubi: UBI device description object 1223801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy */ 1224801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiyvoid ubi_eba_close(const struct ubi_device *ubi) 1225801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy{ 1226801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy int i, num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; 1227801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1228801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy dbg_eba("close EBA unit"); 1229801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy 1230801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy for (i = 0; i < num_volumes; i++) { 1231801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (!ubi->volumes[i]) 1232801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy continue; 1233801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kfree(ubi->volumes[i]->eba_tbl); 1234801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy } 1235801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy if (ubi_devices_cnt == 1) 1236801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy kmem_cache_destroy(ltree_slab); 1237801c135ce73d5df1caf3eca35b66a10824ae0707Artem B. Bityutskiy} 1238