diff options
| author | Kyungmin Park <kyungmin.park@samsung.com> | 2008-11-19 16:27:23 +0100 | 
|---|---|---|
| committer | Stefan Roese <sr@denx.de> | 2008-11-19 20:34:39 +0100 | 
| commit | f412fefa079c6aa9a9763f6869bf787ea6bf6e1b (patch) | |
| tree | ce0f7eb4c1b6a45ce1a60bd33fae225832d8cd09 | |
| parent | 2d262c4853cb5b6ddce1a28a9641f2de3688d7ea (diff) | |
| download | olio-uboot-2014.01-f412fefa079c6aa9a9763f6869bf787ea6bf6e1b.tar.xz olio-uboot-2014.01-f412fefa079c6aa9a9763f6869bf787ea6bf6e1b.zip | |
UBI: Add basic UBI support to U-Boot (Part 4/8)
This patch adds basic UBI (Unsorted Block Image) support to U-Boot.
It's based on the Linux UBI version and basically has a "OS"
translation wrapper that defines most Linux specific calls
(spin_lock() etc.) into no-ops. Some source code parts have been
uncommented by "#ifdef UBI_LINUX". This makes it easier to compare
this version with the Linux version and simplifies future UBI
ports/bug-fixes from the Linux version.
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Stefan Roese <sr@denx.de>
| -rw-r--r-- | drivers/mtd/ubi/scan.c | 1360 | ||||
| -rw-r--r-- | drivers/mtd/ubi/scan.h | 165 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi-media.h | 372 | ||||
| -rw-r--r-- | drivers/mtd/ubi/ubi.h | 641 | 
4 files changed, 2538 insertions, 0 deletions
| diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c new file mode 100644 index 000000000..d5c1d27dc --- /dev/null +++ b/drivers/mtd/ubi/scan.c @@ -0,0 +1,1360 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Artem Bityutskiy (Битюцкий Артём) + */ + +/* + * UBI scanning unit. + * + * This unit is responsible for scanning the flash media, checking UBI + * headers and providing complete information about the UBI flash image. + * + * The scanning information is represented by a &struct ubi_scan_info' object. + * Information about found volumes is represented by &struct ubi_scan_volume + * objects which are kept in volume RB-tree with root at the @volumes field. + * The RB-tree is indexed by the volume ID. + * + * Found logical eraseblocks are represented by &struct ubi_scan_leb objects. + * These objects are kept in per-volume RB-trees with the root at the + * corresponding &struct ubi_scan_volume object. To put it differently, we keep + * an RB-tree of per-volume objects and each of these objects is the root of + * RB-tree of per-eraseblock objects. + * + * Corrupted physical eraseblocks are put to the @corr list, free physical + * eraseblocks are put to the @free list and the physical eraseblock to be + * erased are put to the @erase list. + */ + +#ifdef UBI_LINUX +#include <linux/err.h> +#include <linux/crc32.h> +#include <asm/div64.h> +#endif + +#include <ubi_uboot.h> +#include "ubi.h" + +#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si); +#else +#define paranoid_check_si(ubi, si) 0 +#endif + +/* Temporary variables used during scanning */ +static struct ubi_ec_hdr *ech; +static struct ubi_vid_hdr *vidh; + +/** + * add_to_list - add physical eraseblock to a list. + * @si: scanning information + * @pnum: physical eraseblock number to add + * @ec: erase counter of the physical eraseblock + * @list: the list to add to + * + * This function adds physical eraseblock @pnum to free, erase, corrupted or + * alien lists. Returns zero in case of success and a negative error code in + * case of failure. + */ +static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, +		       struct list_head *list) +{ +	struct ubi_scan_leb *seb; + +	if (list == &si->free) +		dbg_bld("add to free: PEB %d, EC %d", pnum, ec); +	else if (list == &si->erase) +		dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); +	else if (list == &si->corr) +		dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); +	else if (list == &si->alien) +		dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); +	else +		BUG(); + +	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); +	if (!seb) +		return -ENOMEM; + +	seb->pnum = pnum; +	seb->ec = ec; +	list_add_tail(&seb->u.list, list); +	return 0; +} + +/** + * validate_vid_hdr - check that volume identifier header is correct and + * consistent. + * @vid_hdr: the volume identifier header to check + * @sv: information about the volume this logical eraseblock belongs to + * @pnum: physical eraseblock number the VID header came from + * + * This function checks that data stored in @vid_hdr is consistent. Returns + * non-zero if an inconsistency was found and zero if not. + * + * Note, UBI does sanity check of everything it reads from the flash media. + * Most of the checks are done in the I/O unit. Here we check that the + * information in the VID header is consistent to the information in other VID + * headers of the same volume. + */ +static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, +			    const struct ubi_scan_volume *sv, int pnum) +{ +	int vol_type = vid_hdr->vol_type; +	int vol_id = be32_to_cpu(vid_hdr->vol_id); +	int used_ebs = be32_to_cpu(vid_hdr->used_ebs); +	int data_pad = be32_to_cpu(vid_hdr->data_pad); + +	if (sv->leb_count != 0) { +		int sv_vol_type; + +		/* +		 * This is not the first logical eraseblock belonging to this +		 * volume. Ensure that the data in its VID header is consistent +		 * to the data in previous logical eraseblock headers. +		 */ + +		if (vol_id != sv->vol_id) { +			dbg_err("inconsistent vol_id"); +			goto bad; +		} + +		if (sv->vol_type == UBI_STATIC_VOLUME) +			sv_vol_type = UBI_VID_STATIC; +		else +			sv_vol_type = UBI_VID_DYNAMIC; + +		if (vol_type != sv_vol_type) { +			dbg_err("inconsistent vol_type"); +			goto bad; +		} + +		if (used_ebs != sv->used_ebs) { +			dbg_err("inconsistent used_ebs"); +			goto bad; +		} + +		if (data_pad != sv->data_pad) { +			dbg_err("inconsistent data_pad"); +			goto bad; +		} +	} + +	return 0; + +bad: +	ubi_err("inconsistent VID header at PEB %d", pnum); +	ubi_dbg_dump_vid_hdr(vid_hdr); +	ubi_dbg_dump_sv(sv); +	return -EINVAL; +} + +/** + * add_volume - add volume to the scanning information. + * @si: scanning information + * @vol_id: ID of the volume to add + * @pnum: physical eraseblock number + * @vid_hdr: volume identifier header + * + * If the volume corresponding to the @vid_hdr logical eraseblock is already + * present in the scanning information, this function does nothing. Otherwise + * it adds corresponding volume to the scanning information. Returns a pointer + * to the scanning volume object in case of success and a negative error code + * in case of failure. + */ +static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, +					  int pnum, +					  const struct ubi_vid_hdr *vid_hdr) +{ +	struct ubi_scan_volume *sv; +	struct rb_node **p = &si->volumes.rb_node, *parent = NULL; + +	ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id)); + +	/* Walk the volume RB-tree to look if this volume is already present */ +	while (*p) { +		parent = *p; +		sv = rb_entry(parent, struct ubi_scan_volume, rb); + +		if (vol_id == sv->vol_id) +			return sv; + +		if (vol_id > sv->vol_id) +			p = &(*p)->rb_left; +		else +			p = &(*p)->rb_right; +	} + +	/* The volume is absent - add it */ +	sv = kmalloc(sizeof(struct ubi_scan_volume), GFP_KERNEL); +	if (!sv) +		return ERR_PTR(-ENOMEM); + +	sv->highest_lnum = sv->leb_count = 0; +	sv->vol_id = vol_id; +	sv->root = RB_ROOT; +	sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs); +	sv->data_pad = be32_to_cpu(vid_hdr->data_pad); +	sv->compat = vid_hdr->compat; +	sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME +							    : UBI_STATIC_VOLUME; +	if (vol_id > si->highest_vol_id) +		si->highest_vol_id = vol_id; + +	rb_link_node(&sv->rb, parent, p); +	rb_insert_color(&sv->rb, &si->volumes); +	si->vols_found += 1; +	dbg_bld("added volume %d", vol_id); +	return sv; +} + +/** + * compare_lebs - find out which logical eraseblock is newer. + * @ubi: UBI device description object + * @seb: first logical eraseblock to compare + * @pnum: physical eraseblock number of the second logical eraseblock to + * compare + * @vid_hdr: volume identifier header of the second logical eraseblock + * + * This function compares 2 copies of a LEB and informs which one is newer. In + * case of success this function returns a positive value, in case of failure, a + * negative error code is returned. The success return codes use the following + * bits: + *     o bit 0 is cleared: the first PEB (described by @seb) is newer then the + *       second PEB (described by @pnum and @vid_hdr); + *     o bit 0 is set: the second PEB is newer; + *     o bit 1 is cleared: no bit-flips were detected in the newer LEB; + *     o bit 1 is set: bit-flips were detected in the newer LEB; + *     o bit 2 is cleared: the older LEB is not corrupted; + *     o bit 2 is set: the older LEB is corrupted. + */ +static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, +			int pnum, const struct ubi_vid_hdr *vid_hdr) +{ +	void *buf; +	int len, err, second_is_newer, bitflips = 0, corrupted = 0; +	uint32_t data_crc, crc; +	struct ubi_vid_hdr *vh = NULL; +	unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); + +	if (seb->sqnum == 0 && sqnum2 == 0) { +		long long abs, v1 = seb->leb_ver, v2 = be32_to_cpu(vid_hdr->leb_ver); + +		/* +		 * UBI constantly increases the logical eraseblock version +		 * number and it can overflow. Thus, we have to bear in mind +		 * that versions that are close to %0xFFFFFFFF are less then +		 * versions that are close to %0. +		 * +		 * The UBI WL unit guarantees that the number of pending tasks +		 * is not greater then %0x7FFFFFFF. So, if the difference +		 * between any two versions is greater or equivalent to +		 * %0x7FFFFFFF, there was an overflow and the logical +		 * eraseblock with lower version is actually newer then the one +		 * with higher version. +		 * +		 * FIXME: but this is anyway obsolete and will be removed at +		 * some point. +		 */ +		dbg_bld("using old crappy leb_ver stuff"); + +		if (v1 == v2) { +			ubi_err("PEB %d and PEB %d have the same version %lld", +				seb->pnum, pnum, v1); +			return -EINVAL; +		} + +		abs = v1 - v2; +		if (abs < 0) +			abs = -abs; + +		if (abs < 0x7FFFFFFF) +			/* Non-overflow situation */ +			second_is_newer = (v2 > v1); +		else +			second_is_newer = (v2 < v1); +	} else +		/* Obviously the LEB with lower sequence counter is older */ +		second_is_newer = sqnum2 > seb->sqnum; + +	/* +	 * Now we know which copy is newer. If the copy flag of the PEB with +	 * newer version is not set, then we just return, otherwise we have to +	 * check data CRC. For the second PEB we already have the VID header, +	 * for the first one - we'll need to re-read it from flash. +	 * +	 * FIXME: this may be optimized so that we wouldn't read twice. +	 */ + +	if (second_is_newer) { +		if (!vid_hdr->copy_flag) { +			/* It is not a copy, so it is newer */ +			dbg_bld("second PEB %d is newer, copy_flag is unset", +				pnum); +			return 1; +		} +	} else { +		pnum = seb->pnum; + +		vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); +		if (!vh) +			return -ENOMEM; + +		err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); +		if (err) { +			if (err == UBI_IO_BITFLIPS) +				bitflips = 1; +			else { +				dbg_err("VID of PEB %d header is bad, but it " +					"was OK earlier", pnum); +				if (err > 0) +					err = -EIO; + +				goto out_free_vidh; +			} +		} + +		if (!vh->copy_flag) { +			/* It is not a copy, so it is newer */ +			dbg_bld("first PEB %d is newer, copy_flag is unset", +				pnum); +			err = bitflips << 1; +			goto out_free_vidh; +		} + +		vid_hdr = vh; +	} + +	/* Read the data of the copy and check the CRC */ + +	len = be32_to_cpu(vid_hdr->data_size); +	buf = vmalloc(len); +	if (!buf) { +		err = -ENOMEM; +		goto out_free_vidh; +	} + +	err = ubi_io_read_data(ubi, buf, pnum, 0, len); +	if (err && err != UBI_IO_BITFLIPS) +		goto out_free_buf; + +	data_crc = be32_to_cpu(vid_hdr->data_crc); +	crc = crc32(UBI_CRC32_INIT, buf, len); +	if (crc != data_crc) { +		dbg_bld("PEB %d CRC error: calculated %#08x, must be %#08x", +			pnum, crc, data_crc); +		corrupted = 1; +		bitflips = 0; +		second_is_newer = !second_is_newer; +	} else { +		dbg_bld("PEB %d CRC is OK", pnum); +		bitflips = !!err; +	} + +	vfree(buf); +	ubi_free_vid_hdr(ubi, vh); + +	if (second_is_newer) +		dbg_bld("second PEB %d is newer, copy_flag is set", pnum); +	else +		dbg_bld("first PEB %d is newer, copy_flag is set", pnum); + +	return second_is_newer | (bitflips << 1) | (corrupted << 2); + +out_free_buf: +	vfree(buf); +out_free_vidh: +	ubi_free_vid_hdr(ubi, vh); +	return err; +} + +/** + * ubi_scan_add_used - add information about a physical eraseblock to the + * scanning information. + * @ubi: UBI device description object + * @si: scanning information + * @pnum: the physical eraseblock number + * @ec: erase counter + * @vid_hdr: the volume identifier header + * @bitflips: if bit-flips were detected when this physical eraseblock was read + * + * This function adds information about a used physical eraseblock to the + * 'used' tree of the corresponding volume. The function is rather complex + * because it has to handle cases when this is not the first physical + * eraseblock belonging to the same logical eraseblock, and the newer one has + * to be picked, while the older one has to be dropped. This function returns + * zero in case of success and a negative error code in case of failure. + */ +int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, +		      int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, +		      int bitflips) +{ +	int err, vol_id, lnum; +	uint32_t leb_ver; +	unsigned long long sqnum; +	struct ubi_scan_volume *sv; +	struct ubi_scan_leb *seb; +	struct rb_node **p, *parent = NULL; + +	vol_id = be32_to_cpu(vid_hdr->vol_id); +	lnum = be32_to_cpu(vid_hdr->lnum); +	sqnum = be64_to_cpu(vid_hdr->sqnum); +	leb_ver = be32_to_cpu(vid_hdr->leb_ver); + +	dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, ver %u, bitflips %d", +		pnum, vol_id, lnum, ec, sqnum, leb_ver, bitflips); + +	sv = add_volume(si, vol_id, pnum, vid_hdr); +	if (IS_ERR(sv) < 0) +		return PTR_ERR(sv); + +	if (si->max_sqnum < sqnum) +		si->max_sqnum = sqnum; + +	/* +	 * Walk the RB-tree of logical eraseblocks of volume @vol_id to look +	 * if this is the first instance of this logical eraseblock or not. +	 */ +	p = &sv->root.rb_node; +	while (*p) { +		int cmp_res; + +		parent = *p; +		seb = rb_entry(parent, struct ubi_scan_leb, u.rb); +		if (lnum != seb->lnum) { +			if (lnum < seb->lnum) +				p = &(*p)->rb_left; +			else +				p = &(*p)->rb_right; +			continue; +		} + +		/* +		 * There is already a physical eraseblock describing the same +		 * logical eraseblock present. +		 */ + +		dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " +			"LEB ver %u, EC %d", seb->pnum, seb->sqnum, +			seb->leb_ver, seb->ec); + +		/* +		 * Make sure that the logical eraseblocks have different +		 * versions. Otherwise the image is bad. +		 */ +		if (seb->leb_ver == leb_ver && leb_ver != 0) { +			ubi_err("two LEBs with same version %u", leb_ver); +			ubi_dbg_dump_seb(seb, 0); +			ubi_dbg_dump_vid_hdr(vid_hdr); +			return -EINVAL; +		} + +		/* +		 * Make sure that the logical eraseblocks have different +		 * sequence numbers. Otherwise the image is bad. +		 * +		 * FIXME: remove 'sqnum != 0' check when leb_ver is removed. +		 */ +		if (seb->sqnum == sqnum && sqnum != 0) { +			ubi_err("two LEBs with same sequence number %llu", +				sqnum); +			ubi_dbg_dump_seb(seb, 0); +			ubi_dbg_dump_vid_hdr(vid_hdr); +			return -EINVAL; +		} + +		/* +		 * Now we have to drop the older one and preserve the newer +		 * one. +		 */ +		cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr); +		if (cmp_res < 0) +			return cmp_res; + +		if (cmp_res & 1) { +			/* +			 * This logical eraseblock is newer then the one +			 * found earlier. +			 */ +			err = validate_vid_hdr(vid_hdr, sv, pnum); +			if (err) +				return err; + +			if (cmp_res & 4) +				err = add_to_list(si, seb->pnum, seb->ec, +						  &si->corr); +			else +				err = add_to_list(si, seb->pnum, seb->ec, +						  &si->erase); +			if (err) +				return err; + +			seb->ec = ec; +			seb->pnum = pnum; +			seb->scrub = ((cmp_res & 2) || bitflips); +			seb->sqnum = sqnum; +			seb->leb_ver = leb_ver; + +			if (sv->highest_lnum == lnum) +				sv->last_data_size = +					be32_to_cpu(vid_hdr->data_size); + +			return 0; +		} else { +			/* +			 * This logical eraseblock is older then the one found +			 * previously. +			 */ +			if (cmp_res & 4) +				return add_to_list(si, pnum, ec, &si->corr); +			else +				return add_to_list(si, pnum, ec, &si->erase); +		} +	} + +	/* +	 * We've met this logical eraseblock for the first time, add it to the +	 * scanning information. +	 */ + +	err = validate_vid_hdr(vid_hdr, sv, pnum); +	if (err) +		return err; + +	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); +	if (!seb) +		return -ENOMEM; + +	seb->ec = ec; +	seb->pnum = pnum; +	seb->lnum = lnum; +	seb->sqnum = sqnum; +	seb->scrub = bitflips; +	seb->leb_ver = leb_ver; + +	if (sv->highest_lnum <= lnum) { +		sv->highest_lnum = lnum; +		sv->last_data_size = be32_to_cpu(vid_hdr->data_size); +	} + +	sv->leb_count += 1; +	rb_link_node(&seb->u.rb, parent, p); +	rb_insert_color(&seb->u.rb, &sv->root); +	return 0; +} + +/** + * ubi_scan_find_sv - find information about a particular volume in the + * scanning information. + * @si: scanning information + * @vol_id: the requested volume ID + * + * This function returns a pointer to the volume description or %NULL if there + * are no data about this volume in the scanning information. + */ +struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, +					 int vol_id) +{ +	struct ubi_scan_volume *sv; +	struct rb_node *p = si->volumes.rb_node; + +	while (p) { +		sv = rb_entry(p, struct ubi_scan_volume, rb); + +		if (vol_id == sv->vol_id) +			return sv; + +		if (vol_id > sv->vol_id) +			p = p->rb_left; +		else +			p = p->rb_right; +	} + +	return NULL; +} + +/** + * ubi_scan_find_seb - find information about a particular logical + * eraseblock in the volume scanning information. + * @sv: a pointer to the volume scanning information + * @lnum: the requested logical eraseblock + * + * This function returns a pointer to the scanning logical eraseblock or %NULL + * if there are no data about it in the scanning volume information. + */ +struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv, +				       int lnum) +{ +	struct ubi_scan_leb *seb; +	struct rb_node *p = sv->root.rb_node; + +	while (p) { +		seb = rb_entry(p, struct ubi_scan_leb, u.rb); + +		if (lnum == seb->lnum) +			return seb; + +		if (lnum > seb->lnum) +			p = p->rb_left; +		else +			p = p->rb_right; +	} + +	return NULL; +} + +/** + * ubi_scan_rm_volume - delete scanning information about a volume. + * @si: scanning information + * @sv: the volume scanning information to delete + */ +void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv) +{ +	struct rb_node *rb; +	struct ubi_scan_leb *seb; + +	dbg_bld("remove scanning information about volume %d", sv->vol_id); + +	while ((rb = rb_first(&sv->root))) { +		seb = rb_entry(rb, struct ubi_scan_leb, u.rb); +		rb_erase(&seb->u.rb, &sv->root); +		list_add_tail(&seb->u.list, &si->erase); +	} + +	rb_erase(&sv->rb, &si->volumes); +	kfree(sv); +	si->vols_found -= 1; +} + +/** + * ubi_scan_erase_peb - erase a physical eraseblock. + * @ubi: UBI device description object + * @si: scanning information + * @pnum: physical eraseblock number to erase; + * @ec: erase counter value to write (%UBI_SCAN_UNKNOWN_EC if it is unknown) + * + * This function erases physical eraseblock 'pnum', and writes the erase + * counter header to it. This function should only be used on UBI device + * initialization stages, when the EBA unit had not been yet initialized. This + * function returns zero in case of success and a negative error code in case + * of failure. + */ +int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, +		       int pnum, int ec) +{ +	int err; +	struct ubi_ec_hdr *ec_hdr; + +	if ((long long)ec >= UBI_MAX_ERASECOUNTER) { +		/* +		 * Erase counter overflow. Upgrade UBI and use 64-bit +		 * erase counters internally. +		 */ +		ubi_err("erase counter overflow at PEB %d, EC %d", pnum, ec); +		return -EINVAL; +	} + +	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); +	if (!ec_hdr) +		return -ENOMEM; + +	ec_hdr->ec = cpu_to_be64(ec); + +	err = ubi_io_sync_erase(ubi, pnum, 0); +	if (err < 0) +		goto out_free; + +	err = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr); + +out_free: +	kfree(ec_hdr); +	return err; +} + +/** + * ubi_scan_get_free_peb - get a free physical eraseblock. + * @ubi: UBI device description object + * @si: scanning information + * + * This function returns a free physical eraseblock. It is supposed to be + * called on the UBI initialization stages when the wear-leveling unit is not + * initialized yet. This function picks a physical eraseblocks from one of the + * lists, writes the EC header if it is needed, and removes it from the list. + * + * This function returns scanning physical eraseblock information in case of + * success and an error code in case of failure. + */ +struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, +					   struct ubi_scan_info *si) +{ +	int err = 0, i; +	struct ubi_scan_leb *seb; + +	if (!list_empty(&si->free)) { +		seb = list_entry(si->free.next, struct ubi_scan_leb, u.list); +		list_del(&seb->u.list); +		dbg_bld("return free PEB %d, EC %d", seb->pnum, seb->ec); +		return seb; +	} + +	for (i = 0; i < 2; i++) { +		struct list_head *head; +		struct ubi_scan_leb *tmp_seb; + +		if (i == 0) +			head = &si->erase; +		else +			head = &si->corr; + +		/* +		 * We try to erase the first physical eraseblock from the @head +		 * list and pick it if we succeed, or try to erase the +		 * next one if not. And so forth. We don't want to take care +		 * about bad eraseblocks here - they'll be handled later. +		 */ +		list_for_each_entry_safe(seb, tmp_seb, head, u.list) { +			if (seb->ec == UBI_SCAN_UNKNOWN_EC) +				seb->ec = si->mean_ec; + +			err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1); +			if (err) +				continue; + +			seb->ec += 1; +			list_del(&seb->u.list); +			dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); +			return seb; +		} +	} + +	ubi_err("no eraseblocks found"); +	return ERR_PTR(-ENOSPC); +} + +/** + * process_eb - read UBI headers, check them and add corresponding data + * to the scanning information. + * @ubi: UBI device description object + * @si: scanning information + * @pnum: the physical eraseblock number + * + * This function returns a zero if the physical eraseblock was successfully + * handled and a negative error code in case of failure. + */ +static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum) +{ +	long long uninitialized_var(ec); +	int err, bitflips = 0, vol_id, ec_corr = 0; + +	dbg_bld("scan PEB %d", pnum); + +	/* Skip bad physical eraseblocks */ +	err = ubi_io_is_bad(ubi, pnum); +	if (err < 0) +		return err; +	else if (err) { +		/* +		 * FIXME: this is actually duty of the I/O unit to initialize +		 * this, but MTD does not provide enough information. +		 */ +		si->bad_peb_count += 1; +		return 0; +	} + +	err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); +	if (err < 0) +		return err; +	else if (err == UBI_IO_BITFLIPS) +		bitflips = 1; +	else if (err == UBI_IO_PEB_EMPTY) +		return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); +	else if (err == UBI_IO_BAD_EC_HDR) { +		/* +		 * We have to also look at the VID header, possibly it is not +		 * corrupted. Set %bitflips flag in order to make this PEB be +		 * moved and EC be re-created. +		 */ +		ec_corr = 1; +		ec = UBI_SCAN_UNKNOWN_EC; +		bitflips = 1; +	} + +	si->is_empty = 0; + +	if (!ec_corr) { +		/* Make sure UBI version is OK */ +		if (ech->version != UBI_VERSION) { +			ubi_err("this UBI version is %d, image version is %d", +				UBI_VERSION, (int)ech->version); +			return -EINVAL; +		} + +		ec = be64_to_cpu(ech->ec); +		if (ec > UBI_MAX_ERASECOUNTER) { +			/* +			 * Erase counter overflow. The EC headers have 64 bits +			 * reserved, but we anyway make use of only 31 bit +			 * values, as this seems to be enough for any existing +			 * flash. Upgrade UBI and use 64-bit erase counters +			 * internally. +			 */ +			ubi_err("erase counter overflow, max is %d", +				UBI_MAX_ERASECOUNTER); +			ubi_dbg_dump_ec_hdr(ech); +			return -EINVAL; +		} +	} + +	/* OK, we've done with the EC header, let's look at the VID header */ + +	err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0); +	if (err < 0) +		return err; +	else if (err == UBI_IO_BITFLIPS) +		bitflips = 1; +	else if (err == UBI_IO_BAD_VID_HDR || +		 (err == UBI_IO_PEB_FREE && ec_corr)) { +		/* VID header is corrupted */ +		err = add_to_list(si, pnum, ec, &si->corr); +		if (err) +			return err; +		goto adjust_mean_ec; +	} else if (err == UBI_IO_PEB_FREE) { +		/* No VID header - the physical eraseblock is free */ +		err = add_to_list(si, pnum, ec, &si->free); +		if (err) +			return err; +		goto adjust_mean_ec; +	} + +	vol_id = be32_to_cpu(vidh->vol_id); +	if (vol_id > UBI_MAX_VOLUMES && vol_id != UBI_LAYOUT_VOLUME_ID) { +		int lnum = be32_to_cpu(vidh->lnum); + +		/* Unsupported internal volume */ +		switch (vidh->compat) { +		case UBI_COMPAT_DELETE: +			ubi_msg("\"delete\" compatible internal volume %d:%d" +				" found, remove it", vol_id, lnum); +			err = add_to_list(si, pnum, ec, &si->corr); +			if (err) +				return err; +			break; + +		case UBI_COMPAT_RO: +			ubi_msg("read-only compatible internal volume %d:%d" +				" found, switch to read-only mode", +				vol_id, lnum); +			ubi->ro_mode = 1; +			break; + +		case UBI_COMPAT_PRESERVE: +			ubi_msg("\"preserve\" compatible internal volume %d:%d" +				" found", vol_id, lnum); +			err = add_to_list(si, pnum, ec, &si->alien); +			if (err) +				return err; +			si->alien_peb_count += 1; +			return 0; + +		case UBI_COMPAT_REJECT: +			ubi_err("incompatible internal volume %d:%d found", +				vol_id, lnum); +			return -EINVAL; +		} +	} + +	/* Both UBI headers seem to be fine */ +	err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips); +	if (err) +		return err; + +adjust_mean_ec: +	if (!ec_corr) { +		si->ec_sum += ec; +		si->ec_count += 1; +		if (ec > si->max_ec) +			si->max_ec = ec; +		if (ec < si->min_ec) +			si->min_ec = ec; +	} + +	return 0; +} + +/** + * ubi_scan - scan an MTD device. + * @ubi: UBI device description object + * + * This function does full scanning of an MTD device and returns complete + * information about it. In case of failure, an error code is returned. + */ +struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) +{ +	int err, pnum; +	struct rb_node *rb1, *rb2; +	struct ubi_scan_volume *sv; +	struct ubi_scan_leb *seb; +	struct ubi_scan_info *si; + +	si = kzalloc(sizeof(struct ubi_scan_info), GFP_KERNEL); +	if (!si) +		return ERR_PTR(-ENOMEM); + +	INIT_LIST_HEAD(&si->corr); +	INIT_LIST_HEAD(&si->free); +	INIT_LIST_HEAD(&si->erase); +	INIT_LIST_HEAD(&si->alien); +	si->volumes = RB_ROOT; +	si->is_empty = 1; + +	err = -ENOMEM; +	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); +	if (!ech) +		goto out_si; + +	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); +	if (!vidh) +		goto out_ech; + +	for (pnum = 0; pnum < ubi->peb_count; pnum++) { +		cond_resched(); + +		dbg_msg("process PEB %d", pnum); +		err = process_eb(ubi, si, pnum); +		if (err < 0) +			goto out_vidh; +	} + +	dbg_msg("scanning is finished"); + +	/* Calculate mean erase counter */ +	if (si->ec_count) { +		do_div(si->ec_sum, si->ec_count); +		si->mean_ec = si->ec_sum; +	} + +	if (si->is_empty) +		ubi_msg("empty MTD device detected"); + +	/* +	 * In case of unknown erase counter we use the mean erase counter +	 * value. +	 */ +	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { +		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) +			if (seb->ec == UBI_SCAN_UNKNOWN_EC) +				seb->ec = si->mean_ec; +	} + +	list_for_each_entry(seb, &si->free, u.list) { +		if (seb->ec == UBI_SCAN_UNKNOWN_EC) +			seb->ec = si->mean_ec; +	} + +	list_for_each_entry(seb, &si->corr, u.list) +		if (seb->ec == UBI_SCAN_UNKNOWN_EC) +			seb->ec = si->mean_ec; + +	list_for_each_entry(seb, &si->erase, u.list) +		if (seb->ec == UBI_SCAN_UNKNOWN_EC) +			seb->ec = si->mean_ec; + +	err = paranoid_check_si(ubi, si); +	if (err) { +		if (err > 0) +			err = -EINVAL; +		goto out_vidh; +	} + +	ubi_free_vid_hdr(ubi, vidh); +	kfree(ech); + +	return si; + +out_vidh: +	ubi_free_vid_hdr(ubi, vidh); +out_ech: +	kfree(ech); +out_si: +	ubi_scan_destroy_si(si); +	return ERR_PTR(err); +} + +/** + * destroy_sv - free the scanning volume information + * @sv: scanning volume information + * + * This function destroys the volume RB-tree (@sv->root) and the scanning + * volume information. + */ +static void destroy_sv(struct ubi_scan_volume *sv) +{ +	struct ubi_scan_leb *seb; +	struct rb_node *this = sv->root.rb_node; + +	while (this) { +		if (this->rb_left) +			this = this->rb_left; +		else if (this->rb_right) +			this = this->rb_right; +		else { +			seb = rb_entry(this, struct ubi_scan_leb, u.rb); +			this = rb_parent(this); +			if (this) { +				if (this->rb_left == &seb->u.rb) +					this->rb_left = NULL; +				else +					this->rb_right = NULL; +			} + +			kfree(seb); +		} +	} +	kfree(sv); +} + +/** + * ubi_scan_destroy_si - destroy scanning information. + * @si: scanning information + */ +void ubi_scan_destroy_si(struct ubi_scan_info *si) +{ +	struct ubi_scan_leb *seb, *seb_tmp; +	struct ubi_scan_volume *sv; +	struct rb_node *rb; + +	list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { +		list_del(&seb->u.list); +		kfree(seb); +	} +	list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { +		list_del(&seb->u.list); +		kfree(seb); +	} +	list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { +		list_del(&seb->u.list); +		kfree(seb); +	} +	list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { +		list_del(&seb->u.list); +		kfree(seb); +	} + +	/* Destroy the volume RB-tree */ +	rb = si->volumes.rb_node; +	while (rb) { +		if (rb->rb_left) +			rb = rb->rb_left; +		else if (rb->rb_right) +			rb = rb->rb_right; +		else { +			sv = rb_entry(rb, struct ubi_scan_volume, rb); + +			rb = rb_parent(rb); +			if (rb) { +				if (rb->rb_left == &sv->rb) +					rb->rb_left = NULL; +				else +					rb->rb_right = NULL; +			} + +			destroy_sv(sv); +		} +	} + +	kfree(si); +} + +#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID + +/** + * paranoid_check_si - check if the scanning information is correct and + * consistent. + * @ubi: UBI device description object + * @si: scanning information + * + * This function returns zero if the scanning information is all right, %1 if + * not and a negative error code if an error occurred. + */ +static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) +{ +	int pnum, err, vols_found = 0; +	struct rb_node *rb1, *rb2; +	struct ubi_scan_volume *sv; +	struct ubi_scan_leb *seb, *last_seb; +	uint8_t *buf; + +	/* +	 * At first, check that scanning information is OK. +	 */ +	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { +		int leb_count = 0; + +		cond_resched(); + +		vols_found += 1; + +		if (si->is_empty) { +			ubi_err("bad is_empty flag"); +			goto bad_sv; +		} + +		if (sv->vol_id < 0 || sv->highest_lnum < 0 || +		    sv->leb_count < 0 || sv->vol_type < 0 || sv->used_ebs < 0 || +		    sv->data_pad < 0 || sv->last_data_size < 0) { +			ubi_err("negative values"); +			goto bad_sv; +		} + +		if (sv->vol_id >= UBI_MAX_VOLUMES && +		    sv->vol_id < UBI_INTERNAL_VOL_START) { +			ubi_err("bad vol_id"); +			goto bad_sv; +		} + +		if (sv->vol_id > si->highest_vol_id) { +			ubi_err("highest_vol_id is %d, but vol_id %d is there", +				si->highest_vol_id, sv->vol_id); +			goto out; +		} + +		if (sv->vol_type != UBI_DYNAMIC_VOLUME && +		    sv->vol_type != UBI_STATIC_VOLUME) { +			ubi_err("bad vol_type"); +			goto bad_sv; +		} + +		if (sv->data_pad > ubi->leb_size / 2) { +			ubi_err("bad data_pad"); +			goto bad_sv; +		} + +		last_seb = NULL; +		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { +			cond_resched(); + +			last_seb = seb; +			leb_count += 1; + +			if (seb->pnum < 0 || seb->ec < 0) { +				ubi_err("negative values"); +				goto bad_seb; +			} + +			if (seb->ec < si->min_ec) { +				ubi_err("bad si->min_ec (%d), %d found", +					si->min_ec, seb->ec); +				goto bad_seb; +			} + +			if (seb->ec > si->max_ec) { +				ubi_err("bad si->max_ec (%d), %d found", +					si->max_ec, seb->ec); +				goto bad_seb; +			} + +			if (seb->pnum >= ubi->peb_count) { +				ubi_err("too high PEB number %d, total PEBs %d", +					seb->pnum, ubi->peb_count); +				goto bad_seb; +			} + +			if (sv->vol_type == UBI_STATIC_VOLUME) { +				if (seb->lnum >= sv->used_ebs) { +					ubi_err("bad lnum or used_ebs"); +					goto bad_seb; +				} +			} else { +				if (sv->used_ebs != 0) { +					ubi_err("non-zero used_ebs"); +					goto bad_seb; +				} +			} + +			if (seb->lnum > sv->highest_lnum) { +				ubi_err("incorrect highest_lnum or lnum"); +				goto bad_seb; +			} +		} + +		if (sv->leb_count != leb_count) { +			ubi_err("bad leb_count, %d objects in the tree", +				leb_count); +			goto bad_sv; +		} + +		if (!last_seb) +			continue; + +		seb = last_seb; + +		if (seb->lnum != sv->highest_lnum) { +			ubi_err("bad highest_lnum"); +			goto bad_seb; +		} +	} + +	if (vols_found != si->vols_found) { +		ubi_err("bad si->vols_found %d, should be %d", +			si->vols_found, vols_found); +		goto out; +	} + +	/* Check that scanning information is correct */ +	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { +		last_seb = NULL; +		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { +			int vol_type; + +			cond_resched(); + +			last_seb = seb; + +			err = ubi_io_read_vid_hdr(ubi, seb->pnum, vidh, 1); +			if (err && err != UBI_IO_BITFLIPS) { +				ubi_err("VID header is not OK (%d)", err); +				if (err > 0) +					err = -EIO; +				return err; +			} + +			vol_type = vidh->vol_type == UBI_VID_DYNAMIC ? +				   UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; +			if (sv->vol_type != vol_type) { +				ubi_err("bad vol_type"); +				goto bad_vid_hdr; +			} + +			if (seb->sqnum != be64_to_cpu(vidh->sqnum)) { +				ubi_err("bad sqnum %llu", seb->sqnum); +				goto bad_vid_hdr; +			} + +			if (sv->vol_id != be32_to_cpu(vidh->vol_id)) { +				ubi_err("bad vol_id %d", sv->vol_id); +				goto bad_vid_hdr; +			} + +			if (sv->compat != vidh->compat) { +				ubi_err("bad compat %d", vidh->compat); +				goto bad_vid_hdr; +			} + +			if (seb->lnum != be32_to_cpu(vidh->lnum)) { +				ubi_err("bad lnum %d", seb->lnum); +				goto bad_vid_hdr; +			} + +			if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) { +				ubi_err("bad used_ebs %d", sv->used_ebs); +				goto bad_vid_hdr; +			} + +			if (sv->data_pad != be32_to_cpu(vidh->data_pad)) { +				ubi_err("bad data_pad %d", sv->data_pad); +				goto bad_vid_hdr; +			} + +			if (seb->leb_ver != be32_to_cpu(vidh->leb_ver)) { +				ubi_err("bad leb_ver %u", seb->leb_ver); +				goto bad_vid_hdr; +			} +		} + +		if (!last_seb) +			continue; + +		if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) { +			ubi_err("bad highest_lnum %d", sv->highest_lnum); +			goto bad_vid_hdr; +		} + +		if (sv->last_data_size != be32_to_cpu(vidh->data_size)) { +			ubi_err("bad last_data_size %d", sv->last_data_size); +			goto bad_vid_hdr; +		} +	} + +	/* +	 * Make sure that all the physical eraseblocks are in one of the lists +	 * or trees. +	 */ +	buf = kzalloc(ubi->peb_count, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	for (pnum = 0; pnum < ubi->peb_count; pnum++) { +		err = ubi_io_is_bad(ubi, pnum); +		if (err < 0) { +			kfree(buf); +			return err; +		} +		else if (err) +			buf[pnum] = 1; +	} + +	ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) +		ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) +			buf[seb->pnum] = 1; + +	list_for_each_entry(seb, &si->free, u.list) +		buf[seb->pnum] = 1; + +	list_for_each_entry(seb, &si->corr, u.list) +		buf[seb->pnum] = 1; + +	list_for_each_entry(seb, &si->erase, u.list) +		buf[seb->pnum] = 1; + +	list_for_each_entry(seb, &si->alien, u.list) +		buf[seb->pnum] = 1; + +	err = 0; +	for (pnum = 0; pnum < ubi->peb_count; pnum++) +		if (!buf[pnum]) { +			ubi_err("PEB %d is not referred", pnum); +			err = 1; +		} + +	kfree(buf); +	if (err) +		goto out; +	return 0; + +bad_seb: +	ubi_err("bad scanning information about LEB %d", seb->lnum); +	ubi_dbg_dump_seb(seb, 0); +	ubi_dbg_dump_sv(sv); +	goto out; + +bad_sv: +	ubi_err("bad scanning information about volume %d", sv->vol_id); +	ubi_dbg_dump_sv(sv); +	goto out; + +bad_vid_hdr: +	ubi_err("bad scanning information about volume %d", sv->vol_id); +	ubi_dbg_dump_sv(sv); +	ubi_dbg_dump_vid_hdr(vidh); + +out: +	ubi_dbg_dump_stack(); +	return 1; +} + +#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h new file mode 100644 index 000000000..966b9b682 --- /dev/null +++ b/drivers/mtd/ubi/scan.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Artem Bityutskiy (Битюцкий Артём) + */ + +#ifndef __UBI_SCAN_H__ +#define __UBI_SCAN_H__ + +/* The erase counter value for this physical eraseblock is unknown */ +#define UBI_SCAN_UNKNOWN_EC (-1) + +/** + * struct ubi_scan_leb - scanning information about a physical eraseblock. + * @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown) + * @pnum: physical eraseblock number + * @lnum: logical eraseblock number + * @scrub: if this physical eraseblock needs scrubbing + * @sqnum: sequence number + * @u: unions RB-tree or @list links + * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects + * @u.list: link in one of the eraseblock lists + * @leb_ver: logical eraseblock version (obsolete) + * + * One object of this type is allocated for each physical eraseblock during + * scanning. + */ +struct ubi_scan_leb { +	int ec; +	int pnum; +	int lnum; +	int scrub; +	unsigned long long sqnum; +	union { +		struct rb_node rb; +		struct list_head list; +	} u; +	uint32_t leb_ver; +}; + +/** + * struct ubi_scan_volume - scanning information about a volume. + * @vol_id: volume ID + * @highest_lnum: highest logical eraseblock number in this volume + * @leb_count: number of logical eraseblocks in this volume + * @vol_type: volume type + * @used_ebs: number of used logical eraseblocks in this volume (only for + * static volumes) + * @last_data_size: amount of data in the last logical eraseblock of this + * volume (always equivalent to the usable logical eraseblock size in case of + * dynamic volumes) + * @data_pad: how many bytes at the end of logical eraseblocks of this volume + * are not used (due to volume alignment) + * @compat: compatibility flags of this volume + * @rb: link in the volume RB-tree + * @root: root of the RB-tree containing all the eraseblock belonging to this + * volume (&struct ubi_scan_leb objects) + * + * One object of this type is allocated for each volume during scanning. + */ +struct ubi_scan_volume { +	int vol_id; +	int highest_lnum; +	int leb_count; +	int vol_type; +	int used_ebs; +	int last_data_size; +	int data_pad; +	int compat; +	struct rb_node rb; +	struct rb_root root; +}; + +/** + * struct ubi_scan_info - UBI scanning information. + * @volumes: root of the volume RB-tree + * @corr: list of corrupted physical eraseblocks + * @free: list of free physical eraseblocks + * @erase: list of physical eraseblocks which have to be erased + * @alien: list of physical eraseblocks which should not be used by UBI (e.g., + * @bad_peb_count: count of bad physical eraseblocks + * those belonging to "preserve"-compatible internal volumes) + * @vols_found: number of volumes found during scanning + * @highest_vol_id: highest volume ID + * @alien_peb_count: count of physical eraseblocks in the @alien list + * @is_empty: flag indicating whether the MTD device is empty or not + * @min_ec: lowest erase counter value + * @max_ec: highest erase counter value + * @max_sqnum: highest sequence number value + * @mean_ec: mean erase counter value + * @ec_sum: a temporary variable used when calculating @mean_ec + * @ec_count: a temporary variable used when calculating @mean_ec + * + * This data structure contains the result of scanning and may be used by other + * UBI units to build final UBI data structures, further error-recovery and so + * on. + */ +struct ubi_scan_info { +	struct rb_root volumes; +	struct list_head corr; +	struct list_head free; +	struct list_head erase; +	struct list_head alien; +	int bad_peb_count; +	int vols_found; +	int highest_vol_id; +	int alien_peb_count; +	int is_empty; +	int min_ec; +	int max_ec; +	unsigned long long max_sqnum; +	int mean_ec; +	uint64_t ec_sum; +	int ec_count; +}; + +struct ubi_device; +struct ubi_vid_hdr; + +/* + * ubi_scan_move_to_list - move a physical eraseblock from the volume tree to a + * list. + * + * @sv: volume scanning information + * @seb: scanning eraseblock infprmation + * @list: the list to move to + */ +static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv, +					 struct ubi_scan_leb *seb, +					 struct list_head *list) +{ +		rb_erase(&seb->u.rb, &sv->root); +		list_add_tail(&seb->u.list, list); +} + +int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, +		      int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, +		      int bitflips); +struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, +					 int vol_id); +struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv, +				       int lnum); +void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv); +struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, +					   struct ubi_scan_info *si); +int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, +		       int pnum, int ec); +struct ubi_scan_info *ubi_scan(struct ubi_device *ubi); +void ubi_scan_destroy_si(struct ubi_scan_info *si); + +#endif /* !__UBI_SCAN_H__ */ diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h new file mode 100644 index 000000000..c3185d9fd --- /dev/null +++ b/drivers/mtd/ubi/ubi-media.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Authors: Artem Bityutskiy (Битюцкий Артём) + *          Thomas Gleixner + *          Frank Haverkamp + *          Oliver Lohmann + *          Andreas Arnez + */ + +/* + * This file defines the layout of UBI headers and all the other UBI on-flash + * data structures. + */ + +#ifndef __UBI_MEDIA_H__ +#define __UBI_MEDIA_H__ + +#include <asm/byteorder.h> + +/* The version of UBI images supported by this implementation */ +#define UBI_VERSION 1 + +/* The highest erase counter value supported by this implementation */ +#define UBI_MAX_ERASECOUNTER 0x7FFFFFFF + +/* The initial CRC32 value used when calculating CRC checksums */ +#define UBI_CRC32_INIT 0xFFFFFFFFU + +/* Erase counter header magic number (ASCII "UBI#") */ +#define UBI_EC_HDR_MAGIC  0x55424923 +/* Volume identifier header magic number (ASCII "UBI!") */ +#define UBI_VID_HDR_MAGIC 0x55424921 + +/* + * Volume type constants used in the volume identifier header. + * + * @UBI_VID_DYNAMIC: dynamic volume + * @UBI_VID_STATIC: static volume + */ +enum { +	UBI_VID_DYNAMIC = 1, +	UBI_VID_STATIC  = 2 +}; + +/* + * Volume flags used in the volume table record. + * + * @UBI_VTBL_AUTORESIZE_FLG: auto-resize this volume + * + * %UBI_VTBL_AUTORESIZE_FLG flag can be set only for one volume in the volume + * table. UBI automatically re-sizes the volume which has this flag and makes + * the volume to be of largest possible size. This means that if after the + * initialization UBI finds out that there are available physical eraseblocks + * present on the device, it automatically appends all of them to the volume + * (the physical eraseblocks reserved for bad eraseblocks handling and other + * reserved physical eraseblocks are not taken). So, if there is a volume with + * the %UBI_VTBL_AUTORESIZE_FLG flag set, the amount of available logical + * eraseblocks will be zero after UBI is loaded, because all of them will be + * reserved for this volume. Note, the %UBI_VTBL_AUTORESIZE_FLG bit is cleared + * after the volume had been initialized. + * + * The auto-resize feature is useful for device production purposes. For + * example, different NAND flash chips may have different amount of initial bad + * eraseblocks, depending of particular chip instance. Manufacturers of NAND + * chips usually guarantee that the amount of initial bad eraseblocks does not + * exceed certain percent, e.g. 2%. When one creates an UBI image which will be + * flashed to the end devices in production, he does not know the exact amount + * of good physical eraseblocks the NAND chip on the device will have, but this + * number is required to calculate the volume sized and put them to the volume + * table of the UBI image. In this case, one of the volumes (e.g., the one + * which will store the root file system) is marked as "auto-resizable", and + * UBI will adjust its size on the first boot if needed. + * + * Note, first UBI reserves some amount of physical eraseblocks for bad + * eraseblock handling, and then re-sizes the volume, not vice-versa. This + * means that the pool of reserved physical eraseblocks will always be present. + */ +enum { +	UBI_VTBL_AUTORESIZE_FLG = 0x01, +}; + +/* + * Compatibility constants used by internal volumes. + * + * @UBI_COMPAT_DELETE: delete this internal volume before anything is written + * to the flash + * @UBI_COMPAT_RO: attach this device in read-only mode + * @UBI_COMPAT_PRESERVE: preserve this internal volume - do not touch its + * physical eraseblocks, don't allow the wear-leveling unit to move them + * @UBI_COMPAT_REJECT: reject this UBI image + */ +enum { +	UBI_COMPAT_DELETE   = 1, +	UBI_COMPAT_RO       = 2, +	UBI_COMPAT_PRESERVE = 4, +	UBI_COMPAT_REJECT   = 5 +}; + +/* Sizes of UBI headers */ +#define UBI_EC_HDR_SIZE  sizeof(struct ubi_ec_hdr) +#define UBI_VID_HDR_SIZE sizeof(struct ubi_vid_hdr) + +/* Sizes of UBI headers without the ending CRC */ +#define UBI_EC_HDR_SIZE_CRC  (UBI_EC_HDR_SIZE  - sizeof(__be32)) +#define UBI_VID_HDR_SIZE_CRC (UBI_VID_HDR_SIZE - sizeof(__be32)) + +/** + * struct ubi_ec_hdr - UBI erase counter header. + * @magic: erase counter header magic number (%UBI_EC_HDR_MAGIC) + * @version: version of UBI implementation which is supposed to accept this + * UBI image + * @padding1: reserved for future, zeroes + * @ec: the erase counter + * @vid_hdr_offset: where the VID header starts + * @data_offset: where the user data start + * @padding2: reserved for future, zeroes + * @hdr_crc: erase counter header CRC checksum + * + * The erase counter header takes 64 bytes and has a plenty of unused space for + * future usage. The unused fields are zeroed. The @version field is used to + * indicate the version of UBI implementation which is supposed to be able to + * work with this UBI image. If @version is greater then the current UBI + * version, the image is rejected. This may be useful in future if something + * is changed radically. This field is duplicated in the volume identifier + * header. + * + * The @vid_hdr_offset and @data_offset fields contain the offset of the the + * volume identifier header and user data, relative to the beginning of the + * physical eraseblock. These values have to be the same for all physical + * eraseblocks. + */ +struct ubi_ec_hdr { +	__be32  magic; +	__u8    version; +	__u8    padding1[3]; +	__be64  ec; /* Warning: the current limit is 31-bit anyway! */ +	__be32  vid_hdr_offset; +	__be32  data_offset; +	__u8    padding2[36]; +	__be32  hdr_crc; +} __attribute__ ((packed)); + +/** + * struct ubi_vid_hdr - on-flash UBI volume identifier header. + * @magic: volume identifier header magic number (%UBI_VID_HDR_MAGIC) + * @version: UBI implementation version which is supposed to accept this UBI + * image (%UBI_VERSION) + * @vol_type: volume type (%UBI_VID_DYNAMIC or %UBI_VID_STATIC) + * @copy_flag: if this logical eraseblock was copied from another physical + * eraseblock (for wear-leveling reasons) + * @compat: compatibility of this volume (%0, %UBI_COMPAT_DELETE, + * %UBI_COMPAT_IGNORE, %UBI_COMPAT_PRESERVE, or %UBI_COMPAT_REJECT) + * @vol_id: ID of this volume + * @lnum: logical eraseblock number + * @leb_ver: version of this logical eraseblock (IMPORTANT: obsolete, to be + * removed, kept only for not breaking older UBI users) + * @data_size: how many bytes of data this logical eraseblock contains + * @used_ebs: total number of used logical eraseblocks in this volume + * @data_pad: how many bytes at the end of this physical eraseblock are not + * used + * @data_crc: CRC checksum of the data stored in this logical eraseblock + * @padding1: reserved for future, zeroes + * @sqnum: sequence number + * @padding2: reserved for future, zeroes + * @hdr_crc: volume identifier header CRC checksum + * + * The @sqnum is the value of the global sequence counter at the time when this + * VID header was created. The global sequence counter is incremented each time + * UBI writes a new VID header to the flash, i.e. when it maps a logical + * eraseblock to a new physical eraseblock. The global sequence counter is an + * unsigned 64-bit integer and we assume it never overflows. The @sqnum + * (sequence number) is used to distinguish between older and newer versions of + * logical eraseblocks. + * + * There are 2 situations when there may be more then one physical eraseblock + * corresponding to the same logical eraseblock, i.e., having the same @vol_id + * and @lnum values in the volume identifier header. Suppose we have a logical + * eraseblock L and it is mapped to the physical eraseblock P. + * + * 1. Because UBI may erase physical eraseblocks asynchronously, the following + * situation is possible: L is asynchronously erased, so P is scheduled for + * erasure, then L is written to,i.e. mapped to another physical eraseblock P1, + * so P1 is written to, then an unclean reboot happens. Result - there are 2 + * physical eraseblocks P and P1 corresponding to the same logical eraseblock + * L. But P1 has greater sequence number, so UBI picks P1 when it attaches the + * flash. + * + * 2. From time to time UBI moves logical eraseblocks to other physical + * eraseblocks for wear-leveling reasons. If, for example, UBI moves L from P + * to P1, and an unclean reboot happens before P is physically erased, there + * are two physical eraseblocks P and P1 corresponding to L and UBI has to + * select one of them when the flash is attached. The @sqnum field says which + * PEB is the original (obviously P will have lower @sqnum) and the copy. But + * it is not enough to select the physical eraseblock with the higher sequence + * number, because the unclean reboot could have happen in the middle of the + * copying process, so the data in P is corrupted. It is also not enough to + * just select the physical eraseblock with lower sequence number, because the + * data there may be old (consider a case if more data was added to P1 after + * the copying). Moreover, the unclean reboot may happen when the erasure of P + * was just started, so it result in unstable P, which is "mostly" OK, but + * still has unstable bits. + * + * UBI uses the @copy_flag field to indicate that this logical eraseblock is a + * copy. UBI also calculates data CRC when the data is moved and stores it at + * the @data_crc field of the copy (P1). So when UBI needs to pick one physical + * eraseblock of two (P or P1), the @copy_flag of the newer one (P1) is + * examined. If it is cleared, the situation* is simple and the newer one is + * picked. If it is set, the data CRC of the copy (P1) is examined. If the CRC + * checksum is correct, this physical eraseblock is selected (P1). Otherwise + * the older one (P) is selected. + * + * Note, there is an obsolete @leb_ver field which was used instead of @sqnum + * in the past. But it is not used anymore and we keep it in order to be able + * to deal with old UBI images. It will be removed at some point. + * + * There are 2 sorts of volumes in UBI: user volumes and internal volumes. + * Internal volumes are not seen from outside and are used for various internal + * UBI purposes. In this implementation there is only one internal volume - the + * layout volume. Internal volumes are the main mechanism of UBI extensions. + * For example, in future one may introduce a journal internal volume. Internal + * volumes have their own reserved range of IDs. + * + * The @compat field is only used for internal volumes and contains the "degree + * of their compatibility". It is always zero for user volumes. This field + * provides a mechanism to introduce UBI extensions and to be still compatible + * with older UBI binaries. For example, if someone introduced a journal in + * future, he would probably use %UBI_COMPAT_DELETE compatibility for the + * journal volume.  And in this case, older UBI binaries, which know nothing + * about the journal volume, would just delete this volume and work perfectly + * fine. This is similar to what Ext2fs does when it is fed by an Ext3fs image + * - it just ignores the Ext3fs journal. + * + * The @data_crc field contains the CRC checksum of the contents of the logical + * eraseblock if this is a static volume. In case of dynamic volumes, it does + * not contain the CRC checksum as a rule. The only exception is when the + * data of the physical eraseblock was moved by the wear-leveling unit, then + * the wear-leveling unit calculates the data CRC and stores it in the + * @data_crc field. And of course, the @copy_flag is %in this case. + * + * The @data_size field is used only for static volumes because UBI has to know + * how many bytes of data are stored in this eraseblock. For dynamic volumes, + * this field usually contains zero. The only exception is when the data of the + * physical eraseblock was moved to another physical eraseblock for + * wear-leveling reasons. In this case, UBI calculates CRC checksum of the + * contents and uses both @data_crc and @data_size fields. In this case, the + * @data_size field contains data size. + * + * The @used_ebs field is used only for static volumes and indicates how many + * eraseblocks the data of the volume takes. For dynamic volumes this field is + * not used and always contains zero. + * + * The @data_pad is calculated when volumes are created using the alignment + * parameter. So, effectively, the @data_pad field reduces the size of logical + * eraseblocks of this volume. This is very handy when one uses block-oriented + * software (say, cramfs) on top of the UBI volume. + */ +struct ubi_vid_hdr { +	__be32  magic; +	__u8    version; +	__u8    vol_type; +	__u8    copy_flag; +	__u8    compat; +	__be32  vol_id; +	__be32  lnum; +	__be32  leb_ver; /* obsolete, to be removed, don't use */ +	__be32  data_size; +	__be32  used_ebs; +	__be32  data_pad; +	__be32  data_crc; +	__u8    padding1[4]; +	__be64  sqnum; +	__u8    padding2[12]; +	__be32  hdr_crc; +} __attribute__ ((packed)); + +/* Internal UBI volumes count */ +#define UBI_INT_VOL_COUNT 1 + +/* + * Starting ID of internal volumes. There is reserved room for 4096 internal + * volumes. + */ +#define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) + +/* The layout volume contains the volume table */ + +#define UBI_LAYOUT_VOLUME_ID     UBI_INTERNAL_VOL_START +#define UBI_LAYOUT_VOLUME_TYPE   UBI_VID_DYNAMIC +#define UBI_LAYOUT_VOLUME_ALIGN  1 +#define UBI_LAYOUT_VOLUME_EBS    2 +#define UBI_LAYOUT_VOLUME_NAME   "layout volume" +#define UBI_LAYOUT_VOLUME_COMPAT UBI_COMPAT_REJECT + +/* The maximum number of volumes per one UBI device */ +#define UBI_MAX_VOLUMES 128 + +/* The maximum volume name length */ +#define UBI_VOL_NAME_MAX 127 + +/* Size of the volume table record */ +#define UBI_VTBL_RECORD_SIZE sizeof(struct ubi_vtbl_record) + +/* Size of the volume table record without the ending CRC */ +#define UBI_VTBL_RECORD_SIZE_CRC (UBI_VTBL_RECORD_SIZE - sizeof(__be32)) + +/** + * struct ubi_vtbl_record - a record in the volume table. + * @reserved_pebs: how many physical eraseblocks are reserved for this volume + * @alignment: volume alignment + * @data_pad: how many bytes are unused at the end of the each physical + * eraseblock to satisfy the requested alignment + * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) + * @upd_marker: if volume update was started but not finished + * @name_len: volume name length + * @name: the volume name + * @flags: volume flags (%UBI_VTBL_AUTORESIZE_FLG) + * @padding: reserved, zeroes + * @crc: a CRC32 checksum of the record + * + * The volume table records are stored in the volume table, which is stored in + * the layout volume. The layout volume consists of 2 logical eraseblock, each + * of which contains a copy of the volume table (i.e., the volume table is + * duplicated). The volume table is an array of &struct ubi_vtbl_record + * objects indexed by the volume ID. + * + * If the size of the logical eraseblock is large enough to fit + * %UBI_MAX_VOLUMES records, the volume table contains %UBI_MAX_VOLUMES + * records. Otherwise, it contains as many records as it can fit (i.e., size of + * logical eraseblock divided by sizeof(struct ubi_vtbl_record)). + * + * The @upd_marker flag is used to implement volume update. It is set to %1 + * before update and set to %0 after the update. So if the update operation was + * interrupted, UBI knows that the volume is corrupted. + * + * The @alignment field is specified when the volume is created and cannot be + * later changed. It may be useful, for example, when a block-oriented file + * system works on top of UBI. The @data_pad field is calculated using the + * logical eraseblock size and @alignment. The alignment must be multiple to the + * minimal flash I/O unit. If @alignment is 1, all the available space of + * the physical eraseblocks is used. + * + * Empty records contain all zeroes and the CRC checksum of those zeroes. + */ +struct ubi_vtbl_record { +	__be32  reserved_pebs; +	__be32  alignment; +	__be32  data_pad; +	__u8    vol_type; +	__u8    upd_marker; +	__be16  name_len; +	__u8    name[UBI_VOL_NAME_MAX+1]; +	__u8    flags; +	__u8    padding[23]; +	__be32  crc; +} __attribute__ ((packed)); + +#endif /* !__UBI_MEDIA_H__ */ diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h new file mode 100644 index 000000000..bf77a1574 --- /dev/null +++ b/drivers/mtd/ubi/ubi.h @@ -0,0 +1,641 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * Copyright (c) Nokia Corporation, 2006, 2007 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Artem Bityutskiy (Битюцкий Артём) + */ + +#ifndef __UBI_UBI_H__ +#define __UBI_UBI_H__ + +#ifdef UBI_LINUX +#include <linux/init.h> +#include <linux/types.h> +#include <linux/list.h> +#include <linux/rbtree.h> +#include <linux/sched.h> +#include <linux/wait.h> +#include <linux/mutex.h> +#include <linux/rwsem.h> +#include <linux/spinlock.h> +#include <linux/fs.h> +#include <linux/cdev.h> +#include <linux/device.h> +#include <linux/string.h> +#include <linux/vmalloc.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/ubi.h> +#endif + +#include <linux/types.h> +#include <linux/list.h> +#include <linux/rbtree.h> +#include <linux/string.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/ubi.h> + +#include "ubi-media.h" +#include "scan.h" +#include "debug.h" + +/* Maximum number of supported UBI devices */ +#define UBI_MAX_DEVICES 32 + +/* UBI name used for character devices, sysfs, etc */ +#define UBI_NAME_STR "ubi" + +/* Normal UBI messages */ +#define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__) +/* UBI warning messages */ +#define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \ +				  __func__, ##__VA_ARGS__) +/* UBI error messages */ +#define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \ +				 __func__, ##__VA_ARGS__) + +/* Lowest number PEBs reserved for bad PEB handling */ +#define MIN_RESEVED_PEBS 2 + +/* Background thread name pattern */ +#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd" + +/* This marker in the EBA table means that the LEB is um-mapped */ +#define UBI_LEB_UNMAPPED -1 + +/* + * In case of errors, UBI tries to repeat the operation several times before + * returning error. The below constant defines how many times UBI re-tries. + */ +#define UBI_IO_RETRIES 3 + +/* + * Error codes returned by the I/O unit. + * + * UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only + * 0xFF bytes + * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a + * valid erase counter header, and the rest are %0xFF bytes + * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) + * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or + * CRC) + * UBI_IO_BITFLIPS: bit-flips were detected and corrected + */ +enum { +	UBI_IO_PEB_EMPTY = 1, +	UBI_IO_PEB_FREE, +	UBI_IO_BAD_EC_HDR, +	UBI_IO_BAD_VID_HDR, +	UBI_IO_BITFLIPS +}; + +/** + * struct ubi_wl_entry - wear-leveling entry. + * @rb: link in the corresponding RB-tree + * @ec: erase counter + * @pnum: physical eraseblock number + * + * This data structure is used in the WL unit. Each physical eraseblock has a + * corresponding &struct wl_entry object which may be kept in different + * RB-trees. See WL unit for details. + */ +struct ubi_wl_entry { +	struct rb_node rb; +	int ec; +	int pnum; +}; + +/** + * struct ubi_ltree_entry - an entry in the lock tree. + * @rb: links RB-tree nodes + * @vol_id: volume ID of the locked logical eraseblock + * @lnum: locked logical eraseblock number + * @users: how many tasks are using this logical eraseblock or wait for it + * @mutex: read/write mutex to implement read/write access serialization to + *         the (@vol_id, @lnum) logical eraseblock + * + * This data structure is used in the EBA unit to implement per-LEB locking. + * When a logical eraseblock is being locked - corresponding + * &struct ubi_ltree_entry object is inserted to the lock tree (@ubi->ltree). + * See EBA unit for details. + */ +struct ubi_ltree_entry { +	struct rb_node rb; +	int vol_id; +	int lnum; +	int users; +	struct rw_semaphore mutex; +}; + +struct ubi_volume_desc; + +/** + * struct ubi_volume - UBI volume description data structure. + * @dev: device object to make use of the the Linux device model + * @cdev: character device object to create character device + * @ubi: reference to the UBI device description object + * @vol_id: volume ID + * @ref_count: volume reference count + * @readers: number of users holding this volume in read-only mode + * @writers: number of users holding this volume in read-write mode + * @exclusive: whether somebody holds this volume in exclusive mode + * + * @reserved_pebs: how many physical eraseblocks are reserved for this volume + * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) + * @usable_leb_size: logical eraseblock size without padding + * @used_ebs: how many logical eraseblocks in this volume contain data + * @last_eb_bytes: how many bytes are stored in the last logical eraseblock + * @used_bytes: how many bytes of data this volume contains + * @alignment: volume alignment + * @data_pad: how many bytes are not used at the end of physical eraseblocks to + *            satisfy the requested alignment + * @name_len: volume name length + * @name: volume name + * + * @upd_ebs: how many eraseblocks are expected to be updated + * @ch_lnum: LEB number which is being changing by the atomic LEB change + *           operation + * @ch_dtype: data persistency type which is being changing by the atomic LEB + *            change operation + * @upd_bytes: how many bytes are expected to be received for volume update or + *             atomic LEB change + * @upd_received: how many bytes were already received for volume update or + *                atomic LEB change + * @upd_buf: update buffer which is used to collect update data or data for + *           atomic LEB change + * + * @eba_tbl: EBA table of this volume (LEB->PEB mapping) + * @checked: %1 if this static volume was checked + * @corrupted: %1 if the volume is corrupted (static volumes only) + * @upd_marker: %1 if the update marker is set for this volume + * @updating: %1 if the volume is being updated + * @changing_leb: %1 if the atomic LEB change ioctl command is in progress + * + * @gluebi_desc: gluebi UBI volume descriptor + * @gluebi_refcount: reference count of the gluebi MTD device + * @gluebi_mtd: MTD device description object of the gluebi MTD device + * + * The @corrupted field indicates that the volume's contents is corrupted. + * Since UBI protects only static volumes, this field is not relevant to + * dynamic volumes - it is user's responsibility to assure their data + * integrity. + * + * The @upd_marker flag indicates that this volume is either being updated at + * the moment or is damaged because of an unclean reboot. + */ +struct ubi_volume { +	struct device dev; +	struct cdev cdev; +	struct ubi_device *ubi; +	int vol_id; +	int ref_count; +	int readers; +	int writers; +	int exclusive; + +	int reserved_pebs; +	int vol_type; +	int usable_leb_size; +	int used_ebs; +	int last_eb_bytes; +	long long used_bytes; +	int alignment; +	int data_pad; +	int name_len; +	char name[UBI_VOL_NAME_MAX+1]; + +	int upd_ebs; +	int ch_lnum; +	int ch_dtype; +	long long upd_bytes; +	long long upd_received; +	void *upd_buf; + +	int *eba_tbl; +	unsigned int checked:1; +	unsigned int corrupted:1; +	unsigned int upd_marker:1; +	unsigned int updating:1; +	unsigned int changing_leb:1; + +#ifdef CONFIG_MTD_UBI_GLUEBI +	/* +	 * Gluebi-related stuff may be compiled out. +	 * TODO: this should not be built into UBI but should be a separate +	 * ubimtd driver which works on top of UBI and emulates MTD devices. +	 */ +	struct ubi_volume_desc *gluebi_desc; +	int gluebi_refcount; +	struct mtd_info gluebi_mtd; +#endif +}; + +/** + * struct ubi_volume_desc - descriptor of the UBI volume returned when it is + * opened. + * @vol: reference to the corresponding volume description object + * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE) + */ +struct ubi_volume_desc { +	struct ubi_volume *vol; +	int mode; +}; + +struct ubi_wl_entry; + +/** + * struct ubi_device - UBI device description structure + * @dev: UBI device object to use the the Linux device model + * @cdev: character device object to create character device + * @ubi_num: UBI device number + * @ubi_name: UBI device name + * @vol_count: number of volumes in this UBI device + * @volumes: volumes of this UBI device + * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs, + *                @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, + *                @vol->readers, @vol->writers, @vol->exclusive, + *                @vol->ref_count, @vol->mapping and @vol->eba_tbl. + * @ref_count: count of references on the UBI device + * + * @rsvd_pebs: count of reserved physical eraseblocks + * @avail_pebs: count of available physical eraseblocks + * @beb_rsvd_pebs: how many physical eraseblocks are reserved for bad PEB + *                 handling + * @beb_rsvd_level: normal level of PEBs reserved for bad PEB handling + * + * @autoresize_vol_id: ID of the volume which has to be auto-resized at the end + *                     of UBI ititializetion + * @vtbl_slots: how many slots are available in the volume table + * @vtbl_size: size of the volume table in bytes + * @vtbl: in-RAM volume table copy + * @volumes_mutex: protects on-flash volume table and serializes volume + *                 changes, like creation, deletion, update, resize + * + * @max_ec: current highest erase counter value + * @mean_ec: current mean erase counter value + * + * @global_sqnum: global sequence number + * @ltree_lock: protects the lock tree and @global_sqnum + * @ltree: the lock tree + * @alc_mutex: serializes "atomic LEB change" operations + * + * @used: RB-tree of used physical eraseblocks + * @free: RB-tree of free physical eraseblocks + * @scrub: RB-tree of physical eraseblocks which need scrubbing + * @prot: protection trees + * @prot.pnum: protection tree indexed by physical eraseblock numbers + * @prot.aec: protection tree indexed by absolute erase counter value + * @wl_lock: protects the @used, @free, @prot, @lookuptbl, @abs_ec, @move_from, + *           @move_to, @move_to_put @erase_pending, @wl_scheduled, and @works + *           fields + * @move_mutex: serializes eraseblock moves + * @wl_scheduled: non-zero if the wear-leveling was scheduled + * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any + *             physical eraseblock + * @abs_ec: absolute erase counter + * @move_from: physical eraseblock from where the data is being moved + * @move_to: physical eraseblock where the data is being moved to + * @move_to_put: if the "to" PEB was put + * @works: list of pending works + * @works_count: count of pending works + * @bgt_thread: background thread description object + * @thread_enabled: if the background thread is enabled + * @bgt_name: background thread name + * + * @flash_size: underlying MTD device size (in bytes) + * @peb_count: count of physical eraseblocks on the MTD device + * @peb_size: physical eraseblock size + * @bad_peb_count: count of bad physical eraseblocks + * @good_peb_count: count of good physical eraseblocks + * @min_io_size: minimal input/output unit size of the underlying MTD device + * @hdrs_min_io_size: minimal I/O unit size used for VID and EC headers + * @ro_mode: if the UBI device is in read-only mode + * @leb_size: logical eraseblock size + * @leb_start: starting offset of logical eraseblocks within physical + * eraseblocks + * @ec_hdr_alsize: size of the EC header aligned to @hdrs_min_io_size + * @vid_hdr_alsize: size of the VID header aligned to @hdrs_min_io_size + * @vid_hdr_offset: starting offset of the volume identifier header (might be + * unaligned) + * @vid_hdr_aloffset: starting offset of the VID header aligned to + * @hdrs_min_io_size + * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset + * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or + *               not + * @mtd: MTD device descriptor + * + * @peb_buf1: a buffer of PEB size used for different purposes + * @peb_buf2: another buffer of PEB size used for different purposes + * @buf_mutex: proptects @peb_buf1 and @peb_buf2 + * @dbg_peb_buf: buffer of PEB size used for debugging + * @dbg_buf_mutex: proptects @dbg_peb_buf + */ +struct ubi_device { +	struct cdev cdev; +	struct device dev; +	int ubi_num; +	char ubi_name[sizeof(UBI_NAME_STR)+5]; +	int vol_count; +	struct ubi_volume *volumes[UBI_MAX_VOLUMES+UBI_INT_VOL_COUNT]; +	spinlock_t volumes_lock; +	int ref_count; + +	int rsvd_pebs; +	int avail_pebs; +	int beb_rsvd_pebs; +	int beb_rsvd_level; + +	int autoresize_vol_id; +	int vtbl_slots; +	int vtbl_size; +	struct ubi_vtbl_record *vtbl; +	struct mutex volumes_mutex; + +	int max_ec; +	/* TODO: mean_ec is not updated run-time, fix */ +	int mean_ec; + +	/* EBA unit's stuff */ +	unsigned long long global_sqnum; +	spinlock_t ltree_lock; +	struct rb_root ltree; +	struct mutex alc_mutex; + +	/* Wear-leveling unit's stuff */ +	struct rb_root used; +	struct rb_root free; +	struct rb_root scrub; +	struct { +		struct rb_root pnum; +		struct rb_root aec; +	} prot; +	spinlock_t wl_lock; +	struct mutex move_mutex; +	struct rw_semaphore work_sem; +	int wl_scheduled; +	struct ubi_wl_entry **lookuptbl; +	unsigned long long abs_ec; +	struct ubi_wl_entry *move_from; +	struct ubi_wl_entry *move_to; +	int move_to_put; +	struct list_head works; +	int works_count; +	struct task_struct *bgt_thread; +	int thread_enabled; +	char bgt_name[sizeof(UBI_BGT_NAME_PATTERN)+2]; + +	/* I/O unit's stuff */ +	long long flash_size; +	int peb_count; +	int peb_size; +	int bad_peb_count; +	int good_peb_count; +	int min_io_size; +	int hdrs_min_io_size; +	int ro_mode; +	int leb_size; +	int leb_start; +	int ec_hdr_alsize; +	int vid_hdr_alsize; +	int vid_hdr_offset; +	int vid_hdr_aloffset; +	int vid_hdr_shift; +	int bad_allowed; +	struct mtd_info *mtd; + +	void *peb_buf1; +	void *peb_buf2; +	struct mutex buf_mutex; +	struct mutex ckvol_mutex; +#ifdef CONFIG_MTD_UBI_DEBUG +	void *dbg_peb_buf; +	struct mutex dbg_buf_mutex; +#endif +}; + +extern struct kmem_cache *ubi_wl_entry_slab; +extern struct file_operations ubi_ctrl_cdev_operations; +extern struct file_operations ubi_cdev_operations; +extern struct file_operations ubi_vol_cdev_operations; +extern struct class *ubi_class; +extern struct mutex ubi_devices_mutex; + +/* vtbl.c */ +int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, +			   struct ubi_vtbl_record *vtbl_rec); +int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si); + +/* vmt.c */ +int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); +int ubi_remove_volume(struct ubi_volume_desc *desc); +int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs); +int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol); +void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol); + +/* upd.c */ +int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, +		     long long bytes); +int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, +			 const void __user *buf, int count); +int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, +			 const struct ubi_leb_change_req *req); +int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, +			     const void __user *buf, int count); + +/* misc.c */ +int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, int length); +int ubi_check_volume(struct ubi_device *ubi, int vol_id); +void ubi_calculate_reserved(struct ubi_device *ubi); + +/* gluebi.c */ +#ifdef CONFIG_MTD_UBI_GLUEBI +int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol); +int ubi_destroy_gluebi(struct ubi_volume *vol); +void ubi_gluebi_updated(struct ubi_volume *vol); +#else +#define ubi_create_gluebi(ubi, vol) 0 +#define ubi_destroy_gluebi(vol) 0 +#define ubi_gluebi_updated(vol) +#endif + +/* eba.c */ +int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, +		      int lnum); +int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, +		     void *buf, int offset, int len, int check); +int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, +		      const void *buf, int offset, int len, int dtype); +int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, +			 int lnum, const void *buf, int len, int dtype, +			 int used_ebs); +int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, +			      int lnum, const void *buf, int len, int dtype); +int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, +		     struct ubi_vid_hdr *vid_hdr); +int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); +void ubi_eba_close(const struct ubi_device *ubi); + +/* wl.c */ +int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); +int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture); +int ubi_wl_flush(struct ubi_device *ubi); +int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); +int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); +void ubi_wl_close(struct ubi_device *ubi); +int ubi_thread(void *u); + +/* io.c */ +int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, +		int len); +int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, +		 int len); +int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture); +int ubi_io_is_bad(const struct ubi_device *ubi, int pnum); +int ubi_io_mark_bad(const struct ubi_device *ubi, int pnum); +int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, +		       struct ubi_ec_hdr *ec_hdr, int verbose); +int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, +			struct ubi_ec_hdr *ec_hdr); +int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, +			struct ubi_vid_hdr *vid_hdr, int verbose); +int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, +			 struct ubi_vid_hdr *vid_hdr); + +/* build.c */ +int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset); +int ubi_detach_mtd_dev(int ubi_num, int anyway); +struct ubi_device *ubi_get_device(int ubi_num); +void ubi_put_device(struct ubi_device *ubi); +struct ubi_device *ubi_get_by_major(int major); +int ubi_major2num(int major); + +/* + * ubi_rb_for_each_entry - walk an RB-tree. + * @rb: a pointer to type 'struct rb_node' to to use as a loop counter + * @pos: a pointer to RB-tree entry type to use as a loop counter + * @root: RB-tree's root + * @member: the name of the 'struct rb_node' within the RB-tree entry + */ +#define ubi_rb_for_each_entry(rb, pos, root, member)                         \ +	for (rb = rb_first(root),                                            \ +	     pos = (rb ? container_of(rb, typeof(*pos), member) : NULL);     \ +	     rb;                                                             \ +	     rb = rb_next(rb), pos = container_of(rb, typeof(*pos), member)) + +/** + * ubi_zalloc_vid_hdr - allocate a volume identifier header object. + * @ubi: UBI device description object + * @gfp_flags: GFP flags to allocate with + * + * This function returns a pointer to the newly allocated and zero-filled + * volume identifier header object in case of success and %NULL in case of + * failure. + */ +static inline struct ubi_vid_hdr * +ubi_zalloc_vid_hdr(const struct ubi_device *ubi, gfp_t gfp_flags) +{ +	void *vid_hdr; + +	vid_hdr = kzalloc(ubi->vid_hdr_alsize, gfp_flags); +	if (!vid_hdr) +		return NULL; + +	/* +	 * VID headers may be stored at un-aligned flash offsets, so we shift +	 * the pointer. +	 */ +	return vid_hdr + ubi->vid_hdr_shift; +} + +/** + * ubi_free_vid_hdr - free a volume identifier header object. + * @ubi: UBI device description object + * @vid_hdr: the object to free + */ +static inline void ubi_free_vid_hdr(const struct ubi_device *ubi, +				    struct ubi_vid_hdr *vid_hdr) +{ +	void *p = vid_hdr; + +	if (!p) +		return; + +	kfree(p - ubi->vid_hdr_shift); +} + +/* + * This function is equivalent to 'ubi_io_read()', but @offset is relative to + * the beginning of the logical eraseblock, not to the beginning of the + * physical eraseblock. + */ +static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf, +				   int pnum, int offset, int len) +{ +	ubi_assert(offset >= 0); +	return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len); +} + +/* + * This function is equivalent to 'ubi_io_write()', but @offset is relative to + * the beginning of the logical eraseblock, not to the beginning of the + * physical eraseblock. + */ +static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf, +				    int pnum, int offset, int len) +{ +	ubi_assert(offset >= 0); +	return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len); +} + +/** + * ubi_ro_mode - switch to read-only mode. + * @ubi: UBI device description object + */ +static inline void ubi_ro_mode(struct ubi_device *ubi) +{ +	if (!ubi->ro_mode) { +		ubi->ro_mode = 1; +		ubi_warn("switch to read-only mode"); +	} +} + +/** + * vol_id2idx - get table index by volume ID. + * @ubi: UBI device description object + * @vol_id: volume ID + */ +static inline int vol_id2idx(const struct ubi_device *ubi, int vol_id) +{ +	if (vol_id >= UBI_INTERNAL_VOL_START) +		return vol_id - UBI_INTERNAL_VOL_START + ubi->vtbl_slots; +	else +		return vol_id; +} + +/** + * idx2vol_id - get volume ID by table index. + * @ubi: UBI device description object + * @idx: table index + */ +static inline int idx2vol_id(const struct ubi_device *ubi, int idx) +{ +	if (idx >= ubi->vtbl_slots) +		return idx - ubi->vtbl_slots + UBI_INTERNAL_VOL_START; +	else +		return idx; +} + +#endif /* !__UBI_UBI_H__ */ |