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

📄 scan.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
	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_gen("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 the scanning information. * @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 (!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 */

⌨️ 快捷键说明

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