847 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) International Business Machines Corp., 20064 *5 * Author: Artem Bityutskiy (Битюцкий Артём)6 */7 8/*9 * This file contains implementation of volume creation, deletion, updating and10 * resizing.11 */12 13#include <linux/err.h>14#include <linux/math64.h>15#include <linux/slab.h>16#include <linux/export.h>17#include "ubi.h"18 19static int self_check_volumes(struct ubi_device *ubi);20 21static ssize_t vol_attribute_show(struct device *dev,22 struct device_attribute *attr, char *buf);23 24/* Device attributes corresponding to files in '/<sysfs>/class/ubi/ubiX_Y' */25static struct device_attribute attr_vol_reserved_ebs =26 __ATTR(reserved_ebs, S_IRUGO, vol_attribute_show, NULL);27static struct device_attribute attr_vol_type =28 __ATTR(type, S_IRUGO, vol_attribute_show, NULL);29static struct device_attribute attr_vol_name =30 __ATTR(name, S_IRUGO, vol_attribute_show, NULL);31static struct device_attribute attr_vol_corrupted =32 __ATTR(corrupted, S_IRUGO, vol_attribute_show, NULL);33static struct device_attribute attr_vol_alignment =34 __ATTR(alignment, S_IRUGO, vol_attribute_show, NULL);35static struct device_attribute attr_vol_usable_eb_size =36 __ATTR(usable_eb_size, S_IRUGO, vol_attribute_show, NULL);37static struct device_attribute attr_vol_data_bytes =38 __ATTR(data_bytes, S_IRUGO, vol_attribute_show, NULL);39static struct device_attribute attr_vol_upd_marker =40 __ATTR(upd_marker, S_IRUGO, vol_attribute_show, NULL);41 42/*43 * "Show" method for files in '/<sysfs>/class/ubi/ubiX_Y/'.44 *45 * Consider a situation:46 * A. process 1 opens a sysfs file related to volume Y, say47 * /<sysfs>/class/ubi/ubiX_Y/reserved_ebs;48 * B. process 2 removes volume Y;49 * C. process 1 starts reading the /<sysfs>/class/ubi/ubiX_Y/reserved_ebs file;50 *51 * In this situation, this function will return %-ENODEV because it will find52 * out that the volume was removed from the @ubi->volumes array.53 */54static ssize_t vol_attribute_show(struct device *dev,55 struct device_attribute *attr, char *buf)56{57 int ret;58 struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);59 struct ubi_device *ubi = vol->ubi;60 61 spin_lock(&ubi->volumes_lock);62 if (!ubi->volumes[vol->vol_id] || ubi->volumes[vol->vol_id]->is_dead) {63 spin_unlock(&ubi->volumes_lock);64 return -ENODEV;65 }66 /* Take a reference to prevent volume removal */67 vol->ref_count += 1;68 spin_unlock(&ubi->volumes_lock);69 70 if (attr == &attr_vol_reserved_ebs)71 ret = sprintf(buf, "%d\n", vol->reserved_pebs);72 else if (attr == &attr_vol_type) {73 const char *tp;74 75 if (vol->vol_type == UBI_DYNAMIC_VOLUME)76 tp = "dynamic";77 else78 tp = "static";79 ret = sprintf(buf, "%s\n", tp);80 } else if (attr == &attr_vol_name)81 ret = sprintf(buf, "%s\n", vol->name);82 else if (attr == &attr_vol_corrupted)83 ret = sprintf(buf, "%d\n", vol->corrupted);84 else if (attr == &attr_vol_alignment)85 ret = sprintf(buf, "%d\n", vol->alignment);86 else if (attr == &attr_vol_usable_eb_size)87 ret = sprintf(buf, "%d\n", vol->usable_leb_size);88 else if (attr == &attr_vol_data_bytes)89 ret = sprintf(buf, "%lld\n", vol->used_bytes);90 else if (attr == &attr_vol_upd_marker)91 ret = sprintf(buf, "%d\n", vol->upd_marker);92 else93 /* This must be a bug */94 ret = -EINVAL;95 96 /* We've done the operation, drop volume and UBI device references */97 spin_lock(&ubi->volumes_lock);98 vol->ref_count -= 1;99 ubi_assert(vol->ref_count >= 0);100 spin_unlock(&ubi->volumes_lock);101 return ret;102}103 104static struct attribute *volume_dev_attrs[] = {105 &attr_vol_reserved_ebs.attr,106 &attr_vol_type.attr,107 &attr_vol_name.attr,108 &attr_vol_corrupted.attr,109 &attr_vol_alignment.attr,110 &attr_vol_usable_eb_size.attr,111 &attr_vol_data_bytes.attr,112 &attr_vol_upd_marker.attr,113 NULL114};115ATTRIBUTE_GROUPS(volume_dev);116 117/* Release method for volume devices */118static void vol_release(struct device *dev)119{120 struct ubi_volume *vol = container_of(dev, struct ubi_volume, dev);121 122 ubi_eba_replace_table(vol, NULL);123 ubi_fastmap_destroy_checkmap(vol);124 kfree(vol);125}126 127static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol)128{129 struct fwnode_handle *fw_vols, *fw_vol;130 const char *volname;131 u32 volid;132 133 fw_vols = device_get_named_child_node(vol->dev.parent->parent, "volumes");134 if (!fw_vols)135 return NULL;136 137 fwnode_for_each_child_node(fw_vols, fw_vol) {138 if (!fwnode_property_read_string(fw_vol, "volname", &volname) &&139 strncmp(volname, vol->name, vol->name_len))140 continue;141 142 if (!fwnode_property_read_u32(fw_vol, "volid", &volid) &&143 vol->vol_id != volid)144 continue;145 146 return fw_vol;147 }148 149 return NULL;150}151 152/**153 * ubi_create_volume - create volume.154 * @ubi: UBI device description object155 * @req: volume creation request156 *157 * This function creates volume described by @req. If @req->vol_id id158 * %UBI_VOL_NUM_AUTO, this function automatically assign ID to the new volume159 * and saves it in @req->vol_id. Returns zero in case of success and a negative160 * error code in case of failure. Note, the caller has to have the161 * @ubi->device_mutex locked.162 */163int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)164{165 int i, err, vol_id = req->vol_id;166 struct ubi_volume *vol;167 struct ubi_vtbl_record vtbl_rec;168 struct ubi_eba_table *eba_tbl = NULL;169 170 if (ubi->ro_mode)171 return -EROFS;172 173 vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);174 if (!vol)175 return -ENOMEM;176 177 device_initialize(&vol->dev);178 vol->dev.release = vol_release;179 vol->dev.parent = &ubi->dev;180 vol->dev.class = &ubi_class;181 vol->dev.groups = volume_dev_groups;182 183 if (req->flags & UBI_VOL_SKIP_CRC_CHECK_FLG)184 vol->skip_check = 1;185 186 spin_lock(&ubi->volumes_lock);187 if (vol_id == UBI_VOL_NUM_AUTO) {188 /* Find unused volume ID */189 dbg_gen("search for vacant volume ID");190 for (i = 0; i < ubi->vtbl_slots; i++)191 if (!ubi->volumes[i]) {192 vol_id = i;193 break;194 }195 196 if (vol_id == UBI_VOL_NUM_AUTO) {197 ubi_err(ubi, "out of volume IDs");198 err = -ENFILE;199 goto out_unlock;200 }201 req->vol_id = vol_id;202 }203 204 dbg_gen("create device %d, volume %d, %llu bytes, type %d, name %s",205 ubi->ubi_num, vol_id, (unsigned long long)req->bytes,206 (int)req->vol_type, req->name);207 208 /* Ensure that this volume does not exist */209 err = -EEXIST;210 if (ubi->volumes[vol_id]) {211 ubi_err(ubi, "volume %d already exists", vol_id);212 goto out_unlock;213 }214 215 /* Ensure that the name is unique */216 for (i = 0; i < ubi->vtbl_slots; i++)217 if (ubi->volumes[i] && !ubi->volumes[i]->is_dead &&218 ubi->volumes[i]->name_len == req->name_len &&219 !strcmp(ubi->volumes[i]->name, req->name)) {220 ubi_err(ubi, "volume \"%s\" exists (ID %d)",221 req->name, i);222 goto out_unlock;223 }224 225 /* Calculate how many eraseblocks are requested */226 vol->usable_leb_size = ubi->leb_size - ubi->leb_size % req->alignment;227 vol->reserved_pebs = div_u64(req->bytes + vol->usable_leb_size - 1,228 vol->usable_leb_size);229 230 /* Reserve physical eraseblocks */231 if (vol->reserved_pebs > ubi->avail_pebs) {232 ubi_err(ubi, "not enough PEBs, only %d available",233 ubi->avail_pebs);234 if (ubi->corr_peb_count)235 ubi_err(ubi, "%d PEBs are corrupted and not used",236 ubi->corr_peb_count);237 err = -ENOSPC;238 goto out_unlock;239 }240 ubi->avail_pebs -= vol->reserved_pebs;241 ubi->rsvd_pebs += vol->reserved_pebs;242 spin_unlock(&ubi->volumes_lock);243 244 vol->vol_id = vol_id;245 vol->alignment = req->alignment;246 vol->data_pad = ubi->leb_size % vol->alignment;247 vol->vol_type = req->vol_type;248 vol->name_len = req->name_len;249 memcpy(vol->name, req->name, vol->name_len);250 vol->ubi = ubi;251 device_set_node(&vol->dev, find_volume_fwnode(vol));252 253 /*254 * Finish all pending erases because there may be some LEBs belonging255 * to the same volume ID.256 */257 err = ubi_wl_flush(ubi, vol_id, UBI_ALL);258 if (err)259 goto out_acc;260 261 eba_tbl = ubi_eba_create_table(vol, vol->reserved_pebs);262 if (IS_ERR(eba_tbl)) {263 err = PTR_ERR(eba_tbl);264 goto out_acc;265 }266 267 ubi_eba_replace_table(vol, eba_tbl);268 269 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {270 vol->used_ebs = vol->reserved_pebs;271 vol->last_eb_bytes = vol->usable_leb_size;272 vol->used_bytes =273 (long long)vol->used_ebs * vol->usable_leb_size;274 } else {275 vol->used_ebs = div_u64_rem(vol->used_bytes,276 vol->usable_leb_size,277 &vol->last_eb_bytes);278 if (vol->last_eb_bytes != 0)279 vol->used_ebs += 1;280 else281 vol->last_eb_bytes = vol->usable_leb_size;282 }283 284 /* Make volume "available" before it becomes accessible via sysfs */285 spin_lock(&ubi->volumes_lock);286 ubi->volumes[vol_id] = vol;287 ubi->vol_count += 1;288 spin_unlock(&ubi->volumes_lock);289 290 /* Register character device for the volume */291 cdev_init(&vol->cdev, &ubi_vol_cdev_operations);292 vol->cdev.owner = THIS_MODULE;293 294 vol->dev.devt = MKDEV(MAJOR(ubi->cdev.dev), vol_id + 1);295 dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);296 err = cdev_device_add(&vol->cdev, &vol->dev);297 if (err) {298 ubi_err(ubi, "cannot add device");299 goto out_mapping;300 }301 302 /* Fill volume table record */303 memset(&vtbl_rec, 0, sizeof(struct ubi_vtbl_record));304 vtbl_rec.reserved_pebs = cpu_to_be32(vol->reserved_pebs);305 vtbl_rec.alignment = cpu_to_be32(vol->alignment);306 vtbl_rec.data_pad = cpu_to_be32(vol->data_pad);307 vtbl_rec.name_len = cpu_to_be16(vol->name_len);308 if (vol->vol_type == UBI_DYNAMIC_VOLUME)309 vtbl_rec.vol_type = UBI_VID_DYNAMIC;310 else311 vtbl_rec.vol_type = UBI_VID_STATIC;312 313 if (vol->skip_check)314 vtbl_rec.flags |= UBI_VTBL_SKIP_CRC_CHECK_FLG;315 316 memcpy(vtbl_rec.name, vol->name, vol->name_len);317 318 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);319 if (err)320 goto out_sysfs;321 322 ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED);323 self_check_volumes(ubi);324 return err;325 326out_sysfs:327 /*328 * We have registered our device, we should not free the volume329 * description object in this function in case of an error - it is330 * freed by the release function.331 */332 cdev_device_del(&vol->cdev, &vol->dev);333out_mapping:334 spin_lock(&ubi->volumes_lock);335 ubi->volumes[vol_id] = NULL;336 ubi->vol_count -= 1;337 spin_unlock(&ubi->volumes_lock);338out_acc:339 spin_lock(&ubi->volumes_lock);340 ubi->rsvd_pebs -= vol->reserved_pebs;341 ubi->avail_pebs += vol->reserved_pebs;342out_unlock:343 spin_unlock(&ubi->volumes_lock);344 put_device(&vol->dev);345 ubi_err(ubi, "cannot create volume %d, error %d", vol_id, err);346 return err;347}348 349/**350 * ubi_remove_volume - remove volume.351 * @desc: volume descriptor352 * @no_vtbl: do not change volume table if not zero353 *354 * This function removes volume described by @desc. The volume has to be opened355 * in "exclusive" mode. Returns zero in case of success and a negative error356 * code in case of failure. The caller has to have the @ubi->device_mutex357 * locked.358 */359int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)360{361 struct ubi_volume *vol = desc->vol;362 struct ubi_device *ubi = vol->ubi;363 int i, err, vol_id = vol->vol_id, reserved_pebs = vol->reserved_pebs;364 365 dbg_gen("remove device %d, volume %d", ubi->ubi_num, vol_id);366 ubi_assert(desc->mode == UBI_EXCLUSIVE);367 ubi_assert(vol == ubi->volumes[vol_id]);368 369 if (ubi->ro_mode)370 return -EROFS;371 372 spin_lock(&ubi->volumes_lock);373 if (vol->ref_count > 1) {374 /*375 * The volume is busy, probably someone is reading one of its376 * sysfs files.377 */378 err = -EBUSY;379 goto out_unlock;380 }381 382 /*383 * Mark volume as dead at this point to prevent that anyone384 * can take a reference to the volume from now on.385 * This is necessary as we have to release the spinlock before386 * calling ubi_volume_notify.387 */388 vol->is_dead = true;389 spin_unlock(&ubi->volumes_lock);390 391 ubi_volume_notify(ubi, vol, UBI_VOLUME_SHUTDOWN);392 393 spin_lock(&ubi->volumes_lock);394 ubi->volumes[vol_id] = NULL;395 spin_unlock(&ubi->volumes_lock);396 397 if (!no_vtbl) {398 err = ubi_change_vtbl_record(ubi, vol_id, NULL);399 if (err)400 goto out_err;401 }402 403 for (i = 0; i < vol->reserved_pebs; i++) {404 err = ubi_eba_unmap_leb(ubi, vol, i);405 if (err)406 goto out_err;407 }408 409 cdev_device_del(&vol->cdev, &vol->dev);410 put_device(&vol->dev);411 412 spin_lock(&ubi->volumes_lock);413 ubi->rsvd_pebs -= reserved_pebs;414 ubi->avail_pebs += reserved_pebs;415 ubi_update_reserved(ubi);416 ubi->vol_count -= 1;417 spin_unlock(&ubi->volumes_lock);418 419 ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED);420 if (!no_vtbl)421 self_check_volumes(ubi);422 423 return 0;424 425out_err:426 ubi_err(ubi, "cannot remove volume %d, error %d", vol_id, err);427 spin_lock(&ubi->volumes_lock);428 ubi->volumes[vol_id] = vol;429out_unlock:430 spin_unlock(&ubi->volumes_lock);431 return err;432}433 434/**435 * ubi_resize_volume - re-size volume.436 * @desc: volume descriptor437 * @reserved_pebs: new size in physical eraseblocks438 *439 * This function re-sizes the volume and returns zero in case of success, and a440 * negative error code in case of failure. The caller has to have the441 * @ubi->device_mutex locked.442 */443int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)444{445 int i, err, pebs;446 struct ubi_volume *vol = desc->vol;447 struct ubi_device *ubi = vol->ubi;448 struct ubi_vtbl_record vtbl_rec;449 struct ubi_eba_table *new_eba_tbl = NULL;450 struct ubi_eba_table *old_eba_tbl = NULL;451 int vol_id = vol->vol_id;452 453 if (ubi->ro_mode)454 return -EROFS;455 456 dbg_gen("re-size device %d, volume %d to from %d to %d PEBs",457 ubi->ubi_num, vol_id, vol->reserved_pebs, reserved_pebs);458 459 if (vol->vol_type == UBI_STATIC_VOLUME &&460 reserved_pebs < vol->used_ebs) {461 ubi_err(ubi, "too small size %d, %d LEBs contain data",462 reserved_pebs, vol->used_ebs);463 return -EINVAL;464 }465 466 /* If the size is the same, we have nothing to do */467 if (reserved_pebs == vol->reserved_pebs)468 return 0;469 470 new_eba_tbl = ubi_eba_create_table(vol, reserved_pebs);471 if (IS_ERR(new_eba_tbl))472 return PTR_ERR(new_eba_tbl);473 474 spin_lock(&ubi->volumes_lock);475 if (vol->ref_count > 1) {476 spin_unlock(&ubi->volumes_lock);477 err = -EBUSY;478 goto out_free;479 }480 spin_unlock(&ubi->volumes_lock);481 482 /* Reserve physical eraseblocks */483 pebs = reserved_pebs - vol->reserved_pebs;484 if (pebs > 0) {485 spin_lock(&ubi->volumes_lock);486 if (pebs > ubi->avail_pebs) {487 ubi_err(ubi, "not enough PEBs: requested %d, available %d",488 pebs, ubi->avail_pebs);489 if (ubi->corr_peb_count)490 ubi_err(ubi, "%d PEBs are corrupted and not used",491 ubi->corr_peb_count);492 spin_unlock(&ubi->volumes_lock);493 err = -ENOSPC;494 goto out_free;495 }496 497 ubi->avail_pebs -= pebs;498 ubi->rsvd_pebs += pebs;499 ubi_eba_copy_table(vol, new_eba_tbl, vol->reserved_pebs);500 old_eba_tbl = vol->eba_tbl;501 vol->eba_tbl = new_eba_tbl;502 vol->reserved_pebs = reserved_pebs;503 spin_unlock(&ubi->volumes_lock);504 }505 506 if (pebs < 0) {507 for (i = 0; i < -pebs; i++) {508 err = ubi_eba_unmap_leb(ubi, vol, reserved_pebs + i);509 if (err)510 goto out_free;511 }512 spin_lock(&ubi->volumes_lock);513 ubi->rsvd_pebs += pebs;514 ubi->avail_pebs -= pebs;515 ubi_update_reserved(ubi);516 ubi_eba_copy_table(vol, new_eba_tbl, reserved_pebs);517 old_eba_tbl = vol->eba_tbl;518 vol->eba_tbl = new_eba_tbl;519 vol->reserved_pebs = reserved_pebs;520 spin_unlock(&ubi->volumes_lock);521 }522 523 /*524 * When we shrink a volume we have to flush all pending (erase) work.525 * Otherwise it can happen that upon next attach UBI finds a LEB with526 * lnum > highest_lnum and refuses to attach.527 */528 if (pebs < 0) {529 err = ubi_wl_flush(ubi, vol_id, UBI_ALL);530 if (err)531 goto out_acc;532 }533 534 /* Change volume table record */535 vtbl_rec = ubi->vtbl[vol_id];536 vtbl_rec.reserved_pebs = cpu_to_be32(reserved_pebs);537 err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);538 if (err)539 goto out_acc;540 541 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {542 vol->used_ebs = reserved_pebs;543 vol->last_eb_bytes = vol->usable_leb_size;544 vol->used_bytes =545 (long long)vol->used_ebs * vol->usable_leb_size;546 }547 548 /* destroy old table */549 ubi_eba_destroy_table(old_eba_tbl);550 ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED);551 self_check_volumes(ubi);552 return err;553 554out_acc:555 spin_lock(&ubi->volumes_lock);556 vol->reserved_pebs = reserved_pebs - pebs;557 ubi->rsvd_pebs -= pebs;558 ubi->avail_pebs += pebs;559 if (pebs > 0)560 ubi_eba_copy_table(vol, old_eba_tbl, vol->reserved_pebs);561 else562 ubi_eba_copy_table(vol, old_eba_tbl, reserved_pebs);563 vol->eba_tbl = old_eba_tbl;564 spin_unlock(&ubi->volumes_lock);565out_free:566 ubi_eba_destroy_table(new_eba_tbl);567 return err;568}569 570/**571 * ubi_rename_volumes - re-name UBI volumes.572 * @ubi: UBI device description object573 * @rename_list: list of &struct ubi_rename_entry objects574 *575 * This function re-names or removes volumes specified in the re-name list.576 * Returns zero in case of success and a negative error code in case of577 * failure.578 */579int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list)580{581 int err;582 struct ubi_rename_entry *re;583 584 err = ubi_vtbl_rename_volumes(ubi, rename_list);585 if (err)586 return err;587 588 list_for_each_entry(re, rename_list, list) {589 if (re->remove) {590 err = ubi_remove_volume(re->desc, 1);591 if (err)592 break;593 } else {594 struct ubi_volume *vol = re->desc->vol;595 596 spin_lock(&ubi->volumes_lock);597 vol->name_len = re->new_name_len;598 memcpy(vol->name, re->new_name, re->new_name_len + 1);599 spin_unlock(&ubi->volumes_lock);600 ubi_volume_notify(ubi, vol, UBI_VOLUME_RENAMED);601 }602 }603 604 if (!err)605 self_check_volumes(ubi);606 return err;607}608 609/**610 * ubi_add_volume - add volume.611 * @ubi: UBI device description object612 * @vol: volume description object613 *614 * This function adds an existing volume and initializes all its data615 * structures. Returns zero in case of success and a negative error code in616 * case of failure.617 */618int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol)619{620 int err, vol_id = vol->vol_id;621 dev_t dev;622 623 dbg_gen("add volume %d", vol_id);624 625 /* Register character device for the volume */626 cdev_init(&vol->cdev, &ubi_vol_cdev_operations);627 vol->cdev.owner = THIS_MODULE;628 dev = MKDEV(MAJOR(ubi->cdev.dev), vol->vol_id + 1);629 err = cdev_add(&vol->cdev, dev, 1);630 if (err) {631 ubi_err(ubi, "cannot add character device for volume %d, error %d",632 vol_id, err);633 vol_release(&vol->dev);634 return err;635 }636 637 vol->dev.release = vol_release;638 vol->dev.parent = &ubi->dev;639 vol->dev.devt = dev;640 vol->dev.class = &ubi_class;641 vol->dev.groups = volume_dev_groups;642 dev_set_name(&vol->dev, "%s_%d", ubi->ubi_name, vol->vol_id);643 device_set_node(&vol->dev, find_volume_fwnode(vol));644 err = device_register(&vol->dev);645 if (err) {646 cdev_del(&vol->cdev);647 put_device(&vol->dev);648 return err;649 }650 651 self_check_volumes(ubi);652 return err;653}654 655/**656 * ubi_free_volume - free volume.657 * @ubi: UBI device description object658 * @vol: volume description object659 *660 * This function frees all resources for volume @vol but does not remove it.661 * Used only when the UBI device is detached.662 */663void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol)664{665 dbg_gen("free volume %d", vol->vol_id);666 667 ubi->volumes[vol->vol_id] = NULL;668 cdev_del(&vol->cdev);669 device_unregister(&vol->dev);670}671 672/**673 * self_check_volume - check volume information.674 * @ubi: UBI device description object675 * @vol_id: volume ID676 *677 * Returns zero if volume is all right and a negative error code if not.678 */679static int self_check_volume(struct ubi_device *ubi, int vol_id)680{681 int idx = vol_id2idx(ubi, vol_id);682 int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker;683 const struct ubi_volume *vol;684 long long n;685 const char *name;686 687 spin_lock(&ubi->volumes_lock);688 reserved_pebs = be32_to_cpu(ubi->vtbl[vol_id].reserved_pebs);689 vol = ubi->volumes[idx];690 691 if (!vol) {692 if (reserved_pebs) {693 ubi_err(ubi, "no volume info, but volume exists");694 goto fail;695 }696 spin_unlock(&ubi->volumes_lock);697 return 0;698 }699 700 if (vol->reserved_pebs < 0 || vol->alignment < 0 || vol->data_pad < 0 ||701 vol->name_len < 0) {702 ubi_err(ubi, "negative values");703 goto fail;704 }705 if (vol->alignment > ubi->leb_size || vol->alignment == 0) {706 ubi_err(ubi, "bad alignment");707 goto fail;708 }709 710 n = vol->alignment & (ubi->min_io_size - 1);711 if (vol->alignment != 1 && n) {712 ubi_err(ubi, "alignment is not multiple of min I/O unit");713 goto fail;714 }715 716 n = ubi->leb_size % vol->alignment;717 if (vol->data_pad != n) {718 ubi_err(ubi, "bad data_pad, has to be %lld", n);719 goto fail;720 }721 722 if (vol->vol_type != UBI_DYNAMIC_VOLUME &&723 vol->vol_type != UBI_STATIC_VOLUME) {724 ubi_err(ubi, "bad vol_type");725 goto fail;726 }727 728 if (vol->upd_marker && vol->corrupted) {729 ubi_err(ubi, "update marker and corrupted simultaneously");730 goto fail;731 }732 733 if (vol->reserved_pebs > ubi->good_peb_count) {734 ubi_err(ubi, "too large reserved_pebs");735 goto fail;736 }737 738 n = ubi->leb_size - vol->data_pad;739 if (vol->usable_leb_size != ubi->leb_size - vol->data_pad) {740 ubi_err(ubi, "bad usable_leb_size, has to be %lld", n);741 goto fail;742 }743 744 if (vol->name_len > UBI_VOL_NAME_MAX) {745 ubi_err(ubi, "too long volume name, max is %d",746 UBI_VOL_NAME_MAX);747 goto fail;748 }749 750 n = strnlen(vol->name, vol->name_len + 1);751 if (n != vol->name_len) {752 ubi_err(ubi, "bad name_len %lld", n);753 goto fail;754 }755 756 n = (long long)vol->used_ebs * vol->usable_leb_size;757 if (vol->vol_type == UBI_DYNAMIC_VOLUME) {758 if (vol->corrupted) {759 ubi_err(ubi, "corrupted dynamic volume");760 goto fail;761 }762 if (vol->used_ebs != vol->reserved_pebs) {763 ubi_err(ubi, "bad used_ebs");764 goto fail;765 }766 if (vol->last_eb_bytes != vol->usable_leb_size) {767 ubi_err(ubi, "bad last_eb_bytes");768 goto fail;769 }770 if (vol->used_bytes != n) {771 ubi_err(ubi, "bad used_bytes");772 goto fail;773 }774 775 if (vol->skip_check) {776 ubi_err(ubi, "bad skip_check");777 goto fail;778 }779 } else {780 if (vol->used_ebs < 0 || vol->used_ebs > vol->reserved_pebs) {781 ubi_err(ubi, "bad used_ebs");782 goto fail;783 }784 if (vol->last_eb_bytes < 0 ||785 vol->last_eb_bytes > vol->usable_leb_size) {786 ubi_err(ubi, "bad last_eb_bytes");787 goto fail;788 }789 if (vol->used_bytes < 0 || vol->used_bytes > n ||790 vol->used_bytes < n - vol->usable_leb_size) {791 ubi_err(ubi, "bad used_bytes");792 goto fail;793 }794 }795 796 alignment = be32_to_cpu(ubi->vtbl[vol_id].alignment);797 data_pad = be32_to_cpu(ubi->vtbl[vol_id].data_pad);798 name_len = be16_to_cpu(ubi->vtbl[vol_id].name_len);799 upd_marker = ubi->vtbl[vol_id].upd_marker;800 name = &ubi->vtbl[vol_id].name[0];801 if (ubi->vtbl[vol_id].vol_type == UBI_VID_DYNAMIC)802 vol_type = UBI_DYNAMIC_VOLUME;803 else804 vol_type = UBI_STATIC_VOLUME;805 806 if (alignment != vol->alignment || data_pad != vol->data_pad ||807 upd_marker != vol->upd_marker || vol_type != vol->vol_type ||808 name_len != vol->name_len || strncmp(name, vol->name, name_len)) {809 ubi_err(ubi, "volume info is different");810 goto fail;811 }812 813 spin_unlock(&ubi->volumes_lock);814 return 0;815 816fail:817 ubi_err(ubi, "self-check failed for volume %d", vol_id);818 if (vol)819 ubi_dump_vol_info(vol);820 ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id);821 dump_stack();822 spin_unlock(&ubi->volumes_lock);823 return -EINVAL;824}825 826/**827 * self_check_volumes - check information about all volumes.828 * @ubi: UBI device description object829 *830 * Returns zero if volumes are all right and a negative error code if not.831 */832static int self_check_volumes(struct ubi_device *ubi)833{834 int i, err = 0;835 836 if (!ubi_dbg_chk_gen(ubi))837 return 0;838 839 for (i = 0; i < ubi->vtbl_slots; i++) {840 err = self_check_volume(ubi, i);841 if (err)842 break;843 }844 845 return err;846}847