162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006
462306a36Sopenharmony_ci * Copyright (c) Nokia Corporation, 2006, 2007
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci/*
1062306a36Sopenharmony_ci * This file includes volume table manipulation code. The volume table is an
1162306a36Sopenharmony_ci * on-flash table containing volume meta-data like name, number of reserved
1262306a36Sopenharmony_ci * physical eraseblocks, type, etc. The volume table is stored in the so-called
1362306a36Sopenharmony_ci * "layout volume".
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * The layout volume is an internal volume which is organized as follows. It
1662306a36Sopenharmony_ci * consists of two logical eraseblocks - LEB 0 and LEB 1. Each logical
1762306a36Sopenharmony_ci * eraseblock stores one volume table copy, i.e. LEB 0 and LEB 1 duplicate each
1862306a36Sopenharmony_ci * other. This redundancy guarantees robustness to unclean reboots. The volume
1962306a36Sopenharmony_ci * table is basically an array of volume table records. Each record contains
2062306a36Sopenharmony_ci * full information about the volume and protected by a CRC checksum. Note,
2162306a36Sopenharmony_ci * nowadays we use the atomic LEB change operation when updating the volume
2262306a36Sopenharmony_ci * table, so we do not really need 2 LEBs anymore, but we preserve the older
2362306a36Sopenharmony_ci * design for the backward compatibility reasons.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci * When the volume table is changed, it is first changed in RAM. Then LEB 0 is
2662306a36Sopenharmony_ci * erased, and the updated volume table is written back to LEB 0. Then same for
2762306a36Sopenharmony_ci * LEB 1. This scheme guarantees recoverability from unclean reboots.
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * In this UBI implementation the on-flash volume table does not contain any
3062306a36Sopenharmony_ci * information about how much data static volumes contain.
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci * But it would still be beneficial to store this information in the volume
3362306a36Sopenharmony_ci * table. For example, suppose we have a static volume X, and all its physical
3462306a36Sopenharmony_ci * eraseblocks became bad for some reasons. Suppose we are attaching the
3562306a36Sopenharmony_ci * corresponding MTD device, for some reason we find no logical eraseblocks
3662306a36Sopenharmony_ci * corresponding to the volume X. According to the volume table volume X does
3762306a36Sopenharmony_ci * exist. So we don't know whether it is just empty or all its physical
3862306a36Sopenharmony_ci * eraseblocks went bad. So we cannot alarm the user properly.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * The volume table also stores so-called "update marker", which is used for
4162306a36Sopenharmony_ci * volume updates. Before updating the volume, the update marker is set, and
4262306a36Sopenharmony_ci * after the update operation is finished, the update marker is cleared. So if
4362306a36Sopenharmony_ci * the update operation was interrupted (e.g. by an unclean reboot) - the
4462306a36Sopenharmony_ci * update marker is still there and we know that the volume's contents is
4562306a36Sopenharmony_ci * damaged.
4662306a36Sopenharmony_ci */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#include <linux/crc32.h>
4962306a36Sopenharmony_ci#include <linux/err.h>
5062306a36Sopenharmony_ci#include <linux/slab.h>
5162306a36Sopenharmony_ci#include <asm/div64.h>
5262306a36Sopenharmony_ci#include "ubi.h"
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic void self_vtbl_check(const struct ubi_device *ubi);
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* Empty volume table record */
5762306a36Sopenharmony_cistatic struct ubi_vtbl_record empty_vtbl_record;
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/**
6062306a36Sopenharmony_ci * ubi_update_layout_vol - helper for updatting layout volumes on flash
6162306a36Sopenharmony_ci * @ubi: UBI device description object
6262306a36Sopenharmony_ci */
6362306a36Sopenharmony_cistatic int ubi_update_layout_vol(struct ubi_device *ubi)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	struct ubi_volume *layout_vol;
6662306a36Sopenharmony_ci	int i, err;
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	layout_vol = ubi->volumes[vol_id2idx(ubi, UBI_LAYOUT_VOLUME_ID)];
6962306a36Sopenharmony_ci	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
7062306a36Sopenharmony_ci		err = ubi_eba_atomic_leb_change(ubi, layout_vol, i, ubi->vtbl,
7162306a36Sopenharmony_ci						ubi->vtbl_size);
7262306a36Sopenharmony_ci		if (err)
7362306a36Sopenharmony_ci			return err;
7462306a36Sopenharmony_ci	}
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return 0;
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/**
8062306a36Sopenharmony_ci * ubi_change_vtbl_record - change volume table record.
8162306a36Sopenharmony_ci * @ubi: UBI device description object
8262306a36Sopenharmony_ci * @idx: table index to change
8362306a36Sopenharmony_ci * @vtbl_rec: new volume table record
8462306a36Sopenharmony_ci *
8562306a36Sopenharmony_ci * This function changes volume table record @idx. If @vtbl_rec is %NULL, empty
8662306a36Sopenharmony_ci * volume table record is written. The caller does not have to calculate CRC of
8762306a36Sopenharmony_ci * the record as it is done by this function. Returns zero in case of success
8862306a36Sopenharmony_ci * and a negative error code in case of failure.
8962306a36Sopenharmony_ci */
9062306a36Sopenharmony_ciint ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
9162306a36Sopenharmony_ci			   struct ubi_vtbl_record *vtbl_rec)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	int err;
9462306a36Sopenharmony_ci	uint32_t crc;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	ubi_assert(idx >= 0 && idx < ubi->vtbl_slots);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	if (!vtbl_rec)
9962306a36Sopenharmony_ci		vtbl_rec = &empty_vtbl_record;
10062306a36Sopenharmony_ci	else {
10162306a36Sopenharmony_ci		crc = crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
10262306a36Sopenharmony_ci		vtbl_rec->crc = cpu_to_be32(crc);
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	memcpy(&ubi->vtbl[idx], vtbl_rec, sizeof(struct ubi_vtbl_record));
10662306a36Sopenharmony_ci	err = ubi_update_layout_vol(ubi);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	self_vtbl_check(ubi);
10962306a36Sopenharmony_ci	return err ? err : 0;
11062306a36Sopenharmony_ci}
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/**
11362306a36Sopenharmony_ci * ubi_vtbl_rename_volumes - rename UBI volumes in the volume table.
11462306a36Sopenharmony_ci * @ubi: UBI device description object
11562306a36Sopenharmony_ci * @rename_list: list of &struct ubi_rename_entry objects
11662306a36Sopenharmony_ci *
11762306a36Sopenharmony_ci * This function re-names multiple volumes specified in @req in the volume
11862306a36Sopenharmony_ci * table. Returns zero in case of success and a negative error code in case of
11962306a36Sopenharmony_ci * failure.
12062306a36Sopenharmony_ci */
12162306a36Sopenharmony_ciint ubi_vtbl_rename_volumes(struct ubi_device *ubi,
12262306a36Sopenharmony_ci			    struct list_head *rename_list)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	struct ubi_rename_entry *re;
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ci	list_for_each_entry(re, rename_list, list) {
12762306a36Sopenharmony_ci		uint32_t crc;
12862306a36Sopenharmony_ci		struct ubi_volume *vol = re->desc->vol;
12962306a36Sopenharmony_ci		struct ubi_vtbl_record *vtbl_rec = &ubi->vtbl[vol->vol_id];
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci		if (re->remove) {
13262306a36Sopenharmony_ci			memcpy(vtbl_rec, &empty_vtbl_record,
13362306a36Sopenharmony_ci			       sizeof(struct ubi_vtbl_record));
13462306a36Sopenharmony_ci			continue;
13562306a36Sopenharmony_ci		}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci		vtbl_rec->name_len = cpu_to_be16(re->new_name_len);
13862306a36Sopenharmony_ci		memcpy(vtbl_rec->name, re->new_name, re->new_name_len);
13962306a36Sopenharmony_ci		memset(vtbl_rec->name + re->new_name_len, 0,
14062306a36Sopenharmony_ci		       UBI_VOL_NAME_MAX + 1 - re->new_name_len);
14162306a36Sopenharmony_ci		crc = crc32(UBI_CRC32_INIT, vtbl_rec,
14262306a36Sopenharmony_ci			    UBI_VTBL_RECORD_SIZE_CRC);
14362306a36Sopenharmony_ci		vtbl_rec->crc = cpu_to_be32(crc);
14462306a36Sopenharmony_ci	}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	return ubi_update_layout_vol(ubi);
14762306a36Sopenharmony_ci}
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci/**
15062306a36Sopenharmony_ci * vtbl_check - check if volume table is not corrupted and sensible.
15162306a36Sopenharmony_ci * @ubi: UBI device description object
15262306a36Sopenharmony_ci * @vtbl: volume table
15362306a36Sopenharmony_ci *
15462306a36Sopenharmony_ci * This function returns zero if @vtbl is all right, %1 if CRC is incorrect,
15562306a36Sopenharmony_ci * and %-EINVAL if it contains inconsistent data.
15662306a36Sopenharmony_ci */
15762306a36Sopenharmony_cistatic int vtbl_check(const struct ubi_device *ubi,
15862306a36Sopenharmony_ci		      const struct ubi_vtbl_record *vtbl)
15962306a36Sopenharmony_ci{
16062306a36Sopenharmony_ci	int i, n, reserved_pebs, alignment, data_pad, vol_type, name_len;
16162306a36Sopenharmony_ci	int upd_marker, err;
16262306a36Sopenharmony_ci	uint32_t crc;
16362306a36Sopenharmony_ci	const char *name;
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++) {
16662306a36Sopenharmony_ci		cond_resched();
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
16962306a36Sopenharmony_ci		alignment = be32_to_cpu(vtbl[i].alignment);
17062306a36Sopenharmony_ci		data_pad = be32_to_cpu(vtbl[i].data_pad);
17162306a36Sopenharmony_ci		upd_marker = vtbl[i].upd_marker;
17262306a36Sopenharmony_ci		vol_type = vtbl[i].vol_type;
17362306a36Sopenharmony_ci		name_len = be16_to_cpu(vtbl[i].name_len);
17462306a36Sopenharmony_ci		name = &vtbl[i].name[0];
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		crc = crc32(UBI_CRC32_INIT, &vtbl[i], UBI_VTBL_RECORD_SIZE_CRC);
17762306a36Sopenharmony_ci		if (be32_to_cpu(vtbl[i].crc) != crc) {
17862306a36Sopenharmony_ci			ubi_err(ubi, "bad CRC at record %u: %#08x, not %#08x",
17962306a36Sopenharmony_ci				 i, crc, be32_to_cpu(vtbl[i].crc));
18062306a36Sopenharmony_ci			ubi_dump_vtbl_record(&vtbl[i], i);
18162306a36Sopenharmony_ci			return 1;
18262306a36Sopenharmony_ci		}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		if (reserved_pebs == 0) {
18562306a36Sopenharmony_ci			if (memcmp(&vtbl[i], &empty_vtbl_record,
18662306a36Sopenharmony_ci						UBI_VTBL_RECORD_SIZE)) {
18762306a36Sopenharmony_ci				err = 2;
18862306a36Sopenharmony_ci				goto bad;
18962306a36Sopenharmony_ci			}
19062306a36Sopenharmony_ci			continue;
19162306a36Sopenharmony_ci		}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci		if (reserved_pebs < 0 || alignment < 0 || data_pad < 0 ||
19462306a36Sopenharmony_ci		    name_len < 0) {
19562306a36Sopenharmony_ci			err = 3;
19662306a36Sopenharmony_ci			goto bad;
19762306a36Sopenharmony_ci		}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci		if (alignment > ubi->leb_size || alignment == 0) {
20062306a36Sopenharmony_ci			err = 4;
20162306a36Sopenharmony_ci			goto bad;
20262306a36Sopenharmony_ci		}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci		n = alignment & (ubi->min_io_size - 1);
20562306a36Sopenharmony_ci		if (alignment != 1 && n) {
20662306a36Sopenharmony_ci			err = 5;
20762306a36Sopenharmony_ci			goto bad;
20862306a36Sopenharmony_ci		}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci		n = ubi->leb_size % alignment;
21162306a36Sopenharmony_ci		if (data_pad != n) {
21262306a36Sopenharmony_ci			ubi_err(ubi, "bad data_pad, has to be %d", n);
21362306a36Sopenharmony_ci			err = 6;
21462306a36Sopenharmony_ci			goto bad;
21562306a36Sopenharmony_ci		}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) {
21862306a36Sopenharmony_ci			err = 7;
21962306a36Sopenharmony_ci			goto bad;
22062306a36Sopenharmony_ci		}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci		if (upd_marker != 0 && upd_marker != 1) {
22362306a36Sopenharmony_ci			err = 8;
22462306a36Sopenharmony_ci			goto bad;
22562306a36Sopenharmony_ci		}
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci		if (reserved_pebs > ubi->good_peb_count) {
22862306a36Sopenharmony_ci			ubi_err(ubi, "too large reserved_pebs %d, good PEBs %d",
22962306a36Sopenharmony_ci				reserved_pebs, ubi->good_peb_count);
23062306a36Sopenharmony_ci			err = 9;
23162306a36Sopenharmony_ci			goto bad;
23262306a36Sopenharmony_ci		}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		if (name_len > UBI_VOL_NAME_MAX) {
23562306a36Sopenharmony_ci			err = 10;
23662306a36Sopenharmony_ci			goto bad;
23762306a36Sopenharmony_ci		}
23862306a36Sopenharmony_ci
23962306a36Sopenharmony_ci		if (name[0] == '\0') {
24062306a36Sopenharmony_ci			err = 11;
24162306a36Sopenharmony_ci			goto bad;
24262306a36Sopenharmony_ci		}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci		if (name_len != strnlen(name, name_len + 1)) {
24562306a36Sopenharmony_ci			err = 12;
24662306a36Sopenharmony_ci			goto bad;
24762306a36Sopenharmony_ci		}
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci	/* Checks that all names are unique */
25162306a36Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots - 1; i++) {
25262306a36Sopenharmony_ci		for (n = i + 1; n < ubi->vtbl_slots; n++) {
25362306a36Sopenharmony_ci			int len1 = be16_to_cpu(vtbl[i].name_len);
25462306a36Sopenharmony_ci			int len2 = be16_to_cpu(vtbl[n].name_len);
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci			if (len1 > 0 && len1 == len2 &&
25762306a36Sopenharmony_ci			    !strncmp(vtbl[i].name, vtbl[n].name, len1)) {
25862306a36Sopenharmony_ci				ubi_err(ubi, "volumes %d and %d have the same name \"%s\"",
25962306a36Sopenharmony_ci					i, n, vtbl[i].name);
26062306a36Sopenharmony_ci				ubi_dump_vtbl_record(&vtbl[i], i);
26162306a36Sopenharmony_ci				ubi_dump_vtbl_record(&vtbl[n], n);
26262306a36Sopenharmony_ci				return -EINVAL;
26362306a36Sopenharmony_ci			}
26462306a36Sopenharmony_ci		}
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return 0;
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cibad:
27062306a36Sopenharmony_ci	ubi_err(ubi, "volume table check failed: record %d, error %d", i, err);
27162306a36Sopenharmony_ci	ubi_dump_vtbl_record(&vtbl[i], i);
27262306a36Sopenharmony_ci	return -EINVAL;
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/**
27662306a36Sopenharmony_ci * create_vtbl - create a copy of volume table.
27762306a36Sopenharmony_ci * @ubi: UBI device description object
27862306a36Sopenharmony_ci * @ai: attaching information
27962306a36Sopenharmony_ci * @copy: number of the volume table copy
28062306a36Sopenharmony_ci * @vtbl: contents of the volume table
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in
28362306a36Sopenharmony_ci * case of failure.
28462306a36Sopenharmony_ci */
28562306a36Sopenharmony_cistatic int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai,
28662306a36Sopenharmony_ci		       int copy, void *vtbl)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	int err, tries = 0;
28962306a36Sopenharmony_ci	struct ubi_vid_io_buf *vidb;
29062306a36Sopenharmony_ci	struct ubi_vid_hdr *vid_hdr;
29162306a36Sopenharmony_ci	struct ubi_ainf_peb *new_aeb;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	dbg_gen("create volume table (copy #%d)", copy + 1);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci	vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
29662306a36Sopenharmony_ci	if (!vidb)
29762306a36Sopenharmony_ci		return -ENOMEM;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	vid_hdr = ubi_get_vid_hdr(vidb);
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ciretry:
30262306a36Sopenharmony_ci	new_aeb = ubi_early_get_peb(ubi, ai);
30362306a36Sopenharmony_ci	if (IS_ERR(new_aeb)) {
30462306a36Sopenharmony_ci		err = PTR_ERR(new_aeb);
30562306a36Sopenharmony_ci		goto out_free;
30662306a36Sopenharmony_ci	}
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	vid_hdr->vol_type = UBI_LAYOUT_VOLUME_TYPE;
30962306a36Sopenharmony_ci	vid_hdr->vol_id = cpu_to_be32(UBI_LAYOUT_VOLUME_ID);
31062306a36Sopenharmony_ci	vid_hdr->compat = UBI_LAYOUT_VOLUME_COMPAT;
31162306a36Sopenharmony_ci	vid_hdr->data_size = vid_hdr->used_ebs =
31262306a36Sopenharmony_ci			     vid_hdr->data_pad = cpu_to_be32(0);
31362306a36Sopenharmony_ci	vid_hdr->lnum = cpu_to_be32(copy);
31462306a36Sopenharmony_ci	vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	/* The EC header is already there, write the VID header */
31762306a36Sopenharmony_ci	err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vidb);
31862306a36Sopenharmony_ci	if (err)
31962306a36Sopenharmony_ci		goto write_error;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	/* Write the layout volume contents */
32262306a36Sopenharmony_ci	err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size);
32362306a36Sopenharmony_ci	if (err)
32462306a36Sopenharmony_ci		goto write_error;
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	/*
32762306a36Sopenharmony_ci	 * And add it to the attaching information. Don't delete the old version
32862306a36Sopenharmony_ci	 * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
32962306a36Sopenharmony_ci	 */
33062306a36Sopenharmony_ci	err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
33162306a36Sopenharmony_ci	ubi_free_aeb(ai, new_aeb);
33262306a36Sopenharmony_ci	ubi_free_vid_buf(vidb);
33362306a36Sopenharmony_ci	return err;
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ciwrite_error:
33662306a36Sopenharmony_ci	if (err == -EIO && ++tries <= 5) {
33762306a36Sopenharmony_ci		/*
33862306a36Sopenharmony_ci		 * Probably this physical eraseblock went bad, try to pick
33962306a36Sopenharmony_ci		 * another one.
34062306a36Sopenharmony_ci		 */
34162306a36Sopenharmony_ci		list_add(&new_aeb->u.list, &ai->erase);
34262306a36Sopenharmony_ci		goto retry;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci	ubi_free_aeb(ai, new_aeb);
34562306a36Sopenharmony_ciout_free:
34662306a36Sopenharmony_ci	ubi_free_vid_buf(vidb);
34762306a36Sopenharmony_ci	return err;
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci}
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci/**
35262306a36Sopenharmony_ci * process_lvol - process the layout volume.
35362306a36Sopenharmony_ci * @ubi: UBI device description object
35462306a36Sopenharmony_ci * @ai: attaching information
35562306a36Sopenharmony_ci * @av: layout volume attaching information
35662306a36Sopenharmony_ci *
35762306a36Sopenharmony_ci * This function is responsible for reading the layout volume, ensuring it is
35862306a36Sopenharmony_ci * not corrupted, and recovering from corruptions if needed. Returns volume
35962306a36Sopenharmony_ci * table in case of success and a negative error code in case of failure.
36062306a36Sopenharmony_ci */
36162306a36Sopenharmony_cistatic struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi,
36262306a36Sopenharmony_ci					    struct ubi_attach_info *ai,
36362306a36Sopenharmony_ci					    struct ubi_ainf_volume *av)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	int err;
36662306a36Sopenharmony_ci	struct rb_node *rb;
36762306a36Sopenharmony_ci	struct ubi_ainf_peb *aeb;
36862306a36Sopenharmony_ci	struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL };
36962306a36Sopenharmony_ci	int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1};
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	/*
37262306a36Sopenharmony_ci	 * UBI goes through the following steps when it changes the layout
37362306a36Sopenharmony_ci	 * volume:
37462306a36Sopenharmony_ci	 * a. erase LEB 0;
37562306a36Sopenharmony_ci	 * b. write new data to LEB 0;
37662306a36Sopenharmony_ci	 * c. erase LEB 1;
37762306a36Sopenharmony_ci	 * d. write new data to LEB 1.
37862306a36Sopenharmony_ci	 *
37962306a36Sopenharmony_ci	 * Before the change, both LEBs contain the same data.
38062306a36Sopenharmony_ci	 *
38162306a36Sopenharmony_ci	 * Due to unclean reboots, the contents of LEB 0 may be lost, but there
38262306a36Sopenharmony_ci	 * should LEB 1. So it is OK if LEB 0 is corrupted while LEB 1 is not.
38362306a36Sopenharmony_ci	 * Similarly, LEB 1 may be lost, but there should be LEB 0. And
38462306a36Sopenharmony_ci	 * finally, unclean reboots may result in a situation when neither LEB
38562306a36Sopenharmony_ci	 * 0 nor LEB 1 are corrupted, but they are different. In this case, LEB
38662306a36Sopenharmony_ci	 * 0 contains more recent information.
38762306a36Sopenharmony_ci	 *
38862306a36Sopenharmony_ci	 * So the plan is to first check LEB 0. Then
38962306a36Sopenharmony_ci	 * a. if LEB 0 is OK, it must be containing the most recent data; then
39062306a36Sopenharmony_ci	 *    we compare it with LEB 1, and if they are different, we copy LEB
39162306a36Sopenharmony_ci	 *    0 to LEB 1;
39262306a36Sopenharmony_ci	 * b. if LEB 0 is corrupted, but LEB 1 has to be OK, and we copy LEB 1
39362306a36Sopenharmony_ci	 *    to LEB 0.
39462306a36Sopenharmony_ci	 */
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	dbg_gen("check layout volume");
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	/* Read both LEB 0 and LEB 1 into memory */
39962306a36Sopenharmony_ci	ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) {
40062306a36Sopenharmony_ci		leb[aeb->lnum] = vzalloc(ubi->vtbl_size);
40162306a36Sopenharmony_ci		if (!leb[aeb->lnum]) {
40262306a36Sopenharmony_ci			err = -ENOMEM;
40362306a36Sopenharmony_ci			goto out_free;
40462306a36Sopenharmony_ci		}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci		err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0,
40762306a36Sopenharmony_ci				       ubi->vtbl_size);
40862306a36Sopenharmony_ci		if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err))
40962306a36Sopenharmony_ci			/*
41062306a36Sopenharmony_ci			 * Scrub the PEB later. Note, -EBADMSG indicates an
41162306a36Sopenharmony_ci			 * uncorrectable ECC error, but we have our own CRC and
41262306a36Sopenharmony_ci			 * the data will be checked later. If the data is OK,
41362306a36Sopenharmony_ci			 * the PEB will be scrubbed (because we set
41462306a36Sopenharmony_ci			 * aeb->scrub). If the data is not OK, the contents of
41562306a36Sopenharmony_ci			 * the PEB will be recovered from the second copy, and
41662306a36Sopenharmony_ci			 * aeb->scrub will be cleared in
41762306a36Sopenharmony_ci			 * 'ubi_add_to_av()'.
41862306a36Sopenharmony_ci			 */
41962306a36Sopenharmony_ci			aeb->scrub = 1;
42062306a36Sopenharmony_ci		else if (err)
42162306a36Sopenharmony_ci			goto out_free;
42262306a36Sopenharmony_ci	}
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	err = -EINVAL;
42562306a36Sopenharmony_ci	if (leb[0]) {
42662306a36Sopenharmony_ci		leb_corrupted[0] = vtbl_check(ubi, leb[0]);
42762306a36Sopenharmony_ci		if (leb_corrupted[0] < 0)
42862306a36Sopenharmony_ci			goto out_free;
42962306a36Sopenharmony_ci	}
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	if (!leb_corrupted[0]) {
43262306a36Sopenharmony_ci		/* LEB 0 is OK */
43362306a36Sopenharmony_ci		if (leb[1])
43462306a36Sopenharmony_ci			leb_corrupted[1] = memcmp(leb[0], leb[1],
43562306a36Sopenharmony_ci						  ubi->vtbl_size);
43662306a36Sopenharmony_ci		if (leb_corrupted[1]) {
43762306a36Sopenharmony_ci			ubi_warn(ubi, "volume table copy #2 is corrupted");
43862306a36Sopenharmony_ci			err = create_vtbl(ubi, ai, 1, leb[0]);
43962306a36Sopenharmony_ci			if (err)
44062306a36Sopenharmony_ci				goto out_free;
44162306a36Sopenharmony_ci			ubi_msg(ubi, "volume table was restored");
44262306a36Sopenharmony_ci		}
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci		/* Both LEB 1 and LEB 2 are OK and consistent */
44562306a36Sopenharmony_ci		vfree(leb[1]);
44662306a36Sopenharmony_ci		return leb[0];
44762306a36Sopenharmony_ci	} else {
44862306a36Sopenharmony_ci		/* LEB 0 is corrupted or does not exist */
44962306a36Sopenharmony_ci		if (leb[1]) {
45062306a36Sopenharmony_ci			leb_corrupted[1] = vtbl_check(ubi, leb[1]);
45162306a36Sopenharmony_ci			if (leb_corrupted[1] < 0)
45262306a36Sopenharmony_ci				goto out_free;
45362306a36Sopenharmony_ci		}
45462306a36Sopenharmony_ci		if (leb_corrupted[1]) {
45562306a36Sopenharmony_ci			/* Both LEB 0 and LEB 1 are corrupted */
45662306a36Sopenharmony_ci			ubi_err(ubi, "both volume tables are corrupted");
45762306a36Sopenharmony_ci			goto out_free;
45862306a36Sopenharmony_ci		}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci		ubi_warn(ubi, "volume table copy #1 is corrupted");
46162306a36Sopenharmony_ci		err = create_vtbl(ubi, ai, 0, leb[1]);
46262306a36Sopenharmony_ci		if (err)
46362306a36Sopenharmony_ci			goto out_free;
46462306a36Sopenharmony_ci		ubi_msg(ubi, "volume table was restored");
46562306a36Sopenharmony_ci
46662306a36Sopenharmony_ci		vfree(leb[0]);
46762306a36Sopenharmony_ci		return leb[1];
46862306a36Sopenharmony_ci	}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ciout_free:
47162306a36Sopenharmony_ci	vfree(leb[0]);
47262306a36Sopenharmony_ci	vfree(leb[1]);
47362306a36Sopenharmony_ci	return ERR_PTR(err);
47462306a36Sopenharmony_ci}
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci/**
47762306a36Sopenharmony_ci * create_empty_lvol - create empty layout volume.
47862306a36Sopenharmony_ci * @ubi: UBI device description object
47962306a36Sopenharmony_ci * @ai: attaching information
48062306a36Sopenharmony_ci *
48162306a36Sopenharmony_ci * This function returns volume table contents in case of success and a
48262306a36Sopenharmony_ci * negative error code in case of failure.
48362306a36Sopenharmony_ci */
48462306a36Sopenharmony_cistatic struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,
48562306a36Sopenharmony_ci						 struct ubi_attach_info *ai)
48662306a36Sopenharmony_ci{
48762306a36Sopenharmony_ci	int i;
48862306a36Sopenharmony_ci	struct ubi_vtbl_record *vtbl;
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci	vtbl = vzalloc(ubi->vtbl_size);
49162306a36Sopenharmony_ci	if (!vtbl)
49262306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++)
49562306a36Sopenharmony_ci		memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {
49862306a36Sopenharmony_ci		int err;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci		err = create_vtbl(ubi, ai, i, vtbl);
50162306a36Sopenharmony_ci		if (err) {
50262306a36Sopenharmony_ci			vfree(vtbl);
50362306a36Sopenharmony_ci			return ERR_PTR(err);
50462306a36Sopenharmony_ci		}
50562306a36Sopenharmony_ci	}
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	return vtbl;
50862306a36Sopenharmony_ci}
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci/**
51162306a36Sopenharmony_ci * init_volumes - initialize volume information for existing volumes.
51262306a36Sopenharmony_ci * @ubi: UBI device description object
51362306a36Sopenharmony_ci * @ai: scanning information
51462306a36Sopenharmony_ci * @vtbl: volume table
51562306a36Sopenharmony_ci *
51662306a36Sopenharmony_ci * This function allocates volume description objects for existing volumes.
51762306a36Sopenharmony_ci * Returns zero in case of success and a negative error code in case of
51862306a36Sopenharmony_ci * failure.
51962306a36Sopenharmony_ci */
52062306a36Sopenharmony_cistatic int init_volumes(struct ubi_device *ubi,
52162306a36Sopenharmony_ci			const struct ubi_attach_info *ai,
52262306a36Sopenharmony_ci			const struct ubi_vtbl_record *vtbl)
52362306a36Sopenharmony_ci{
52462306a36Sopenharmony_ci	int i, err, reserved_pebs = 0;
52562306a36Sopenharmony_ci	struct ubi_ainf_volume *av;
52662306a36Sopenharmony_ci	struct ubi_volume *vol;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++) {
52962306a36Sopenharmony_ci		cond_resched();
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_ci		if (be32_to_cpu(vtbl[i].reserved_pebs) == 0)
53262306a36Sopenharmony_ci			continue; /* Empty record */
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci		vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);
53562306a36Sopenharmony_ci		if (!vol)
53662306a36Sopenharmony_ci			return -ENOMEM;
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci		vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);
53962306a36Sopenharmony_ci		vol->alignment = be32_to_cpu(vtbl[i].alignment);
54062306a36Sopenharmony_ci		vol->data_pad = be32_to_cpu(vtbl[i].data_pad);
54162306a36Sopenharmony_ci		vol->upd_marker = vtbl[i].upd_marker;
54262306a36Sopenharmony_ci		vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?
54362306a36Sopenharmony_ci					UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;
54462306a36Sopenharmony_ci		vol->name_len = be16_to_cpu(vtbl[i].name_len);
54562306a36Sopenharmony_ci		vol->usable_leb_size = ubi->leb_size - vol->data_pad;
54662306a36Sopenharmony_ci		memcpy(vol->name, vtbl[i].name, vol->name_len);
54762306a36Sopenharmony_ci		vol->name[vol->name_len] = '\0';
54862306a36Sopenharmony_ci		vol->vol_id = i;
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci		if (vtbl[i].flags & UBI_VTBL_SKIP_CRC_CHECK_FLG)
55162306a36Sopenharmony_ci			vol->skip_check = 1;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci		if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
55462306a36Sopenharmony_ci			/* Auto re-size flag may be set only for one volume */
55562306a36Sopenharmony_ci			if (ubi->autoresize_vol_id != -1) {
55662306a36Sopenharmony_ci				ubi_err(ubi, "more than one auto-resize volume (%d and %d)",
55762306a36Sopenharmony_ci					ubi->autoresize_vol_id, i);
55862306a36Sopenharmony_ci				kfree(vol);
55962306a36Sopenharmony_ci				return -EINVAL;
56062306a36Sopenharmony_ci			}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci			ubi->autoresize_vol_id = i;
56362306a36Sopenharmony_ci		}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci		ubi_assert(!ubi->volumes[i]);
56662306a36Sopenharmony_ci		ubi->volumes[i] = vol;
56762306a36Sopenharmony_ci		ubi->vol_count += 1;
56862306a36Sopenharmony_ci		vol->ubi = ubi;
56962306a36Sopenharmony_ci		reserved_pebs += vol->reserved_pebs;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci		/*
57262306a36Sopenharmony_ci		 * We use ubi->peb_count and not vol->reserved_pebs because
57362306a36Sopenharmony_ci		 * we want to keep the code simple. Otherwise we'd have to
57462306a36Sopenharmony_ci		 * resize/check the bitmap upon volume resize too.
57562306a36Sopenharmony_ci		 * Allocating a few bytes more does not hurt.
57662306a36Sopenharmony_ci		 */
57762306a36Sopenharmony_ci		err = ubi_fastmap_init_checkmap(vol, ubi->peb_count);
57862306a36Sopenharmony_ci		if (err)
57962306a36Sopenharmony_ci			return err;
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci		/*
58262306a36Sopenharmony_ci		 * In case of dynamic volume UBI knows nothing about how many
58362306a36Sopenharmony_ci		 * data is stored there. So assume the whole volume is used.
58462306a36Sopenharmony_ci		 */
58562306a36Sopenharmony_ci		if (vol->vol_type == UBI_DYNAMIC_VOLUME) {
58662306a36Sopenharmony_ci			vol->used_ebs = vol->reserved_pebs;
58762306a36Sopenharmony_ci			vol->last_eb_bytes = vol->usable_leb_size;
58862306a36Sopenharmony_ci			vol->used_bytes =
58962306a36Sopenharmony_ci				(long long)vol->used_ebs * vol->usable_leb_size;
59062306a36Sopenharmony_ci			continue;
59162306a36Sopenharmony_ci		}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		/* Static volumes only */
59462306a36Sopenharmony_ci		av = ubi_find_av(ai, i);
59562306a36Sopenharmony_ci		if (!av || !av->leb_count) {
59662306a36Sopenharmony_ci			/*
59762306a36Sopenharmony_ci			 * No eraseblocks belonging to this volume found. We
59862306a36Sopenharmony_ci			 * don't actually know whether this static volume is
59962306a36Sopenharmony_ci			 * completely corrupted or just contains no data. And
60062306a36Sopenharmony_ci			 * we cannot know this as long as data size is not
60162306a36Sopenharmony_ci			 * stored on flash. So we just assume the volume is
60262306a36Sopenharmony_ci			 * empty. FIXME: this should be handled.
60362306a36Sopenharmony_ci			 */
60462306a36Sopenharmony_ci			continue;
60562306a36Sopenharmony_ci		}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci		if (av->leb_count != av->used_ebs) {
60862306a36Sopenharmony_ci			/*
60962306a36Sopenharmony_ci			 * We found a static volume which misses several
61062306a36Sopenharmony_ci			 * eraseblocks. Treat it as corrupted.
61162306a36Sopenharmony_ci			 */
61262306a36Sopenharmony_ci			ubi_warn(ubi, "static volume %d misses %d LEBs - corrupted",
61362306a36Sopenharmony_ci				 av->vol_id, av->used_ebs - av->leb_count);
61462306a36Sopenharmony_ci			vol->corrupted = 1;
61562306a36Sopenharmony_ci			continue;
61662306a36Sopenharmony_ci		}
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci		vol->used_ebs = av->used_ebs;
61962306a36Sopenharmony_ci		vol->used_bytes =
62062306a36Sopenharmony_ci			(long long)(vol->used_ebs - 1) * vol->usable_leb_size;
62162306a36Sopenharmony_ci		vol->used_bytes += av->last_data_size;
62262306a36Sopenharmony_ci		vol->last_eb_bytes = av->last_data_size;
62362306a36Sopenharmony_ci	}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	/* And add the layout volume */
62662306a36Sopenharmony_ci	vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);
62762306a36Sopenharmony_ci	if (!vol)
62862306a36Sopenharmony_ci		return -ENOMEM;
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci	vol->reserved_pebs = UBI_LAYOUT_VOLUME_EBS;
63162306a36Sopenharmony_ci	vol->alignment = UBI_LAYOUT_VOLUME_ALIGN;
63262306a36Sopenharmony_ci	vol->vol_type = UBI_DYNAMIC_VOLUME;
63362306a36Sopenharmony_ci	vol->name_len = sizeof(UBI_LAYOUT_VOLUME_NAME) - 1;
63462306a36Sopenharmony_ci	memcpy(vol->name, UBI_LAYOUT_VOLUME_NAME, vol->name_len + 1);
63562306a36Sopenharmony_ci	vol->usable_leb_size = ubi->leb_size;
63662306a36Sopenharmony_ci	vol->used_ebs = vol->reserved_pebs;
63762306a36Sopenharmony_ci	vol->last_eb_bytes = vol->reserved_pebs;
63862306a36Sopenharmony_ci	vol->used_bytes =
63962306a36Sopenharmony_ci		(long long)vol->used_ebs * (ubi->leb_size - vol->data_pad);
64062306a36Sopenharmony_ci	vol->vol_id = UBI_LAYOUT_VOLUME_ID;
64162306a36Sopenharmony_ci	vol->ref_count = 1;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	ubi_assert(!ubi->volumes[i]);
64462306a36Sopenharmony_ci	ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol;
64562306a36Sopenharmony_ci	reserved_pebs += vol->reserved_pebs;
64662306a36Sopenharmony_ci	ubi->vol_count += 1;
64762306a36Sopenharmony_ci	vol->ubi = ubi;
64862306a36Sopenharmony_ci	err = ubi_fastmap_init_checkmap(vol, UBI_LAYOUT_VOLUME_EBS);
64962306a36Sopenharmony_ci	if (err)
65062306a36Sopenharmony_ci		return err;
65162306a36Sopenharmony_ci
65262306a36Sopenharmony_ci	if (reserved_pebs > ubi->avail_pebs) {
65362306a36Sopenharmony_ci		ubi_err(ubi, "not enough PEBs, required %d, available %d",
65462306a36Sopenharmony_ci			reserved_pebs, ubi->avail_pebs);
65562306a36Sopenharmony_ci		if (ubi->corr_peb_count)
65662306a36Sopenharmony_ci			ubi_err(ubi, "%d PEBs are corrupted and not used",
65762306a36Sopenharmony_ci				ubi->corr_peb_count);
65862306a36Sopenharmony_ci		return -ENOSPC;
65962306a36Sopenharmony_ci	}
66062306a36Sopenharmony_ci	ubi->rsvd_pebs += reserved_pebs;
66162306a36Sopenharmony_ci	ubi->avail_pebs -= reserved_pebs;
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	return 0;
66462306a36Sopenharmony_ci}
66562306a36Sopenharmony_ci
66662306a36Sopenharmony_ci/**
66762306a36Sopenharmony_ci * check_av - check volume attaching information.
66862306a36Sopenharmony_ci * @vol: UBI volume description object
66962306a36Sopenharmony_ci * @av: volume attaching information
67062306a36Sopenharmony_ci *
67162306a36Sopenharmony_ci * This function returns zero if the volume attaching information is consistent
67262306a36Sopenharmony_ci * to the data read from the volume tabla, and %-EINVAL if not.
67362306a36Sopenharmony_ci */
67462306a36Sopenharmony_cistatic int check_av(const struct ubi_volume *vol,
67562306a36Sopenharmony_ci		    const struct ubi_ainf_volume *av)
67662306a36Sopenharmony_ci{
67762306a36Sopenharmony_ci	int err;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	if (av->highest_lnum >= vol->reserved_pebs) {
68062306a36Sopenharmony_ci		err = 1;
68162306a36Sopenharmony_ci		goto bad;
68262306a36Sopenharmony_ci	}
68362306a36Sopenharmony_ci	if (av->leb_count > vol->reserved_pebs) {
68462306a36Sopenharmony_ci		err = 2;
68562306a36Sopenharmony_ci		goto bad;
68662306a36Sopenharmony_ci	}
68762306a36Sopenharmony_ci	if (av->vol_type != vol->vol_type) {
68862306a36Sopenharmony_ci		err = 3;
68962306a36Sopenharmony_ci		goto bad;
69062306a36Sopenharmony_ci	}
69162306a36Sopenharmony_ci	if (av->used_ebs > vol->reserved_pebs) {
69262306a36Sopenharmony_ci		err = 4;
69362306a36Sopenharmony_ci		goto bad;
69462306a36Sopenharmony_ci	}
69562306a36Sopenharmony_ci	if (av->data_pad != vol->data_pad) {
69662306a36Sopenharmony_ci		err = 5;
69762306a36Sopenharmony_ci		goto bad;
69862306a36Sopenharmony_ci	}
69962306a36Sopenharmony_ci	return 0;
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_cibad:
70262306a36Sopenharmony_ci	ubi_err(vol->ubi, "bad attaching information, error %d", err);
70362306a36Sopenharmony_ci	ubi_dump_av(av);
70462306a36Sopenharmony_ci	ubi_dump_vol_info(vol);
70562306a36Sopenharmony_ci	return -EINVAL;
70662306a36Sopenharmony_ci}
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci/**
70962306a36Sopenharmony_ci * check_attaching_info - check that attaching information.
71062306a36Sopenharmony_ci * @ubi: UBI device description object
71162306a36Sopenharmony_ci * @ai: attaching information
71262306a36Sopenharmony_ci *
71362306a36Sopenharmony_ci * Even though we protect on-flash data by CRC checksums, we still don't trust
71462306a36Sopenharmony_ci * the media. This function ensures that attaching information is consistent to
71562306a36Sopenharmony_ci * the information read from the volume table. Returns zero if the attaching
71662306a36Sopenharmony_ci * information is OK and %-EINVAL if it is not.
71762306a36Sopenharmony_ci */
71862306a36Sopenharmony_cistatic int check_attaching_info(const struct ubi_device *ubi,
71962306a36Sopenharmony_ci			       struct ubi_attach_info *ai)
72062306a36Sopenharmony_ci{
72162306a36Sopenharmony_ci	int err, i;
72262306a36Sopenharmony_ci	struct ubi_ainf_volume *av;
72362306a36Sopenharmony_ci	struct ubi_volume *vol;
72462306a36Sopenharmony_ci
72562306a36Sopenharmony_ci	if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {
72662306a36Sopenharmony_ci		ubi_err(ubi, "found %d volumes while attaching, maximum is %d + %d",
72762306a36Sopenharmony_ci			ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);
72862306a36Sopenharmony_ci		return -EINVAL;
72962306a36Sopenharmony_ci	}
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ci	if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&
73262306a36Sopenharmony_ci	    ai->highest_vol_id < UBI_INTERNAL_VOL_START) {
73362306a36Sopenharmony_ci		ubi_err(ubi, "too large volume ID %d found",
73462306a36Sopenharmony_ci			ai->highest_vol_id);
73562306a36Sopenharmony_ci		return -EINVAL;
73662306a36Sopenharmony_ci	}
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
73962306a36Sopenharmony_ci		cond_resched();
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci		av = ubi_find_av(ai, i);
74262306a36Sopenharmony_ci		vol = ubi->volumes[i];
74362306a36Sopenharmony_ci		if (!vol) {
74462306a36Sopenharmony_ci			if (av)
74562306a36Sopenharmony_ci				ubi_remove_av(ai, av);
74662306a36Sopenharmony_ci			continue;
74762306a36Sopenharmony_ci		}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci		if (vol->reserved_pebs == 0) {
75062306a36Sopenharmony_ci			ubi_assert(i < ubi->vtbl_slots);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci			if (!av)
75362306a36Sopenharmony_ci				continue;
75462306a36Sopenharmony_ci
75562306a36Sopenharmony_ci			/*
75662306a36Sopenharmony_ci			 * During attaching we found a volume which does not
75762306a36Sopenharmony_ci			 * exist according to the information in the volume
75862306a36Sopenharmony_ci			 * table. This must have happened due to an unclean
75962306a36Sopenharmony_ci			 * reboot while the volume was being removed. Discard
76062306a36Sopenharmony_ci			 * these eraseblocks.
76162306a36Sopenharmony_ci			 */
76262306a36Sopenharmony_ci			ubi_msg(ubi, "finish volume %d removal", av->vol_id);
76362306a36Sopenharmony_ci			ubi_remove_av(ai, av);
76462306a36Sopenharmony_ci		} else if (av) {
76562306a36Sopenharmony_ci			err = check_av(vol, av);
76662306a36Sopenharmony_ci			if (err)
76762306a36Sopenharmony_ci				return err;
76862306a36Sopenharmony_ci		}
76962306a36Sopenharmony_ci	}
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	return 0;
77262306a36Sopenharmony_ci}
77362306a36Sopenharmony_ci
77462306a36Sopenharmony_ci/**
77562306a36Sopenharmony_ci * ubi_read_volume_table - read the volume table.
77662306a36Sopenharmony_ci * @ubi: UBI device description object
77762306a36Sopenharmony_ci * @ai: attaching information
77862306a36Sopenharmony_ci *
77962306a36Sopenharmony_ci * This function reads volume table, checks it, recover from errors if needed,
78062306a36Sopenharmony_ci * or creates it if needed. Returns zero in case of success and a negative
78162306a36Sopenharmony_ci * error code in case of failure.
78262306a36Sopenharmony_ci */
78362306a36Sopenharmony_ciint ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai)
78462306a36Sopenharmony_ci{
78562306a36Sopenharmony_ci	int err;
78662306a36Sopenharmony_ci	struct ubi_ainf_volume *av;
78762306a36Sopenharmony_ci
78862306a36Sopenharmony_ci	empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);
78962306a36Sopenharmony_ci
79062306a36Sopenharmony_ci	/*
79162306a36Sopenharmony_ci	 * The number of supported volumes is limited by the eraseblock size
79262306a36Sopenharmony_ci	 * and by the UBI_MAX_VOLUMES constant.
79362306a36Sopenharmony_ci	 */
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	if (ubi->leb_size < UBI_VTBL_RECORD_SIZE) {
79662306a36Sopenharmony_ci		ubi_err(ubi, "LEB size too small for a volume record");
79762306a36Sopenharmony_ci		return -EINVAL;
79862306a36Sopenharmony_ci	}
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE;
80162306a36Sopenharmony_ci	if (ubi->vtbl_slots > UBI_MAX_VOLUMES)
80262306a36Sopenharmony_ci		ubi->vtbl_slots = UBI_MAX_VOLUMES;
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci	ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;
80562306a36Sopenharmony_ci	ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID);
80862306a36Sopenharmony_ci	if (!av) {
80962306a36Sopenharmony_ci		/*
81062306a36Sopenharmony_ci		 * No logical eraseblocks belonging to the layout volume were
81162306a36Sopenharmony_ci		 * found. This could mean that the flash is just empty. In
81262306a36Sopenharmony_ci		 * this case we create empty layout volume.
81362306a36Sopenharmony_ci		 *
81462306a36Sopenharmony_ci		 * But if flash is not empty this must be a corruption or the
81562306a36Sopenharmony_ci		 * MTD device just contains garbage.
81662306a36Sopenharmony_ci		 */
81762306a36Sopenharmony_ci		if (ai->is_empty) {
81862306a36Sopenharmony_ci			ubi->vtbl = create_empty_lvol(ubi, ai);
81962306a36Sopenharmony_ci			if (IS_ERR(ubi->vtbl))
82062306a36Sopenharmony_ci				return PTR_ERR(ubi->vtbl);
82162306a36Sopenharmony_ci		} else {
82262306a36Sopenharmony_ci			ubi_err(ubi, "the layout volume was not found");
82362306a36Sopenharmony_ci			return -EINVAL;
82462306a36Sopenharmony_ci		}
82562306a36Sopenharmony_ci	} else {
82662306a36Sopenharmony_ci		if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) {
82762306a36Sopenharmony_ci			/* This must not happen with proper UBI images */
82862306a36Sopenharmony_ci			ubi_err(ubi, "too many LEBs (%d) in layout volume",
82962306a36Sopenharmony_ci				av->leb_count);
83062306a36Sopenharmony_ci			return -EINVAL;
83162306a36Sopenharmony_ci		}
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_ci		ubi->vtbl = process_lvol(ubi, ai, av);
83462306a36Sopenharmony_ci		if (IS_ERR(ubi->vtbl))
83562306a36Sopenharmony_ci			return PTR_ERR(ubi->vtbl);
83662306a36Sopenharmony_ci	}
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ci	ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/*
84162306a36Sopenharmony_ci	 * The layout volume is OK, initialize the corresponding in-RAM data
84262306a36Sopenharmony_ci	 * structures.
84362306a36Sopenharmony_ci	 */
84462306a36Sopenharmony_ci	err = init_volumes(ubi, ai, ubi->vtbl);
84562306a36Sopenharmony_ci	if (err)
84662306a36Sopenharmony_ci		goto out_free;
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	/*
84962306a36Sopenharmony_ci	 * Make sure that the attaching information is consistent to the
85062306a36Sopenharmony_ci	 * information stored in the volume table.
85162306a36Sopenharmony_ci	 */
85262306a36Sopenharmony_ci	err = check_attaching_info(ubi, ai);
85362306a36Sopenharmony_ci	if (err)
85462306a36Sopenharmony_ci		goto out_free;
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_ci	return 0;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ciout_free:
85962306a36Sopenharmony_ci	vfree(ubi->vtbl);
86062306a36Sopenharmony_ci	ubi_free_all_volumes(ubi);
86162306a36Sopenharmony_ci	return err;
86262306a36Sopenharmony_ci}
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci/**
86562306a36Sopenharmony_ci * self_vtbl_check - check volume table.
86662306a36Sopenharmony_ci * @ubi: UBI device description object
86762306a36Sopenharmony_ci */
86862306a36Sopenharmony_cistatic void self_vtbl_check(const struct ubi_device *ubi)
86962306a36Sopenharmony_ci{
87062306a36Sopenharmony_ci	if (!ubi_dbg_chk_gen(ubi))
87162306a36Sopenharmony_ci		return;
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_ci	if (vtbl_check(ubi, ubi->vtbl)) {
87462306a36Sopenharmony_ci		ubi_err(ubi, "self-check failed");
87562306a36Sopenharmony_ci		BUG();
87662306a36Sopenharmony_ci	}
87762306a36Sopenharmony_ci}
878