* [PATCH 01/22] UBI: Fastmap: Add EBA selfcheck
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 02/22] UBI: Fastmap: Fix NULL pointer bug Richard Weinberger
` (19 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Using this self-check it's possible to proof Fastmap's
correctness.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/attach.c | 16 +++++++++
drivers/mtd/ubi/eba.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/mtd/ubi/ubi.h | 2 +
3 files changed, 102 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 4c6b97b..1573d94 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1262,6 +1262,22 @@ int ubi_attach(struct ubi_device *ubi)
if (err)
goto out_wl;
+ if (ai->fm) {
+ struct ubi_attach_info *scan_ai;
+ scan_ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
+ if (!scan_ai)
+ goto out_ai;
+
+ err = scan_all(ubi, scan_ai);
+ if (err) {
+ kfree(scan_ai);
+ goto out_ai;
+ }
+
+ self_check_eba(ubi, ai, scan_ai);
+ ubi_destroy_ai(ubi, scan_ai);
+ }
+
ubi_destroy_ai(ubi, ai);
/* TODO: UBI auto formats the flash if it is empty (see ubi->is_empty).
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 654f121..d112b10 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -1204,6 +1204,90 @@ static void print_rsvd_warning(struct ubi_device *ubi,
ubi->corr_peb_count);
}
+int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
+ struct ubi_attach_info *ai_scan)
+{
+ int i, j, num_volumes, ret = 0;
+ int **scan_eba, **fm_eba;
+ struct ubi_ainf_volume *av;
+ struct ubi_volume *vol;
+ struct ubi_ainf_peb *aeb;
+ struct rb_node *rb;
+
+ num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT;
+
+ scan_eba = kmalloc(sizeof(*scan_eba) * num_volumes, GFP_KERNEL);
+ if (!scan_eba)
+ return -ENOMEM;
+
+ fm_eba = kmalloc(sizeof(*fm_eba) * num_volumes, GFP_KERNEL);
+ if (!fm_eba) {
+ kfree(scan_eba);
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < num_volumes; i++) {
+ vol = ubi->volumes[i];
+ if (!vol)
+ continue;
+
+ scan_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**scan_eba),
+ GFP_KERNEL);
+ if (!scan_eba[i]) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ fm_eba[i] = kmalloc(vol->reserved_pebs * sizeof(**fm_eba),
+ GFP_KERNEL);
+ if (!scan_eba[i]) {
+ ret = -ENOMEM;
+ goto out_free;
+ }
+
+ for (j = 0; j < vol->reserved_pebs; j++)
+ scan_eba[i][j] = fm_eba[i][j] = UBI_LEB_UNMAPPED;
+
+ av = ubi_find_av(ai_scan, idx2vol_id(ubi, i));
+ if (!av)
+ continue;
+
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb)
+ scan_eba[i][aeb->lnum] = aeb->pnum;
+
+ av = ubi_find_av(ai_fastmap, idx2vol_id(ubi, i));
+ if (!av)
+ continue;
+
+ ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb)
+ fm_eba[i][aeb->lnum] = aeb->pnum;
+
+ for (j = 0; j < vol->reserved_pebs; j++) {
+ if (scan_eba[i][j] != fm_eba[i][j]) {
+ if (scan_eba[i][j] == UBI_LEB_UNMAPPED)
+ continue;
+
+ ubi_err("LEB:%i is mapped to PEB:%i instead of PEB:%i!", i, fm_eba[i][j], scan_eba[i][j]);
+ BUG();
+ }
+ }
+ }
+
+out_free:
+ for (i = 0; i < num_volumes; i++) {
+ if (!ubi->volumes[i])
+ continue;
+
+ kfree(scan_eba[i]);
+ kfree(fm_eba[i]);
+ }
+
+ kfree(scan_eba);
+ kfree(fm_eba);
+
+ return ret;
+}
+
/**
* ubi_eba_init - initialize the EBA sub-system using attaching information.
* @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index ba6bfd1..f4bd3c9 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -723,6 +723,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
struct ubi_vid_hdr *vid_hdr);
int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai);
unsigned long long ubi_next_sqnum(struct ubi_device *ubi);
+int self_check_eba(struct ubi_device *ubi, struct ubi_attach_info *ai_fastmap,
+ struct ubi_attach_info *ai_scan);
/* wl.c */
int ubi_wl_get_peb(struct ubi_device *ubi);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 02/22] UBI: Fastmap: Fix NULL pointer bug
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
2012-06-18 16:18 ` [PATCH 01/22] UBI: Fastmap: Add EBA selfcheck Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 03/22] UBI: Fastmap: Keep fastmap after attaching Richard Weinberger
` (18 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 8b033e5..5bbf1e3 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1290,11 +1290,14 @@ int ubi_update_fastmap(struct ubi_device *ubi)
goto err;
}
- tmp_e->pnum = old_fm->e[0]->pnum;
- tmp_e->ec = old_fm->e[0]->ec;
+ new_fm->e[0]->pnum = old_fm->e[0]->pnum;
+ new_fm->e[0]->ec = old_fm->e[0]->ec;
} else {
/* we've got a new early PEB, return the old one */
ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0);
+
+ new_fm->e[0]->pnum = tmp_e->pnum;
+ new_fm->e[0]->ec = tmp_e->ec;
}
/* return all other fastmap block to the wl system */
@@ -1307,10 +1310,10 @@ int ubi_update_fastmap(struct ubi_device *ubi)
goto err;
}
- }
- new_fm->e[0]->pnum = tmp_e->pnum;
- new_fm->e[0]->ec = tmp_e->ec;
+ new_fm->e[0]->pnum = tmp_e->pnum;
+ new_fm->e[0]->ec = tmp_e->ec;
+ }
if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
ubi_err("fastmap too large");
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 03/22] UBI: Fastmap: Keep fastmap after attaching
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
2012-06-18 16:18 ` [PATCH 01/22] UBI: Fastmap: Add EBA selfcheck Richard Weinberger
2012-06-18 16:18 ` [PATCH 02/22] UBI: Fastmap: Fix NULL pointer bug Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 04/22] UBI: Fastmap: Store scrub list in fastmap Richard Weinberger
` (17 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/attach.c | 14 +---------
drivers/mtd/ubi/fastmap.c | 67 ++++++++++++++++++++++-----------------------
drivers/mtd/ubi/ubi.h | 2 -
3 files changed, 34 insertions(+), 49 deletions(-)
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 1573d94..9ae66e4 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1262,7 +1262,7 @@ int ubi_attach(struct ubi_device *ubi)
if (err)
goto out_wl;
- if (ai->fm) {
+ if (ubi->fm) {
struct ubi_attach_info *scan_ai;
scan_ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
if (!scan_ai)
@@ -1385,18 +1385,6 @@ void ubi_destroy_ai(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (ai->aeb_slab_cache)
kmem_cache_destroy(ai->aeb_slab_cache);
- /* Return all PEBs back to the WL sub-system */
- if (ai->fm) {
- int i, torture;
-
- for (i = 0; i < ai->fm->used_blocks; i++) {
- torture = ai->fm->to_be_tortured[i];
- ubi_wl_put_fm_peb(ubi, ai->fm->e[i], torture);
- }
-
- kfree(ai->fm);
- }
-
kfree(ai);
}
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 5bbf1e3..9ed4723 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -774,6 +774,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
struct ubi_fm_sb *fmsb;
struct ubi_vid_hdr *vh;
struct ubi_ec_hdr *ech;
+ struct ubi_fastmap_layout *fm;
int i, used_blocks, pnum, sb_pnum = 0, ret = 0;
void *fm_raw = NULL;
size_t fm_size;
@@ -792,8 +793,8 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
goto out;
}
- ai->fm = kzalloc(sizeof(*ai->fm), GFP_KERNEL);
- if (!ai->fm) {
+ fm = kzalloc(sizeof(*fm), GFP_KERNEL);
+ if (!fm) {
ret = -ENOMEM;
kfree(fmsb);
goto free_raw;
@@ -802,10 +803,10 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ret = ubi_io_read(ubi, fmsb, sb_pnum, ubi->leb_start, sizeof(*fmsb));
if (ret && ret != UBI_IO_BITFLIPS) {
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto out;
} else if (ret == UBI_IO_BITFLIPS)
- ai->fm->to_be_tortured[0] = 1;
+ fm->to_be_tortured[0] = 1;
if (be32_to_cpu(fmsb->magic) != UBI_FM_SB_MAGIC) {
/* TODO: not urgent, but examine all the error messages and
@@ -818,7 +819,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ubi_err("super block magic does not match");
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto out;
}
@@ -826,7 +827,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ubi_err("unknown fastmap format version!");
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto out;
}
@@ -835,7 +836,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ubi_err("number of fastmap blocks is invalid");
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto out;
}
@@ -845,7 +846,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!fm_raw) {
ret = -ENOMEM;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto out;
}
@@ -853,7 +854,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!ech) {
ret = -ENOMEM;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_raw;
}
@@ -861,7 +862,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!vh) {
ret = -ENOMEM;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
kfree(ech);
goto free_raw;
}
@@ -871,7 +872,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (ubi_io_is_bad(ubi, pnum)) {
ret = UBI_BAD_FASTMAP;
- kfree(ai->fm);
+ kfree(fm);
kfree(fmsb);
goto free_hdr;
}
@@ -883,10 +884,10 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (ret > 0)
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
} else if (ret == UBI_IO_BITFLIPS)
- ai->fm->to_be_tortured[i] = 1;
+ fm->to_be_tortured[i] = 1;
if (!ubi->image_seq)
ubi->image_seq = be32_to_cpu(ech->image_seq);
@@ -894,7 +895,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (be32_to_cpu(ech->image_seq) != ubi->image_seq) {
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
@@ -903,7 +904,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ubi_err("unable to read fastmap block# %i (PEB: %i)",
i, pnum);
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
@@ -911,7 +912,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (be32_to_cpu(vh->vol_id) != UBI_FM_SB_VOLUME_ID) {
ret = UBI_BAD_FASTMAP;
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
} else {
@@ -931,7 +932,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
ubi_err("unable to read fastmap block# %i (PEB: %i)",
i, pnum);
kfree(fmsb);
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
}
@@ -945,7 +946,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (crc != tmp_crc) {
ubi_err("fastmap data CRC is invalid");
ret = UBI_BAD_FASTMAP;
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
@@ -955,12 +956,12 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (ret) {
if (ret > 0)
ret = UBI_BAD_FASTMAP;
- kfree(ai->fm);
+ kfree(fm);
goto free_hdr;
}
- ai->fm->size = fm_size;
- ai->fm->used_blocks = used_blocks;
+ fm->size = fm_size;
+ fm->used_blocks = used_blocks;
for (i = 0; i < used_blocks; i++) {
struct ubi_wl_entry *e;
@@ -968,19 +969,21 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai)
e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
if (!e) {
while (i--)
- kfree(ai->fm->e[i]);
+ kfree(fm->e[i]);
- kfree(ai->fm);
- ai->fm = NULL;
+ kfree(fm);
+ fm = NULL;
ret = -ENOMEM;
goto free_hdr;
}
e->pnum = be32_to_cpu(fmsb->block_loc[i]);
e->ec = be32_to_cpu(fmsb->block_ec[i]);
- ai->fm->e[i] = e;
+ fm->e[i] = e;
}
+ ubi->fm = fm;
+
free_hdr:
ubi_free_vid_hdr(ubi, vh);
kfree(ech);
@@ -1294,7 +1297,8 @@ int ubi_update_fastmap(struct ubi_device *ubi)
new_fm->e[0]->ec = old_fm->e[0]->ec;
} else {
/* we've got a new early PEB, return the old one */
- ubi_wl_put_fm_peb(ubi, old_fm->e[0], 0);
+ ubi_wl_put_fm_peb(ubi, old_fm->e[0],
+ old_fm->to_be_tortured[0]);
new_fm->e[0]->pnum = tmp_e->pnum;
new_fm->e[0]->ec = tmp_e->ec;
@@ -1302,7 +1306,8 @@ int ubi_update_fastmap(struct ubi_device *ubi)
/* return all other fastmap block to the wl system */
for (i = 1; i < old_fm->used_blocks; i++)
- ubi_wl_put_fm_peb(ubi, old_fm->e[i], 0);
+ ubi_wl_put_fm_peb(ubi, old_fm->e[i],
+ old_fm->to_be_tortured[i]);
} else {
if (!tmp_e) {
ubi_err("could not find an early PEB");
@@ -1346,13 +1351,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
new_fm->e[i]->ec = tmp_e->ec;
}
- if (old_fm) {
- for (i = 0; i < old_fm->used_blocks; i++)
- kfree(old_fm->e[i]);
-
- kfree(old_fm);
- }
-
+ kfree(old_fm);
/* Ensure that the PEBs of the old fastmap got erased and added to the
* free list before we write the fastmap. Otherwise fastmp does not
* see these PEBs and we leak them.
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index f4bd3c9..dcbc420 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -625,7 +625,6 @@ struct ubi_ainf_volume {
* @ec_sum: a temporary variable used when calculating @mean_ec
* @ec_count: a temporary variable used when calculating @mean_ec
* @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects
- * @fm: the fastmap used for attaching
*
* This data structure contains the result of attaching an MTD device and may
* be used by other UBI sub-systems to build final UBI data structures, further
@@ -652,7 +651,6 @@ struct ubi_attach_info {
uint64_t ec_sum;
int ec_count;
struct kmem_cache *aeb_slab_cache;
- struct ubi_fastmap_layout *fm;
};
#include "debug.h"
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 04/22] UBI: Fastmap: Store scrub list in fastmap
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (2 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 03/22] UBI: Fastmap: Keep fastmap after attaching Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 05/22] UBI: Fastmap: Rework ubi_wl_put_fm_peb() Richard Weinberger
` (16 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
If scrub work is pending while writing the fastmap we have to
store it into the fastmap otherwise we'd leak PEBs.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 26 ++++++++++++++++++++++++++
drivers/mtd/ubi/ubi-media.h | 3 ++-
2 files changed, 28 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 9ed4723..bc29835 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -560,6 +560,17 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
be32_to_cpu(fmec->ec), 0);
}
+ /* read EC values from scrub list */
+ for (i = 0; i < be32_to_cpu(fmhdr->scrub_peb_count); i++) {
+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+ fm_pos += sizeof(*fmec);
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+ add_aeb(ai, &used, be32_to_cpu(fmec->pnum),
+ be32_to_cpu(fmec->ec), 1);
+ }
+
ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
ai->bad_peb_count = be32_to_cpu(fmhdr->bad_peb_count);
@@ -1016,6 +1027,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct ubi_volume *vol;
struct ubi_vid_hdr *avhdr, *dvhdr;
int ret, i, j, free_peb_count, used_peb_count, vol_count;
+ int scrub_peb_count;
fm_raw = vzalloc(new_fm->size);
if (!fm_raw) {
@@ -1055,6 +1067,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
fmh->magic = cpu_to_be32(UBI_FM_HDR_MAGIC);
free_peb_count = 0;
used_peb_count = 0;
+ scrub_peb_count = 0;
vol_count = 0;
fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
@@ -1099,6 +1112,19 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
}
fmh->used_peb_count = cpu_to_be32(used_peb_count);
+ for (node = rb_first(&ubi->scrub); node; node = rb_next(node)) {
+ wl_e = rb_entry(node, struct ubi_wl_entry, u.rb);
+ fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+
+ fec->pnum = cpu_to_be32(wl_e->pnum);
+ fec->ec = cpu_to_be32(wl_e->ec);
+
+ scrub_peb_count++;
+ fm_pos += sizeof(*fec);
+ ubi_assert(fm_pos <= new_fm->size);
+ }
+ fmh->scrub_peb_count = cpu_to_be32(scrub_peb_count);
+
for (i = 0; i < UBI_MAX_VOLUMES + UBI_INT_VOL_COUNT; i++) {
vol = ubi->volumes[i];
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index a36748c..bea8c95 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -440,9 +440,10 @@ struct ubi_fm_hdr {
__be32 magic;
__be32 free_peb_count;
__be32 used_peb_count;
+ __be32 scrub_peb_count;
__be32 vol_count;
__be32 bad_peb_count;
- __u8 padding[12];
+ __u8 padding[8];
} __packed;
/* struct ubi_fm_hdr is followed by struct ubi_fm_scan_pool */
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 05/22] UBI: Fastmap: Rework ubi_wl_put_fm_peb()
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (3 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 04/22] UBI: Fastmap: Store scrub list in fastmap Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 06/22] UBI: Fastmap: Make EBA table self check depend on chk_gen Richard Weinberger
` (15 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/wl.c | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a64cd83..369e07f 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -827,13 +827,14 @@ static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
*
* see: ubi_wl_put_peb()
*/
-int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e,
- int torture)
+int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e,
+ int torture)
{
struct ubi_wl_entry *e;
- int pnum = used_e->pnum;
+ int pnum = fm_e->pnum;
dbg_wl("PEB %d", pnum);
+
ubi_assert(pnum >= 0);
ubi_assert(pnum < ubi->peb_count);
@@ -845,11 +846,11 @@ int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e,
* has never seen any PEB used by the original fastmap.
*/
if (!e) {
- e = used_e;
-
+ e = fm_e;
ubi_assert(e->ec);
ubi->lookuptbl[pnum] = e;
- }
+ } else
+ kfree(fm_e);
spin_unlock(&ubi->wl_lock);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 06/22] UBI: Fastmap: Make EBA table self check depend on chk_gen
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (4 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 05/22] UBI: Fastmap: Rework ubi_wl_put_fm_peb() Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 07/22] UBI: Fastmap: Fix build (a left over from the ai->fm removal) Richard Weinberger
` (14 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/attach.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index 9ae66e4..5cba456 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1262,7 +1262,7 @@ int ubi_attach(struct ubi_device *ubi)
if (err)
goto out_wl;
- if (ubi->fm) {
+ if (ubi->fm && ubi->dbg->chk_gen) {
struct ubi_attach_info *scan_ai;
scan_ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL);
if (!scan_ai)
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 07/22] UBI: Fastmap: Fix build (a left over from the ai->fm removal)
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (5 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 06/22] UBI: Fastmap: Make EBA table self check depend on chk_gen Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 08/22] Revert "UBI: Fastmap: Check for duplicated PEBs in add_aeb()" Richard Weinberger
` (13 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/wl.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 369e07f..4d9384b 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1727,8 +1727,8 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
dbg_wl("found %i PEBs", found_pebs);
- if (ai->fm)
- ubi_assert(ubi->peb_count == found_pebs + ai->fm->used_blocks);
+ if (ubi->fm)
+ ubi_assert(ubi->peb_count == found_pebs + ubi->fm->used_blocks);
else
ubi_assert(ubi->peb_count == found_pebs);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 08/22] Revert "UBI: Fastmap: Check for duplicated PEBs in add_aeb()"
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (6 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 07/22] UBI: Fastmap: Fix build (a left over from the ai->fm removal) Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 09/22] UBI: Fastmap: Fix PEB count assert Richard Weinberger
` (12 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
This reverts commit 95bbb0d1b2ea86103edfdd4b07ddfb058b1e0eff.
That check is no longer needed.
It must not happen that fastmap creates duplicates.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index bc29835..caefcb3 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -54,10 +54,6 @@ static int add_aeb(struct ubi_attach_info *ai, struct list_head *list,
{
struct ubi_ainf_peb *aeb;
- list_for_each_entry(aeb, list, u.list)
- if (aeb->pnum == pnum)
- return 0;
-
aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL);
if (!aeb)
return -ENOMEM;
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 09/22] UBI: Fastmap: Fix PEB count assert
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (7 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 08/22] Revert "UBI: Fastmap: Check for duplicated PEBs in add_aeb()" Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 10/22] UBI: Fastmap: Remove more useless new lines Richard Weinberger
` (11 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Use also the bad PEB count value, otherwise the assert will fail
if the FLASH has bad blocks.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/wl.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 4d9384b..58d74e4 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1728,9 +1728,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
dbg_wl("found %i PEBs", found_pebs);
if (ubi->fm)
- ubi_assert(ubi->peb_count == found_pebs + ubi->fm->used_blocks);
+ ubi_assert(ubi->peb_count - ubi->bad_peb_count == \
+ found_pebs + ubi->fm->used_blocks);
else
- ubi_assert(ubi->peb_count == found_pebs);
+ ubi_assert(ubi->peb_count - ubi->bad_peb_count == found_pebs);
if (ubi->avail_pebs < WL_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)",
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 10/22] UBI: Fastmap: Remove more useless new lines
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (8 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 09/22] UBI: Fastmap: Fix PEB count assert Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 11/22] UBI: Fastmap: Get rid of ubi_wl_flush() in ubi_update_fastmap() Richard Weinberger
` (10 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 8 --------
1 files changed, 0 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index caefcb3..8aa43e8 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1272,7 +1272,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
if (!ec_hdr) {
ret = -ENOMEM;
-
goto err;
}
@@ -1282,7 +1281,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (ret && ret != UBI_IO_BITFLIPS) {
ubi_err("unable to read EC header");
kfree(ec_hdr);
-
goto err;
}
@@ -1291,7 +1289,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (ret < 0) {
ubi_err("unable to erase old SB");
kfree(ec_hdr);
-
goto err;
}
@@ -1301,7 +1298,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
ubi_err("erase counter overflow!");
kfree(ec_hdr);
ret = -EINVAL;
-
goto err;
}
@@ -1311,7 +1307,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
kfree(ec_hdr);
if (ret) {
ubi_err("unable to write new EC header");
-
goto err;
}
@@ -1334,7 +1329,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (!tmp_e) {
ubi_err("could not find an early PEB");
ret = -ENOSPC;
-
goto err;
}
@@ -1345,7 +1339,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
ubi_err("fastmap too large");
ret = -ENOSPC;
-
goto err;
}
@@ -1365,7 +1358,6 @@ int ubi_update_fastmap(struct ubi_device *ubi)
kfree(new_fm->e[i]);
}
ret = -ENOSPC;
-
goto err;
}
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 11/22] UBI: Fastmap: Get rid of ubi_wl_flush() in ubi_update_fastmap()
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (9 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 10/22] UBI: Fastmap: Remove more useless new lines Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 12/22] UBI: Fastmap: Locking fixes Richard Weinberger
` (9 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 76 ++++++++++++++++++++++++++++++++++--------
drivers/mtd/ubi/ubi-media.h | 8 +++--
drivers/mtd/ubi/ubi.h | 21 ++++++++++++
drivers/mtd/ubi/wl.c | 32 ++++++------------
4 files changed, 98 insertions(+), 39 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 8aa43e8..ff09fd4 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -348,7 +348,7 @@ static void unmap_peb(struct ubi_attach_info *ai, int pnum)
*/
static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
int *pebs, int pool_size, unsigned long long *max_sqnum,
- struct list_head *eba_orphans)
+ struct list_head *eba_orphans, struct list_head *free)
{
struct ubi_vid_hdr *vh;
struct ubi_ec_hdr *ech;
@@ -402,9 +402,9 @@ static int scan_pool(struct ubi_device *ubi, struct ubi_attach_info *ai,
unmap_peb(ai, pnum);
dbg_bld("Adding PEB to free: %i", pnum);
if (err == UBI_IO_FF_BITFLIPS)
- add_aeb(ai, &ai->free, pnum, ec, 1);
+ add_aeb(ai, free, pnum, ec, 1);
else
- add_aeb(ai, &ai->free, pnum, ec, 0);
+ add_aeb(ai, free, pnum, ec, 0);
continue;
} else if (err == 0 || err == UBI_IO_BITFLIPS) {
dbg_bld("Found non empty PEB:%i in pool", pnum);
@@ -471,7 +471,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
struct ubi_attach_info *ai,
void *fm_raw, size_t fm_size)
{
- struct list_head used, eba_orphans;
+ struct list_head used, eba_orphans, free;
struct ubi_ainf_volume *av;
struct ubi_ainf_peb *aeb, *tmp_aeb, *_tmp_aeb;
struct ubi_ec_hdr *ech;
@@ -486,6 +486,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
unsigned long long max_sqnum = 0;
INIT_LIST_HEAD(&used);
+ INIT_LIST_HEAD(&free);
INIT_LIST_HEAD(&eba_orphans);
INIT_LIST_HEAD(&ai->corr);
INIT_LIST_HEAD(&ai->free);
@@ -567,6 +568,17 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
be32_to_cpu(fmec->ec), 1);
}
+ /* read EC values from erase list */
+ for (i = 0; i < be32_to_cpu(fmhdr->erase_peb_count); i++) {
+ fmec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+ fm_pos += sizeof(*fmec);
+ if (fm_pos >= fm_size)
+ goto fail_bad;
+
+ add_aeb(ai, &ai->erase, be32_to_cpu(fmec->pnum),
+ be32_to_cpu(fmec->ec), 1);
+ }
+
ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count);
ai->bad_peb_count = be32_to_cpu(fmhdr->bad_peb_count);
@@ -683,12 +695,12 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
}
ret = scan_pool(ubi, ai, fmpl1->pebs, be32_to_cpu(fmpl1->size),
- &max_sqnum, &eba_orphans);
+ &max_sqnum, &eba_orphans, &free);
if (ret)
goto fail;
ret = scan_pool(ubi, ai, fmpl2->pebs, be32_to_cpu(fmpl2->size),
- &max_sqnum, &eba_orphans);
+ &max_sqnum, &eba_orphans, &free);
if (ret)
goto fail;
@@ -697,11 +709,30 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &used, u.list) {
list_del(&tmp_aeb->u.list);
- dbg_bld("moving PEB from used to erase: %i", tmp_aeb->pnum);
+ ubi_msg("moving PEB from used to erase: %i", tmp_aeb->pnum);
add_aeb(ai, &ai->erase, tmp_aeb->pnum, tmp_aeb->ec, 0);
kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
}
+ if (list_empty(&free))
+ goto out;
+
+ list_for_each_entry(aeb, &ai->free, u.list) {
+ list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
+ if (aeb->pnum == tmp_aeb->pnum) {
+ aeb->scrub = tmp_aeb->scrub;
+ list_del(&tmp_aeb->u.list);
+ kfree(tmp_aeb);
+ continue;
+ }
+ }
+ }
+
+ list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
+ list_del(&tmp_aeb->u.list);
+ list_add_tail(&tmp_aeb->u.list, &ai->free);
+ }
+out:
return 0;
fail_bad:
@@ -1022,8 +1053,9 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
struct ubi_wl_entry *wl_e;
struct ubi_volume *vol;
struct ubi_vid_hdr *avhdr, *dvhdr;
+ struct ubi_work *ubi_wrk;
int ret, i, j, free_peb_count, used_peb_count, vol_count;
- int scrub_peb_count;
+ int scrub_peb_count, erase_peb_count;
fm_raw = vzalloc(new_fm->size);
if (!fm_raw) {
@@ -1064,6 +1096,7 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
free_peb_count = 0;
used_peb_count = 0;
scrub_peb_count = 0;
+ erase_peb_count = 0;
vol_count = 0;
fmpl1 = (struct ubi_fm_scan_pool *)(fm_raw + fm_pos);
@@ -1121,6 +1154,24 @@ static int ubi_write_fastmap(struct ubi_device *ubi,
}
fmh->scrub_peb_count = cpu_to_be32(scrub_peb_count);
+
+ list_for_each_entry(ubi_wrk, &ubi->works, list) {
+ if (ubi_is_erase_work(ubi_wrk)) {
+ wl_e = ubi_wrk->e;
+ ubi_assert(wl_e);
+
+ fec = (struct ubi_fm_ec *)(fm_raw + fm_pos);
+
+ fec->pnum = cpu_to_be32(wl_e->pnum);
+ fec->ec = cpu_to_be32(wl_e->ec);
+
+ erase_peb_count++;
+ fm_pos += sizeof(*fec);
+ ubi_assert(fm_pos <= new_fm->size);
+ }
+ }
+ fmh->erase_peb_count = cpu_to_be32(erase_peb_count);
+
for (i = 0; i < UBI_MAX_VOLUMES + UBI_INT_VOL_COUNT; i++) {
vol = ubi->volumes[i];
@@ -1366,15 +1417,10 @@ int ubi_update_fastmap(struct ubi_device *ubi)
}
kfree(old_fm);
- /* Ensure that the PEBs of the old fastmap got erased and added to the
- * free list before we write the fastmap. Otherwise fastmp does not
- * see these PEBs and we leak them.
- * We need the flush also to ensure that no to be scrubbed PEBs are in
- * flight.
- */
- ubi_wl_flush(ubi);
+ down_write(&ubi->work_sem);
ret = ubi_write_fastmap(ubi, new_fm);
+ up_write(&ubi->work_sem);
out_unlock:
mutex_unlock(&ubi->fm_mutex);
diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h
index bea8c95..a0648c1 100644
--- a/drivers/mtd/ubi/ubi-media.h
+++ b/drivers/mtd/ubi/ubi-media.h
@@ -433,17 +433,19 @@ struct ubi_fm_sb {
* @magic: fastmap header magic number (%UBI_FM_HDR_MAGIC)
* @free_peb_count: number of free PEBs known by this fastmap
* @free_peb_count: number of used PEBs known by this fastmap
- * @vol_count: number of UBI volumes known by this fastmap
* @bad_peb_count: number of bad PEBs known by this fastmap
+ * @erase_peb_count: number of bad PEBs which have to be erased
+ * @vol_count: number of UBI volumes known by this fastmap
*/
struct ubi_fm_hdr {
__be32 magic;
__be32 free_peb_count;
__be32 used_peb_count;
__be32 scrub_peb_count;
- __be32 vol_count;
__be32 bad_peb_count;
- __u8 padding[8];
+ __be32 erase_peb_count;
+ __be32 vol_count;
+ __u8 padding[4];
} __packed;
/* struct ubi_fm_hdr is followed by struct ubi_fm_scan_pool */
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index dcbc420..8588f9c 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -653,6 +653,26 @@ struct ubi_attach_info {
struct kmem_cache *aeb_slab_cache;
};
+/**
+ * struct ubi_work - UBI work description data structure.
+ * @list: a link in the list of pending works
+ * @func: worker function
+ * @e: physical eraseblock to erase
+ * @torture: if the physical eraseblock has to be tortured
+ *
+ * The @func pointer points to the worker function. If the @cancel argument is
+ * not zero, the worker has to free the resources and exit immediately. The
+ * worker has to return zero in case of success and a negative error code in
+ * case of failure.
+ */
+struct ubi_work {
+ struct list_head list;
+ int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
+ /* The below fields are only relevant to erasure works */
+ struct ubi_wl_entry *e;
+ int torture;
+};
+
#include "debug.h"
extern struct kmem_cache *ubi_wl_entry_slab;
@@ -734,6 +754,7 @@ void ubi_wl_close(struct ubi_device *ubi);
int ubi_thread(void *u);
struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int max_pnum);
int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *used_e, int torture);
+int ubi_is_erase_work(struct ubi_work *wrk);
/* io.c */
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 58d74e4..25d2e0b 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -135,32 +135,11 @@
*/
#define WL_MAX_FAILURES 32
-/**
- * struct ubi_work - UBI work description data structure.
- * @list: a link in the list of pending works
- * @func: worker function
- * @e: physical eraseblock to erase
- * @torture: if the physical eraseblock has to be tortured
- *
- * The @func pointer points to the worker function. If the @cancel argument is
- * not zero, the worker has to free the resources and exit immediately. The
- * worker has to return zero in case of success and a negative error code in
- * case of failure.
- */
-struct ubi_work {
- struct list_head list;
- int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel);
- /* The below fields are only relevant to erasure works */
- struct ubi_wl_entry *e;
- int torture;
-};
-
static int self_check_ec(struct ubi_device *ubi, int pnum, int ec);
static int self_check_in_wl_tree(const struct ubi_device *ubi,
struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
struct ubi_wl_entry *e);
-
/**
* ubi_ubi_is_fm_block - returns 1 if a PEB is currently used in a fastmap.
* @ubi: UBI device description object
@@ -760,6 +739,7 @@ repeat:
*/
static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
{
+ down_read(&ubi->work_sem);
spin_lock(&ubi->wl_lock);
list_add_tail(&wrk->list, &ubi->works);
ubi_assert(ubi->works_count >= 0);
@@ -767,12 +747,22 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk)
if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi))
wake_up_process(ubi->bgt_thread);
spin_unlock(&ubi->wl_lock);
+ up_read(&ubi->work_sem);
}
static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk,
int cancel);
/**
+ * ubi_is_erase_work - checks whether a work is erase work
+ * @wrk: The work object to be checked
+ */
+int ubi_is_erase_work(struct ubi_work *wrk)
+{
+ return wrk->func == erase_worker;
+}
+
+/**
* schedule_erase - schedule an erase work.
* @ubi: UBI device description object
* @e: the WL entry of the physical eraseblock to erase
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 12/22] UBI: Fastmap: Locking fixes
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (10 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 11/22] UBI: Fastmap: Get rid of ubi_wl_flush() in ubi_update_fastmap() Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 13/22] UBI: Fastmap: Fix EC values Richard Weinberger
` (8 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Add a new rw semaphore to block EBA table changes
while creating the fastmap.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/eba.c | 12 ++++++++++++
drivers/mtd/ubi/fastmap.c | 2 ++
drivers/mtd/ubi/ubi.h | 2 ++
3 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index d112b10..2bee8be 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -340,7 +340,9 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol,
dbg_eba("erase LEB %d:%d, PEB %d", vol_id, lnum, pnum);
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED;
+ up_read(&ubi->fm_sem);
err = ubi_wl_put_peb(ubi, pnum, 0);
out_unlock:
@@ -549,7 +551,9 @@ retry:
mutex_unlock(&ubi->buf_mutex);
ubi_free_vid_hdr(ubi, vid_hdr);
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = new_pnum;
+ up_read(&ubi->fm_sem);
ubi_wl_put_peb(ubi, pnum, 1);
ubi_msg("data was successfully recovered");
@@ -667,7 +671,9 @@ retry:
}
}
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = pnum;
+ up_read(&ubi->fm_sem);
leb_write_unlock(ubi, vol_id, lnum);
ubi_free_vid_hdr(ubi, vid_hdr);
@@ -785,7 +791,9 @@ retry:
}
ubi_assert(vol->eba_tbl[lnum] < 0);
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = pnum;
+ up_read(&ubi->fm_sem);
leb_write_unlock(ubi, vol_id, lnum);
ubi_free_vid_hdr(ubi, vid_hdr);
@@ -906,7 +914,9 @@ retry:
goto out_leb_unlock;
}
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = pnum;
+ up_read(&ubi->fm_sem);
out_leb_unlock:
leb_write_unlock(ubi, vol_id, lnum);
@@ -1154,7 +1164,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
}
ubi_assert(vol->eba_tbl[lnum] == from);
+ down_read(&ubi->fm_sem);
vol->eba_tbl[lnum] = to;
+ up_read(&ubi->fm_sem);
out_unlock_buf:
mutex_unlock(&ubi->buf_mutex);
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index ff09fd4..33a14cf 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1418,9 +1418,11 @@ int ubi_update_fastmap(struct ubi_device *ubi)
kfree(old_fm);
+ down_write(&ubi->fm_sem);
down_write(&ubi->work_sem);
ret = ubi_write_fastmap(ubi, new_fm);
up_write(&ubi->work_sem);
+ up_write(&ubi->fm_sem);
out_unlock:
mutex_unlock(&ubi->fm_mutex);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 8588f9c..8abbcd5 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -384,6 +384,7 @@ struct ubi_wl_entry;
* @fm_pool: in-memory data structure of the fastmap pool
* @fm_pool_mutex: serializes ubi_wl_get_peb()
* @fm_mutex: serializes ubi_update_fastmap()
+ * @fm_sem: allows ubi_update_fastmap() to block EBA table changes
* @attached_by_scanning: this UBI device was attached by the old scanning
* methold. All fastmap volumes have to be deleted.
*
@@ -482,6 +483,7 @@ struct ubi_device {
struct ubi_fastmap_layout *fm;
struct ubi_fm_pool fm_pool;
struct ubi_fm_pool fm_wl_pool;
+ struct rw_semaphore fm_sem;
struct mutex fm_mutex;
struct mutex fm_pool_mutex;
int attached_by_scanning;
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 13/22] UBI: Fastmap: Fix EC values
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (11 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 12/22] UBI: Fastmap: Locking fixes Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 14/22] UBI: Fastmap: Fix copy&paste error Richard Weinberger
` (7 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Return the correct EC values back to the WL sub-system.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 2 ++
drivers/mtd/ubi/wl.c | 4 +++-
2 files changed, 5 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 33a14cf..b4f7fce 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -721,6 +721,7 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
if (aeb->pnum == tmp_aeb->pnum) {
aeb->scrub = tmp_aeb->scrub;
+ aeb->ec = tmp_aeb->ec;
list_del(&tmp_aeb->u.list);
kfree(tmp_aeb);
continue;
@@ -1345,6 +1346,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
ec = be64_to_cpu(ec_hdr->ec);
ec += ret;
+ old_fm->e[0]->ec = ec;
if (ec > UBI_MAX_ERASECOUNTER) {
ubi_err("erase counter overflow!");
kfree(ec_hdr);
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index 25d2e0b..eec3940 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -839,8 +839,10 @@ int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e,
e = fm_e;
ubi_assert(e->ec);
ubi->lookuptbl[pnum] = e;
- } else
+ } else {
+ e->ec = fm_e->ec;
kfree(fm_e);
+ }
spin_unlock(&ubi->wl_lock);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 14/22] UBI: Fastmap: Fix copy&paste error
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (12 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 13/22] UBI: Fastmap: Fix EC values Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 15/22] UBI: Fastmap: Kill old fastmap in case of a failure Richard Weinberger
` (6 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index b4f7fce..f9e5dbb 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1403,7 +1403,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
tmp_e = ubi_wl_get_fm_peb(ubi, -1);
spin_unlock(&ubi->wl_lock);
- if (!new_fm->e[i]) {
+ if (!tmp_e) {
ubi_err("could not get any free erase block");
while (i--) {
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 15/22] UBI: Fastmap: Kill old fastmap in case of a failure
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (13 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 14/22] UBI: Fastmap: Fix copy&paste error Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:18 ` [PATCH 16/22] UBI: Fastmap: Fix loglevel Richard Weinberger
` (5 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
We have to make sure that the old (and from this point on
invalid) fastmap is killed if we fail to create a new one.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 177 +++++++++++++++++++++++++--------------------
1 files changed, 100 insertions(+), 77 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index f9e5dbb..7d36034 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1266,6 +1266,59 @@ out:
return ret;
}
+static int erase_block(struct ubi_device *ubi, int pnum)
+{
+ int ret;
+ struct ubi_ec_hdr *ec_hdr;
+ long long ec;
+
+ ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
+ if (!ec_hdr)
+ return -ENOMEM;
+
+ ret = ubi_io_read_ec_hdr(ubi, pnum, ec_hdr, 0);
+ if (ret < 0)
+ goto out;
+ else if (ret && ret != UBI_IO_BITFLIPS) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = ubi_io_sync_erase(ubi, pnum, 0);
+ if (ret < 0)
+ goto out;
+
+ ec = be64_to_cpu(ec_hdr->ec);
+ ec += ret;
+ if (ec > UBI_MAX_ERASECOUNTER) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ec_hdr->ec = cpu_to_be64(ec);
+ ret = ubi_io_write_ec_hdr(ubi, pnum, ec_hdr);
+ if (ret < 0)
+ goto out;
+
+ ret = ec;
+out:
+ kfree(ec_hdr);
+ return ret;
+}
+
+static int invalidate_fastmap(struct ubi_device *ubi,
+ struct ubi_fastmap_layout *fm)
+{
+ int ret, i;
+
+ ret = erase_block(ubi, fm->e[0]->pnum);
+
+ for (i = 0; i < fm->used_blocks; i++)
+ ubi_wl_put_fm_peb(ubi, fm->e[i], fm->to_be_tortured[i]);
+
+ return ret;
+}
+
/**
* ubi_update_fastmap - will be called by UBI if a volume changes or
* a fastmap pool becomes full.
@@ -1307,10 +1360,35 @@ int ubi_update_fastmap(struct ubi_device *ubi)
}
mutex_lock(&ubi->fm_mutex);
-
old_fm = ubi->fm;
ubi->fm = NULL;
+ if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
+ ubi_err("fastmap too large");
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ for (i = 1; i < new_fm->used_blocks; i++) {
+ spin_lock(&ubi->wl_lock);
+ tmp_e = ubi_wl_get_fm_peb(ubi, -1);
+ spin_unlock(&ubi->wl_lock);
+
+ if (!tmp_e) {
+ int j;
+ ubi_err("could not get any free erase block");
+
+ for (j = 1; j < i; j++)
+ ubi_wl_put_fm_peb(ubi, new_fm->e[j], 0);
+
+ ret = -ENOSPC;
+ goto err;
+ }
+
+ new_fm->e[i]->pnum = tmp_e->pnum;
+ new_fm->e[i]->ec = tmp_e->ec;
+ }
+
spin_lock(&ubi->wl_lock);
tmp_e = ubi_wl_get_fm_peb(ubi, UBI_FM_MAX_START);
spin_unlock(&ubi->wl_lock);
@@ -1318,53 +1396,14 @@ int ubi_update_fastmap(struct ubi_device *ubi)
if (old_fm) {
/* no fresh early PEB was found, reuse the old one */
if (!tmp_e) {
- struct ubi_ec_hdr *ec_hdr;
- long long ec;
-
- ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
- if (!ec_hdr) {
- ret = -ENOMEM;
- goto err;
- }
-
- /* we have to erase the block by hand */
- ret = ubi_io_read_ec_hdr(ubi, old_fm->e[0]->pnum,
- ec_hdr, 0);
- if (ret && ret != UBI_IO_BITFLIPS) {
- ubi_err("unable to read EC header");
- kfree(ec_hdr);
- goto err;
- }
-
- ret = ubi_io_sync_erase(ubi, old_fm->e[0]->pnum,
- 0);
+ ret = erase_block(ubi, old_fm->e[0]->pnum);
if (ret < 0) {
- ubi_err("unable to erase old SB");
- kfree(ec_hdr);
- goto err;
- }
-
- ec = be64_to_cpu(ec_hdr->ec);
- ec += ret;
- old_fm->e[0]->ec = ec;
- if (ec > UBI_MAX_ERASECOUNTER) {
- ubi_err("erase counter overflow!");
- kfree(ec_hdr);
- ret = -EINVAL;
- goto err;
- }
-
- ec_hdr->ec = cpu_to_be64(ec);
- ret = ubi_io_write_ec_hdr(ubi, old_fm->e[0]->pnum,
- ec_hdr);
- kfree(ec_hdr);
- if (ret) {
- ubi_err("unable to write new EC header");
+ ubi_err("could not erase old early PEB");
goto err;
}
new_fm->e[0]->pnum = old_fm->e[0]->pnum;
- new_fm->e[0]->ec = old_fm->e[0]->ec;
+ new_fm->e[0]->ec = ret;
} else {
/* we've got a new early PEB, return the old one */
ubi_wl_put_fm_peb(ubi, old_fm->e[0],
@@ -1389,48 +1428,32 @@ int ubi_update_fastmap(struct ubi_device *ubi)
new_fm->e[0]->ec = tmp_e->ec;
}
- if (new_fm->used_blocks > UBI_FM_MAX_BLOCKS) {
- ubi_err("fastmap too large");
- ret = -ENOSPC;
- goto err;
- }
-
- /* give the wl subsystem a chance to produce some free blocks */
- cond_resched();
-
- for (i = 1; i < new_fm->used_blocks; i++) {
- spin_lock(&ubi->wl_lock);
- tmp_e = ubi_wl_get_fm_peb(ubi, -1);
- spin_unlock(&ubi->wl_lock);
-
- if (!tmp_e) {
- ubi_err("could not get any free erase block");
-
- while (i--) {
- ubi_wl_put_fm_peb(ubi, new_fm->e[i], 0);
- kfree(new_fm->e[i]);
- }
- ret = -ENOSPC;
- goto err;
- }
-
- new_fm->e[i]->pnum = tmp_e->pnum;
- new_fm->e[i]->ec = tmp_e->ec;
- }
-
- kfree(old_fm);
-
- down_write(&ubi->fm_sem);
down_write(&ubi->work_sem);
+ down_write(&ubi->fm_sem);
ret = ubi_write_fastmap(ubi, new_fm);
- up_write(&ubi->work_sem);
up_write(&ubi->fm_sem);
+ up_write(&ubi->work_sem);
+
+ if (ret)
+ goto err;
+
out_unlock:
mutex_unlock(&ubi->fm_mutex);
-
+ kfree(old_fm);
return ret;
err:
kfree(new_fm);
+
+ ubi_warn("Unable to write new fastmap, err=%i", ret);
+
+ ret = 0;
+ if (old_fm) {
+ ret = invalidate_fastmap(ubi, old_fm);
+ if (ret < 0)
+ ubi_err("Unable to invalidiate current fastmap!");
+ else if (ret)
+ ret = 0;
+ }
goto out_unlock;
}
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 16/22] UBI: Fastmap: Fix loglevel
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (14 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 15/22] UBI: Fastmap: Kill old fastmap in case of a failure Richard Weinberger
@ 2012-06-18 16:18 ` Richard Weinberger
2012-06-18 16:19 ` [PATCH 17/22] UBI: Fastmap: Add comments to new functions Richard Weinberger
` (4 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:18 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/wl.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index eec3940..be847d4 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -799,7 +799,7 @@ static int do_sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e,
{
struct ubi_work *wl_wrk;
- ubi_msg("sync erase of PEB %i", e->pnum);
+ dbg_wl("sync erase of PEB %i", e->pnum);
wl_wrk = kmalloc(sizeof(struct ubi_work), GFP_NOFS);
if (!wl_wrk)
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 17/22] UBI: Fastmap: Add comments to new functions
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (15 preceding siblings ...)
2012-06-18 16:18 ` [PATCH 16/22] UBI: Fastmap: Fix loglevel Richard Weinberger
@ 2012-06-18 16:19 ` Richard Weinberger
2012-06-18 16:19 ` [PATCH 18/22] UBI: Fastmap: Rename "early PEB" to "anchor PEB" Richard Weinberger
` (3 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:19 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 10 ++++++++++
1 files changed, 10 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 7d36034..65fd7ee 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1266,6 +1266,11 @@ out:
return ret;
}
+/**
+ * erase_block - Manually erase a PEB
+ * @ubi: UBI device object
+ * @pnum: PEB to be erased
+ */
static int erase_block(struct ubi_device *ubi, int pnum)
{
int ret;
@@ -1306,6 +1311,11 @@ out:
return ret;
}
+/**
+ * invalidate_fastmap - destroys a fastmap
+ * @ubi: UBI device object
+ * @fm: the fastmap to be destroyed
+ */
static int invalidate_fastmap(struct ubi_device *ubi,
struct ubi_fastmap_layout *fm)
{
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 18/22] UBI: Fastmap: Rename "early PEB" to "anchor PEB".
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (16 preceding siblings ...)
2012-06-18 16:19 ` [PATCH 17/22] UBI: Fastmap: Add comments to new functions Richard Weinberger
@ 2012-06-18 16:19 ` Richard Weinberger
2012-06-18 16:19 ` [PATCH 19/22] UBI: Fastmap: Init fm_sem Richard Weinberger
` (2 subsequent siblings)
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:19 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
"early PEB" is a very bad name.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 8 ++++----
drivers/mtd/ubi/wl.c | 8 ++++----
2 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index 65fd7ee..bea9446 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -1404,18 +1404,18 @@ int ubi_update_fastmap(struct ubi_device *ubi)
spin_unlock(&ubi->wl_lock);
if (old_fm) {
- /* no fresh early PEB was found, reuse the old one */
+ /* no fresh anchor PEB was found, reuse the old one */
if (!tmp_e) {
ret = erase_block(ubi, old_fm->e[0]->pnum);
if (ret < 0) {
- ubi_err("could not erase old early PEB");
+ ubi_err("could not erase old anchor PEB");
goto err;
}
new_fm->e[0]->pnum = old_fm->e[0]->pnum;
new_fm->e[0]->ec = ret;
} else {
- /* we've got a new early PEB, return the old one */
+ /* we've got a new anchor PEB, return the old one */
ubi_wl_put_fm_peb(ubi, old_fm->e[0],
old_fm->to_be_tortured[0]);
@@ -1429,7 +1429,7 @@ int ubi_update_fastmap(struct ubi_device *ubi)
old_fm->to_be_tortured[i]);
} else {
if (!tmp_e) {
- ubi_err("could not find an early PEB");
+ ubi_err("could not find an anchor PEB");
ret = -ENOSPC;
goto err;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index be847d4..e5ab683 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -388,12 +388,12 @@ static struct ubi_wl_entry *find_mean_wl_entry(struct rb_root *root)
}
/**
- * find_early_wl_entry - find wear-leveling entry with the lowest pnum.
+ * find_anchor_wl_entry - find wear-leveling entry to used as anchor PEB.
* @root: the RB-tree where to look for
* @max_pnum: highest possible pnum
*/
-static struct ubi_wl_entry *find_early_wl_entry(struct rb_root *root,
- int max_pnum)
+static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root,
+ int max_pnum)
{
struct rb_node *p;
struct ubi_wl_entry *e, *victim = NULL;
@@ -433,7 +433,7 @@ struct ubi_wl_entry *ubi_wl_get_fm_peb(struct ubi_device *ubi, int max_pnum)
if (max_pnum < 0)
e = find_mean_wl_entry(&ubi->free);
else
- e = find_early_wl_entry(&ubi->free, max_pnum);
+ e = find_anchor_wl_entry(&ubi->free, max_pnum);
if (!e)
goto out;
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 19/22] UBI: Fastmap: Init fm_sem
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (17 preceding siblings ...)
2012-06-18 16:19 ` [PATCH 18/22] UBI: Fastmap: Rename "early PEB" to "anchor PEB" Richard Weinberger
@ 2012-06-18 16:19 ` Richard Weinberger
2012-06-18 16:19 ` [PATCH 20/22] UBI: Fastmap: Use good_peb_count in assert Richard Weinberger
2012-06-18 16:19 ` [PATCH 21/22] UBI: Fastmap: Fix and explain duplicated PEBs Richard Weinberger
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:19 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
...forgot to stage this change.
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/build.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index 0ad6789..1ad128d 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -908,6 +908,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset)
mutex_init(&ubi->device_mutex);
mutex_init(&ubi->fm_pool_mutex);
mutex_init(&ubi->fm_mutex);
+ init_rwsem(&ubi->fm_sem);
spin_lock_init(&ubi->volumes_lock);
ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 20/22] UBI: Fastmap: Use good_peb_count in assert
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (18 preceding siblings ...)
2012-06-18 16:19 ` [PATCH 19/22] UBI: Fastmap: Init fm_sem Richard Weinberger
@ 2012-06-18 16:19 ` Richard Weinberger
2012-06-18 16:19 ` [PATCH 21/22] UBI: Fastmap: Fix and explain duplicated PEBs Richard Weinberger
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:19 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/wl.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index e5ab683..f4d2c79 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1720,10 +1720,10 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
dbg_wl("found %i PEBs", found_pebs);
if (ubi->fm)
- ubi_assert(ubi->peb_count - ubi->bad_peb_count == \
+ ubi_assert(ubi->good_peb_count == \
found_pebs + ubi->fm->used_blocks);
else
- ubi_assert(ubi->peb_count - ubi->bad_peb_count == found_pebs);
+ ubi_assert(ubi->good_peb_count == found_pebs);
if (ubi->avail_pebs < WL_RESERVED_PEBS) {
ubi_err("no enough physical eraseblocks (%d, need %d)",
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread* [PATCH 21/22] UBI: Fastmap: Fix and explain duplicated PEBs
2012-06-18 16:18 UBI Fastmap updates Richard Weinberger
` (19 preceding siblings ...)
2012-06-18 16:19 ` [PATCH 20/22] UBI: Fastmap: Use good_peb_count in assert Richard Weinberger
@ 2012-06-18 16:19 ` Richard Weinberger
20 siblings, 0 replies; 22+ messages in thread
From: Richard Weinberger @ 2012-06-18 16:19 UTC (permalink / raw)
To: linux-mtd
Cc: linux-kernel, adrian.hunter, Heinz.Egger, thomas.wucher,
shmulik.ladkani, tglx, tim.bird, Marius.Mazarel, artem.bityutskiy,
Richard Weinberger
Signed-off-by: Richard Weinberger <richard@nod.at>
---
drivers/mtd/ubi/fastmap.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c
index bea9446..45f70db 100644
--- a/drivers/mtd/ubi/fastmap.c
+++ b/drivers/mtd/ubi/fastmap.c
@@ -714,6 +714,15 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
kmem_cache_free(ai->aeb_slab_cache, tmp_aeb);
}
+ /*
+ * Sort out dups. We are allowed to have duplicates here because
+ * the fastmap can be written without refilling all pools.
+ * E.g. If PEB X is in a pool fastmap may detect it as empty and
+ * puts it into the free list. But ff PEB X is in the pool, get's
+ * used and returned (e.g. by schedule_erase()) it remains in
+ * the erase or free list too.
+ * We could also sort out these dups while creating the fastmap.
+ */
if (list_empty(&free))
goto out;
@@ -729,6 +738,18 @@ static int ubi_attach_fastmap(struct ubi_device *ubi,
}
}
+ list_for_each_entry(aeb, &ai->erase, u.list) {
+ list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
+ if (aeb->pnum == tmp_aeb->pnum) {
+ aeb->scrub = tmp_aeb->scrub;
+ aeb->ec = tmp_aeb->ec;
+ list_del(&tmp_aeb->u.list);
+ kfree(tmp_aeb);
+ continue;
+ }
+ }
+ }
+
list_for_each_entry_safe(tmp_aeb, _tmp_aeb, &free, u.list) {
list_del(&tmp_aeb->u.list);
list_add_tail(&tmp_aeb->u.list, &ai->free);
--
1.7.6.5
^ permalink raw reply related [flat|nested] 22+ messages in thread