⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vtbl.c

📁 uboot200903最新版本的通用uboot
💻 C
📖 第 1 页 / 共 2 页
字号:
			err = create_vtbl(ubi, si, 1, leb[0]);			if (err)				goto out_free;			ubi_msg("volume table was restored");		}		/* Both LEB 1 and LEB 2 are OK and consistent */		vfree(leb[1]);		return leb[0];	} else {		/* LEB 0 is corrupted or does not exist */		if (leb[1]) {			leb_corrupted[1] = vtbl_check(ubi, leb[1]);			if (leb_corrupted[1] < 0)				goto out_free;		}		if (leb_corrupted[1]) {			/* Both LEB 0 and LEB 1 are corrupted */			ubi_err("both volume tables are corrupted");			goto out_free;		}		ubi_warn("volume table copy #1 is corrupted");		err = create_vtbl(ubi, si, 0, leb[1]);		if (err)			goto out_free;		ubi_msg("volume table was restored");		vfree(leb[0]);		return leb[1];	}out_free:	vfree(leb[0]);	vfree(leb[1]);	return ERR_PTR(err);}/** * create_empty_lvol - create empty layout volume. * @ubi: UBI device description object * @si: scanning information * * This function returns volume table contents in case of success and a * negative error code in case of failure. */static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi,						 struct ubi_scan_info *si){	int i;	struct ubi_vtbl_record *vtbl;	vtbl = vmalloc(ubi->vtbl_size);	if (!vtbl)		return ERR_PTR(-ENOMEM);	memset(vtbl, 0, ubi->vtbl_size);	for (i = 0; i < ubi->vtbl_slots; i++)		memcpy(&vtbl[i], &empty_vtbl_record, UBI_VTBL_RECORD_SIZE);	for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) {		int err;		err = create_vtbl(ubi, si, i, vtbl);		if (err) {			vfree(vtbl);			return ERR_PTR(err);		}	}	return vtbl;}/** * init_volumes - initialize volume information for existing volumes. * @ubi: UBI device description object * @si: scanning information * @vtbl: volume table * * This function allocates volume description objects for existing volumes. * Returns zero in case of success and a negative error code in case of * failure. */static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,			const struct ubi_vtbl_record *vtbl){	int i, reserved_pebs = 0;	struct ubi_scan_volume *sv;	struct ubi_volume *vol;	for (i = 0; i < ubi->vtbl_slots; i++) {		cond_resched();		if (be32_to_cpu(vtbl[i].reserved_pebs) == 0)			continue; /* Empty record */		vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);		if (!vol)			return -ENOMEM;		vol->reserved_pebs = be32_to_cpu(vtbl[i].reserved_pebs);		vol->alignment = be32_to_cpu(vtbl[i].alignment);		vol->data_pad = be32_to_cpu(vtbl[i].data_pad);		vol->vol_type = vtbl[i].vol_type == UBI_VID_DYNAMIC ?					UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME;		vol->name_len = be16_to_cpu(vtbl[i].name_len);		vol->usable_leb_size = ubi->leb_size - vol->data_pad;		memcpy(vol->name, vtbl[i].name, vol->name_len);		vol->name[vol->name_len] = '\0';		vol->vol_id = i;		if (vtbl[i].flags & UBI_VTBL_AUTORESIZE_FLG) {			/* Auto re-size flag may be set only for one volume */			if (ubi->autoresize_vol_id != -1) {				ubi_err("more then one auto-resize volume (%d "					"and %d)", ubi->autoresize_vol_id, i);				kfree(vol);				return -EINVAL;			}			ubi->autoresize_vol_id = i;		}		ubi_assert(!ubi->volumes[i]);		ubi->volumes[i] = vol;		ubi->vol_count += 1;		vol->ubi = ubi;		reserved_pebs += vol->reserved_pebs;		/*		 * In case of dynamic volume UBI knows nothing about how many		 * data is stored there. So assume the whole volume is used.		 */		if (vol->vol_type == UBI_DYNAMIC_VOLUME) {			vol->used_ebs = vol->reserved_pebs;			vol->last_eb_bytes = vol->usable_leb_size;			vol->used_bytes =				(long long)vol->used_ebs * vol->usable_leb_size;			continue;		}		/* Static volumes only */		sv = ubi_scan_find_sv(si, i);		if (!sv) {			/*			 * No eraseblocks belonging to this volume found. We			 * don't actually know whether this static volume is			 * completely corrupted or just contains no data. And			 * we cannot know this as long as data size is not			 * stored on flash. So we just assume the volume is			 * empty. FIXME: this should be handled.			 */			continue;		}		if (sv->leb_count != sv->used_ebs) {			/*			 * We found a static volume which misses several			 * eraseblocks. Treat it as corrupted.			 */			ubi_warn("static volume %d misses %d LEBs - corrupted",				 sv->vol_id, sv->used_ebs - sv->leb_count);			vol->corrupted = 1;			continue;		}		vol->used_ebs = sv->used_ebs;		vol->used_bytes =			(long long)(vol->used_ebs - 1) * vol->usable_leb_size;		vol->used_bytes += sv->last_data_size;		vol->last_eb_bytes = sv->last_data_size;	}	/* And add the layout volume */	vol = kzalloc(sizeof(struct ubi_volume), GFP_KERNEL);	if (!vol)		return -ENOMEM;	vol->reserved_pebs = UBI_LAYOUT_VOLUME_EBS;	vol->alignment = 1;	vol->vol_type = UBI_DYNAMIC_VOLUME;	vol->name_len = sizeof(UBI_LAYOUT_VOLUME_NAME) - 1;	memcpy(vol->name, UBI_LAYOUT_VOLUME_NAME, vol->name_len + 1);	vol->usable_leb_size = ubi->leb_size;	vol->used_ebs = vol->reserved_pebs;	vol->last_eb_bytes = vol->reserved_pebs;	vol->used_bytes =		(long long)vol->used_ebs * (ubi->leb_size - vol->data_pad);	vol->vol_id = UBI_LAYOUT_VOLUME_ID;	vol->ref_count = 1;	ubi_assert(!ubi->volumes[i]);	ubi->volumes[vol_id2idx(ubi, vol->vol_id)] = vol;	reserved_pebs += vol->reserved_pebs;	ubi->vol_count += 1;	vol->ubi = ubi;	if (reserved_pebs > ubi->avail_pebs)		ubi_err("not enough PEBs, required %d, available %d",			reserved_pebs, ubi->avail_pebs);	ubi->rsvd_pebs += reserved_pebs;	ubi->avail_pebs -= reserved_pebs;	return 0;}/** * check_sv - check volume scanning information. * @vol: UBI volume description object * @sv: volume scanning information * * This function returns zero if the volume scanning information is consistent * to the data read from the volume tabla, and %-EINVAL if not. */static int check_sv(const struct ubi_volume *vol,		    const struct ubi_scan_volume *sv){	int err;	if (sv->highest_lnum >= vol->reserved_pebs) {		err = 1;		goto bad;	}	if (sv->leb_count > vol->reserved_pebs) {		err = 2;		goto bad;	}	if (sv->vol_type != vol->vol_type) {		err = 3;		goto bad;	}	if (sv->used_ebs > vol->reserved_pebs) {		err = 4;		goto bad;	}	if (sv->data_pad != vol->data_pad) {		err = 5;		goto bad;	}	return 0;bad:	ubi_err("bad scanning information, error %d", err);	ubi_dbg_dump_sv(sv);	ubi_dbg_dump_vol_info(vol);	return -EINVAL;}/** * check_scanning_info - check that scanning information. * @ubi: UBI device description object * @si: scanning information * * Even though we protect on-flash data by CRC checksums, we still don't trust * the media. This function ensures that scanning information is consistent to * the information read from the volume table. Returns zero if the scanning * information is OK and %-EINVAL if it is not. */static int check_scanning_info(const struct ubi_device *ubi,			       struct ubi_scan_info *si){	int err, i;	struct ubi_scan_volume *sv;	struct ubi_volume *vol;	if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) {		ubi_err("scanning found %d volumes, maximum is %d + %d",			si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots);		return -EINVAL;	}	if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT &&	    si->highest_vol_id < UBI_INTERNAL_VOL_START) {		ubi_err("too large volume ID %d found by scanning",			si->highest_vol_id);		return -EINVAL;	}	for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {		cond_resched();		sv = ubi_scan_find_sv(si, i);		vol = ubi->volumes[i];		if (!vol) {			if (sv)				ubi_scan_rm_volume(si, sv);			continue;		}		if (vol->reserved_pebs == 0) {			ubi_assert(i < ubi->vtbl_slots);			if (!sv)				continue;			/*			 * During scanning we found a volume which does not			 * exist according to the information in the volume			 * table. This must have happened due to an unclean			 * reboot while the volume was being removed. Discard			 * these eraseblocks.			 */			ubi_msg("finish volume %d removal", sv->vol_id);			ubi_scan_rm_volume(si, sv);		} else if (sv) {			err = check_sv(vol, sv);			if (err)				return err;		}	}	return 0;}/** * ubi_read_volume_table - read volume table. * information. * @ubi: UBI device description object * @si: scanning information * * This function reads volume table, checks it, recover from errors if needed, * or creates it if needed. Returns zero in case of success and a negative * error code in case of failure. */int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si){	int i, err;	struct ubi_scan_volume *sv;	empty_vtbl_record.crc = cpu_to_be32(0xf116c36b);	/*	 * The number of supported volumes is limited by the eraseblock size	 * and by the UBI_MAX_VOLUMES constant.	 */	ubi->vtbl_slots = ubi->leb_size / UBI_VTBL_RECORD_SIZE;	if (ubi->vtbl_slots > UBI_MAX_VOLUMES)		ubi->vtbl_slots = UBI_MAX_VOLUMES;	ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE;	ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size);	sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID);	if (!sv) {		/*		 * No logical eraseblocks belonging to the layout volume were		 * found. This could mean that the flash is just empty. In		 * this case we create empty layout volume.		 *		 * But if flash is not empty this must be a corruption or the		 * MTD device just contains garbage.		 */		if (si->is_empty) {			ubi->vtbl = create_empty_lvol(ubi, si);			if (IS_ERR(ubi->vtbl))				return PTR_ERR(ubi->vtbl);		} else {			ubi_err("the layout volume was not found");			return -EINVAL;		}	} else {		if (sv->leb_count > UBI_LAYOUT_VOLUME_EBS) {			/* This must not happen with proper UBI images */			dbg_err("too many LEBs (%d) in layout volume",				sv->leb_count);			return -EINVAL;		}		ubi->vtbl = process_lvol(ubi, si, sv);		if (IS_ERR(ubi->vtbl))			return PTR_ERR(ubi->vtbl);	}	ubi->avail_pebs = ubi->good_peb_count;	/*	 * The layout volume is OK, initialize the corresponding in-RAM data	 * structures.	 */	err = init_volumes(ubi, si, ubi->vtbl);	if (err)		goto out_free;	/*	 * Get sure that the scanning information is consistent to the	 * information stored in the volume table.	 */	err = check_scanning_info(ubi, si);	if (err)		goto out_free;	return 0;out_free:	vfree(ubi->vtbl);	for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++)		if (ubi->volumes[i]) {			kfree(ubi->volumes[i]);			ubi->volumes[i] = NULL;		}	return err;}#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID/** * paranoid_vtbl_check - check volume table. * @ubi: UBI device description object */static void paranoid_vtbl_check(const struct ubi_device *ubi){	if (vtbl_check(ubi, ubi->vtbl)) {		ubi_err("paranoid check failed");		BUG();	}}#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -