Skip to content

Commit

Permalink
Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
Browse files Browse the repository at this point in the history
* 'linux-next' of git://git.infradead.org/ubi-2.6:
  UBI: do not warn unnecessarily
  UBI: do not print message about corruptes PEBs if we have none of them
  UBI: improve delete-compatible volumes handling
  UBI: fix error message and compilation warnings
  UBI: generate random image_seq when formatting MTD devices
  UBI: improve ECC error message
  UBI: improve corrupted flash handling
  UBI: introduce eraseblock counter variables
  UBI: introduce a new IO return code
  UBI: simplify IO error codes
  • Loading branch information
Linus Torvalds committed Aug 3, 2010
2 parents c939f9f + 64d4b4c commit 7046e66
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 74 deletions.
3 changes: 2 additions & 1 deletion drivers/mtd/ubi/build.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
ubi->max_ec = si->max_ec;
ubi->mean_ec = si->mean_ec;
ubi_msg("max. sequence number: %llu", si->max_sqnum);

err = ubi_read_volume_table(ubi, si);
if (err)
Expand Down Expand Up @@ -981,7 +982,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_msg("number of PEBs reserved for bad PEB handling: %d",
ubi->beb_rsvd_pebs);
ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec);
ubi_msg("image sequence number: %d", ubi->image_seq);
ubi_msg("image sequence number: %d", ubi->image_seq);

/*
* The below lock makes sure we do not race with 'ubi_thread()' which
Expand Down
49 changes: 43 additions & 6 deletions drivers/mtd/ubi/eba.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* may try to recover data. FIXME: but this is
* not implemented.
*/
if (err == UBI_IO_BAD_VID_HDR) {
if (err == UBI_IO_BAD_HDR_READ ||
err == UBI_IO_BAD_HDR) {
ubi_warn("corrupted VID header at PEB "
"%d, LEB %d:%d", pnum, vol_id,
lnum);
Expand Down Expand Up @@ -961,8 +962,8 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
*/
static int is_error_sane(int err)
{
if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR ||
err == -ETIMEDOUT)
if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT)
return 0;
return 1;
}
Expand Down Expand Up @@ -1164,6 +1165,44 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
return err;
}

/**
* print_rsvd_warning - warn about not having enough reserved PEBs.
* @ubi: UBI device description object
*
* This is a helper function for 'ubi_eba_init_scan()' which is called when UBI
* cannot reserve enough PEBs for bad block handling. This function makes a
* decision whether we have to print a warning or not. The algorithm is as
* follows:
* o if this is a new UBI image, then just print the warning
* o if this is an UBI image which has already been used for some time, print
* a warning only if we can reserve less than 10% of the expected amount of
* the reserved PEB.
*
* The idea is that when UBI is used, PEBs become bad, and the reserved pool
* of PEBs becomes smaller, which is normal and we do not want to scare users
* with a warning every time they attach the MTD device. This was an issue
* reported by real users.
*/
static void print_rsvd_warning(struct ubi_device *ubi,
struct ubi_scan_info *si)
{
/*
* The 1 << 18 (256KiB) number is picked randomly, just a reasonably
* large number to distinguish between newly flashed and used images.
*/
if (si->max_sqnum > (1 << 18)) {
int min = ubi->beb_rsvd_level / 10;

if (!min)
min = 1;
if (ubi->beb_rsvd_pebs > min)
return;
}

ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
" need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
}

/**
* ubi_eba_init_scan - initialize the EBA sub-system using scanning information.
* @ubi: UBI device description object
Expand Down Expand Up @@ -1236,9 +1275,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < ubi->beb_rsvd_level) {
/* No enough free physical eraseblocks */
ubi->beb_rsvd_pebs = ubi->avail_pebs;
ubi_warn("cannot reserve enough PEBs for bad PEB "
"handling, reserved %d, need %d",
ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
print_rsvd_warning(ubi, si);
} else
ubi->beb_rsvd_pebs = ubi->beb_rsvd_level;

Expand Down
60 changes: 33 additions & 27 deletions drivers/mtd/ubi/io.c
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
retry:
err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
if (err) {
const char *errstr = (err == -EBADMSG) ? " (ECC error)" : "";

if (err == -EUCLEAN) {
/*
* -EUCLEAN is reported if there was a bit-flip which
Expand All @@ -165,15 +167,15 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
}

if (read != len && retries++ < UBI_IO_RETRIES) {
dbg_io("error %d while reading %d bytes from PEB %d:%d,"
dbg_io("error %d%s while reading %d bytes from PEB %d:%d,"
" read only %zd bytes, retry",
err, len, pnum, offset, read);
err, errstr, len, pnum, offset, read);
yield();
goto retry;
}

ubi_err("error %d while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, len, pnum, offset, read);
ubi_err("error %d%s while reading %d bytes from PEB %d:%d, "
"read %zd bytes", err, errstr, len, pnum, offset, read);
ubi_dbg_dump_stack();

/*
Expand Down Expand Up @@ -515,7 +517,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
* In this case we probably anyway have garbage in this PEB.
*/
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
if (err1 == UBI_IO_BAD_VID_HDR)
if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR)
/*
* The VID header is corrupted, so we can safely erase this
* PEB and not afraid that it will be treated as a valid PEB in
Expand Down Expand Up @@ -709,7 +711,7 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
* o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon (but may be not);
* o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error);
* o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error);
* o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty;
* o a negative error code in case of failure.
*/
Expand All @@ -736,23 +738,21 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
* header is still OK, we just report this as there was a
* bit-flip.
*/
read_err = err;
if (err == -EBADMSG)
read_err = UBI_IO_BAD_HDR_READ;
}

magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) {
if (read_err)
return read_err;

/*
* The magic field is wrong. Let's check if we have read all
* 0xFF. If yes, this physical eraseblock is assumed to be
* empty.
*
* But if there was a read error, we do not test it for all
* 0xFFs. Even if it does contain all 0xFFs, this error
* indicates that something is still wrong with this physical
* eraseblock and we anyway cannot treat it as empty.
*/
if (read_err != -EBADMSG &&
check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
/* The physical eraseblock is supposedly empty */
if (verbose)
ubi_warn("no EC header found at PEB %d, "
Expand All @@ -774,7 +774,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
return UBI_IO_BAD_EC_HDR;
return UBI_IO_BAD_HDR;
}

crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC);
Expand All @@ -788,7 +788,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc);
return UBI_IO_BAD_EC_HDR;
return read_err ?: UBI_IO_BAD_HDR;
}

/* And of course validate what has just been read from the media */
Expand All @@ -798,6 +798,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
return -EINVAL;
}

/*
* If there was %-EBADMSG, but the header CRC is still OK, report about
* a bit-flip to force scrubbing on this PEB.
*/
return read_err ? UBI_IO_BITFLIPS : 0;
}

Expand Down Expand Up @@ -977,7 +981,7 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
* o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon;
* o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC
* o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC
* error detected);
* o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID
* header there);
Expand Down Expand Up @@ -1008,22 +1012,20 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
* CRC check-sum and we will identify this. If the VID header is
* still OK, we just report this as there was a bit-flip.
*/
read_err = err;
if (err == -EBADMSG)
read_err = UBI_IO_BAD_HDR_READ;
}

magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) {
if (read_err)
return read_err;

/*
* If we have read all 0xFF bytes, the VID header probably does
* not exist and the physical eraseblock is assumed to be free.
*
* But if there was a read error, we do not test the data for
* 0xFFs. Even if it does contain all 0xFFs, this error
* indicates that something is still wrong with this physical
* eraseblock and it cannot be regarded as free.
*/
if (read_err != -EBADMSG &&
check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
/* The physical eraseblock is supposedly free */
if (verbose)
ubi_warn("no VID header found at PEB %d, "
Expand All @@ -1045,7 +1047,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
return UBI_IO_BAD_VID_HDR;
return UBI_IO_BAD_HDR;
}

crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC);
Expand All @@ -1059,7 +1061,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG)
dbg_msg("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc);
return UBI_IO_BAD_VID_HDR;
return read_err ?: UBI_IO_BAD_HDR;
}

/* Validate the VID header that we have just read */
Expand All @@ -1069,6 +1071,10 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
return -EINVAL;
}

/*
* If there was a read error (%-EBADMSG), but the header CRC is still
* OK, report about a bit-flip to force scrubbing on this PEB.
*/
return read_err ? UBI_IO_BITFLIPS : 0;
}

Expand Down
Loading

0 comments on commit 7046e66

Please sign in to comment.