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); return1;
}
} else { if (!aeb->copy_flag) { /* It is not a copy, so it is newer */
dbg_bld("first PEB %d is newer, copy_flag is unset",
pnum); return bitflips << 1;
}
vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL); if (!vidb) return -ENOMEM;
pnum = aeb->pnum;
err = ubi_io_read_vid_hdr(ubi, pnum, vidb, 0); if (err) { if (err == UBI_IO_BITFLIPS)
bitflips = 1; else {
ubi_err(ubi, "VID of PEB %d header is bad, but it was OK earlier, err %d",
pnum, err); if (err > 0)
err = -EIO;
av = add_volume(ai, vol_id, pnum, vid_hdr); if (IS_ERR(av)) return PTR_ERR(av);
if (ai->max_sqnum < sqnum)
ai->max_sqnum = sqnum;
/* *WalktheRB-treeoflogicaleraseblocksofvolume@vol_idtolook *ifthisisthefirstinstanceofthislogicaleraseblockornot.
*/
p = &av->root.rb_node; while (*p) { int cmp_res;
parent = *p;
aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb); if (lnum != aeb->lnum) { if (lnum < aeb->lnum)
p = &(*p)->rb_left; else
p = &(*p)->rb_right; continue;
}
if (ubi_check_pattern(ubi->peb_buf, 0xFF, ubi->leb_size)) goto out_unlock;
ubi_err(ubi, "PEB %d contains corrupted VID header, and the data does not contain all 0xFF",
pnum);
ubi_err(ubi, "this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection");
ubi_dump_vid_hdr(vid_hdr);
pr_err("hexdump of PEB %d offset %d, length %d",
pnum, ubi->leb_start, ubi->leb_size);
ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
ubi->peb_buf, ubi->leb_size, 1);
err = 1;
/**
* scan_peb - scan and process UBI headers of a PEB.
* @ubi: UBI device description object
* @ai: attaching information
* @pnum: the physical eraseblock number
* @fast: true if we're scanning for a Fastmap
*
* This function reads UBI headers of PEB @pnum, checks them, and adds
* information about this PEB to the corresponding list or RB-tree in the
* "attaching info" structure. Returns zero if the physical eraseblock was
* successfully handled and a negative error code in case of failure.
*/
static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai,
int pnum, bool fast)
{
struct ubi_ec_hdr *ech = ai->ech;
struct ubi_vid_io_buf *vidb = ai->vidb;
struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb);
long long ec;
int err, bitflips = 0, vol_id = -1, ec_err = 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) {
ai->bad_peb_count += 1;
return 0;
}
err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
if (err < 0)
return err;
switch (err) {
case 0:
break;
case UBI_IO_BITFLIPS:
bitflips = 1;
break;
case UBI_IO_FF:
ai->empty_peb_count += 1;
return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
UBI_UNKNOWN, 0, &ai->erase);
case UBI_IO_FF_BITFLIPS:
ai->empty_peb_count += 1;
return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
UBI_UNKNOWN, 1, &ai->erase);
case UBI_IO_BAD_HDR_EBADMSG:
case UBI_IO_BAD_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_err = err;
ec = UBI_UNKNOWN;
bitflips = 1;
break;
default:
ubi_err(ubi, "'ubi_io_read_ec_hdr()' returned unknown code %d",
err);
return -EINVAL;
}
if (!ec_err) {
int image_seq;
/* Make sure UBI version is OK */
if (ech->version != UBI_VERSION) {
ubi_err(ubi, "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(ubi, "erase counter overflow, max is %d",
UBI_MAX_ERASECOUNTER);
ubi_dump_ec_hdr(ech);
return -EINVAL;
}
/*
* Make sure that all PEBs have the same image sequence number.
* This allows us to detect situations when users flash UBI
* images incorrectly, so that the flash has the new UBI image
* and leftovers from the old one. This feature was added
* relatively recently, and the sequence number was always
* zero, because old UBI implementations always set it to zero.
* For this reasons, we do not panic if some PEBs have zero
* sequence number, while other PEBs have non-zero sequence
* number.
*/
image_seq = be32_to_cpu(ech->image_seq);
if (!ubi->image_seq)
ubi->image_seq = image_seq;
if (image_seq && ubi->image_seq != image_seq) {
ubi_err(ubi, "bad image sequence number %d in PEB %d, expected %d",
image_seq, pnum, ubi->image_seq);
ubi_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, vidb, 0);
if (err < 0)
return err;
switch (err) {
case 0:
break;
case UBI_IO_BITFLIPS:
bitflips = 1;
break;
case UBI_IO_BAD_HDR_EBADMSG:
if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
/*
* Both EC and VID headers are corrupted and were read
* with data integrity error, probably this is a bad
* PEB, bit it is not marked as bad yet. This may also
* be a result of power cut during erasure.
*/
ai->maybe_bad_peb_count += 1;
fallthrough;
case UBI_IO_BAD_HDR:
/*
* If we're facing a bad VID header we have to drop *all*
* Fastmap data structures we find. The most recent Fastmap
* could be bad and therefore there is a chance that we attach
* from an old one. On a fine MTD stack a PEB must not render
* bad all of a sudden, but the reality is different.
* So, let's be paranoid and help finding the root cause by
* falling back to scanning mode instead of attaching with a
* bad EBA table and cause data corruption which is hard to
* analyze.
*/
if (fast)
ai->force_full_scan = 1;
if (ec_err)
/*
* Both headers are corrupted. There is a possibility
* that this a valid UBI PEB which has corresponding
* LEB, but the headers are corrupted. However, it is
* impossible to distinguish it from a PEB which just
* contains garbage because of a power cut during erase
* operation. So we just schedule this PEB for erasure.
*
* Besides, in case of NOR flash, we deliberately
* corrupt both headers because NOR flash erasure is
* slow and can start from the end.
*/
err = 0;
else
/*
* The EC was OK, but the VID header is corrupted. We
* have to check what is in the data area.
*/
err = check_corruption(ubi, vidh, pnum);
if (err < 0)
return err;
else if (!err)
/* This corruption is caused by a power cut */
err = add_to_list(ai, pnum, UBI_UNKNOWN,
UBI_UNKNOWN, ec, 1, &ai->erase);
else
/* This is an unexpected corruption */
err = add_corrupted(ai, pnum, ec);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF_BITFLIPS:
err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN,
ec, 1, &ai->erase);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF:
if (ec_err || bitflips)
err = add_to_list(ai, pnum, UBI_UNKNOWN,
UBI_UNKNOWN, ec, 1, &ai->erase);
else
err = add_to_list(ai, pnum, UBI_UNKNOWN,
UBI_UNKNOWN, ec, 0, &ai->free);
if (err)
return err;
goto adjust_mean_ec;
default:
ubi_err(ubi, "'ubi_io_read_vid_hdr()' returned unknown code %d",
err);
return -EINVAL;
}
vol_id = be32_to_cpu(vidh->vol_id);
if (vol_id > UBI_MAX_VOLUMES && !vol_ignored(vol_id)) {
int lnum = be32_to_cpu(vidh->lnum);
adjust_mean_ec:
if (!ec_err) {
ai->ec_sum += ec;
ai->ec_count += 1;
if (ec > ai->max_ec)
ai->max_ec = ec;
if (ec < ai->min_ec)
ai->min_ec = ec;
}
return 0;
}
/**
* late_analysis - analyze the overall situation with PEB.
* @ubi: UBI device description object
* @ai: attaching information
*
* This is a helper function which takes a look what PEBs we have after we
* gather information about all of them ("ai" is compete). It decides whether
* the flash is empty and should be formatted of whether there are too many
* corrupted PEBs and we should not attach this MTD device. Returns zero if we
* should proceed with attaching the MTD device, and %-EINVAL if we should not.
*/
static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
struct ubi_ainf_peb *aeb;
int max_corr, peb_count;
/*
* Few corrupted PEBs is not a problem and may be just a result of
* unclean reboots. However, many of them may indicate some problems
* with the flash HW or driver.
*/
if (ai->corr_peb_count) {
ubi_err(ubi, "%d PEBs are corrupted and preserved",
ai->corr_peb_count);
pr_err("Corrupted PEBs are:");
list_for_each_entry(aeb, &ai->corr, u.list)
pr_cont(" %d", aeb->pnum);
pr_cont("\n");
/*
* If too many PEBs are corrupted, we refuse attaching,
* otherwise, only print a warning.
*/
if (ai->corr_peb_count >= max_corr) {
ubi_err(ubi, "too many corrupted PEBs, refusing");
return -EINVAL;
}
}
if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) {
/*
* All PEBs are empty, or almost all - a couple PEBs look like
* they may be bad PEBs which were not marked as bad yet.
*
* This piece of code basically tries to distinguish between
* the following situations:
*
* 1. Flash is empty, but there are few bad PEBs, which are not
* marked as bad so far, and which were read with error. We
* want to go ahead and format this flash. While formatting,
* the faulty PEBs will probably be marked as bad.
*
* 2. Flash contains non-UBI data and we do not want to format
* it and destroy possibly important information.
*/
if (ai->maybe_bad_peb_count <= 2) {
ai->is_empty = 1;
ubi_msg(ubi, "empty MTD device detected");
get_random_bytes(&ubi->image_seq,
sizeof(ubi->image_seq));
} else {
ubi_err(ubi, "MTD device is not UBI-formatted and possibly contains non-UBI data - refusing it");
return -EINVAL;
}
}
return 0;
}
/**
* destroy_av - free volume attaching information.
* @av: volume attaching information
* @ai: attaching information
* @list: put the aeb elements in there if !NULL, otherwise free them
*
* This function destroys the volume attaching information.
*/
static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av,
struct list_head *list)
{
struct ubi_ainf_peb *aeb;
struct rb_node *this = av->root.rb_node;
while (this) {
if (this->rb_left)
this = this->rb_left;
else if (this->rb_right)
this = this->rb_right;
else {
aeb = rb_entry(this, struct ubi_ainf_peb, u.rb);
this = rb_parent(this);
if (this) {
if (this->rb_left == &aeb->u.rb)
this->rb_left = NULL;
else
this->rb_right = NULL;
}
/**
* scan_all - scan entire MTD device.
* @ubi: UBI device description object
* @ai: attach info object
* @start: start scanning at this PEB
*
* This function does full scanning of an MTD device and returns complete
* information about it in form of a "struct ubi_attach_info" object. In case
* of failure, an error code is returned.
*/
static int scan_all(struct ubi_device *ubi, struct ubi_attach_info *ai,
int start)
{
int err, pnum;
struct rb_node *rb1, *rb2;
struct ubi_ainf_volume *av;
struct ubi_ainf_peb *aeb;
err = -ENOMEM;
ai->ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ai->ech)
return err;
ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!ai->vidb)
goto out_ech;
for (pnum = start; pnum < ubi->peb_count; pnum++) {
cond_resched();
/* Calculate mean erase counter */
if (ai->ec_count)
ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
err = late_analysis(ubi, ai);
if (err)
goto out_vidh;
/*
* In case of unknown erase counter we use the mean erase counter
* value.
*/
ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb)
if (aeb->ec == UBI_UNKNOWN)
aeb->ec = ai->mean_ec;
}
/**
* scan_fast - try to find a fastmap and attach from it.
* @ubi: UBI device description object
* @ai: attach info object
*
* Returns 0 on success, negative return values indicate an internal
* error.
* UBI_NO_FASTMAP denotes that no fastmap was found.
* UBI_BAD_FASTMAP denotes that the found fastmap was invalid.
*/
static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
{
int err, pnum;
struct ubi_attach_info *scan_ai;
err = -ENOMEM;
scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
if (!scan_ai)
goto out;
scan_ai->ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!scan_ai->ech)
goto out_ai;
scan_ai->vidb = ubi_alloc_vid_buf(ubi, GFP_KERNEL);
if (!scan_ai->vidb)
goto out_ech;
for (pnum = 0; pnum < UBI_FM_MAX_START; pnum++) {
cond_resched();
if (err) {
/*
* Didn't attach via fastmap, do a full scan but reuse what
* we've aready scanned.
*/
destroy_ai(*ai);
*ai = scan_ai;
} else
destroy_ai(scan_ai);
/**
* ubi_attach - attach an MTD device.
* @ubi: UBI device descriptor
* @force_scan: if set to non-zero attach by scanning
*
* This function returns zero in case of success and a negative error code in
* case of failure.
*/
int ubi_attach(struct ubi_device *ubi, int force_scan)
{
int err;
struct ubi_attach_info *ai;
ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
#ifdef CONFIG_MTD_UBI_FASTMAP
/* On small flash devices we disable fastmap in any case. */
if ((int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) <= UBI_FM_MAX_START) {
ubi->fm_disabled = 1;
force_scan = 1;
}
if (force_scan)
err = scan_all(ubi, ai, 0);
else {
err = scan_fast(ubi, &ai);
if (err > 0 || mtd_is_eccerr(err)) {
if (err != UBI_NO_FASTMAP) {
destroy_ai(ai);
ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
/**
* self_check_ai - check the attaching information.
* @ubi: UBI device description object
* @ai: attaching information
*
* This function returns zero if the attaching information is all right, and a
* negative error code if not or if an error occurred.
*/
static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
{
struct ubi_vid_io_buf *vidb = ai->vidb;
struct ubi_vid_hdr *vidh = ubi_get_vid_hdr(vidb);
int pnum, err, vols_found = 0;
struct rb_node *rb1, *rb2;
struct ubi_ainf_volume *av;
struct ubi_ainf_peb *aeb, *last_aeb;
uint8_t *buf;
if (!ubi_dbg_chk_gen(ubi))
return 0;
/*
* At first, check that attaching information is OK.
*/
ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) {
int leb_count = 0;
cond_resched();
vols_found += 1;
if (ai->is_empty) {
ubi_err(ubi, "bad is_empty flag");
goto bad_av;
}
/*
* 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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.