diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-06-28 12:16:55 -0400 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-07-05 11:47:03 -0400 |
commit | 40a71a87fa8e0cb3ec0fca4d152263734b203eb2 (patch) | |
tree | 8bdd27304fc4d28c850c76f2b1f4a32c802612f8 /drivers | |
parent | 8e4a718ff38d8539938ec3421935904c27e00c39 (diff) |
UBI: add empty eraseblocks verification
This patch adds code which makes sure eraseblocks contain all 0xFF
bytes before starting using them. The verification is done only when
debugging checks are enabled.
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/ubi/debug.h | 6 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 17 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 8 |
3 files changed, 21 insertions, 10 deletions
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 13777e5beac9..6fc7fda2ab91 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
@@ -93,6 +93,12 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | |||
93 | #define UBI_IO_DEBUG 0 | 93 | #define UBI_IO_DEBUG 0 |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | ||
97 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); | ||
98 | #else | ||
99 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | ||
100 | #endif | ||
101 | |||
96 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 102 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT |
97 | #define DBG_DISABLE_BGT 1 | 103 | #define DBG_DISABLE_BGT 1 |
98 | #else | 104 | #else |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index effaff28bab1..6c5441e8791d 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
@@ -98,8 +98,6 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, | |||
98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); | 98 | static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); |
99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, | 99 | static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, |
100 | const struct ubi_vid_hdr *vid_hdr); | 100 | const struct ubi_vid_hdr *vid_hdr); |
101 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | ||
102 | int len); | ||
103 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum); | 101 | static int paranoid_check_empty(struct ubi_device *ubi, int pnum); |
104 | #else | 102 | #else |
105 | #define paranoid_check_not_bad(ubi, pnum) 0 | 103 | #define paranoid_check_not_bad(ubi, pnum) 0 |
@@ -107,7 +105,6 @@ static int paranoid_check_empty(struct ubi_device *ubi, int pnum); | |||
107 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 | 105 | #define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 |
108 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 | 106 | #define paranoid_check_peb_vid_hdr(ubi, pnum) 0 |
109 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 | 107 | #define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 |
110 | #define paranoid_check_all_ff(ubi, pnum, offset, len) 0 | ||
111 | #define paranoid_check_empty(ubi, pnum) 0 | 108 | #define paranoid_check_empty(ubi, pnum) 0 |
112 | #endif | 109 | #endif |
113 | 110 | ||
@@ -244,7 +241,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
244 | return err > 0 ? -EINVAL : err; | 241 | return err > 0 ? -EINVAL : err; |
245 | 242 | ||
246 | /* The area we are writing to has to contain all 0xFF bytes */ | 243 | /* The area we are writing to has to contain all 0xFF bytes */ |
247 | err = paranoid_check_all_ff(ubi, pnum, offset, len); | 244 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); |
248 | if (err) | 245 | if (err) |
249 | return err > 0 ? -EINVAL : err; | 246 | return err > 0 ? -EINVAL : err; |
250 | 247 | ||
@@ -350,7 +347,7 @@ retry: | |||
350 | return -EIO; | 347 | return -EIO; |
351 | } | 348 | } |
352 | 349 | ||
353 | err = paranoid_check_all_ff(ubi, pnum, 0, ubi->peb_size); | 350 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); |
354 | if (err) | 351 | if (err) |
355 | return err > 0 ? -EINVAL : err; | 352 | return err > 0 ? -EINVAL : err; |
356 | 353 | ||
@@ -672,8 +669,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
672 | if (read_err != -EBADMSG && | 669 | if (read_err != -EBADMSG && |
673 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { | 670 | check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { |
674 | /* The physical eraseblock is supposedly empty */ | 671 | /* The physical eraseblock is supposedly empty */ |
675 | err = paranoid_check_all_ff(ubi, pnum, 0, | 672 | err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); |
676 | ubi->peb_size); | ||
677 | if (err) | 673 | if (err) |
678 | return err > 0 ? UBI_IO_BAD_EC_HDR : err; | 674 | return err > 0 ? UBI_IO_BAD_EC_HDR : err; |
679 | 675 | ||
@@ -1229,7 +1225,7 @@ exit: | |||
1229 | } | 1225 | } |
1230 | 1226 | ||
1231 | /** | 1227 | /** |
1232 | * paranoid_check_all_ff - check that a region of flash is empty. | 1228 | * ubi_dbg_check_all_ff - check that a region of flash is empty. |
1233 | * @ubi: UBI device description object | 1229 | * @ubi: UBI device description object |
1234 | * @pnum: the physical eraseblock number to check | 1230 | * @pnum: the physical eraseblock number to check |
1235 | * @offset: the starting offset within the physical eraseblock to check | 1231 | * @offset: the starting offset within the physical eraseblock to check |
@@ -1239,13 +1235,14 @@ exit: | |||
1239 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error | 1235 | * @offset of the physical eraseblock @pnum, %1 if not, and a negative error |
1240 | * code if an error occurred. | 1236 | * code if an error occurred. |
1241 | */ | 1237 | */ |
1242 | static int paranoid_check_all_ff(struct ubi_device *ubi, int pnum, int offset, | 1238 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) |
1243 | int len) | ||
1244 | { | 1239 | { |
1245 | size_t read; | 1240 | size_t read; |
1246 | int err; | 1241 | int err; |
1247 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; | 1242 | loff_t addr = (loff_t)pnum * ubi->peb_size + offset; |
1248 | 1243 | ||
1244 | ubi_assert(!mutex_is_locked(&ubi->dbg_buf_mutex)); | ||
1245 | |||
1249 | mutex_lock(&ubi->dbg_buf_mutex); | 1246 | mutex_lock(&ubi->dbg_buf_mutex); |
1250 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); | 1247 | err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); |
1251 | if (err && err != -EUCLEAN) { | 1248 | if (err && err != -EUCLEAN) { |
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 2b2472300610..e4be446e05ed 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c | |||
@@ -459,6 +459,14 @@ retry: | |||
459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); | 459 | dbg_wl("PEB %d EC %d", e->pnum, e->ec); |
460 | prot_queue_add(ubi, e); | 460 | prot_queue_add(ubi, e); |
461 | spin_unlock(&ubi->wl_lock); | 461 | spin_unlock(&ubi->wl_lock); |
462 | |||
463 | err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, | ||
464 | ubi->peb_size - ubi->vid_hdr_aloffset); | ||
465 | if (err) { | ||
466 | dbg_err("new PEB does not contain all 0xFF bytes"); | ||
467 | return err > 0 ? -EINVAL : err; | ||
468 | } | ||
469 | |||
462 | return e->pnum; | 470 | return e->pnum; |
463 | } | 471 | } |
464 | 472 | ||