1*c91a719dSKyungmin Park /* 2*c91a719dSKyungmin Park * Copyright (c) International Business Machines Corp., 2006 3*c91a719dSKyungmin Park * 4*c91a719dSKyungmin Park * This program is free software; you can redistribute it and/or modify 5*c91a719dSKyungmin Park * it under the terms of the GNU General Public License as published by 6*c91a719dSKyungmin Park * the Free Software Foundation; either version 2 of the License, or 7*c91a719dSKyungmin Park * (at your option) any later version. 8*c91a719dSKyungmin Park * 9*c91a719dSKyungmin Park * This program is distributed in the hope that it will be useful, 10*c91a719dSKyungmin Park * but WITHOUT ANY WARRANTY; without even the implied warranty of 11*c91a719dSKyungmin Park * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 12*c91a719dSKyungmin Park * the GNU General Public License for more details. 13*c91a719dSKyungmin Park * 14*c91a719dSKyungmin Park * You should have received a copy of the GNU General Public License 15*c91a719dSKyungmin Park * along with this program; if not, write to the Free Software 16*c91a719dSKyungmin Park * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*c91a719dSKyungmin Park * 18*c91a719dSKyungmin Park * Author: Artem Bityutskiy (Битюцкий Артём) 19*c91a719dSKyungmin Park */ 20*c91a719dSKyungmin Park 21*c91a719dSKyungmin Park /* 22*c91a719dSKyungmin Park * This file contains implementation of volume creation, deletion, updating and 23*c91a719dSKyungmin Park * resizing. 24*c91a719dSKyungmin Park */ 25*c91a719dSKyungmin Park 26*c91a719dSKyungmin Park #ifdef UBI_LINUX 27*c91a719dSKyungmin Park #include <linux/err.h> 28*c91a719dSKyungmin Park #include <asm/div64.h> 29*c91a719dSKyungmin Park #endif 30*c91a719dSKyungmin Park 31*c91a719dSKyungmin Park #include <ubi_uboot.h> 32*c91a719dSKyungmin Park #include "ubi.h" 33*c91a719dSKyungmin Park 34*c91a719dSKyungmin Park #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID 35*c91a719dSKyungmin Park static void paranoid_check_volumes(struct ubi_device *ubi); 36*c91a719dSKyungmin Park #else 37*c91a719dSKyungmin Park #define paranoid_check_volumes(ubi) 38*c91a719dSKyungmin Park #endif 39*c91a719dSKyungmin Park 40*c91a719dSKyungmin Park #ifdef UBI_LINUX 41*c91a719dSKyungmin Park static ssize_t vol_attribute_show(struct device *dev, 42*c91a719dSKyungmin Park struct device_attribute *attr, char *buf); 43*c91a719dSKyungmin Park 44*c91a719dSKyungmin Park /* Device attributes corresponding to files in '/<sysfs>/class/ubi/ubiX_Y' */ 45*c91a719dSKyungmin Park static struct device_attribute attr_vol_reserved_ebs = 46*c91a719dSKyungmin Park __ATTR(reserved_ebs, S_IRUGO, vol_attribute_show, NULL); 47*c91a719dSKyungmin Park static struct device_attribute attr_vol_type = 48*c91a719dSKyungmin Park __ATTR(type, S_IRUGO, vol_attribute_show, NULL); 49*c91a719dSKyungmin Park static struct device_attribute attr_vol_name = 50*c91a719dSKyungmin Park __ATTR(name, S_IRUGO, vol_attribute_show, NULL); 51*c91a719dSKyungmin Park static struct device_attribute attr_vol_corrupted = 52*c91a719dSKyungmin Park __ATTR(corrupted, S_IRUGO, vol_attribute_show, NULL); 53*c91a719dSKyungmin Park static struct device_attribute attr_vol_alignment = 54*c91a719dSKyungmin Park __ATTR(alignment, S_IRUGO, vol_attribute_show, NULL); 55*c91a719dSKyungmin Park static struct device_attribute attr_vol_usable_eb_size = 56*c91a719dSKyungmin Park __ATTR(usable_eb_size, S_IRUGO, vol_attribute_show, NULL); 57*c91a719dSKyungmin Park static struct device_attribute attr_vol_data_bytes = 58*c91a719dSKyungmin Park __ATTR(data_bytes, S_IRUGO, vol_attribute_show, NULL); 59*c91a719dSKyungmin Park static struct device_attribute attr_vol_upd_marker = 60*c91a719dSKyungmin Park __ATTR(upd_marker, S_IRUGO, vol_attribute_show, NULL); 61*c91a719dSKyungmin Park 62*c91a719dSKyungmin Park /* 63*c91a719dSKyungmin Park * "Show" method for files in '/<sysfs>/class/ubi/ubiX_Y/'. 64*c91a719dSKyungmin Park * 65*c91a719dSKyungmin Park * Consider a situation: 66*c91a719dSKyungmin Park * A. process 1 opens a sysfs file related to volume Y, say 67*c91a719dSKyungmin Park * /<sysfs>/class/ubi/ubiX_Y/reserved_ebs; 68*c91a719dSKyungmin Park * B. process 2 removes volume Y; 69*c91a719dSKyungmin Park * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file; 70*c91a719dSKyungmin Park * 71*c91a719dSKyungmin Park * In this situation, this function will return %-ENODEV because it will find 72*c91a719dSKyungmin Park * out that the volume was removed from the @ubi->volumes array. 73*c91a719dSKyungmin Park */ 74*c91a719dSKyungmin Park static ssize_t vol_attribute_show(struct device *dev, 75*c91a719dSKyungmin Park struct device_attribute *attr, char *buf) 76*c91a719dSKyungmin Park { 77*c91a719dSKyungmin Park int ret; 78*c91a719dSKyungmin Park struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); 79*c91a719dSKyungmin Park struct ubi_device *ubi; 80*c91a719dSKyungmin Park 81*c91a719dSKyungmin Park ubi = ubi_get_device(vol->ubi->ubi_num); 82*c91a719dSKyungmin Park if (!ubi) 83*c91a719dSKyungmin Park return -ENODEV; 84*c91a719dSKyungmin Park 85*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 86*c91a719dSKyungmin Park if (!ubi->volumes[vol->vol_id]) { 87*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 88*c91a719dSKyungmin Park ubi_put_device(ubi); 89*c91a719dSKyungmin Park return -ENODEV; 90*c91a719dSKyungmin Park } 91*c91a719dSKyungmin Park /* Take a reference to prevent volume removal */ 92*c91a719dSKyungmin Park vol->ref_count += 1; 93*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 94*c91a719dSKyungmin Park 95*c91a719dSKyungmin Park if (attr == &attr_vol_reserved_ebs) 96*c91a719dSKyungmin Park ret = sprintf(buf, "%d\n", vol->reserved_pebs); 97*c91a719dSKyungmin Park else if (attr == &attr_vol_type) { 98*c91a719dSKyungmin Park const char *tp; 99*c91a719dSKyungmin Park 100*c91a719dSKyungmin Park if (vol->vol_type == UBI_DYNAMIC_VOLUME) 101*c91a719dSKyungmin Park tp = "dynamic"; 102*c91a719dSKyungmin Park else 103*c91a719dSKyungmin Park tp = "static"; 104*c91a719dSKyungmin Park ret = sprintf(buf, "%s\n", tp); 105*c91a719dSKyungmin Park } else if (attr == &attr_vol_name) 106*c91a719dSKyungmin Park ret = sprintf(buf, "%s\n", vol->name); 107*c91a719dSKyungmin Park else if (attr == &attr_vol_corrupted) 108*c91a719dSKyungmin Park ret = sprintf(buf, "%d\n", vol->corrupted); 109*c91a719dSKyungmin Park else if (attr == &attr_vol_alignment) 110*c91a719dSKyungmin Park ret = sprintf(buf, "%d\n", vol->alignment); 111*c91a719dSKyungmin Park else if (attr == &attr_vol_usable_eb_size) 112*c91a719dSKyungmin Park ret = sprintf(buf, "%d\n", vol->usable_leb_size); 113*c91a719dSKyungmin Park else if (attr == &attr_vol_data_bytes) 114*c91a719dSKyungmin Park ret = sprintf(buf, "%lld\n", vol->used_bytes); 115*c91a719dSKyungmin Park else if (attr == &attr_vol_upd_marker) 116*c91a719dSKyungmin Park ret = sprintf(buf, "%d\n", vol->upd_marker); 117*c91a719dSKyungmin Park else 118*c91a719dSKyungmin Park /* This must be a bug */ 119*c91a719dSKyungmin Park ret = -EINVAL; 120*c91a719dSKyungmin Park 121*c91a719dSKyungmin Park /* We've done the operation, drop volume and UBI device references */ 122*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 123*c91a719dSKyungmin Park vol->ref_count -= 1; 124*c91a719dSKyungmin Park ubi_assert(vol->ref_count >= 0); 125*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 126*c91a719dSKyungmin Park ubi_put_device(ubi); 127*c91a719dSKyungmin Park return ret; 128*c91a719dSKyungmin Park } 129*c91a719dSKyungmin Park #endif 130*c91a719dSKyungmin Park 131*c91a719dSKyungmin Park /* Release method for volume devices */ 132*c91a719dSKyungmin Park static void vol_release(struct device *dev) 133*c91a719dSKyungmin Park { 134*c91a719dSKyungmin Park struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev); 135*c91a719dSKyungmin Park 136*c91a719dSKyungmin Park kfree(vol); 137*c91a719dSKyungmin Park } 138*c91a719dSKyungmin Park 139*c91a719dSKyungmin Park #ifdef UBI_LINUX 140*c91a719dSKyungmin Park /** 141*c91a719dSKyungmin Park * volume_sysfs_init - initialize sysfs for new volume. 142*c91a719dSKyungmin Park * @ubi: UBI device description object 143*c91a719dSKyungmin Park * @vol: volume description object 144*c91a719dSKyungmin Park * 145*c91a719dSKyungmin Park * This function returns zero in case of success and a negative error code in 146*c91a719dSKyungmin Park * case of failure. 147*c91a719dSKyungmin Park * 148*c91a719dSKyungmin Park * Note, this function does not free allocated resources in case of failure - 149*c91a719dSKyungmin Park * the caller does it. This is because this would cause release() here and the 150*c91a719dSKyungmin Park * caller would oops. 151*c91a719dSKyungmin Park */ 152*c91a719dSKyungmin Park static int volume_sysfs_init(struct ubi_device *ubi, struct ubi_volume *vol) 153*c91a719dSKyungmin Park { 154*c91a719dSKyungmin Park int err; 155*c91a719dSKyungmin Park 156*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_reserved_ebs); 157*c91a719dSKyungmin Park if (err) 158*c91a719dSKyungmin Park return err; 159*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_type); 160*c91a719dSKyungmin Park if (err) 161*c91a719dSKyungmin Park return err; 162*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_name); 163*c91a719dSKyungmin Park if (err) 164*c91a719dSKyungmin Park return err; 165*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_corrupted); 166*c91a719dSKyungmin Park if (err) 167*c91a719dSKyungmin Park return err; 168*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_alignment); 169*c91a719dSKyungmin Park if (err) 170*c91a719dSKyungmin Park return err; 171*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_usable_eb_size); 172*c91a719dSKyungmin Park if (err) 173*c91a719dSKyungmin Park return err; 174*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_data_bytes); 175*c91a719dSKyungmin Park if (err) 176*c91a719dSKyungmin Park return err; 177*c91a719dSKyungmin Park err = device_create_file(&vol->dev, &attr_vol_upd_marker); 178*c91a719dSKyungmin Park return err; 179*c91a719dSKyungmin Park } 180*c91a719dSKyungmin Park 181*c91a719dSKyungmin Park /** 182*c91a719dSKyungmin Park * volume_sysfs_close - close sysfs for a volume. 183*c91a719dSKyungmin Park * @vol: volume description object 184*c91a719dSKyungmin Park */ 185*c91a719dSKyungmin Park static void volume_sysfs_close(struct ubi_volume *vol) 186*c91a719dSKyungmin Park { 187*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_upd_marker); 188*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_data_bytes); 189*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_usable_eb_size); 190*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_alignment); 191*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_corrupted); 192*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_name); 193*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_type); 194*c91a719dSKyungmin Park device_remove_file(&vol->dev, &attr_vol_reserved_ebs); 195*c91a719dSKyungmin Park device_unregister(&vol->dev); 196*c91a719dSKyungmin Park } 197*c91a719dSKyungmin Park #endif 198*c91a719dSKyungmin Park 199*c91a719dSKyungmin Park /** 200*c91a719dSKyungmin Park * ubi_create_volume - create volume. 201*c91a719dSKyungmin Park * @ubi: UBI device description object 202*c91a719dSKyungmin Park * @req: volume creation request 203*c91a719dSKyungmin Park * 204*c91a719dSKyungmin Park * This function creates volume described by @req. If @req->vol_id id 205*c91a719dSKyungmin Park * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume 206*c91a719dSKyungmin Park * and saves it in @req->vol_id. Returns zero in case of success and a negative 207*c91a719dSKyungmin Park * error code in case of failure. Note, the caller has to have the 208*c91a719dSKyungmin Park * @ubi->volumes_mutex locked. 209*c91a719dSKyungmin Park */ 210*c91a719dSKyungmin Park int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) 211*c91a719dSKyungmin Park { 212*c91a719dSKyungmin Park int i, err, vol_id = req->vol_id, dont_free = 0; 213*c91a719dSKyungmin Park struct ubi_volume *vol; 214*c91a719dSKyungmin Park struct ubi_vtbl_record vtbl_rec; 215*c91a719dSKyungmin Park uint64_t bytes; 216*c91a719dSKyungmin Park dev_t dev; 217*c91a719dSKyungmin Park 218*c91a719dSKyungmin Park if (ubi->ro_mode) 219*c91a719dSKyungmin Park return -EROFS; 220*c91a719dSKyungmin Park 221*c91a719dSKyungmin Park vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL); 222*c91a719dSKyungmin Park if (!vol) 223*c91a719dSKyungmin Park return -ENOMEM; 224*c91a719dSKyungmin Park 225*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 226*c91a719dSKyungmin Park if (vol_id == UBI_VOL_NUM_AUTO) { 227*c91a719dSKyungmin Park /* Find unused volume ID */ 228*c91a719dSKyungmin Park dbg_msg("search for vacant volume ID"); 229*c91a719dSKyungmin Park for (i = 0; i < ubi->vtbl_slots; i++) 230*c91a719dSKyungmin Park if (!ubi->volumes[i]) { 231*c91a719dSKyungmin Park vol_id = i; 232*c91a719dSKyungmin Park break; 233*c91a719dSKyungmin Park } 234*c91a719dSKyungmin Park 235*c91a719dSKyungmin Park if (vol_id == UBI_VOL_NUM_AUTO) { 236*c91a719dSKyungmin Park dbg_err("out of volume IDs"); 237*c91a719dSKyungmin Park err = -ENFILE; 238*c91a719dSKyungmin Park goto out_unlock; 239*c91a719dSKyungmin Park } 240*c91a719dSKyungmin Park req->vol_id = vol_id; 241*c91a719dSKyungmin Park } 242*c91a719dSKyungmin Park 243*c91a719dSKyungmin Park dbg_msg("volume ID %d, %llu bytes, type %d, name %s", 244*c91a719dSKyungmin Park vol_id, (unsigned long long)req->bytes, 245*c91a719dSKyungmin Park (int)req->vol_type, req->name); 246*c91a719dSKyungmin Park 247*c91a719dSKyungmin Park /* Ensure that this volume does not exist */ 248*c91a719dSKyungmin Park err = -EEXIST; 249*c91a719dSKyungmin Park if (ubi->volumes[vol_id]) { 250*c91a719dSKyungmin Park dbg_err("volume %d already exists", vol_id); 251*c91a719dSKyungmin Park goto out_unlock; 252*c91a719dSKyungmin Park } 253*c91a719dSKyungmin Park 254*c91a719dSKyungmin Park /* Ensure that the name is unique */ 255*c91a719dSKyungmin Park for (i = 0; i < ubi->vtbl_slots; i++) 256*c91a719dSKyungmin Park if (ubi->volumes[i] && 257*c91a719dSKyungmin Park ubi->volumes[i]->name_len == req->name_len && 258*c91a719dSKyungmin Park !strcmp(ubi->volumes[i]->name, req->name)) { 259*c91a719dSKyungmin Park dbg_err("volume \"%s\" exists (ID %d)", req->name, i); 260*c91a719dSKyungmin Park goto out_unlock; 261*c91a719dSKyungmin Park } 262*c91a719dSKyungmin Park 263*c91a719dSKyungmin Park /* Calculate how many eraseblocks are requested */ 264*c91a719dSKyungmin Park vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment; 265*c91a719dSKyungmin Park bytes = req->bytes; 266*c91a719dSKyungmin Park if (do_div(bytes, vol->usable_leb_size)) 267*c91a719dSKyungmin Park vol->reserved_pebs = 1; 268*c91a719dSKyungmin Park vol->reserved_pebs += bytes; 269*c91a719dSKyungmin Park 270*c91a719dSKyungmin Park /* Reserve physical eraseblocks */ 271*c91a719dSKyungmin Park if (vol->reserved_pebs > ubi->avail_pebs) { 272*c91a719dSKyungmin Park dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); 273*c91a719dSKyungmin Park err = -ENOSPC; 274*c91a719dSKyungmin Park goto out_unlock; 275*c91a719dSKyungmin Park } 276*c91a719dSKyungmin Park ubi->avail_pebs -= vol->reserved_pebs; 277*c91a719dSKyungmin Park ubi->rsvd_pebs += vol->reserved_pebs; 278*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 279*c91a719dSKyungmin Park 280*c91a719dSKyungmin Park vol->vol_id = vol_id; 281*c91a719dSKyungmin Park vol->alignment = req->alignment; 282*c91a719dSKyungmin Park vol->data_pad = ubi->leb_size % vol->alignment; 283*c91a719dSKyungmin Park vol->vol_type = req->vol_type; 284*c91a719dSKyungmin Park vol->name_len = req->name_len; 285*c91a719dSKyungmin Park memcpy(vol->name, req->name, vol->name_len + 1); 286*c91a719dSKyungmin Park vol->ubi = ubi; 287*c91a719dSKyungmin Park 288*c91a719dSKyungmin Park /* 289*c91a719dSKyungmin Park * Finish all pending erases because there may be some LEBs belonging 290*c91a719dSKyungmin Park * to the same volume ID. 291*c91a719dSKyungmin Park */ 292*c91a719dSKyungmin Park err = ubi_wl_flush(ubi); 293*c91a719dSKyungmin Park if (err) 294*c91a719dSKyungmin Park goto out_acc; 295*c91a719dSKyungmin Park 296*c91a719dSKyungmin Park vol->eba_tbl = kmalloc(vol->reserved_pebs * sizeof(int), GFP_KERNEL); 297*c91a719dSKyungmin Park if (!vol->eba_tbl) { 298*c91a719dSKyungmin Park err = -ENOMEM; 299*c91a719dSKyungmin Park goto out_acc; 300*c91a719dSKyungmin Park } 301*c91a719dSKyungmin Park 302*c91a719dSKyungmin Park for (i = 0; i < vol->reserved_pebs; i++) 303*c91a719dSKyungmin Park vol->eba_tbl[i] = UBI_LEB_UNMAPPED; 304*c91a719dSKyungmin Park 305*c91a719dSKyungmin Park if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 306*c91a719dSKyungmin Park vol->used_ebs = vol->reserved_pebs; 307*c91a719dSKyungmin Park vol->last_eb_bytes = vol->usable_leb_size; 308*c91a719dSKyungmin Park vol->used_bytes = 309*c91a719dSKyungmin Park (long long)vol->used_ebs * vol->usable_leb_size; 310*c91a719dSKyungmin Park } else { 311*c91a719dSKyungmin Park bytes = vol->used_bytes; 312*c91a719dSKyungmin Park vol->last_eb_bytes = do_div(bytes, vol->usable_leb_size); 313*c91a719dSKyungmin Park vol->used_ebs = bytes; 314*c91a719dSKyungmin Park if (vol->last_eb_bytes) 315*c91a719dSKyungmin Park vol->used_ebs += 1; 316*c91a719dSKyungmin Park else 317*c91a719dSKyungmin Park vol->last_eb_bytes = vol->usable_leb_size; 318*c91a719dSKyungmin Park } 319*c91a719dSKyungmin Park 320*c91a719dSKyungmin Park /* Register character device for the volume */ 321*c91a719dSKyungmin Park cdev_init(&vol->cdev, &ubi_vol_cdev_operations); 322*c91a719dSKyungmin Park vol->cdev.owner = THIS_MODULE; 323*c91a719dSKyungmin Park dev = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1); 324*c91a719dSKyungmin Park err = cdev_add(&vol->cdev, dev, 1); 325*c91a719dSKyungmin Park if (err) { 326*c91a719dSKyungmin Park ubi_err("cannot add character device"); 327*c91a719dSKyungmin Park goto out_mapping; 328*c91a719dSKyungmin Park } 329*c91a719dSKyungmin Park 330*c91a719dSKyungmin Park err = ubi_create_gluebi(ubi, vol); 331*c91a719dSKyungmin Park if (err) 332*c91a719dSKyungmin Park goto out_cdev; 333*c91a719dSKyungmin Park 334*c91a719dSKyungmin Park vol->dev.release = vol_release; 335*c91a719dSKyungmin Park vol->dev.parent = &ubi->dev; 336*c91a719dSKyungmin Park vol->dev.devt = dev; 337*c91a719dSKyungmin Park vol->dev.class = ubi_class; 338*c91a719dSKyungmin Park 339*c91a719dSKyungmin Park sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); 340*c91a719dSKyungmin Park err = device_register(&vol->dev); 341*c91a719dSKyungmin Park if (err) { 342*c91a719dSKyungmin Park ubi_err("cannot register device"); 343*c91a719dSKyungmin Park goto out_gluebi; 344*c91a719dSKyungmin Park } 345*c91a719dSKyungmin Park 346*c91a719dSKyungmin Park err = volume_sysfs_init(ubi, vol); 347*c91a719dSKyungmin Park if (err) 348*c91a719dSKyungmin Park goto out_sysfs; 349*c91a719dSKyungmin Park 350*c91a719dSKyungmin Park /* Fill volume table record */ 351*c91a719dSKyungmin Park memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record)); 352*c91a719dSKyungmin Park vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs); 353*c91a719dSKyungmin Park vtbl_rec.alignment = cpu_to_be32(vol->alignment); 354*c91a719dSKyungmin Park vtbl_rec.data_pad = cpu_to_be32(vol->data_pad); 355*c91a719dSKyungmin Park vtbl_rec.name_len = cpu_to_be16(vol->name_len); 356*c91a719dSKyungmin Park if (vol->vol_type == UBI_DYNAMIC_VOLUME) 357*c91a719dSKyungmin Park vtbl_rec.vol_type = UBI_VID_DYNAMIC; 358*c91a719dSKyungmin Park else 359*c91a719dSKyungmin Park vtbl_rec.vol_type = UBI_VID_STATIC; 360*c91a719dSKyungmin Park memcpy(vtbl_rec.name, vol->name, vol->name_len + 1); 361*c91a719dSKyungmin Park 362*c91a719dSKyungmin Park err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 363*c91a719dSKyungmin Park if (err) 364*c91a719dSKyungmin Park goto out_sysfs; 365*c91a719dSKyungmin Park 366*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 367*c91a719dSKyungmin Park ubi->volumes[vol_id] = vol; 368*c91a719dSKyungmin Park ubi->vol_count += 1; 369*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 370*c91a719dSKyungmin Park 371*c91a719dSKyungmin Park paranoid_check_volumes(ubi); 372*c91a719dSKyungmin Park return 0; 373*c91a719dSKyungmin Park 374*c91a719dSKyungmin Park out_sysfs: 375*c91a719dSKyungmin Park /* 376*c91a719dSKyungmin Park * We have registered our device, we should not free the volume* 377*c91a719dSKyungmin Park * description object in this function in case of an error - it is 378*c91a719dSKyungmin Park * freed by the release function. 379*c91a719dSKyungmin Park * 380*c91a719dSKyungmin Park * Get device reference to prevent the release function from being 381*c91a719dSKyungmin Park * called just after sysfs has been closed. 382*c91a719dSKyungmin Park */ 383*c91a719dSKyungmin Park dont_free = 1; 384*c91a719dSKyungmin Park get_device(&vol->dev); 385*c91a719dSKyungmin Park volume_sysfs_close(vol); 386*c91a719dSKyungmin Park out_gluebi: 387*c91a719dSKyungmin Park if (ubi_destroy_gluebi(vol)) 388*c91a719dSKyungmin Park dbg_err("cannot destroy gluebi for volume %d:%d", 389*c91a719dSKyungmin Park ubi->ubi_num, vol_id); 390*c91a719dSKyungmin Park out_cdev: 391*c91a719dSKyungmin Park cdev_del(&vol->cdev); 392*c91a719dSKyungmin Park out_mapping: 393*c91a719dSKyungmin Park kfree(vol->eba_tbl); 394*c91a719dSKyungmin Park out_acc: 395*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 396*c91a719dSKyungmin Park ubi->rsvd_pebs -= vol->reserved_pebs; 397*c91a719dSKyungmin Park ubi->avail_pebs += vol->reserved_pebs; 398*c91a719dSKyungmin Park out_unlock: 399*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 400*c91a719dSKyungmin Park if (dont_free) 401*c91a719dSKyungmin Park put_device(&vol->dev); 402*c91a719dSKyungmin Park else 403*c91a719dSKyungmin Park kfree(vol); 404*c91a719dSKyungmin Park ubi_err("cannot create volume %d, error %d", vol_id, err); 405*c91a719dSKyungmin Park return err; 406*c91a719dSKyungmin Park } 407*c91a719dSKyungmin Park 408*c91a719dSKyungmin Park /** 409*c91a719dSKyungmin Park * ubi_remove_volume - remove volume. 410*c91a719dSKyungmin Park * @desc: volume descriptor 411*c91a719dSKyungmin Park * 412*c91a719dSKyungmin Park * This function removes volume described by @desc. The volume has to be opened 413*c91a719dSKyungmin Park * in "exclusive" mode. Returns zero in case of success and a negative error 414*c91a719dSKyungmin Park * code in case of failure. The caller has to have the @ubi->volumes_mutex 415*c91a719dSKyungmin Park * locked. 416*c91a719dSKyungmin Park */ 417*c91a719dSKyungmin Park int ubi_remove_volume(struct ubi_volume_desc *desc) 418*c91a719dSKyungmin Park { 419*c91a719dSKyungmin Park struct ubi_volume *vol = desc->vol; 420*c91a719dSKyungmin Park struct ubi_device *ubi = vol->ubi; 421*c91a719dSKyungmin Park int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs; 422*c91a719dSKyungmin Park 423*c91a719dSKyungmin Park dbg_msg("remove UBI volume %d", vol_id); 424*c91a719dSKyungmin Park ubi_assert(desc->mode == UBI_EXCLUSIVE); 425*c91a719dSKyungmin Park ubi_assert(vol == ubi->volumes[vol_id]); 426*c91a719dSKyungmin Park 427*c91a719dSKyungmin Park if (ubi->ro_mode) 428*c91a719dSKyungmin Park return -EROFS; 429*c91a719dSKyungmin Park 430*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 431*c91a719dSKyungmin Park if (vol->ref_count > 1) { 432*c91a719dSKyungmin Park /* 433*c91a719dSKyungmin Park * The volume is busy, probably someone is reading one of its 434*c91a719dSKyungmin Park * sysfs files. 435*c91a719dSKyungmin Park */ 436*c91a719dSKyungmin Park err = -EBUSY; 437*c91a719dSKyungmin Park goto out_unlock; 438*c91a719dSKyungmin Park } 439*c91a719dSKyungmin Park ubi->volumes[vol_id] = NULL; 440*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 441*c91a719dSKyungmin Park 442*c91a719dSKyungmin Park err = ubi_destroy_gluebi(vol); 443*c91a719dSKyungmin Park if (err) 444*c91a719dSKyungmin Park goto out_err; 445*c91a719dSKyungmin Park 446*c91a719dSKyungmin Park err = ubi_change_vtbl_record(ubi, vol_id, NULL); 447*c91a719dSKyungmin Park if (err) 448*c91a719dSKyungmin Park goto out_err; 449*c91a719dSKyungmin Park 450*c91a719dSKyungmin Park for (i = 0; i < vol->reserved_pebs; i++) { 451*c91a719dSKyungmin Park err = ubi_eba_unmap_leb(ubi, vol, i); 452*c91a719dSKyungmin Park if (err) 453*c91a719dSKyungmin Park goto out_err; 454*c91a719dSKyungmin Park } 455*c91a719dSKyungmin Park 456*c91a719dSKyungmin Park kfree(vol->eba_tbl); 457*c91a719dSKyungmin Park vol->eba_tbl = NULL; 458*c91a719dSKyungmin Park cdev_del(&vol->cdev); 459*c91a719dSKyungmin Park volume_sysfs_close(vol); 460*c91a719dSKyungmin Park 461*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 462*c91a719dSKyungmin Park ubi->rsvd_pebs -= reserved_pebs; 463*c91a719dSKyungmin Park ubi->avail_pebs += reserved_pebs; 464*c91a719dSKyungmin Park i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 465*c91a719dSKyungmin Park if (i > 0) { 466*c91a719dSKyungmin Park i = ubi->avail_pebs >= i ? i : ubi->avail_pebs; 467*c91a719dSKyungmin Park ubi->avail_pebs -= i; 468*c91a719dSKyungmin Park ubi->rsvd_pebs += i; 469*c91a719dSKyungmin Park ubi->beb_rsvd_pebs += i; 470*c91a719dSKyungmin Park if (i > 0) 471*c91a719dSKyungmin Park ubi_msg("reserve more %d PEBs", i); 472*c91a719dSKyungmin Park } 473*c91a719dSKyungmin Park ubi->vol_count -= 1; 474*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 475*c91a719dSKyungmin Park 476*c91a719dSKyungmin Park paranoid_check_volumes(ubi); 477*c91a719dSKyungmin Park return 0; 478*c91a719dSKyungmin Park 479*c91a719dSKyungmin Park out_err: 480*c91a719dSKyungmin Park ubi_err("cannot remove volume %d, error %d", vol_id, err); 481*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 482*c91a719dSKyungmin Park ubi->volumes[vol_id] = vol; 483*c91a719dSKyungmin Park out_unlock: 484*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 485*c91a719dSKyungmin Park return err; 486*c91a719dSKyungmin Park } 487*c91a719dSKyungmin Park 488*c91a719dSKyungmin Park /** 489*c91a719dSKyungmin Park * ubi_resize_volume - re-size volume. 490*c91a719dSKyungmin Park * @desc: volume descriptor 491*c91a719dSKyungmin Park * @reserved_pebs: new size in physical eraseblocks 492*c91a719dSKyungmin Park * 493*c91a719dSKyungmin Park * This function re-sizes the volume and returns zero in case of success, and a 494*c91a719dSKyungmin Park * negative error code in case of failure. The caller has to have the 495*c91a719dSKyungmin Park * @ubi->volumes_mutex locked. 496*c91a719dSKyungmin Park */ 497*c91a719dSKyungmin Park int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) 498*c91a719dSKyungmin Park { 499*c91a719dSKyungmin Park int i, err, pebs, *new_mapping; 500*c91a719dSKyungmin Park struct ubi_volume *vol = desc->vol; 501*c91a719dSKyungmin Park struct ubi_device *ubi = vol->ubi; 502*c91a719dSKyungmin Park struct ubi_vtbl_record vtbl_rec; 503*c91a719dSKyungmin Park int vol_id = vol->vol_id; 504*c91a719dSKyungmin Park 505*c91a719dSKyungmin Park if (ubi->ro_mode) 506*c91a719dSKyungmin Park return -EROFS; 507*c91a719dSKyungmin Park 508*c91a719dSKyungmin Park dbg_msg("re-size volume %d to from %d to %d PEBs", 509*c91a719dSKyungmin Park vol_id, vol->reserved_pebs, reserved_pebs); 510*c91a719dSKyungmin Park 511*c91a719dSKyungmin Park if (vol->vol_type == UBI_STATIC_VOLUME && 512*c91a719dSKyungmin Park reserved_pebs < vol->used_ebs) { 513*c91a719dSKyungmin Park dbg_err("too small size %d, %d LEBs contain data", 514*c91a719dSKyungmin Park reserved_pebs, vol->used_ebs); 515*c91a719dSKyungmin Park return -EINVAL; 516*c91a719dSKyungmin Park } 517*c91a719dSKyungmin Park 518*c91a719dSKyungmin Park /* If the size is the same, we have nothing to do */ 519*c91a719dSKyungmin Park if (reserved_pebs == vol->reserved_pebs) 520*c91a719dSKyungmin Park return 0; 521*c91a719dSKyungmin Park 522*c91a719dSKyungmin Park new_mapping = kmalloc(reserved_pebs * sizeof(int), GFP_KERNEL); 523*c91a719dSKyungmin Park if (!new_mapping) 524*c91a719dSKyungmin Park return -ENOMEM; 525*c91a719dSKyungmin Park 526*c91a719dSKyungmin Park for (i = 0; i < reserved_pebs; i++) 527*c91a719dSKyungmin Park new_mapping[i] = UBI_LEB_UNMAPPED; 528*c91a719dSKyungmin Park 529*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 530*c91a719dSKyungmin Park if (vol->ref_count > 1) { 531*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 532*c91a719dSKyungmin Park err = -EBUSY; 533*c91a719dSKyungmin Park goto out_free; 534*c91a719dSKyungmin Park } 535*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 536*c91a719dSKyungmin Park 537*c91a719dSKyungmin Park /* Reserve physical eraseblocks */ 538*c91a719dSKyungmin Park pebs = reserved_pebs - vol->reserved_pebs; 539*c91a719dSKyungmin Park if (pebs > 0) { 540*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 541*c91a719dSKyungmin Park if (pebs > ubi->avail_pebs) { 542*c91a719dSKyungmin Park dbg_err("not enough PEBs: requested %d, available %d", 543*c91a719dSKyungmin Park pebs, ubi->avail_pebs); 544*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 545*c91a719dSKyungmin Park err = -ENOSPC; 546*c91a719dSKyungmin Park goto out_free; 547*c91a719dSKyungmin Park } 548*c91a719dSKyungmin Park ubi->avail_pebs -= pebs; 549*c91a719dSKyungmin Park ubi->rsvd_pebs += pebs; 550*c91a719dSKyungmin Park for (i = 0; i < vol->reserved_pebs; i++) 551*c91a719dSKyungmin Park new_mapping[i] = vol->eba_tbl[i]; 552*c91a719dSKyungmin Park kfree(vol->eba_tbl); 553*c91a719dSKyungmin Park vol->eba_tbl = new_mapping; 554*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 555*c91a719dSKyungmin Park } 556*c91a719dSKyungmin Park 557*c91a719dSKyungmin Park /* Change volume table record */ 558*c91a719dSKyungmin Park memcpy(&vtbl_rec, &ubi->vtbl[vol_id], sizeof(struct ubi_vtbl_record)); 559*c91a719dSKyungmin Park vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs); 560*c91a719dSKyungmin Park err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 561*c91a719dSKyungmin Park if (err) 562*c91a719dSKyungmin Park goto out_acc; 563*c91a719dSKyungmin Park 564*c91a719dSKyungmin Park if (pebs < 0) { 565*c91a719dSKyungmin Park for (i = 0; i < -pebs; i++) { 566*c91a719dSKyungmin Park err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i); 567*c91a719dSKyungmin Park if (err) 568*c91a719dSKyungmin Park goto out_acc; 569*c91a719dSKyungmin Park } 570*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 571*c91a719dSKyungmin Park ubi->rsvd_pebs += pebs; 572*c91a719dSKyungmin Park ubi->avail_pebs -= pebs; 573*c91a719dSKyungmin Park pebs = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs; 574*c91a719dSKyungmin Park if (pebs > 0) { 575*c91a719dSKyungmin Park pebs = ubi->avail_pebs >= pebs ? pebs : ubi->avail_pebs; 576*c91a719dSKyungmin Park ubi->avail_pebs -= pebs; 577*c91a719dSKyungmin Park ubi->rsvd_pebs += pebs; 578*c91a719dSKyungmin Park ubi->beb_rsvd_pebs += pebs; 579*c91a719dSKyungmin Park if (pebs > 0) 580*c91a719dSKyungmin Park ubi_msg("reserve more %d PEBs", pebs); 581*c91a719dSKyungmin Park } 582*c91a719dSKyungmin Park for (i = 0; i < reserved_pebs; i++) 583*c91a719dSKyungmin Park new_mapping[i] = vol->eba_tbl[i]; 584*c91a719dSKyungmin Park kfree(vol->eba_tbl); 585*c91a719dSKyungmin Park vol->eba_tbl = new_mapping; 586*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 587*c91a719dSKyungmin Park } 588*c91a719dSKyungmin Park 589*c91a719dSKyungmin Park vol->reserved_pebs = reserved_pebs; 590*c91a719dSKyungmin Park if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 591*c91a719dSKyungmin Park vol->used_ebs = reserved_pebs; 592*c91a719dSKyungmin Park vol->last_eb_bytes = vol->usable_leb_size; 593*c91a719dSKyungmin Park vol->used_bytes = 594*c91a719dSKyungmin Park (long long)vol->used_ebs * vol->usable_leb_size; 595*c91a719dSKyungmin Park } 596*c91a719dSKyungmin Park 597*c91a719dSKyungmin Park paranoid_check_volumes(ubi); 598*c91a719dSKyungmin Park return 0; 599*c91a719dSKyungmin Park 600*c91a719dSKyungmin Park out_acc: 601*c91a719dSKyungmin Park if (pebs > 0) { 602*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 603*c91a719dSKyungmin Park ubi->rsvd_pebs -= pebs; 604*c91a719dSKyungmin Park ubi->avail_pebs += pebs; 605*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 606*c91a719dSKyungmin Park } 607*c91a719dSKyungmin Park out_free: 608*c91a719dSKyungmin Park kfree(new_mapping); 609*c91a719dSKyungmin Park return err; 610*c91a719dSKyungmin Park } 611*c91a719dSKyungmin Park 612*c91a719dSKyungmin Park /** 613*c91a719dSKyungmin Park * ubi_add_volume - add volume. 614*c91a719dSKyungmin Park * @ubi: UBI device description object 615*c91a719dSKyungmin Park * @vol: volume description object 616*c91a719dSKyungmin Park * 617*c91a719dSKyungmin Park * This function adds an existing volume and initializes all its data 618*c91a719dSKyungmin Park * structures. Returns zero in case of success and a negative error code in 619*c91a719dSKyungmin Park * case of failure. 620*c91a719dSKyungmin Park */ 621*c91a719dSKyungmin Park int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) 622*c91a719dSKyungmin Park { 623*c91a719dSKyungmin Park int err, vol_id = vol->vol_id; 624*c91a719dSKyungmin Park dev_t dev; 625*c91a719dSKyungmin Park 626*c91a719dSKyungmin Park dbg_msg("add volume %d", vol_id); 627*c91a719dSKyungmin Park ubi_dbg_dump_vol_info(vol); 628*c91a719dSKyungmin Park 629*c91a719dSKyungmin Park /* Register character device for the volume */ 630*c91a719dSKyungmin Park cdev_init(&vol->cdev, &ubi_vol_cdev_operations); 631*c91a719dSKyungmin Park vol->cdev.owner = THIS_MODULE; 632*c91a719dSKyungmin Park dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1); 633*c91a719dSKyungmin Park err = cdev_add(&vol->cdev, dev, 1); 634*c91a719dSKyungmin Park if (err) { 635*c91a719dSKyungmin Park ubi_err("cannot add character device for volume %d, error %d", 636*c91a719dSKyungmin Park vol_id, err); 637*c91a719dSKyungmin Park return err; 638*c91a719dSKyungmin Park } 639*c91a719dSKyungmin Park 640*c91a719dSKyungmin Park err = ubi_create_gluebi(ubi, vol); 641*c91a719dSKyungmin Park if (err) 642*c91a719dSKyungmin Park goto out_cdev; 643*c91a719dSKyungmin Park 644*c91a719dSKyungmin Park vol->dev.release = vol_release; 645*c91a719dSKyungmin Park vol->dev.parent = &ubi->dev; 646*c91a719dSKyungmin Park vol->dev.devt = dev; 647*c91a719dSKyungmin Park vol->dev.class = ubi_class; 648*c91a719dSKyungmin Park sprintf(&vol->dev.bus_id[0], "%s_%d", ubi->ubi_name, vol->vol_id); 649*c91a719dSKyungmin Park err = device_register(&vol->dev); 650*c91a719dSKyungmin Park if (err) 651*c91a719dSKyungmin Park goto out_gluebi; 652*c91a719dSKyungmin Park 653*c91a719dSKyungmin Park err = volume_sysfs_init(ubi, vol); 654*c91a719dSKyungmin Park if (err) { 655*c91a719dSKyungmin Park cdev_del(&vol->cdev); 656*c91a719dSKyungmin Park err = ubi_destroy_gluebi(vol); 657*c91a719dSKyungmin Park volume_sysfs_close(vol); 658*c91a719dSKyungmin Park return err; 659*c91a719dSKyungmin Park } 660*c91a719dSKyungmin Park 661*c91a719dSKyungmin Park paranoid_check_volumes(ubi); 662*c91a719dSKyungmin Park return 0; 663*c91a719dSKyungmin Park 664*c91a719dSKyungmin Park out_gluebi: 665*c91a719dSKyungmin Park err = ubi_destroy_gluebi(vol); 666*c91a719dSKyungmin Park out_cdev: 667*c91a719dSKyungmin Park cdev_del(&vol->cdev); 668*c91a719dSKyungmin Park return err; 669*c91a719dSKyungmin Park } 670*c91a719dSKyungmin Park 671*c91a719dSKyungmin Park /** 672*c91a719dSKyungmin Park * ubi_free_volume - free volume. 673*c91a719dSKyungmin Park * @ubi: UBI device description object 674*c91a719dSKyungmin Park * @vol: volume description object 675*c91a719dSKyungmin Park * 676*c91a719dSKyungmin Park * This function frees all resources for volume @vol but does not remove it. 677*c91a719dSKyungmin Park * Used only when the UBI device is detached. 678*c91a719dSKyungmin Park */ 679*c91a719dSKyungmin Park void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) 680*c91a719dSKyungmin Park { 681*c91a719dSKyungmin Park int err; 682*c91a719dSKyungmin Park 683*c91a719dSKyungmin Park dbg_msg("free volume %d", vol->vol_id); 684*c91a719dSKyungmin Park 685*c91a719dSKyungmin Park ubi->volumes[vol->vol_id] = NULL; 686*c91a719dSKyungmin Park err = ubi_destroy_gluebi(vol); 687*c91a719dSKyungmin Park cdev_del(&vol->cdev); 688*c91a719dSKyungmin Park volume_sysfs_close(vol); 689*c91a719dSKyungmin Park } 690*c91a719dSKyungmin Park 691*c91a719dSKyungmin Park #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID 692*c91a719dSKyungmin Park 693*c91a719dSKyungmin Park /** 694*c91a719dSKyungmin Park * paranoid_check_volume - check volume information. 695*c91a719dSKyungmin Park * @ubi: UBI device description object 696*c91a719dSKyungmin Park * @vol_id: volume ID 697*c91a719dSKyungmin Park */ 698*c91a719dSKyungmin Park static void paranoid_check_volume(struct ubi_device *ubi, int vol_id) 699*c91a719dSKyungmin Park { 700*c91a719dSKyungmin Park int idx = vol_id2idx(ubi, vol_id); 701*c91a719dSKyungmin Park int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; 702*c91a719dSKyungmin Park const struct ubi_volume *vol; 703*c91a719dSKyungmin Park long long n; 704*c91a719dSKyungmin Park const char *name; 705*c91a719dSKyungmin Park 706*c91a719dSKyungmin Park spin_lock(&ubi->volumes_lock); 707*c91a719dSKyungmin Park reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs); 708*c91a719dSKyungmin Park vol = ubi->volumes[idx]; 709*c91a719dSKyungmin Park 710*c91a719dSKyungmin Park if (!vol) { 711*c91a719dSKyungmin Park if (reserved_pebs) { 712*c91a719dSKyungmin Park ubi_err("no volume info, but volume exists"); 713*c91a719dSKyungmin Park goto fail; 714*c91a719dSKyungmin Park } 715*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 716*c91a719dSKyungmin Park return; 717*c91a719dSKyungmin Park } 718*c91a719dSKyungmin Park 719*c91a719dSKyungmin Park if (vol->exclusive) { 720*c91a719dSKyungmin Park /* 721*c91a719dSKyungmin Park * The volume may be being created at the moment, do not check 722*c91a719dSKyungmin Park * it (e.g., it may be in the middle of ubi_create_volume(). 723*c91a719dSKyungmin Park */ 724*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 725*c91a719dSKyungmin Park return; 726*c91a719dSKyungmin Park } 727*c91a719dSKyungmin Park 728*c91a719dSKyungmin Park if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 || 729*c91a719dSKyungmin Park vol->name_len < 0) { 730*c91a719dSKyungmin Park ubi_err("negative values"); 731*c91a719dSKyungmin Park goto fail; 732*c91a719dSKyungmin Park } 733*c91a719dSKyungmin Park if (vol->alignment > ubi->leb_size || vol->alignment == 0) { 734*c91a719dSKyungmin Park ubi_err("bad alignment"); 735*c91a719dSKyungmin Park goto fail; 736*c91a719dSKyungmin Park } 737*c91a719dSKyungmin Park 738*c91a719dSKyungmin Park n = vol->alignment & (ubi->min_io_size - 1); 739*c91a719dSKyungmin Park if (vol->alignment != 1 && n) { 740*c91a719dSKyungmin Park ubi_err("alignment is not multiple of min I/O unit"); 741*c91a719dSKyungmin Park goto fail; 742*c91a719dSKyungmin Park } 743*c91a719dSKyungmin Park 744*c91a719dSKyungmin Park n = ubi->leb_size % vol->alignment; 745*c91a719dSKyungmin Park if (vol->data_pad != n) { 746*c91a719dSKyungmin Park ubi_err("bad data_pad, has to be %lld", n); 747*c91a719dSKyungmin Park goto fail; 748*c91a719dSKyungmin Park } 749*c91a719dSKyungmin Park 750*c91a719dSKyungmin Park if (vol->vol_type != UBI_DYNAMIC_VOLUME && 751*c91a719dSKyungmin Park vol->vol_type != UBI_STATIC_VOLUME) { 752*c91a719dSKyungmin Park ubi_err("bad vol_type"); 753*c91a719dSKyungmin Park goto fail; 754*c91a719dSKyungmin Park } 755*c91a719dSKyungmin Park 756*c91a719dSKyungmin Park if (vol->upd_marker && vol->corrupted) { 757*c91a719dSKyungmin Park dbg_err("update marker and corrupted simultaneously"); 758*c91a719dSKyungmin Park goto fail; 759*c91a719dSKyungmin Park } 760*c91a719dSKyungmin Park 761*c91a719dSKyungmin Park if (vol->reserved_pebs > ubi->good_peb_count) { 762*c91a719dSKyungmin Park ubi_err("too large reserved_pebs"); 763*c91a719dSKyungmin Park goto fail; 764*c91a719dSKyungmin Park } 765*c91a719dSKyungmin Park 766*c91a719dSKyungmin Park n = ubi->leb_size - vol->data_pad; 767*c91a719dSKyungmin Park if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) { 768*c91a719dSKyungmin Park ubi_err("bad usable_leb_size, has to be %lld", n); 769*c91a719dSKyungmin Park goto fail; 770*c91a719dSKyungmin Park } 771*c91a719dSKyungmin Park 772*c91a719dSKyungmin Park if (vol->name_len > UBI_VOL_NAME_MAX) { 773*c91a719dSKyungmin Park ubi_err("too long volume name, max is %d", UBI_VOL_NAME_MAX); 774*c91a719dSKyungmin Park goto fail; 775*c91a719dSKyungmin Park } 776*c91a719dSKyungmin Park 777*c91a719dSKyungmin Park if (!vol->name) { 778*c91a719dSKyungmin Park ubi_err("NULL volume name"); 779*c91a719dSKyungmin Park goto fail; 780*c91a719dSKyungmin Park } 781*c91a719dSKyungmin Park 782*c91a719dSKyungmin Park n = strnlen(vol->name, vol->name_len + 1); 783*c91a719dSKyungmin Park if (n != vol->name_len) { 784*c91a719dSKyungmin Park ubi_err("bad name_len %lld", n); 785*c91a719dSKyungmin Park goto fail; 786*c91a719dSKyungmin Park } 787*c91a719dSKyungmin Park 788*c91a719dSKyungmin Park n = (long long)vol->used_ebs * vol->usable_leb_size; 789*c91a719dSKyungmin Park if (vol->vol_type == UBI_DYNAMIC_VOLUME) { 790*c91a719dSKyungmin Park if (vol->corrupted) { 791*c91a719dSKyungmin Park ubi_err("corrupted dynamic volume"); 792*c91a719dSKyungmin Park goto fail; 793*c91a719dSKyungmin Park } 794*c91a719dSKyungmin Park if (vol->used_ebs != vol->reserved_pebs) { 795*c91a719dSKyungmin Park ubi_err("bad used_ebs"); 796*c91a719dSKyungmin Park goto fail; 797*c91a719dSKyungmin Park } 798*c91a719dSKyungmin Park if (vol->last_eb_bytes != vol->usable_leb_size) { 799*c91a719dSKyungmin Park ubi_err("bad last_eb_bytes"); 800*c91a719dSKyungmin Park goto fail; 801*c91a719dSKyungmin Park } 802*c91a719dSKyungmin Park if (vol->used_bytes != n) { 803*c91a719dSKyungmin Park ubi_err("bad used_bytes"); 804*c91a719dSKyungmin Park goto fail; 805*c91a719dSKyungmin Park } 806*c91a719dSKyungmin Park } else { 807*c91a719dSKyungmin Park if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) { 808*c91a719dSKyungmin Park ubi_err("bad used_ebs"); 809*c91a719dSKyungmin Park goto fail; 810*c91a719dSKyungmin Park } 811*c91a719dSKyungmin Park if (vol->last_eb_bytes < 0 || 812*c91a719dSKyungmin Park vol->last_eb_bytes > vol->usable_leb_size) { 813*c91a719dSKyungmin Park ubi_err("bad last_eb_bytes"); 814*c91a719dSKyungmin Park goto fail; 815*c91a719dSKyungmin Park } 816*c91a719dSKyungmin Park if (vol->used_bytes < 0 || vol->used_bytes > n || 817*c91a719dSKyungmin Park vol->used_bytes < n - vol->usable_leb_size) { 818*c91a719dSKyungmin Park ubi_err("bad used_bytes"); 819*c91a719dSKyungmin Park goto fail; 820*c91a719dSKyungmin Park } 821*c91a719dSKyungmin Park } 822*c91a719dSKyungmin Park 823*c91a719dSKyungmin Park alignment = be32_to_cpu(ubi->vtbl[vol_id].alignment); 824*c91a719dSKyungmin Park data_pad = be32_to_cpu(ubi->vtbl[vol_id].data_pad); 825*c91a719dSKyungmin Park name_len = be16_to_cpu(ubi->vtbl[vol_id].name_len); 826*c91a719dSKyungmin Park upd_marker = ubi->vtbl[vol_id].upd_marker; 827*c91a719dSKyungmin Park name = &ubi->vtbl[vol_id].name[0]; 828*c91a719dSKyungmin Park if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC) 829*c91a719dSKyungmin Park vol_type = UBI_DYNAMIC_VOLUME; 830*c91a719dSKyungmin Park else 831*c91a719dSKyungmin Park vol_type = UBI_STATIC_VOLUME; 832*c91a719dSKyungmin Park 833*c91a719dSKyungmin Park if (alignment != vol->alignment || data_pad != vol->data_pad || 834*c91a719dSKyungmin Park upd_marker != vol->upd_marker || vol_type != vol->vol_type || 835*c91a719dSKyungmin Park name_len!= vol->name_len || strncmp(name, vol->name, name_len)) { 836*c91a719dSKyungmin Park ubi_err("volume info is different"); 837*c91a719dSKyungmin Park goto fail; 838*c91a719dSKyungmin Park } 839*c91a719dSKyungmin Park 840*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 841*c91a719dSKyungmin Park return; 842*c91a719dSKyungmin Park 843*c91a719dSKyungmin Park fail: 844*c91a719dSKyungmin Park ubi_err("paranoid check failed for volume %d", vol_id); 845*c91a719dSKyungmin Park ubi_dbg_dump_vol_info(vol); 846*c91a719dSKyungmin Park ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); 847*c91a719dSKyungmin Park spin_unlock(&ubi->volumes_lock); 848*c91a719dSKyungmin Park BUG(); 849*c91a719dSKyungmin Park } 850*c91a719dSKyungmin Park 851*c91a719dSKyungmin Park /** 852*c91a719dSKyungmin Park * paranoid_check_volumes - check information about all volumes. 853*c91a719dSKyungmin Park * @ubi: UBI device description object 854*c91a719dSKyungmin Park */ 855*c91a719dSKyungmin Park static void paranoid_check_volumes(struct ubi_device *ubi) 856*c91a719dSKyungmin Park { 857*c91a719dSKyungmin Park int i; 858*c91a719dSKyungmin Park 859*c91a719dSKyungmin Park for (i = 0; i < ubi->vtbl_slots; i++) 860*c91a719dSKyungmin Park paranoid_check_volume(ubi, i); 861*c91a719dSKyungmin Park } 862*c91a719dSKyungmin Park #endif 863