Commit 4f3a29da authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6

* 'linux-next' of git://git.infradead.org/ubi-2.6:
  UBI: tighten the corrupted PEB criteria
  UBI: fix check_data_ff return code
  UBI: remember copy_flag while scanning
  UBI: preserve corrupted PEBs
  UBI: add truly corrupted PEBs to corrupted list
  UBI: introduce debugging helper function
  UBI: make check_pattern function non-static
  UBI: do not put eraseblocks to the corrupted list unnecessarily
  UBI: separate out corrupted list
  UBI: change cascade of ifs to switch statements
  UBI: rename a local variable
  UBI: handle bit-flips when no header found
  UBI: remove duplicate IO error codes
  UBI: rename IO error code
  UBI: fix small 80 characters limit style issue
  UBI: cleanup and simplify Kconfig
parents 06d36293 45aafd32
menu "UBI - Unsorted block images" menuconfig MTD_UBI
depends on MTD tristate "Enable UBI - Unsorted block images"
config MTD_UBI
tristate "Enable UBI"
depends on MTD
select CRC32 select CRC32
help help
UBI is a software layer above MTD layer which admits of LVM-like UBI is a software layer above MTD layer which admits of LVM-like
...@@ -12,11 +8,12 @@ config MTD_UBI ...@@ -12,11 +8,12 @@ config MTD_UBI
capabilities. Please, consult the MTD web site for more details capabilities. Please, consult the MTD web site for more details
(www.linux-mtd.infradead.org). (www.linux-mtd.infradead.org).
if MTD_UBI
config MTD_UBI_WL_THRESHOLD config MTD_UBI_WL_THRESHOLD
int "UBI wear-leveling threshold" int "UBI wear-leveling threshold"
default 4096 default 4096
range 2 65536 range 2 65536
depends on MTD_UBI
help help
This parameter defines the maximum difference between the highest This parameter defines the maximum difference between the highest
erase counter value and the lowest erase counter value of eraseblocks erase counter value and the lowest erase counter value of eraseblocks
...@@ -34,7 +31,6 @@ config MTD_UBI_BEB_RESERVE ...@@ -34,7 +31,6 @@ config MTD_UBI_BEB_RESERVE
int "Percentage of reserved eraseblocks for bad eraseblocks handling" int "Percentage of reserved eraseblocks for bad eraseblocks handling"
default 1 default 1
range 0 25 range 0 25
depends on MTD_UBI
help help
If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
reserves some amount of physical eraseblocks to handle new bad reserves some amount of physical eraseblocks to handle new bad
...@@ -48,8 +44,6 @@ config MTD_UBI_BEB_RESERVE ...@@ -48,8 +44,6 @@ config MTD_UBI_BEB_RESERVE
config MTD_UBI_GLUEBI config MTD_UBI_GLUEBI
tristate "MTD devices emulation driver (gluebi)" tristate "MTD devices emulation driver (gluebi)"
default n
depends on MTD_UBI
help help
This option enables gluebi - an additional driver which emulates MTD This option enables gluebi - an additional driver which emulates MTD
devices on top of UBI volumes: for each UBI volumes an MTD device is devices on top of UBI volumes: for each UBI volumes an MTD device is
...@@ -59,4 +53,5 @@ config MTD_UBI_GLUEBI ...@@ -59,4 +53,5 @@ config MTD_UBI_GLUEBI
software. software.
source "drivers/mtd/ubi/Kconfig.debug" source "drivers/mtd/ubi/Kconfig.debug"
endmenu
endif # MTD_UBI
comment "UBI debugging options" comment "UBI debugging options"
depends on MTD_UBI
config MTD_UBI_DEBUG config MTD_UBI_DEBUG
bool "UBI debugging" bool "UBI debugging"
depends on SYSFS depends on SYSFS
depends on MTD_UBI
select DEBUG_FS select DEBUG_FS
select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
help help
This option enables UBI debugging. This option enables UBI debugging.
if MTD_UBI_DEBUG
config MTD_UBI_DEBUG_MSG config MTD_UBI_DEBUG_MSG
bool "UBI debugging messages" bool "UBI debugging messages"
depends on MTD_UBI_DEBUG
default n
help help
This option enables UBI debugging messages. This option enables UBI debugging messages.
config MTD_UBI_DEBUG_PARANOID config MTD_UBI_DEBUG_PARANOID
bool "Extra self-checks" bool "Extra self-checks"
default n
depends on MTD_UBI_DEBUG
help help
This option enables extra checks in UBI code. Note this slows UBI down This option enables extra checks in UBI code. Note this slows UBI down
significantly. significantly.
config MTD_UBI_DEBUG_DISABLE_BGT config MTD_UBI_DEBUG_DISABLE_BGT
bool "Do not enable the UBI background thread" bool "Do not enable the UBI background thread"
depends on MTD_UBI_DEBUG
default n
help help
This option switches the background thread off by default. The thread This option switches the background thread off by default. The thread
may be also be enabled/disabled via UBI sysfs. may be also be enabled/disabled via UBI sysfs.
config MTD_UBI_DEBUG_EMULATE_BITFLIPS config MTD_UBI_DEBUG_EMULATE_BITFLIPS
bool "Emulate flash bit-flips" bool "Emulate flash bit-flips"
depends on MTD_UBI_DEBUG
default n
help help
This option emulates bit-flips with probability 1/50, which in turn This option emulates bit-flips with probability 1/50, which in turn
causes scrubbing. Useful for debugging and stressing UBI. causes scrubbing. Useful for debugging and stressing UBI.
config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
bool "Emulate flash write failures" bool "Emulate flash write failures"
depends on MTD_UBI_DEBUG
default n
help help
This option emulates write failures with probability 1/100. Useful for This option emulates write failures with probability 1/100. Useful for
debugging and testing how UBI handlines errors. debugging and testing how UBI handlines errors.
config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
bool "Emulate flash erase failures" bool "Emulate flash erase failures"
depends on MTD_UBI_DEBUG
default n
help help
This option emulates erase failures with probability 1/100. Useful for This option emulates erase failures with probability 1/100. Useful for
debugging and testing how UBI handlines errors. debugging and testing how UBI handlines errors.
menu "Additional UBI debugging messages" comment "Additional UBI debugging messages"
depends on MTD_UBI_DEBUG
config MTD_UBI_DEBUG_MSG_BLD config MTD_UBI_DEBUG_MSG_BLD
bool "Additional UBI initialization and build messages" bool "Additional UBI initialization and build messages"
default n
depends on MTD_UBI_DEBUG
help help
This option enables detailed UBI initialization and device build This option enables detailed UBI initialization and device build
debugging messages. debugging messages.
config MTD_UBI_DEBUG_MSG_EBA config MTD_UBI_DEBUG_MSG_EBA
bool "Eraseblock association unit messages" bool "Eraseblock association unit messages"
default n
depends on MTD_UBI_DEBUG
help help
This option enables debugging messages from the UBI eraseblock This option enables debugging messages from the UBI eraseblock
association unit. association unit.
config MTD_UBI_DEBUG_MSG_WL config MTD_UBI_DEBUG_MSG_WL
bool "Wear-leveling unit messages" bool "Wear-leveling unit messages"
default n
depends on MTD_UBI_DEBUG
help help
This option enables debugging messages from the UBI wear-leveling This option enables debugging messages from the UBI wear-leveling
unit. unit.
config MTD_UBI_DEBUG_MSG_IO config MTD_UBI_DEBUG_MSG_IO
bool "Input/output unit messages" bool "Input/output unit messages"
default n
depends on MTD_UBI_DEBUG
help help
This option enables debugging messages from the UBI input/output unit. This option enables debugging messages from the UBI input/output unit.
endmenu # UBI debugging messages endif # MTD_UBI_DEBUG
...@@ -95,8 +95,8 @@ DEFINE_MUTEX(ubi_devices_mutex); ...@@ -95,8 +95,8 @@ DEFINE_MUTEX(ubi_devices_mutex);
static DEFINE_SPINLOCK(ubi_devices_lock); static DEFINE_SPINLOCK(ubi_devices_lock);
/* "Show" method for files in '/<sysfs>/class/ubi/' */ /* "Show" method for files in '/<sysfs>/class/ubi/' */
static ssize_t ubi_version_show(struct class *class, struct class_attribute *attr, static ssize_t ubi_version_show(struct class *class,
char *buf) struct class_attribute *attr, char *buf)
{ {
return sprintf(buf, "%d\n", UBI_VERSION); return sprintf(buf, "%d\n", UBI_VERSION);
} }
...@@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi) ...@@ -591,6 +591,7 @@ static int attach_by_scanning(struct ubi_device *ubi)
ubi->bad_peb_count = si->bad_peb_count; ubi->bad_peb_count = si->bad_peb_count;
ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count;
ubi->corr_peb_count = si->corr_peb_count;
ubi->max_ec = si->max_ec; ubi->max_ec = si->max_ec;
ubi->mean_ec = si->mean_ec; ubi->mean_ec = si->mean_ec;
ubi_msg("max. sequence number: %llu", si->max_sqnum); ubi_msg("max. sequence number: %llu", si->max_sqnum);
...@@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) ...@@ -972,6 +973,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20);
ubi_msg("number of good PEBs: %d", ubi->good_peb_count); ubi_msg("number of good PEBs: %d", ubi->good_peb_count);
ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count);
ubi_msg("number of corrupted PEBs: %d", ubi->corr_peb_count);
ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots);
ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD);
ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT);
......
...@@ -57,6 +57,9 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type); ...@@ -57,6 +57,9 @@ void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type);
void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) \
print_hex_dump(l, ps, pt, r, g, b, len, a)
#ifdef CONFIG_MTD_UBI_DEBUG_MSG #ifdef CONFIG_MTD_UBI_DEBUG_MSG
/* General debugging messages */ /* General debugging messages */
#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) #define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
...@@ -172,6 +175,7 @@ static inline int ubi_dbg_is_erase_failure(void) ...@@ -172,6 +175,7 @@ static inline int ubi_dbg_is_erase_failure(void)
#define ubi_dbg_dump_seb(seb, type) ({}) #define ubi_dbg_dump_seb(seb, type) ({})
#define ubi_dbg_dump_mkvol_req(req) ({}) #define ubi_dbg_dump_mkvol_req(req) ({})
#define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({}) #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
#define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) ({})
#define UBI_IO_DEBUG 0 #define UBI_IO_DEBUG 0
#define DBG_DISABLE_BGT 0 #define DBG_DISABLE_BGT 0
......
...@@ -418,7 +418,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, ...@@ -418,7 +418,7 @@ int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum,
* may try to recover data. FIXME: but this is * may try to recover data. FIXME: but this is
* not implemented. * not implemented.
*/ */
if (err == UBI_IO_BAD_HDR_READ || if (err == UBI_IO_BAD_HDR_EBADMSG ||
err == UBI_IO_BAD_HDR) { err == UBI_IO_BAD_HDR) {
ubi_warn("corrupted VID header at PEB " ubi_warn("corrupted VID header at PEB "
"%d, LEB %d:%d", pnum, vol_id, "%d, LEB %d:%d", pnum, vol_id,
...@@ -963,7 +963,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, ...@@ -963,7 +963,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol,
static int is_error_sane(int err) static int is_error_sane(int err)
{ {
if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR || if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR ||
err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT) err == UBI_IO_BAD_HDR_EBADMSG || err == -ETIMEDOUT)
return 0; return 0;
return 1; return 1;
} }
...@@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi, ...@@ -1201,6 +1201,9 @@ static void print_rsvd_warning(struct ubi_device *ubi,
ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d," ubi_warn("cannot reserve enough PEBs for bad PEB handling, reserved %d,"
" need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level); " need %d", ubi->beb_rsvd_pebs, ubi->beb_rsvd_level);
if (ubi->corr_peb_count)
ubi_warn("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
} }
/** /**
...@@ -1263,6 +1266,9 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -1263,6 +1266,9 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < EBA_RESERVED_PEBS) { if (ubi->avail_pebs < EBA_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)", ubi_err("no enough physical eraseblocks (%d, need %d)",
ubi->avail_pebs, EBA_RESERVED_PEBS); ubi->avail_pebs, EBA_RESERVED_PEBS);
if (ubi->corr_peb_count)
ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
err = -ENOSPC; err = -ENOSPC;
goto out_free; goto out_free;
} }
......
...@@ -376,25 +376,6 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum) ...@@ -376,25 +376,6 @@ static int do_sync_erase(struct ubi_device *ubi, int pnum)
return 0; return 0;
} }
/**
* check_pattern - check if buffer contains only a certain byte pattern.
* @buf: buffer to check
* @patt: the pattern to check
* @size: buffer size in bytes
*
* This function returns %1 in there are only @patt bytes in @buf, and %0 if
* something else was also found.
*/
static int check_pattern(const void *buf, uint8_t patt, int size)
{
int i;
for (i = 0; i < size; i++)
if (((const uint8_t *)buf)[i] != patt)
return 0;
return 1;
}
/* Patterns to write to a physical eraseblock when torturing it */ /* Patterns to write to a physical eraseblock when torturing it */
static uint8_t patterns[] = {0xa5, 0x5a, 0x0}; static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
...@@ -426,7 +407,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum) ...@@ -426,7 +407,7 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
if (err) if (err)
goto out; goto out;
err = check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size); err = ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->peb_size);
if (err == 0) { if (err == 0) {
ubi_err("erased PEB %d, but a non-0xFF byte found", ubi_err("erased PEB %d, but a non-0xFF byte found",
pnum); pnum);
...@@ -445,7 +426,8 @@ static int torture_peb(struct ubi_device *ubi, int pnum) ...@@ -445,7 +426,8 @@ static int torture_peb(struct ubi_device *ubi, int pnum)
if (err) if (err)
goto out; goto out;
err = check_pattern(ubi->peb_buf1, patterns[i], ubi->peb_size); err = ubi_check_pattern(ubi->peb_buf1, patterns[i],
ubi->peb_size);
if (err == 0) { if (err == 0) {
ubi_err("pattern %x checking failed for PEB %d", ubi_err("pattern %x checking failed for PEB %d",
patterns[i], pnum); patterns[i], pnum);
...@@ -517,7 +499,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) ...@@ -517,7 +499,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum)
* In this case we probably anyway have garbage in this PEB. * In this case we probably anyway have garbage in this PEB.
*/ */
err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR) if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
/* /*
* The VID header is corrupted, so we can safely erase this * 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 * PEB and not afraid that it will be treated as a valid PEB in
...@@ -712,47 +694,47 @@ static int validate_ec_hdr(const struct ubi_device *ubi, ...@@ -712,47 +694,47 @@ static int validate_ec_hdr(const struct ubi_device *ubi,
* and corrected by the flash driver; this is harmless but may indicate that * and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon (but may be not); * this eraseblock may become bad soon (but may be not);
* o %UBI_IO_BAD_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 %UBI_IO_BAD_HDR_EBADMSG is the same as %UBI_IO_BAD_HDR, but there also was
* a data integrity error (uncorrectable ECC error in case of NAND);
* o %UBI_IO_FF if only 0xFF bytes were read (the PEB is supposedly empty)
* o a negative error code in case of failure. * o a negative error code in case of failure.
*/ */
int ubi_io_read_ec_hdr(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) struct ubi_ec_hdr *ec_hdr, int verbose)
{ {
int err, read_err = 0; int err, read_err;
uint32_t crc, magic, hdr_crc; uint32_t crc, magic, hdr_crc;
dbg_io("read EC header from PEB %d", pnum); dbg_io("read EC header from PEB %d", pnum);
ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE);
if (err) { if (read_err) {
if (err != UBI_IO_BITFLIPS && err != -EBADMSG) if (read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
return err; return read_err;
/* /*
* We read all the data, but either a correctable bit-flip * We read all the data, but either a correctable bit-flip
* occurred, or MTD reported about some data integrity error, * occurred, or MTD reported a data integrity error
* like an ECC error in case of NAND. The former is harmless, * (uncorrectable ECC error in case of NAND). The former is
* the later may mean that the read data is corrupted. But we * harmless, the later may mean that the read data is
* have a CRC check-sum and we will detect this. If the EC * corrupted. But we have a CRC check-sum and we will detect
* header is still OK, we just report this as there was a * this. If the EC header is still OK, we just report this as
* bit-flip. * there was a bit-flip, to force scrubbing.
*/ */
if (err == -EBADMSG)
read_err = UBI_IO_BAD_HDR_READ;
} }
magic = be32_to_cpu(ec_hdr->magic); magic = be32_to_cpu(ec_hdr->magic);
if (magic != UBI_EC_HDR_MAGIC) { if (magic != UBI_EC_HDR_MAGIC) {
if (read_err) if (read_err == -EBADMSG)
return read_err; return UBI_IO_BAD_HDR_EBADMSG;
/* /*
* The magic field is wrong. Let's check if we have read all * The magic field is wrong. Let's check if we have read all
* 0xFF. If yes, this physical eraseblock is assumed to be * 0xFF. If yes, this physical eraseblock is assumed to be
* empty. * empty.
*/ */
if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { if (ubi_check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) {
/* The physical eraseblock is supposedly empty */ /* The physical eraseblock is supposedly empty */
if (verbose) if (verbose)
ubi_warn("no EC header found at PEB %d, " ubi_warn("no EC header found at PEB %d, "
...@@ -760,7 +742,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ...@@ -760,7 +742,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
else if (UBI_IO_DEBUG) else if (UBI_IO_DEBUG)
dbg_msg("no EC header found at PEB %d, " dbg_msg("no EC header found at PEB %d, "
"only 0xFF bytes", pnum); "only 0xFF bytes", pnum);
return UBI_IO_PEB_EMPTY; if (!read_err)
return UBI_IO_FF;
else
return UBI_IO_FF_BITFLIPS;
} }
/* /*
...@@ -788,7 +773,11 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ...@@ -788,7 +773,11 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG) } else if (UBI_IO_DEBUG)
dbg_msg("bad EC header CRC at PEB %d, calculated " dbg_msg("bad EC header CRC at PEB %d, calculated "
"%#08x, read %#08x", pnum, crc, hdr_crc); "%#08x, read %#08x", pnum, crc, hdr_crc);
return read_err ?: UBI_IO_BAD_HDR;
if (!read_err)
return UBI_IO_BAD_HDR;
else
return UBI_IO_BAD_HDR_EBADMSG;
} }
/* And of course validate what has just been read from the media */ /* And of course validate what has just been read from the media */
...@@ -975,22 +964,16 @@ static int validate_vid_hdr(const struct ubi_device *ubi, ...@@ -975,22 +964,16 @@ static int validate_vid_hdr(const struct ubi_device *ubi,
* *
* This function reads the volume identifier header from physical eraseblock * This function reads the volume identifier header from physical eraseblock
* @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read * @pnum and stores it in @vid_hdr. It also checks CRC checksum of the read
* volume identifier header. The following codes may be returned: * volume identifier header. The error codes are the same as in
* 'ubi_io_read_ec_hdr()'.
* *
* o %0 if the CRC checksum is correct and the header was successfully read; * Note, the implementation of this function is also very similar to
* o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected * 'ubi_io_read_ec_hdr()', so refer commentaries in 'ubi_io_read_ec_hdr()'.
* and corrected by the flash driver; this is harmless but may indicate that
* this eraseblock may become bad soon;
* 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);
* o a negative error code in case of failure.
*/ */
int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
struct ubi_vid_hdr *vid_hdr, int verbose) struct ubi_vid_hdr *vid_hdr, int verbose)
{ {
int err, read_err = 0; int err, read_err;
uint32_t crc, magic, hdr_crc; uint32_t crc, magic, hdr_crc;
void *p; void *p;
...@@ -998,48 +981,29 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ...@@ -998,48 +981,29 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
ubi_assert(pnum >= 0 && pnum < ubi->peb_count); ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
p = (char *)vid_hdr - ubi->vid_hdr_shift; p = (char *)vid_hdr - ubi->vid_hdr_shift;
err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize); ubi->vid_hdr_alsize);
if (err) { if (read_err && read_err != UBI_IO_BITFLIPS && read_err != -EBADMSG)
if (err != UBI_IO_BITFLIPS && err != -EBADMSG) return read_err;
return err;
/*
* We read all the data, but either a correctable bit-flip
* occurred, or MTD reported about some data integrity error,
* like an ECC error in case of NAND. The former is harmless,
* the later may mean the read data is corrupted. But we have a
* 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.
*/
if (err == -EBADMSG)
read_err = UBI_IO_BAD_HDR_READ;
}
magic = be32_to_cpu(vid_hdr->magic); magic = be32_to_cpu(vid_hdr->magic);
if (magic != UBI_VID_HDR_MAGIC) { if (magic != UBI_VID_HDR_MAGIC) {
if (read_err) if (read_err == -EBADMSG)
return read_err; return UBI_IO_BAD_HDR_EBADMSG;
/* if (ubi_check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
* If we have read all 0xFF bytes, the VID header probably does
* not exist and the physical eraseblock is assumed to be free.
*/
if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) {
/* The physical eraseblock is supposedly free */
if (verbose) if (verbose)
ubi_warn("no VID header found at PEB %d, " ubi_warn("no VID header found at PEB %d, "
"only 0xFF bytes", pnum); "only 0xFF bytes", pnum);
else if (UBI_IO_DEBUG) else if (UBI_IO_DEBUG)
dbg_msg("no VID header found at PEB %d, " dbg_msg("no VID header found at PEB %d, "
"only 0xFF bytes", pnum); "only 0xFF bytes", pnum);
return UBI_IO_PEB_FREE; if (!read_err)
return UBI_IO_FF;
else
return UBI_IO_FF_BITFLIPS;
} }
/*
* This is not a valid VID header, and these are not 0xFF
* bytes. Report that the header is corrupted.
*/
if (verbose) { if (verbose) {
ubi_warn("bad magic number at PEB %d: %08x instead of " ubi_warn("bad magic number at PEB %d: %08x instead of "
"%08x", pnum, magic, UBI_VID_HDR_MAGIC); "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
...@@ -1061,20 +1025,18 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ...@@ -1061,20 +1025,18 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
} else if (UBI_IO_DEBUG) } else if (UBI_IO_DEBUG)
dbg_msg("bad CRC at PEB %d, calculated %#08x, " dbg_msg("bad CRC at PEB %d, calculated %#08x, "
"read %#08x", pnum, crc, hdr_crc); "read %#08x", pnum, crc, hdr_crc);
return read_err ?: UBI_IO_BAD_HDR; if (!read_err)
return UBI_IO_BAD_HDR;
else
return UBI_IO_BAD_HDR_EBADMSG;
} }
/* Validate the VID header that we have just read */
err = validate_vid_hdr(ubi, vid_hdr); err = validate_vid_hdr(ubi, vid_hdr);
if (err) { if (err) {
ubi_err("validation failed for PEB %d", pnum); ubi_err("validation failed for PEB %d", pnum);
return -EINVAL; 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; return read_err ? UBI_IO_BITFLIPS : 0;
} }
...@@ -1383,7 +1345,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) ...@@ -1383,7 +1345,7 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len)
goto error; goto error;
} }
err = check_pattern(ubi->dbg_peb_buf, 0xFF, len); err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
if (err == 0) { if (err == 0) {
ubi_err("flash region at PEB %d:%d, length %d does not " ubi_err("flash region at PEB %d:%d, length %d does not "
"contain all 0xFF bytes", pnum, offset, len); "contain all 0xFF bytes", pnum, offset, len);
......
...@@ -103,3 +103,22 @@ void ubi_calculate_reserved(struct ubi_device *ubi) ...@@ -103,3 +103,22 @@ void ubi_calculate_reserved(struct ubi_device *ubi)
if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS) if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
ubi->beb_rsvd_level = MIN_RESEVED_PEBS; ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
} }
/**
* ubi_check_pattern - check if buffer contains only a certain byte pattern.
* @buf: buffer to check
* @patt: the pattern to check
* @size: buffer size in bytes
*
* This function returns %1 in there are only @patt bytes in @buf, and %0 if
* something else was also found.
*/
int ubi_check_pattern(const void *buf, uint8_t patt, int size)
{
int i;
for (i = 0; i < size; i++)
if (((const uint8_t *)buf)[i] != patt)
return 0;
return 1;
}
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
* objects which are kept in volume RB-tree with root at the @volumes field. * objects which are kept in volume RB-tree with root at the @volumes field.
* The RB-tree is indexed by the volume ID. * The RB-tree is indexed by the volume ID.
* *
* Found logical eraseblocks are represented by &struct ubi_scan_leb objects. * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects.
* These objects are kept in per-volume RB-trees with the root at the * 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 * 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 * an RB-tree of per-volume objects and each of these objects is the root of
...@@ -38,6 +38,33 @@ ...@@ -38,6 +38,33 @@
* Corrupted physical eraseblocks are put to the @corr list, free physical * Corrupted physical eraseblocks are put to the @corr list, free physical
* eraseblocks are put to the @free list and the physical eraseblock to be * eraseblocks are put to the @free list and the physical eraseblock to be
* erased are put to the @erase list. * erased are put to the @erase list.
*
* UBI tries to distinguish between 2 types of corruptions.
* 1. Corruptions caused by power cuts. These are harmless and expected
* corruptions and UBI tries to handle them gracefully, without printing too
* many warnings and error messages. The idea is that we do not lose
* important data in these case - we may lose only the data which was being
* written to the media just before the power cut happened, and the upper
* layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
* these PEBs to the head of the @erase list and they are scheduled for
* erasure.
*
* 2. Unexpected corruptions which are not caused by power cuts. During
* scanning, such PEBs are put to the @corr list and UBI preserves them.
* Obviously, this lessens the amount of available PEBs, and if at some
* point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
* informs about such PEBs every time the MTD device is attached.
*
* However, it is difficult to reliably distinguish between these types of
* corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
* header is corrupted and the data area does not contain all 0xFFs, and there
* were not bit-flips or integrity errors while reading the data area. Otherwise
* UBI assumes (1.). The assumptions are:
* o if the data area contains only 0xFFs, there is no data, and it is safe
* to just erase this PEB.
* o if the data area has bit-flips and data integrity errors (ECC errors on
* NAND), it is probably a PEB which was being erased when power cut
* happened.
*/ */
#include <linux/err.h> #include <linux/err.h>
...@@ -62,26 +89,26 @@ static struct ubi_vid_hdr *vidh; ...@@ -62,26 +89,26 @@ static struct ubi_vid_hdr *vidh;
* @si: scanning information * @si: scanning information
* @pnum: physical eraseblock number to add * @pnum: physical eraseblock number to add
* @ec: erase counter of the physical eraseblock * @ec: erase counter of the physical eraseblock
* @to_head: if not zero, add to the head of the list
* @list: the list to add to * @list: the list to add to
* *
* This function adds physical eraseblock @pnum to free, erase, corrupted or * This function adds physical eraseblock @pnum to free, erase, or alien lists.
* alien lists. Returns zero in case of success and a negative error code in * If @to_head is not zero, PEB will be added to the head of the list, which
* case of failure. * basically means it will be processed first later. E.g., we add corrupted
* PEBs (corrupted due to power cuts) to the head of the erase list to make
* sure we erase them first and get rid of corruptions ASAP. This function
* 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, static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head,
struct list_head *list) struct list_head *list)
{ {
struct ubi_scan_leb *seb; struct ubi_scan_leb *seb;
if (list == &si->free) { if (list == &si->free) {
dbg_bld("add to free: PEB %d, EC %d", pnum, ec); dbg_bld("add to free: PEB %d, EC %d", pnum, ec);
si->free_peb_count += 1;
} else if (list == &si->erase) { } else if (list == &si->erase) {
dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); dbg_bld("add to erase: PEB %d, EC %d", pnum, ec);
si->erase_peb_count += 1;
} else if (list == &si->corr) {
dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
si->corr_peb_count += 1;
} else if (list == &si->alien) { } else if (list == &si->alien) {
dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); dbg_bld("add to alien: PEB %d, EC %d", pnum, ec);
si->alien_peb_count += 1; si->alien_peb_count += 1;
...@@ -94,10 +121,40 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, ...@@ -94,10 +121,40 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec,
seb->pnum = pnum; seb->pnum = pnum;
seb->ec = ec; seb->ec = ec;
if (to_head)
list_add(&seb->u.list, list);
else
list_add_tail(&seb->u.list, list); list_add_tail(&seb->u.list, list);
return 0; return 0;
} }
/**
* add_corrupted - add a corrupted physical eraseblock.
* @si: scanning information
* @pnum: physical eraseblock number to add
* @ec: erase counter of the physical eraseblock
*
* This function adds corrupted physical eraseblock @pnum to the 'corr' list.
* The corruption was presumably not caused by a power cut. Returns zero in
* case of success and a negative error code in case of failure.
*/
static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec)
{
struct ubi_scan_leb *seb;
dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
if (!seb)
return -ENOMEM;
si->corr_peb_count += 1;
seb->pnum = pnum;
seb->ec = ec;
list_add(&seb->u.list, &si->corr);
return 0;
}
/** /**
* validate_vid_hdr - check volume identifier header. * validate_vid_hdr - check volume identifier header.
* @vid_hdr: the volume identifier header to check * @vid_hdr: the volume identifier header to check
...@@ -258,8 +315,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, ...@@ -258,8 +315,8 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
* created before sequence numbers support has been added. At * created before sequence numbers support has been added. At
* that times we used 32-bit LEB versions stored in logical * that times we used 32-bit LEB versions stored in logical
* eraseblocks. That was before UBI got into mainline. We do not * eraseblocks. That was before UBI got into mainline. We do not
* support these images anymore. Well, those images will work * support these images anymore. Well, those images still work,
* still work, but only if no unclean reboots happened. * but only if no unclean reboots happened.
*/ */
ubi_err("unsupported on-flash UBI format\n"); ubi_err("unsupported on-flash UBI format\n");
return -EINVAL; return -EINVAL;
...@@ -285,19 +342,25 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, ...@@ -285,19 +342,25 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
return 1; return 1;
} }
} else { } else {
pnum = seb->pnum; if (!seb->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;
}
vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); vh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
if (!vh) if (!vh)
return -ENOMEM; return -ENOMEM;
pnum = seb->pnum;
err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0);
if (err) { if (err) {
if (err == UBI_IO_BITFLIPS) if (err == UBI_IO_BITFLIPS)
bitflips = 1; bitflips = 1;
else { else {
dbg_err("VID of PEB %d header is bad, but it " dbg_err("VID of PEB %d header is bad, but it "
"was OK earlier", pnum); "was OK earlier, err %d", pnum, err);
if (err > 0) if (err > 0)
err = -EIO; err = -EIO;
...@@ -305,14 +368,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, ...@@ -305,14 +368,6 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb,
} }
} }
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; vid_hdr = vh;
} }
...@@ -463,11 +518,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -463,11 +518,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
if (err) if (err)
return err; return err;
if (cmp_res & 4) err = add_to_list(si, seb->pnum, seb->ec, 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); &si->erase);
if (err) if (err)
return err; return err;
...@@ -475,6 +526,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -475,6 +526,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
seb->ec = ec; seb->ec = ec;
seb->pnum = pnum; seb->pnum = pnum;
seb->scrub = ((cmp_res & 2) || bitflips); seb->scrub = ((cmp_res & 2) || bitflips);
seb->copy_flag = vid_hdr->copy_flag;
seb->sqnum = sqnum; seb->sqnum = sqnum;
if (sv->highest_lnum == lnum) if (sv->highest_lnum == lnum)
...@@ -487,10 +539,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -487,10 +539,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
* This logical eraseblock is older than the one found * This logical eraseblock is older than the one found
* previously. * previously.
*/ */
if (cmp_res & 4) return add_to_list(si, pnum, ec, cmp_res & 4,
return add_to_list(si, pnum, ec, &si->corr); &si->erase);
else
return add_to_list(si, pnum, ec, &si->erase);
} }
} }
...@@ -510,8 +560,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -510,8 +560,9 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
seb->ec = ec; seb->ec = ec;
seb->pnum = pnum; seb->pnum = pnum;
seb->lnum = lnum; seb->lnum = lnum;
seb->sqnum = sqnum;
seb->scrub = bitflips; seb->scrub = bitflips;
seb->copy_flag = vid_hdr->copy_flag;
seb->sqnum = sqnum;
if (sv->highest_lnum <= lnum) { if (sv->highest_lnum <= lnum) {
sv->highest_lnum = lnum; sv->highest_lnum = lnum;
...@@ -521,7 +572,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -521,7 +572,6 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si,
sv->leb_count += 1; sv->leb_count += 1;
rb_link_node(&seb->u.rb, parent, p); rb_link_node(&seb->u.rb, parent, p);
rb_insert_color(&seb->u.rb, &sv->root); rb_insert_color(&seb->u.rb, &sv->root);
si->used_peb_count += 1;
return 0; return 0;
} }
...@@ -668,8 +718,8 @@ int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, ...@@ -668,8 +718,8 @@ int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si,
struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
struct ubi_scan_info *si) struct ubi_scan_info *si)
{ {
int err = 0, i; int err = 0;
struct ubi_scan_leb *seb; struct ubi_scan_leb *seb, *tmp_seb;
if (!list_empty(&si->free)) { if (!list_empty(&si->free)) {
seb = list_entry(si->free.next, struct ubi_scan_leb, u.list); seb = list_entry(si->free.next, struct ubi_scan_leb, u.list);
...@@ -678,22 +728,13 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, ...@@ -678,22 +728,13 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
return seb; 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 * We try to erase the first physical eraseblock from the erase list
* list and pick it if we succeed, or try to erase the * and pick it if we succeed, or try to erase the next one if not. And
* next one if not. And so forth. We don't want to take care * so forth. We don't want to take care about bad eraseblocks here -
* about bad eraseblocks here - they'll be handled later. * they'll be handled later.
*/ */
list_for_each_entry_safe(seb, tmp_seb, head, u.list) { list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) {
if (seb->ec == UBI_SCAN_UNKNOWN_EC) if (seb->ec == UBI_SCAN_UNKNOWN_EC)
seb->ec = si->mean_ec; seb->ec = si->mean_ec;
...@@ -706,12 +747,69 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, ...@@ -706,12 +747,69 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi,
dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec);
return seb; return seb;
} }
}
ubi_err("no eraseblocks found"); ubi_err("no free eraseblocks");
return ERR_PTR(-ENOSPC); return ERR_PTR(-ENOSPC);
} }
/**
* check_corruption - check the data area of PEB.
* @ubi: UBI device description object
* @vid_hrd: the (corrupted) VID header of this PEB
* @pnum: the physical eraseblock number to check
*
* This is a helper function which is used to distinguish between VID header
* corruptions caused by power cuts and other reasons. If the PEB contains only
* 0xFF bytes in the data area, the VID header is most probably corrupted
* because of a power cut (%0 is returned in this case). Otherwise, it was
* probably corrupted for some other reasons (%1 is returned in this case). A
* negative error code is returned if a read error occurred.
*
* If the corruption reason was a power cut, UBI can safely erase this PEB.
* Otherwise, it should preserve it to avoid possibly destroying important
* information.
*/
static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr,
int pnum)
{
int err;
mutex_lock(&ubi->buf_mutex);
memset(ubi->peb_buf1, 0x00, ubi->leb_size);
err = ubi_io_read(ubi, ubi->peb_buf1, pnum, ubi->leb_start,
ubi->leb_size);
if (err == UBI_IO_BITFLIPS || err == -EBADMSG) {
/*
* Bit-flips or integrity errors while reading the data area.
* It is difficult to say for sure what type of corruption is
* this, but presumably a power cut happened while this PEB was
* erased, so it became unstable and corrupted, and should be
* erased.
*/
return 0;
}
if (err)
return err;
if (ubi_check_pattern(ubi->peb_buf1, 0xFF, ubi->leb_size)) {
mutex_unlock(&ubi->buf_mutex);
return 0;
}
ubi_err("PEB %d contains corrupted VID header, and the data does not "
"contain all 0xFF, this may be a non-UBI PEB or a severe VID "
"header corruption which requires manual inspection", pnum);
ubi_dbg_dump_vid_hdr(vid_hdr);
dbg_msg("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_buf1, ubi->leb_size, 1);
mutex_unlock(&ubi->buf_mutex);
return 1;
}
/** /**
* process_eb - read, check UBI headers, and add them to scanning information. * process_eb - read, check UBI headers, and add them to scanning information.
* @ubi: UBI device description object * @ubi: UBI device description object
...@@ -725,7 +823,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -725,7 +823,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
int pnum) int pnum)
{ {
long long uninitialized_var(ec); long long uninitialized_var(ec);
int err, bitflips = 0, vol_id, ec_corr = 0; int err, bitflips = 0, vol_id, ec_err = 0;
dbg_bld("scan PEB %d", pnum); dbg_bld("scan PEB %d", pnum);
...@@ -746,22 +844,37 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -746,22 +844,37 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0); err = ubi_io_read_ec_hdr(ubi, pnum, ech, 0);
if (err < 0) if (err < 0)
return err; return err;
else if (err == UBI_IO_BITFLIPS) switch (err) {
case 0:
break;
case UBI_IO_BITFLIPS:
bitflips = 1; bitflips = 1;
else if (err == UBI_IO_PEB_EMPTY) break;
return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); case UBI_IO_FF:
else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { si->empty_peb_count += 1;
return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0,
&si->erase);
case UBI_IO_FF_BITFLIPS:
si->empty_peb_count += 1;
return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1,
&si->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 * We have to also look at the VID header, possibly it is not
* corrupted. Set %bitflips flag in order to make this PEB be * corrupted. Set %bitflips flag in order to make this PEB be
* moved and EC be re-created. * moved and EC be re-created.
*/ */
ec_corr = err; ec_err = err;
ec = UBI_SCAN_UNKNOWN_EC; ec = UBI_SCAN_UNKNOWN_EC;
bitflips = 1; bitflips = 1;
break;
default:
ubi_err("'ubi_io_read_ec_hdr()' returned unknown code %d", err);
return -EINVAL;
} }
if (!ec_corr) { if (!ec_err) {
int image_seq; int image_seq;
/* Make sure UBI version is OK */ /* Make sure UBI version is OK */
...@@ -814,24 +927,67 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -814,24 +927,67 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0); err = ubi_io_read_vid_hdr(ubi, pnum, vidh, 0);
if (err < 0) if (err < 0)
return err; return err;
else if (err == UBI_IO_BITFLIPS) switch (err) {
case 0:
break;
case UBI_IO_BITFLIPS:
bitflips = 1; bitflips = 1;
else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR || break;
(err == UBI_IO_PEB_FREE && ec_corr)) { case UBI_IO_BAD_HDR_EBADMSG:
/* VID header is corrupted */ if (ec_err == UBI_IO_BAD_HDR_EBADMSG)
if (err == UBI_IO_BAD_HDR_READ || /*
ec_corr == UBI_IO_BAD_HDR_READ) * Both EC and VID headers are corrupted and were read
si->read_err_count += 1; * with data integrity error, probably this is a bad
err = add_to_list(si, pnum, ec, &si->corr); * PEB, bit it is not marked as bad yet. This may also
* be a result of power cut during erasure.
*/
si->maybe_bad_peb_count += 1;
case UBI_IO_BAD_HDR:
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.
*/
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(si, pnum, ec, 1, &si->erase);
else
/* This is an unexpected corruption */
err = add_corrupted(si, pnum, ec);
if (err)
return err;
goto adjust_mean_ec;
case UBI_IO_FF_BITFLIPS:
err = add_to_list(si, pnum, ec, 1, &si->erase);
if (err) if (err)
return err; return err;
goto adjust_mean_ec; goto adjust_mean_ec;
} else if (err == UBI_IO_PEB_FREE) { case UBI_IO_FF:
/* No VID header - the physical eraseblock is free */ if (ec_err)
err = add_to_list(si, pnum, ec, &si->free); err = add_to_list(si, pnum, ec, 1, &si->erase);
else
err = add_to_list(si, pnum, ec, 0, &si->free);
if (err) if (err)
return err; return err;
goto adjust_mean_ec; goto adjust_mean_ec;
default:
ubi_err("'ubi_io_read_vid_hdr()' returned unknown code %d",
err);
return -EINVAL;
} }
vol_id = be32_to_cpu(vidh->vol_id); vol_id = be32_to_cpu(vidh->vol_id);
...@@ -843,7 +999,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -843,7 +999,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_DELETE: case UBI_COMPAT_DELETE:
ubi_msg("\"delete\" compatible internal volume %d:%d" ubi_msg("\"delete\" compatible internal volume %d:%d"
" found, will remove it", vol_id, lnum); " found, will remove it", vol_id, lnum);
err = add_to_list(si, pnum, ec, &si->erase); err = add_to_list(si, pnum, ec, 1, &si->erase);
if (err) if (err)
return err; return err;
return 0; return 0;
...@@ -858,7 +1014,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -858,7 +1014,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
case UBI_COMPAT_PRESERVE: case UBI_COMPAT_PRESERVE:
ubi_msg("\"preserve\" compatible internal volume %d:%d" ubi_msg("\"preserve\" compatible internal volume %d:%d"
" found", vol_id, lnum); " found", vol_id, lnum);
err = add_to_list(si, pnum, ec, &si->alien); err = add_to_list(si, pnum, ec, 0, &si->alien);
if (err) if (err)
return err; return err;
return 0; return 0;
...@@ -870,7 +1026,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -870,7 +1026,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
} }
} }
if (ec_corr) if (ec_err)
ubi_warn("valid VID header but corrupted EC header at PEB %d", ubi_warn("valid VID header but corrupted EC header at PEB %d",
pnum); pnum);
err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips); err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips);
...@@ -878,7 +1034,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -878,7 +1034,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
return err; return err;
adjust_mean_ec: adjust_mean_ec:
if (!ec_corr) { if (!ec_err) {
si->ec_sum += ec; si->ec_sum += ec;
si->ec_count += 1; si->ec_count += 1;
if (ec > si->max_ec) if (ec > si->max_ec)
...@@ -904,19 +1060,20 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -904,19 +1060,20 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
{ {
struct ubi_scan_leb *seb; struct ubi_scan_leb *seb;
int max_corr; int max_corr, peb_count;
max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count;
max_corr = max_corr / 20 ?: 8; max_corr = peb_count / 20 ?: 8;
/* /*
* Few corrupted PEBs are not a problem and may be just a result of * Few corrupted PEBs is not a problem and may be just a result of
* unclean reboots. However, many of them may indicate some problems * unclean reboots. However, many of them may indicate some problems
* with the flash HW or driver. * with the flash HW or driver.
*/ */
if (si->corr_peb_count >= 8) { if (si->corr_peb_count) {
ubi_warn("%d PEBs are corrupted", si->corr_peb_count); ubi_err("%d PEBs are corrupted and preserved",
printk(KERN_WARNING "corrupted PEBs are:"); si->corr_peb_count);
printk(KERN_ERR "Corrupted PEBs are:");
list_for_each_entry(seb, &si->corr, u.list) list_for_each_entry(seb, &si->corr, u.list)
printk(KERN_CONT " %d", seb->pnum); printk(KERN_CONT " %d", seb->pnum);
printk(KERN_CONT "\n"); printk(KERN_CONT "\n");
...@@ -931,41 +1088,35 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -931,41 +1088,35 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si)
} }
} }
if (si->free_peb_count + si->used_peb_count + if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) {
si->alien_peb_count == 0) { /*
/* No UBI-formatted eraseblocks were found */ * All PEBs are empty, or almost all - a couple PEBs look like
if (si->corr_peb_count == si->read_err_count && * they may be bad PEBs which were not marked as bad yet.
si->corr_peb_count < 8) {
/* No or just few corrupted PEBs, and all of them had a
* read error. We assume that those are bad PEBs, which
* were just not marked as bad so far.
* *
* This piece of code basically tries to distinguish * This piece of code basically tries to distinguish between
* between the following 2 situations: * the following situations:
* *
* 1. Flash is empty, but there are few bad PEBs, which * 1. Flash is empty, but there are few bad PEBs, which are not
* are not marked as bad so far, and which were read * marked as bad so far, and which were read with error. We
* with error. We want to go ahead and format this * want to go ahead and format this flash. While formatting,
* flash. While formating, the faulty PEBs will * the faulty PEBs will probably be marked as bad.
* probably be marked as bad.
* *
* 2. Flash probably contains non-UBI data and we do * 2. Flash contains non-UBI data and we do not want to format
* not want to format it and destroy possibly needed * it and destroy possibly important information.
* data (e.g., consider the case when the bootloader
* MTD partition was accidentally fed to UBI).
*/ */
if (si->maybe_bad_peb_count <= 2) {
si->is_empty = 1; si->is_empty = 1;
ubi_msg("empty MTD device detected"); ubi_msg("empty MTD device detected");
get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq)); get_random_bytes(&ubi->image_seq,
sizeof(ubi->image_seq));
} else { } else {
ubi_err("MTD device possibly contains non-UBI data, " ubi_err("MTD device is not UBI-formatted and possibly "
"refusing it"); "contains non-UBI data - refusing it");
return -EINVAL; return -EINVAL;
} }
} }
if (si->corr_peb_count > 0)
ubi_msg("corrupted PEBs will be formatted");
return 0; return 0;
} }
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
* @pnum: physical eraseblock number * @pnum: physical eraseblock number
* @lnum: logical eraseblock number * @lnum: logical eraseblock number
* @scrub: if this physical eraseblock needs scrubbing * @scrub: if this physical eraseblock needs scrubbing
* @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB)
* @sqnum: sequence number * @sqnum: sequence number
* @u: unions RB-tree or @list links * @u: unions RB-tree or @list links
* @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects
...@@ -42,7 +43,8 @@ struct ubi_scan_leb { ...@@ -42,7 +43,8 @@ struct ubi_scan_leb {
int ec; int ec;
int pnum; int pnum;
int lnum; int lnum;
int scrub; unsigned int scrub:1;
unsigned int copy_flag:1;
unsigned long long sqnum; unsigned long long sqnum;
union { union {
struct rb_node rb; struct rb_node rb;
...@@ -91,14 +93,13 @@ struct ubi_scan_volume { ...@@ -91,14 +93,13 @@ struct ubi_scan_volume {
* @erase: list of physical eraseblocks which have to be erased * @erase: list of physical eraseblocks which have to be erased
* @alien: list of physical eraseblocks which should not be used by UBI (e.g., * @alien: list of physical eraseblocks which should not be used by UBI (e.g.,
* those belonging to "preserve"-compatible internal volumes) * those belonging to "preserve"-compatible internal volumes)
* @used_peb_count: count of used PEBs
* @corr_peb_count: count of PEBs in the @corr list * @corr_peb_count: count of PEBs in the @corr list
* @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was * @empty_peb_count: count of PEBs which are presumably empty (contain only
* returned) * 0xFF bytes)
* @free_peb_count: count of PEBs in the @free list
* @erase_peb_count: count of PEBs in the @erase list
* @alien_peb_count: count of PEBs in the @alien list * @alien_peb_count: count of PEBs in the @alien list
* @bad_peb_count: count of bad physical eraseblocks * @bad_peb_count: count of bad physical eraseblocks
* @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked
* as bad yet, but which look like bad
* @vols_found: number of volumes found during scanning * @vols_found: number of volumes found during scanning
* @highest_vol_id: highest volume ID * @highest_vol_id: highest volume ID
* @is_empty: flag indicating whether the MTD device is empty or not * @is_empty: flag indicating whether the MTD device is empty or not
...@@ -119,13 +120,11 @@ struct ubi_scan_info { ...@@ -119,13 +120,11 @@ struct ubi_scan_info {
struct list_head free; struct list_head free;
struct list_head erase; struct list_head erase;
struct list_head alien; struct list_head alien;
int used_peb_count;
int corr_peb_count; int corr_peb_count;
int read_err_count; int empty_peb_count;
int free_peb_count;
int erase_peb_count;
int alien_peb_count; int alien_peb_count;
int bad_peb_count; int bad_peb_count;
int maybe_bad_peb_count;
int vols_found; int vols_found;
int highest_vol_id; int highest_vol_id;
int is_empty; int is_empty;
......
...@@ -85,21 +85,26 @@ ...@@ -85,21 +85,26 @@
/* /*
* Error codes returned by the I/O sub-system. * Error codes returned by the I/O sub-system.
* *
* UBI_IO_PEB_EMPTY: the physical eraseblock is empty, i.e. it contains only * UBI_IO_FF: the read region of flash contains only 0xFFs
* %0xFF bytes * UBI_IO_FF_BITFLIPS: the same as %UBI_IO_FF, but also also there was a data
* UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a * integrity error reported by the MTD driver
* valid erase counter header, and the rest are %0xFF bytes * (uncorrectable ECC error in case of NAND)
* UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC)
* UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read * UBI_IO_BAD_HDR_EBADMSG: the same as %UBI_IO_BAD_HDR, but also there was a
* error reported by the flash driver * data integrity error reported by the MTD driver
* (uncorrectable ECC error in case of NAND)
* UBI_IO_BITFLIPS: bit-flips were detected and corrected * UBI_IO_BITFLIPS: bit-flips were detected and corrected
*
* Note, it is probably better to have bit-flip and ebadmsg as flags which can
* be or'ed with other error code. But this is a big change because there are
* may callers, so it does not worth the risk of introducing a bug
*/ */
enum { enum {
UBI_IO_PEB_EMPTY = 1, UBI_IO_FF = 1,
UBI_IO_PEB_FREE, UBI_IO_FF_BITFLIPS,
UBI_IO_BAD_HDR, UBI_IO_BAD_HDR,
UBI_IO_BAD_HDR_READ, UBI_IO_BAD_HDR_EBADMSG,
UBI_IO_BITFLIPS UBI_IO_BITFLIPS,
}; };
/* /*
...@@ -356,6 +361,8 @@ struct ubi_wl_entry; ...@@ -356,6 +361,8 @@ struct ubi_wl_entry;
* @peb_size: physical eraseblock size * @peb_size: physical eraseblock size
* @bad_peb_count: count of bad physical eraseblocks * @bad_peb_count: count of bad physical eraseblocks
* @good_peb_count: count of good physical eraseblocks * @good_peb_count: count of good physical eraseblocks
* @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
* used by UBI)
* @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous * @erroneous_peb_count: count of erroneous physical eraseblocks in @erroneous
* @max_erroneous: maximum allowed amount of erroneous physical eraseblocks * @max_erroneous: maximum allowed amount of erroneous physical eraseblocks
* @min_io_size: minimal input/output unit size of the underlying MTD device * @min_io_size: minimal input/output unit size of the underlying MTD device
...@@ -442,6 +449,7 @@ struct ubi_device { ...@@ -442,6 +449,7 @@ struct ubi_device {
int peb_size; int peb_size;
int bad_peb_count; int bad_peb_count;
int good_peb_count; int good_peb_count;
int corr_peb_count;
int erroneous_peb_count; int erroneous_peb_count;
int max_erroneous; int max_erroneous;
int min_io_size; int min_io_size;
...@@ -506,6 +514,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf, ...@@ -506,6 +514,7 @@ int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
int length); int length);
int ubi_check_volume(struct ubi_device *ubi, int vol_id); int ubi_check_volume(struct ubi_device *ubi, int vol_id);
void ubi_calculate_reserved(struct ubi_device *ubi); void ubi_calculate_reserved(struct ubi_device *ubi);
int ubi_check_pattern(const void *buf, uint8_t patt, int size);
/* eba.c */ /* eba.c */
int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
......
...@@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) ...@@ -261,6 +261,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req)
/* Reserve physical eraseblocks */ /* Reserve physical eraseblocks */
if (vol->reserved_pebs > ubi->avail_pebs) { if (vol->reserved_pebs > ubi->avail_pebs) {
dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); dbg_err("not enough PEBs, only %d available", ubi->avail_pebs);
if (ubi->corr_peb_count)
dbg_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
err = -ENOSPC; err = -ENOSPC;
goto out_unlock; goto out_unlock;
} }
...@@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) ...@@ -527,6 +530,9 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
if (pebs > ubi->avail_pebs) { if (pebs > ubi->avail_pebs) {
dbg_err("not enough PEBs: requested %d, available %d", dbg_err("not enough PEBs: requested %d, available %d",
pebs, ubi->avail_pebs); pebs, ubi->avail_pebs);
if (ubi->corr_peb_count)
dbg_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
spin_unlock(&ubi->volumes_lock); spin_unlock(&ubi->volumes_lock);
err = -ENOSPC; err = -ENOSPC;
goto out_free; goto out_free;
......
...@@ -366,7 +366,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, ...@@ -366,7 +366,7 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si,
* Probably this physical eraseblock went bad, try to pick * Probably this physical eraseblock went bad, try to pick
* another one. * another one.
*/ */
list_add_tail(&new_seb->u.list, &si->corr); list_add(&new_seb->u.list, &si->erase);
goto retry; goto retry;
} }
kfree(new_seb); kfree(new_seb);
...@@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, ...@@ -662,9 +662,13 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si,
ubi->vol_count += 1; ubi->vol_count += 1;
vol->ubi = ubi; vol->ubi = ubi;
if (reserved_pebs > ubi->avail_pebs) if (reserved_pebs > ubi->avail_pebs) {
ubi_err("not enough PEBs, required %d, available %d", ubi_err("not enough PEBs, required %d, available %d",
reserved_pebs, ubi->avail_pebs); reserved_pebs, ubi->avail_pebs);
if (ubi->corr_peb_count)
ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
}
ubi->rsvd_pebs += reserved_pebs; ubi->rsvd_pebs += reserved_pebs;
ubi->avail_pebs -= reserved_pebs; ubi->avail_pebs -= reserved_pebs;
...@@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -837,7 +841,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si)
return PTR_ERR(ubi->vtbl); return PTR_ERR(ubi->vtbl);
} }
ubi->avail_pebs = ubi->good_peb_count; ubi->avail_pebs = ubi->good_peb_count - ubi->corr_peb_count;
/* /*
* The layout volume is OK, initialize the corresponding in-RAM data * The layout volume is OK, initialize the corresponding in-RAM data
......
...@@ -745,7 +745,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -745,7 +745,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0); err = ubi_io_read_vid_hdr(ubi, e1->pnum, vid_hdr, 0);
if (err && err != UBI_IO_BITFLIPS) { if (err && err != UBI_IO_BITFLIPS) {
if (err == UBI_IO_PEB_FREE) { if (err == UBI_IO_FF) {
/* /*
* We are trying to move PEB without a VID header. UBI * We are trying to move PEB without a VID header. UBI
* always write VID headers shortly after the PEB was * always write VID headers shortly after the PEB was
...@@ -759,6 +759,16 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ...@@ -759,6 +759,16 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
dbg_wl("PEB %d has no VID header", e1->pnum); dbg_wl("PEB %d has no VID header", e1->pnum);
protect = 1; protect = 1;
goto out_not_moved; goto out_not_moved;
} else if (err == UBI_IO_FF_BITFLIPS) {
/*
* The same situation as %UBI_IO_FF, but bit-flips were
* detected. It is better to schedule this PEB for
* scrubbing.
*/
dbg_wl("PEB %d has no VID header but has bit-flips",
e1->pnum);
scrubbing = 1;
goto out_not_moved;
} }
ubi_err("error %d while reading VID header from PEB %d", ubi_err("error %d while reading VID header from PEB %d",
...@@ -1468,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -1468,22 +1478,6 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
ubi->lookuptbl[e->pnum] = e; ubi->lookuptbl[e->pnum] = e;
} }
list_for_each_entry(seb, &si->corr, u.list) {
cond_resched();
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e)
goto out_free;
e->pnum = seb->pnum;
e->ec = seb->ec;
ubi->lookuptbl[e->pnum] = e;
if (schedule_erase(ubi, e, 0)) {
kmem_cache_free(ubi_wl_entry_slab, e);
goto out_free;
}
}
ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) {
ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) {
cond_resched(); cond_resched();
...@@ -1510,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) ...@@ -1510,6 +1504,9 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si)
if (ubi->avail_pebs < WL_RESERVED_PEBS) { if (ubi->avail_pebs < WL_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)", ubi_err("no enough physical eraseblocks (%d, need %d)",
ubi->avail_pebs, WL_RESERVED_PEBS); ubi->avail_pebs, WL_RESERVED_PEBS);
if (ubi->corr_peb_count)
ubi_err("%d PEBs are corrupted and not used",
ubi->corr_peb_count);
goto out_free; goto out_free;
} }
ubi->avail_pebs -= WL_RESERVED_PEBS; ubi->avail_pebs -= WL_RESERVED_PEBS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment