Discussion:
[PATCH 2/5] UBI: introduce new bad PEB limit
Artem Bityutskiy
2012-07-30 13:57:38 UTC
Permalink
From: Shmulik Ladkani <shmulik.ladkani at gmail.com>

Introduce 'ubi->bad_peb_limit', which specifies an upper limit of PEBs
UBI expects to go bad. Currently, it is initialized to a fixed percentage
of total PEBs in the UBI device (configurable via CONFIG_MTD_UBI_BEB_LIMIT).

The 'bad_peb_limit' is intended to be used for calculating the amount of PEBs
UBI needs to reserve for bad eraseblock handling.

Artem: minor amendments.

Signed-off-by: Shmulik Ladkani <shmulik.ladkani at gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at linux.intel.com>
---
drivers/mtd/ubi/Kconfig | 26 +++++++++++++++++++-------
drivers/mtd/ubi/build.c | 12 +++++++++++-
drivers/mtd/ubi/ubi.h | 2 ++
3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index ea4b95b..76195ac 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -34,13 +34,25 @@ config MTD_UBI_BEB_RESERVE
help
If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
reserves some amount of physical eraseblocks to handle new bad
- eraseblocks. For example, if a flash physical eraseblock becomes bad,
- UBI uses these reserved physical eraseblocks to relocate the bad one.
- This option specifies how many physical eraseblocks will be reserved
- for bad eraseblock handling (percents of total number of good flash
- eraseblocks). If the underlying flash does not admit of bad
- eraseblocks (e.g. NOR flash), this value is ignored and nothing is
- reserved. Leave the default value if unsure.
+ eraseblocks. When a physical eraseblock becomes bad, UBI uses these
+ reserved physical eraseblocks to relocate the bad one. This
+ configuration option specifies how many physical eraseblocks will be
+ reserved for bad eraseblock handling (percents of total number of
+ good physical eraseblocks on this MTD partition). If the underlying
+ flash does not admit of bad eraseblocks (e.g. NOR flash), this value
+ is ignored and nothing is reserved. Leave the default value if
+ unsure.
+
+config MTD_UBI_BEB_LIMIT
+ int "Percentage of maximum expected bad eraseblocks"
+ default 2
+ range 0 25
+ help
+ This option specifies the maximum bad physical eraseblocks UBI
+ expects on the UBI device (percents of total number of physical
+ eraseblocks on this MTD partition). If the underlying flash does not
+ admit of bad eraseblocks (e.g. NOR flash), this value is ignored.
+ Leave the default value if unsure.

config MTD_UBI_GLUEBI
tristate "MTD devices emulation driver (gluebi)"
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 2c5ed5c..7b6b5f9 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -607,8 +607,18 @@ static int io_init(struct ubi_device *ubi)
ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
ubi->flash_size = ubi->mtd->size;

- if (mtd_can_have_bb(ubi->mtd))
+ if (mtd_can_have_bb(ubi->mtd)) {
ubi->bad_allowed = 1;
+ if (CONFIG_MTD_UBI_BEB_LIMIT > 0) {
+ int percent = CONFIG_MTD_UBI_BEB_LIMIT;
+ int limit = mult_frac(ubi->peb_count, percent, 100);
+
+ /* Round it up */
+ if (mult_frac(limit, 100, percent) < ubi->peb_count)
+ limit += 1;
+ ubi->bad_peb_limit = limit;
+ }
+ }

if (ubi->mtd->type == MTD_NORFLASH) {
ubi_assert(ubi->mtd->writesize == 1);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 84f66e3..aeb459e 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -363,6 +363,7 @@ struct ubi_wl_entry;
* @flash_size: underlying MTD device size (in bytes)
* @peb_count: count of physical eraseblocks on the MTD device
* @peb_size: physical eraseblock size
+ * @bad_peb_limit: top limit of expected bad physical eraseblocks
* @bad_peb_count: count of bad physical eraseblocks
* @good_peb_count: count of good physical eraseblocks
* @corr_peb_count: count of corrupted physical eraseblocks (preserved and not
@@ -410,6 +411,7 @@ struct ubi_device {
int avail_pebs;
int beb_rsvd_pebs;
int beb_rsvd_level;
+ int bad_peb_limit;

int autoresize_vol_id;
int vtbl_slots;
--
1.7.11.2
Artem Bityutskiy
2012-07-30 13:57:40 UTC
Permalink
From: Shmulik Ladkani <shmulik.ladkani at gmail.com>

CONFIG_MTD_UBI_BEB_RESERVE and MIN_RESEVED_PEBS are no longer used,
since the amount of reserved eraseblocks for bad PEB handling is now
derived from 'ubi->bad_peb_limit' (ubi's maximum expected bad
eraseblocks).

Signed-off-by: Shmulik Ladkani <shmulik.ladkani at gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at linux.intel.com>
---
drivers/mtd/ubi/Kconfig | 16 ----------------
drivers/mtd/ubi/ubi.h | 3 ---
2 files changed, 19 deletions(-)

diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 76195ac..b2f4f0f 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -27,22 +27,6 @@ config MTD_UBI_WL_THRESHOLD
life-cycle less than 10000, the threshold should be lessened (e.g.,
to 128 or 256, although it does not have to be power of 2).

-config MTD_UBI_BEB_RESERVE
- int "Percentage of reserved eraseblocks for bad eraseblocks handling"
- default 2
- range 0 25
- help
- If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
- reserves some amount of physical eraseblocks to handle new bad
- eraseblocks. When a physical eraseblock becomes bad, UBI uses these
- reserved physical eraseblocks to relocate the bad one. This
- configuration option specifies how many physical eraseblocks will be
- reserved for bad eraseblock handling (percents of total number of
- good physical eraseblocks on this MTD partition). If the underlying
- flash does not admit of bad eraseblocks (e.g. NOR flash), this value
- is ignored and nothing is reserved. Leave the default value if
- unsure.
-
config MTD_UBI_BEB_LIMIT
int "Percentage of maximum expected bad eraseblocks"
default 2
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index aeb459e..c94612e 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -59,9 +59,6 @@
#define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \
__func__, ##__VA_ARGS__)

-/* Lowest number PEBs reserved for bad PEB handling */
-#define MIN_RESEVED_PEBS 2
-
/* Background thread name pattern */
#define UBI_BGT_NAME_PATTERN "ubi_bgt%dd"
--
1.7.11.2
Artem Bityutskiy
2012-07-30 13:57:39 UTC
Permalink
From: Shmulik Ladkani <shmulik.ladkani at gmail.com>

The existing mechanism of reserving PEBs for bad PEB handling has two
flaws:
- It is calculated as a percentage of good PEBs instead of total PEBs.
- There's no limit on the amount of PEBs UBI reserves for future bad
eraseblock handling.

This patch changes the mechanism to overcome these flaws.

The desired level of PEBs reserved for bad PEB handling (beb_rsvd_level)
is set to the maximum expected bad eraseblocks (bad_peb_limit) minus the
existing number of bad eraseblocks (bad_peb_count).

The actual amount of PEBs reserved for bad PEB handling is usually set
to the desired level (but in some circumstances may be lower than the
desired level, e.g. when attaching to a device that has too few
available PEBs to satisfy the desired level).

In the case where the device has too many bad PEBs (above the expected
limit), then the desired level, and the actual amount of PEBs reserved
are set to zero. No PEBs will be set aside for future bad eraseblock
handling - even if some PEBs are made available (e.g. by shrinking a
volume).
If another PEB goes bad, and there are available PEBs, then the
eraseblock will be marked bad (consuming one available PEB). But if
there are no available PEBs, ubi will go into readonly mode.

Signed-off-by: Shmulik Ladkani <shmulik.ladkani at gmail.com>
---
drivers/mtd/ubi/misc.c | 16 ++++++++++++----
drivers/mtd/ubi/wl.c | 46 +++++++++++++++++++++++++++++-----------------
2 files changed, 41 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/ubi/misc.c b/drivers/mtd/ubi/misc.c
index 8bbfb44..d089df0 100644
--- a/drivers/mtd/ubi/misc.c
+++ b/drivers/mtd/ubi/misc.c
@@ -121,10 +121,18 @@ void ubi_update_reserved(struct ubi_device *ubi)
*/
void ubi_calculate_reserved(struct ubi_device *ubi)
{
- ubi->beb_rsvd_level = ubi->good_peb_count/100;
- ubi->beb_rsvd_level *= CONFIG_MTD_UBI_BEB_RESERVE;
- if (ubi->beb_rsvd_level < MIN_RESEVED_PEBS)
- ubi->beb_rsvd_level = MIN_RESEVED_PEBS;
+ /*
+ * Calculate the actual number of PEBs currently needed to be reserved
+ * for future bad eraseblock handling.
+ */
+ ubi->beb_rsvd_level = ubi->bad_peb_limit - ubi->bad_peb_count;
+ if (ubi->beb_rsvd_level < 0) {
+ ubi->beb_rsvd_level = 0;
+ ubi_warn("number of bad PEBs (%d) is above the expected limit "
+ "(%d), not reserving any PEBs for bad PEB handling, "
+ "will use available PEBs (if any)",
+ ubi->bad_peb_count, ubi->bad_peb_limit);
+ }
}

/**
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index b6be644..bd05276 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -978,9 +978,10 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
int cancel)
{
struct ubi_wl_entry *e = wl_wrk->e;
- int pnum = e->pnum, err, need;
+ int pnum = e->pnum;
int vol_id = wl_wrk->vol_id;
int lnum = wl_wrk->lnum;
+ int err, available_consumed = 0;

if (cancel) {
dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec);
@@ -1045,20 +1046,14 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
}

spin_lock(&ubi->volumes_lock);
- need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs + 1;
- if (need > 0) {
- need = ubi->avail_pebs >= need ? need : ubi->avail_pebs;
- ubi->avail_pebs -= need;
- ubi->rsvd_pebs += need;
- ubi->beb_rsvd_pebs += need;
- if (need > 0)
- ubi_msg("reserve more %d PEBs", need);
- }
-
if (ubi->beb_rsvd_pebs == 0) {
- spin_unlock(&ubi->volumes_lock);
- ubi_err("no reserved physical eraseblocks");
- goto out_ro;
+ if (ubi->avail_pebs == 0) {
+ spin_unlock(&ubi->volumes_lock);
+ ubi_err("no reserved/available physical eraseblocks");
+ goto out_ro;
+ }
+ ubi->avail_pebs -= 1;
+ available_consumed = 1;
}
spin_unlock(&ubi->volumes_lock);

@@ -1068,19 +1063,36 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
goto out_ro;

spin_lock(&ubi->volumes_lock);
- ubi->beb_rsvd_pebs -= 1;
+ if (ubi->beb_rsvd_pebs > 0) {
+ if (available_consumed) {
+ /*
+ * The amount of reserved PEBs increased since we last
+ * checked.
+ */
+ ubi->avail_pebs += 1;
+ available_consumed = 0;
+ }
+ ubi->beb_rsvd_pebs -= 1;
+ }
ubi->bad_peb_count += 1;
ubi->good_peb_count -= 1;
ubi_calculate_reserved(ubi);
- if (ubi->beb_rsvd_pebs)
+ if (available_consumed)
+ ubi_warn("no PEBs in the reserved pool, used an available PEB");
+ else if (ubi->beb_rsvd_pebs)
ubi_msg("%d PEBs left in the reserve", ubi->beb_rsvd_pebs);
else
- ubi_warn("last PEB from the reserved pool was used");
+ ubi_warn("last PEB from the reserve was used");
spin_unlock(&ubi->volumes_lock);

return err;

out_ro:
+ if (available_consumed) {
+ spin_lock(&ubi->volumes_lock);
+ ubi->avail_pebs += 1;
+ spin_unlock(&ubi->volumes_lock);
+ }
ubi_ro_mode(ubi);
return err;
}
--
1.7.11.2
Artem Bityutskiy
2012-07-30 13:57:41 UTC
Permalink
From: Shmulik Ladkani <shmulik.ladkani at gmail.com>

CONFIG_MTD_UBI_BEB_RESERVE has been removed and now we use
CONFIG_MTD_UBI_BEB_LIMIT instead.

Signed-off-by: Shmulik Ladkani <shmulik.ladkani at gmail.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy at linux.intel.com>
---
arch/arm/configs/sam9_l9260_defconfig | 1 -
1 file changed, 1 deletion(-)

diff --git a/arch/arm/configs/sam9_l9260_defconfig b/arch/arm/configs/sam9_l9260_defconfig
index f6917c9..da276f9 100644
--- a/arch/arm/configs/sam9_l9260_defconfig
+++ b/arch/arm/configs/sam9_l9260_defconfig
@@ -39,7 +39,6 @@ CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_ATMEL=y
CONFIG_MTD_NAND_PLATFORM=y
CONFIG_MTD_UBI=y
-CONFIG_MTD_UBI_BEB_RESERVE=3
CONFIG_MTD_UBI_BEB_LIMIT=3
CONFIG_MTD_UBI_GLUEBI=y
CONFIG_BLK_DEV_LOOP=y
--
1.7.11.2
Loading...