From d4c6381303163e774a72db8c172cdc5c23f01588 Mon Sep 17 00:00:00 2001 From: Holger Brunck Date: Tue, 25 Jan 2011 13:04:11 +0200 Subject: UBI: fix NOR erase preparation quirk In 'nor_erase_prepare()' we want to make sure the UBI headers are corrupted. But it is possible that one of the headers just contains all 0xFFs, which is also OK, because UBI will erase it in case of a power cut. Signed-off-by: Holger Brunck Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 811775a..668d240 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -507,11 +507,13 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) * PEB. */ err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); - if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) { + if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR || + err1 == UBI_IO_FF) { struct ubi_ec_hdr ec_hdr; err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0); - if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) + if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR || + err1 == UBI_IO_FF) /* * Both VID and EC headers are corrupted, so we can * safely erase this PEB and not afraid that it will be -- cgit v1.1 From e8cfe009436f9ab6f4234e1f7c406c231747925c Mon Sep 17 00:00:00 2001 From: John Ogness Date: Fri, 21 Jan 2011 15:39:02 +0100 Subject: UBI: cleanup LEB start calculations Wrong macro was used in calculating the data offset: UBI_EC_HDR_SIZE instead of UBI_VID_HDR_SIZE. The data offset should be VID header offset + VID header size (aligned to the minimum I/O unit). This was not a bug only because currently UBI_EC_HDR_SIZE and UBI_VID_HDR_SIZE have the same value of 64 bytes. Commit message was amended by Artem. Signed-off-by: John Ogness Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 5ebe280..ef29635 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -711,7 +711,7 @@ static int io_init(struct ubi_device *ubi) } /* Similar for the data offset */ - ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; + ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE; ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); -- cgit v1.1 From 2fff570e7c8f97e411cd852d64b77b92d9ab8da9 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 3 Dec 2010 15:32:21 +0200 Subject: UBI: add a commentary about allocating VID header buffer on stack Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 668d240..65915a6 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -480,6 +480,13 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) size_t written; loff_t addr; uint32_t data = 0; + /* + * Note, we cannot generally define VID header buffers on stack, + * because of the way we deal with these buffers (see the header + * comment in this file). But we know this is a NOR-specific piece of + * code, so we can do this. But yes, this is error-prone and we should + * (pre-)allocate VID header buffer instead. + */ struct ubi_vid_hdr vid_hdr; /* -- cgit v1.1 From 276832d878d8a892ac7b40fd0ee07fe757e080c7 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sat, 13 Nov 2010 15:08:29 +0200 Subject: UBI: try to reveal buggy MTD drivers When reading data from the flash, corrupt the buffer we are about to read to. The idea is to fix the following possible situation: 1. The buffer contains data from previous operation, e.g., read from another PEB previously. The data looks like expected, e.g., if we just do not read anything and return - the caller would not notice this. E.g., if we are reading a VID header, the buffer may contain a valid VID header from another PEB. 2. The driver is buggy and returns use success or -EBADMSG or -EUCLEAN, but it does not actually put any data to the buffer. This may confuse UBI or upper layers - they may think the buffer contains valid data while in fact it is just old data. Thus, try to reveal such buggy MTD drivers with simple debugging code which fills the read buffer with 0x12 constant. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 65915a6..339a74f 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -146,6 +146,28 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, if (err) return err; + /* + * Deliberately corrupt the buffer to improve robustness. Indeed, if we + * do not do this, the following may happen: + * 1. The buffer contains data from previous operation, e.g., read from + * another PEB previously. The data looks like expected, e.g., if we + * just do not read anything and return - the caller would not + * notice this. E.g., if we are reading a VID header, the buffer may + * contain a valid VID header from another PEB. + * 2. The driver is buggy and returns us success or -EBADMSG or + * -EUCLEAN, but it does not actually put any data to the buffer. + * + * This may confuse UBI or upper layers - they may think the buffer + * contains valid data while in fact it is just old data. This is + * especially possible because UBI (and UBIFS) relies on CRC, and + * treats data as correct even in case of ECC errors if the CRC is + * correct. + * + * Try to prevent this situation by changing the first byte of the + * buffer. + */ + *((uint8_t *)buf) ^= 0xFF; + addr = (loff_t)pnum * ubi->peb_size + offset; retry: err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); -- cgit v1.1 From 7950d023c562823345892aac2e7c6a49f8de9ad1 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 19 Nov 2010 17:05:36 +0200 Subject: UBI: use raw mtd read function in debugging code This change affects only the debugging code. Namely, use mtd->read() function instead of ubi_io_read() to avoid bit-flips injection (ubi_dbg_is_bitflip()) which we do not want on the debugging path. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 339a74f..6f90a65 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1325,10 +1325,12 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { int err, i; + size_t read; + loff_t addr = (loff_t)pnum * ubi->peb_size + offset; mutex_lock(&ubi->dbg_buf_mutex); - err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len); - if (err) + err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); + if (err && err != -EUCLEAN) goto out_unlock; for (i = 0; i < len; i++) { -- cgit v1.1 From 6c1e875ca6f3a47b40dce715bd07fdfdb8388d55 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 31 Oct 2010 17:54:14 +0200 Subject: UBI: add slab cache for ubi_scan_leb objects During scanning UBI allocates one struct ubi_scan_leb object for each PEB, so it can end up allocating thousands of them. Use slab cache to reduce memory consumption for these 48-byte objects, because currently used 'kmalloc()' ends up allocating 64 bytes per object, instead of 48. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 2 ++ drivers/mtd/ubi/scan.c | 32 +++++++++++++++++++++----------- drivers/mtd/ubi/scan.h | 2 ++ 3 files changed, 25 insertions(+), 11 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ef29635..ec0ad19 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -923,6 +923,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) spin_lock_init(&ubi->volumes_lock); ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); + dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb)); + dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry)); err = io_init(ubi); if (err) diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 79ca304..0028bf2 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -115,7 +115,7 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head, } else BUG(); - seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); + seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); if (!seb) return -ENOMEM; @@ -144,7 +144,7 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); + seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); if (!seb) return -ENOMEM; @@ -553,7 +553,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, if (err) return err; - seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); + seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); if (!seb) return -ENOMEM; @@ -1152,9 +1152,15 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) si->volumes = RB_ROOT; err = -ENOMEM; + si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab", + sizeof(struct ubi_scan_leb), + 0, 0, NULL); + if (!si->scan_leb_slab) + goto out_si; + ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ech) - goto out_si; + goto out_slab; vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); if (!vidh) @@ -1215,6 +1221,8 @@ out_vidh: ubi_free_vid_hdr(ubi, vidh); out_ech: kfree(ech); +out_slab: + kmem_cache_destroy(si->scan_leb_slab); out_si: ubi_scan_destroy_si(si); return ERR_PTR(err); @@ -1223,11 +1231,12 @@ out_si: /** * destroy_sv - free the scanning volume information * @sv: scanning volume information + * @si: scanning information * * This function destroys the volume RB-tree (@sv->root) and the scanning * volume information. */ -static void destroy_sv(struct ubi_scan_volume *sv) +static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv) { struct ubi_scan_leb *seb; struct rb_node *this = sv->root.rb_node; @@ -1247,7 +1256,7 @@ static void destroy_sv(struct ubi_scan_volume *sv) this->rb_right = NULL; } - kfree(seb); + kmem_cache_free(si->scan_leb_slab, seb); } } kfree(sv); @@ -1265,19 +1274,19 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { list_del(&seb->u.list); - kfree(seb); + kmem_cache_free(si->scan_leb_slab, seb); } list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { list_del(&seb->u.list); - kfree(seb); + kmem_cache_free(si->scan_leb_slab, seb); } list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { list_del(&seb->u.list); - kfree(seb); + kmem_cache_free(si->scan_leb_slab, seb); } list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { list_del(&seb->u.list); - kfree(seb); + kmem_cache_free(si->scan_leb_slab, seb); } /* Destroy the volume RB-tree */ @@ -1298,10 +1307,11 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) rb->rb_right = NULL; } - destroy_sv(sv); + destroy_sv(si, sv); } } + kmem_cache_destroy(si->scan_leb_slab); kfree(si); } diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index a3264f0..d48aef1 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -109,6 +109,7 @@ struct ubi_scan_volume { * @mean_ec: mean erase counter value * @ec_sum: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec + * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects * * This data structure contains the result of scanning and may be used by other * UBI sub-systems to build final UBI data structures, further error-recovery @@ -134,6 +135,7 @@ struct ubi_scan_info { int mean_ec; uint64_t ec_sum; int ec_count; + struct kmem_cache *scan_leb_slab; }; struct ubi_device; -- cgit v1.1 From fef2deb31f6523203a3fa1af485a5f1fef19cf6b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 29 Oct 2010 08:34:50 +0300 Subject: UBI: cleanup comments about corrupted PEBs Just make them a bit more readable and explanatory. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 54 +++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 20 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 0028bf2..b65cc08 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -39,32 +39,46 @@ * eraseblocks are put to the @free list and the physical eraseblock to be * erased are put to the @erase list. * + * About corruptions + * ~~~~~~~~~~~~~~~~~ + * + * UBI protects EC and VID headers with CRC-32 checksums, so it can detect + * whether the headers are corrupted or not. Sometimes UBI also protects the + * data with CRC-32, e.g., when it executes the atomic LEB change operation, or + * when it moves the contents of a PEB for wear-leveling purposes. + * * 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. + * + * 1. Corruptions caused by power cuts. These are 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 such data losses (e.g., by using the FS journal). + * + * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like + * the reason is a power cut, UBI puts this PEB to the @erase list, and all + * PEBs in the @erase list are scheduled for erasure later. * * 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. + * 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 + * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2 + * if the VID header is corrupted and the data area does not contain all 0xFFs, + * and there were no bit-flips or integrity errors while reading the data area. + * Otherwise UBI assumes corruption type 1. So the decision criteria are as + * follows. + * o If the data area contains only 0xFFs, there is no data, and it is safe + * to just erase this PEB - this is corruption type 1. + * o If the data area has bit-flips or data integrity errors (ECC errors on * NAND), it is probably a PEB which was being erased when power cut - * happened. + * happened, so this is corruption type 1. However, this is just a guess, + * which might be wrong. + * o Otherwise this it corruption type 2. */ #include -- cgit v1.1 From a87f29cbbcbd5bd1e4990367cd18967e9bbeacff Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 31 Oct 2010 18:55:30 +0200 Subject: UBI: always re-read in case of read failures When the read operation fails, UBI tries to re-read several times in a hope that one of the subsequent reads may succeed. However, currently UBI re-reads only if MTD failed to read all data, but does not re-reads if all the data were read, but with an integrity error (-EBADMSB). This patch makes UBI to always re-try reading. This should be useful for reading NAND pages with unstable bits - re-reading may help to get correct data. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 6f90a65..889e25c 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -188,7 +188,7 @@ retry: return UBI_IO_BITFLIPS; } - if (read != len && retries++ < UBI_IO_RETRIES) { + if (retries++ < UBI_IO_RETRIES) { dbg_io("error %d%s while reading %d bytes from PEB %d:%d," " read only %zd bytes, retry", err, errstr, len, pnum, offset, read); -- cgit v1.1 From a75867432a7eb2cdcaa8613a3b72b1d0594dd930 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Mar 2011 17:06:52 +0200 Subject: UBI: allocate write checking buffer on demand Instead of using pre-allocated 'ubi->dbg_peb_buf' buffer in 'ubi_dbg_check_write()', dynamically allocate it when needed. The intend is to get rid of the pre-allocated 'ubi->dbg_peb_buf' buffer completely. And the need for this arises because we want to change to dynamic debugging control instead of compile-time control, i.e., we are going to kill the CONFIG_MTD_UBI_DEBUG_PARANOID Kconfig option, which would mean that 'ubi->dbg_peb_buf' is always allocated, which would be wasteful. Thus, we are getting rid of 'ubi->dbg_peb_buf', and this is a preparation for that. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 24 +++++++++++++++--------- drivers/mtd/ubi/ubi.h | 1 + 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 889e25c..b4d34ba 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1326,16 +1326,22 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, { int err, i; size_t read; + void *buf1; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - mutex_lock(&ubi->dbg_buf_mutex); - err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); + buf1 = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + if (!buf1) { + ubi_err("cannot allocate memory to check writes"); + return 0; + } + + err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1); if (err && err != -EUCLEAN) - goto out_unlock; + goto out_free; for (i = 0; i < len; i++) { uint8_t c = ((uint8_t *)buf)[i]; - uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i]; + uint8_t c1 = ((uint8_t *)buf1)[i]; int dump_len; if (c == c1) @@ -1352,17 +1358,17 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, ubi_msg("hex dump of the read buffer from %d to %d", i, i + dump_len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, - ubi->dbg_peb_buf + i, dump_len, 1); + buf1 + i, dump_len, 1); ubi_dbg_dump_stack(); err = -EINVAL; - goto out_unlock; + goto out_free; } - mutex_unlock(&ubi->dbg_buf_mutex); + vfree(buf1); return 0; -out_unlock: - mutex_unlock(&ubi->dbg_buf_mutex); +out_free: + vfree(buf1); return err; } diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 0b0149c..9af362c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -40,6 +40,7 @@ #include #include #include +#include #include "ubi-media.h" #include "scan.h" -- cgit v1.1 From 332873d60b943c9bf53957c6e334038ac5e9dc6b Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Mar 2011 17:09:40 +0200 Subject: UBI: allocate erase checking buffer on demand Instead of using pre-allocated 'ubi->dbg_peb_buf' buffer in 'ubi_dbg_check_all_ff()', dynamically allocate it when needed. The intend is to get rid of the pre-allocated 'ubi->dbg_peb_buf' buffer completely. And the need for this arises because we want to change to dynamic debugging control instead of compile-time control, i.e., we are going to kill the CONFIG_MTD_UBI_DEBUG_PARANOID Kconfig option, which would mean that 'ubi->dbg_peb_buf' is always allocated, which would be wasteful. Thus, we are getting rid of 'ubi->dbg_peb_buf', and this is a preparation for that. signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index b4d34ba..35da5aa 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -1387,35 +1387,40 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) { size_t read; int err; + void *buf; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - mutex_lock(&ubi->dbg_buf_mutex); - err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf); + buf = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); + if (!buf) { + ubi_err("cannot allocate memory to check for 0xFFs"); + return 0; + } + + err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); if (err && err != -EUCLEAN) { ubi_err("error %d while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, len, pnum, offset, read); goto error; } - err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len); + err = ubi_check_pattern(buf, 0xFF, len); if (err == 0) { ubi_err("flash region at PEB %d:%d, length %d does not " "contain all 0xFF bytes", pnum, offset, len); goto fail; } - mutex_unlock(&ubi->dbg_buf_mutex); + vfree(buf); return 0; fail: ubi_err("paranoid check failed for PEB %d", pnum); ubi_msg("hex dump of the %d-%d region", offset, offset + len); - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, - ubi->dbg_peb_buf, len, 1); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1); err = -EINVAL; error: ubi_dbg_dump_stack(); - mutex_unlock(&ubi->dbg_buf_mutex); + vfree(buf); return err; } -- cgit v1.1 From 6edb9793959fb547a15d5ffe6b142d9f0b3e41a6 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Mar 2011 17:11:29 +0200 Subject: UBI: kill debugging buffer This patch kills the 'ubi->dbg_peb_buf' debugging buffer and the associated mutex, because all users of this buffer are now gone. We are killing this buffer because we are going to switch to dynamic debugging control, just like in UBIFS, which means that CONFIG_MTD_UBI_DEBUG_PARANOID will be removed. In this case we'd end up always allocating 'ubi->dbg_peb_buf', which is rather large (128KiB or more), and this would be wasteful. Thus, we are just killing it. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 13 ------------- drivers/mtd/ubi/ubi.h | 6 ------ 2 files changed, 19 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index ec0ad19..3a04719 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -939,13 +939,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) if (!ubi->peb_buf2) goto out_free; -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID - mutex_init(&ubi->dbg_buf_mutex); - ubi->dbg_peb_buf = vmalloc(ubi->peb_size); - if (!ubi->dbg_peb_buf) - goto out_free; -#endif - err = attach_by_scanning(ubi); if (err) { dbg_err("failed to attach by scanning, error %d", err); @@ -1011,9 +1004,6 @@ out_detach: out_free: vfree(ubi->peb_buf1); vfree(ubi->peb_buf2); -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID - vfree(ubi->dbg_peb_buf); -#endif if (ref) put_device(&ubi->dev); else @@ -1084,9 +1074,6 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) put_mtd_device(ubi->mtd); vfree(ubi->peb_buf1); vfree(ubi->peb_buf2); -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID - vfree(ubi->dbg_peb_buf); -#endif ubi_msg("mtd%d is detached from ubi%d", ubi->mtd->index, ubi->ubi_num); put_device(&ubi->dev); return 0; diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 9af362c..49c864d 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -388,8 +388,6 @@ struct ubi_wl_entry; * @peb_buf2: another buffer of PEB size used for different purposes * @buf_mutex: protects @peb_buf1 and @peb_buf2 * @ckvol_mutex: serializes static volume checking when opening - * @dbg_peb_buf: buffer of PEB size used for debugging - * @dbg_buf_mutex: protects @dbg_peb_buf */ struct ubi_device { struct cdev cdev; @@ -471,10 +469,6 @@ struct ubi_device { void *peb_buf2; struct mutex buf_mutex; struct mutex ckvol_mutex; -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID - void *dbg_peb_buf; - struct mutex dbg_buf_mutex; -#endif }; extern struct kmem_cache *ubi_wl_entry_slab; -- cgit v1.1 From 6f9fdf62db64b1e52e5b7a9f785554e8b877b65c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 11 Mar 2011 13:08:51 +0200 Subject: UBI: remove UBI_IO_DEBUG macro This additional little macro is used to print a bit more messages while scanning the media. However, we have the 'dbg_bld()' macro for this, so we better us 'dbg_bld()' and kill UBI_IO_DEBUG. This simplifies the code a tiny bit. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/debug.h | 3 --- drivers/mtd/ubi/io.c | 34 ++++++++++++++++------------------ 2 files changed, 16 insertions(+), 21 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 9eca950..8bd1d17 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -91,10 +91,8 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD /* Initialization and build messages */ #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#define UBI_IO_DEBUG 1 #else #define dbg_bld(fmt, ...) ({}) -#define UBI_IO_DEBUG 0 #endif #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID @@ -177,7 +175,6 @@ static inline int ubi_dbg_is_erase_failure(void) #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 DBG_DISABLE_BGT 0 #define ubi_dbg_is_bitflip() 0 #define ubi_dbg_is_write_failure() 0 diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 35da5aa..b1ad1ec 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -783,9 +783,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (verbose) ubi_warn("no EC header found at PEB %d, " "only 0xFF bytes", pnum); - else if (UBI_IO_DEBUG) - dbg_msg("no EC header found at PEB %d, " - "only 0xFF bytes", pnum); + dbg_bld("no EC header found at PEB %d, " + "only 0xFF bytes", pnum); if (!read_err) return UBI_IO_FF; else @@ -800,9 +799,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ubi_warn("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_EC_HDR_MAGIC); ubi_dbg_dump_ec_hdr(ec_hdr); - } else if (UBI_IO_DEBUG) - dbg_msg("bad magic number at PEB %d: %08x instead of " - "%08x", pnum, magic, UBI_EC_HDR_MAGIC); + } + dbg_bld("bad magic number at PEB %d: %08x instead of " + "%08x", pnum, magic, UBI_EC_HDR_MAGIC); return UBI_IO_BAD_HDR; } @@ -814,9 +813,9 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, ubi_warn("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); ubi_dbg_dump_ec_hdr(ec_hdr); - } else if (UBI_IO_DEBUG) - dbg_msg("bad EC header CRC at PEB %d, calculated " - "%#08x, read %#08x", pnum, crc, hdr_crc); + } + dbg_bld("bad EC header CRC at PEB %d, calculated " + "%#08x, read %#08x", pnum, crc, hdr_crc); if (!read_err) return UBI_IO_BAD_HDR; @@ -1039,9 +1038,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, if (verbose) ubi_warn("no VID header found at PEB %d, " "only 0xFF bytes", pnum); - else if (UBI_IO_DEBUG) - dbg_msg("no VID header found at PEB %d, " - "only 0xFF bytes", pnum); + dbg_bld("no VID header found at PEB %d, " + "only 0xFF bytes", pnum); if (!read_err) return UBI_IO_FF; else @@ -1052,9 +1050,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ubi_warn("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); ubi_dbg_dump_vid_hdr(vid_hdr); - } else if (UBI_IO_DEBUG) - dbg_msg("bad magic number at PEB %d: %08x instead of " - "%08x", pnum, magic, UBI_VID_HDR_MAGIC); + } + dbg_bld("bad magic number at PEB %d: %08x instead of " + "%08x", pnum, magic, UBI_VID_HDR_MAGIC); return UBI_IO_BAD_HDR; } @@ -1066,9 +1064,9 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, ubi_warn("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); ubi_dbg_dump_vid_hdr(vid_hdr); - } else if (UBI_IO_DEBUG) - dbg_msg("bad CRC at PEB %d, calculated %#08x, " - "read %#08x", pnum, crc, hdr_crc); + } + dbg_bld("bad CRC at PEB %d, calculated %#08x, " + "read %#08x", pnum, crc, hdr_crc); if (!read_err) return UBI_IO_BAD_HDR; else -- cgit v1.1 From b342efd4a49cef9cf1a260c1814aad97722f38f8 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 11 Mar 2011 14:33:23 +0200 Subject: UBI: make debugging messages dynamic This patch adds a possibility to dynamically select UBI debugging messages, instead of selecting them compile-time from the configuration menu. This is much more flexible, and consistent with UBIFS, and this also simplifies UBI Kconfig menu and the code. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/Kconfig.debug | 30 ------------------------ drivers/mtd/ubi/debug.c | 8 +++++++ drivers/mtd/ubi/debug.h | 54 +++++++++++++++++++++++-------------------- 3 files changed, 37 insertions(+), 55 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index fad4adc..d40134e 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -10,11 +10,6 @@ config MTD_UBI_DEBUG if MTD_UBI_DEBUG -config MTD_UBI_DEBUG_MSG - bool "UBI debugging messages" - help - This option enables UBI debugging messages. - config MTD_UBI_DEBUG_PARANOID bool "Extra self-checks" help @@ -45,29 +40,4 @@ config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES This option emulates erase failures with probability 1/100. Useful for debugging and testing how UBI handlines errors. -comment "Additional UBI debugging messages" - -config MTD_UBI_DEBUG_MSG_BLD - bool "Additional UBI initialization and build messages" - help - This option enables detailed UBI initialization and device build - debugging messages. - -config MTD_UBI_DEBUG_MSG_EBA - bool "Eraseblock association unit messages" - help - This option enables debugging messages from the UBI eraseblock - association unit. - -config MTD_UBI_DEBUG_MSG_WL - bool "Wear-leveling unit messages" - help - This option enables debugging messages from the UBI wear-leveling - unit. - -config MTD_UBI_DEBUG_MSG_IO - bool "Input/output unit messages" - help - This option enables debugging messages from the UBI input/output unit. - endif # MTD_UBI_DEBUG diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 4876977..8ae0bc7 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -27,6 +27,14 @@ #ifdef CONFIG_MTD_UBI_DEBUG #include "ubi.h" +#include +#include + +unsigned int ubi_msg_flags; + +module_param_named(debug_msgs, ubi_msg_flags, uint, S_IRUGO | S_IWUSR); + +MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); /** * ubi_dbg_dump_ec_hdr - dump an erase counter header. diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 8bd1d17..bee6fa1 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -38,6 +38,11 @@ printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ current->pid, __func__, ##__VA_ARGS__) +#define dbg_do_msg(typ, fmt, ...) do { \ + if (ubi_msg_flags & typ) \ + dbg_msg(fmt, ##__VA_ARGS__); \ +} while (0) + #define ubi_dbg_dump_stack() dump_stack() struct ubi_ec_hdr; @@ -57,43 +62,42 @@ 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_flash(struct ubi_device *ubi, int pnum, int offset, int len); +extern unsigned int ubi_msg_flags; + +/* + * Debugging message type flags (must match msg_type_names in debug.c). + * + * UBI_MSG_GEN: general messages + * UBI_MSG_EBA: journal messages + * UBI_MSG_WL: mount messages + * UBI_MSG_IO: commit messages + * UBI_MSG_BLD: LEB find messages + */ +enum { + UBI_MSG_GEN = 0x1, + UBI_MSG_EBA = 0x2, + UBI_MSG_WL = 0x4, + UBI_MSG_IO = 0x8, + UBI_MSG_BLD = 0x10, +}; + #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 /* General debugging messages */ -#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#else -#define dbg_gen(fmt, ...) ({}) -#endif +#define dbg_gen(fmt, ...) dbg_do_msg(UBI_MSG_GEN, fmt, ##__VA_ARGS__) -#ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA /* Messages from the eraseblock association sub-system */ -#define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#else -#define dbg_eba(fmt, ...) ({}) -#endif +#define dbg_eba(fmt, ...) dbg_do_msg(UBI_MSG_EBA, fmt, ##__VA_ARGS__) -#ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL /* Messages from the wear-leveling sub-system */ -#define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#else -#define dbg_wl(fmt, ...) ({}) -#endif +#define dbg_wl(fmt, ...) dbg_do_msg(UBI_MSG_WL, fmt, ##__VA_ARGS__) -#ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO /* Messages from the input/output sub-system */ -#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#else -#define dbg_io(fmt, ...) ({}) -#endif +#define dbg_io(fmt, ...) dbg_do_msg(UBI_MSG_IO, fmt, ##__VA_ARGS__) -#ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD /* Initialization and build messages */ -#define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) -#else -#define dbg_bld(fmt, ...) ({}) -#endif +#define dbg_bld(fmt, ...) dbg_do_msg(UBI_MSG_BLD, fmt, ##__VA_ARGS__) #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); -- cgit v1.1 From 92d124f5314913a21f7fa98b22ee457dab171edd Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 14 Mar 2011 18:17:40 +0200 Subject: UBI: make self-checks dynamic This patch adds a possibility to dynamically switch UBI self-checks on and off, instead of toggling them compile-time from the configuration menu. This is much more flexible, and consistent with UBIFS, and this also simplifies UBI Kconfig menu and the code. This patch introduces two levels of self-checks - general, which includes all self-checks which are relatively fast, and I/O, which includes write-verify checks and erase-verify checks, which are relatively slow and involve flash I/O. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/Kconfig.debug | 6 ------ drivers/mtd/ubi/debug.c | 3 +++ drivers/mtd/ubi/debug.h | 18 +++++++++++++----- drivers/mtd/ubi/io.c | 27 ++++++++++++++++++++++++--- drivers/mtd/ubi/scan.c | 9 ++++++--- drivers/mtd/ubi/vmt.c | 7 +++++-- drivers/mtd/ubi/vtbl.c | 9 ++++++--- drivers/mtd/ubi/wl.c | 16 +++++++++++++--- 8 files changed, 70 insertions(+), 25 deletions(-) (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug index d40134e..d8d33dd 100644 --- a/drivers/mtd/ubi/Kconfig.debug +++ b/drivers/mtd/ubi/Kconfig.debug @@ -10,12 +10,6 @@ config MTD_UBI_DEBUG if MTD_UBI_DEBUG -config MTD_UBI_DEBUG_PARANOID - bool "Extra self-checks" - help - This option enables extra checks in UBI code. Note this slows UBI down - significantly. - config MTD_UBI_DEBUG_DISABLE_BGT bool "Do not enable the UBI background thread" help diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 8ae0bc7..4c7a3f6 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -31,10 +31,13 @@ #include unsigned int ubi_msg_flags; +unsigned int ubi_chk_flags; module_param_named(debug_msgs, ubi_msg_flags, uint, S_IRUGO | S_IWUSR); +module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); +MODULE_PARM_DESC(debug_chks, "Debug check flags"); /** * ubi_dbg_dump_ec_hdr - dump an erase counter header. diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index bee6fa1..2511b58 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -99,14 +99,22 @@ enum { /* Initialization and build messages */ #define dbg_bld(fmt, ...) dbg_do_msg(UBI_MSG_BLD, fmt, ##__VA_ARGS__) -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +extern unsigned int ubi_chk_flags; + +/* + * Debugging check flags. + * + * UBI_CHK_GEN: general checks + * UBI_CHK_IO: check writes and erases + */ +enum { + UBI_CHK_GEN = 0x1, + UBI_CHK_IO = 0x2, +}; + int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len); -#else -#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 -#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 -#endif #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT #define DBG_DISABLE_BGT 1 diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index b1ad1ec..aaa6e1e 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -91,7 +91,7 @@ #include #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum); static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum); static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, @@ -1126,7 +1126,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, return err; } -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG /** * paranoid_check_not_bad - ensure that a physical eraseblock is not bad. @@ -1140,6 +1140,9 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) { int err; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + err = ubi_io_is_bad(ubi, pnum); if (!err) return err; @@ -1164,6 +1167,9 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, int err; uint32_t magic; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + magic = be32_to_cpu(ec_hdr->magic); if (magic != UBI_EC_HDR_MAGIC) { ubi_err("bad magic %#08x, must be %#08x", @@ -1199,6 +1205,9 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) uint32_t crc, hdr_crc; struct ubi_ec_hdr *ec_hdr; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); if (!ec_hdr) return -ENOMEM; @@ -1240,6 +1249,9 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, int err; uint32_t magic; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x", @@ -1278,6 +1290,9 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) struct ubi_vid_hdr *vid_hdr; void *p; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); if (!vid_hdr) return -ENOMEM; @@ -1327,6 +1342,9 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, void *buf1; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + buf1 = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); if (!buf1) { ubi_err("cannot allocate memory to check writes"); @@ -1388,6 +1406,9 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) void *buf; loff_t addr = (loff_t)pnum * ubi->peb_size + offset; + if (!(ubi_chk_flags & UBI_CHK_IO)) + return 0; + buf = __vmalloc(len, GFP_KERNEL | GFP_NOFS, PAGE_KERNEL); if (!buf) { ubi_err("cannot allocate memory to check for 0xFFs"); @@ -1422,4 +1443,4 @@ error: return err; } -#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ +#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index b65cc08..11eb8ef 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -88,7 +88,7 @@ #include #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si); #else #define paranoid_check_si(ubi, si) 0 @@ -1329,7 +1329,7 @@ void ubi_scan_destroy_si(struct ubi_scan_info *si) kfree(si); } -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG /** * paranoid_check_si - check the scanning information. @@ -1347,6 +1347,9 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) struct ubi_scan_leb *seb, *last_seb; uint8_t *buf; + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return 0; + /* * At first, check that scanning information is OK. */ @@ -1599,4 +1602,4 @@ out: return -EINVAL; } -#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ +#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index c47620d..b79e0de 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -28,7 +28,7 @@ #include #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG static int paranoid_check_volumes(struct ubi_device *ubi); #else #define paranoid_check_volumes(ubi) 0 @@ -711,7 +711,7 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) volume_sysfs_close(vol); } -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG /** * paranoid_check_volume - check volume information. @@ -876,6 +876,9 @@ static int paranoid_check_volumes(struct ubi_device *ubi) { int i, err = 0; + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return 0; + for (i = 0; i < ubi->vtbl_slots; i++) { err = paranoid_check_volume(ubi, i); if (err) diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index fcdb7f6..0b81c55 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -62,7 +62,7 @@ #include #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG static void paranoid_vtbl_check(const struct ubi_device *ubi); #else #define paranoid_vtbl_check(ubi) @@ -870,7 +870,7 @@ out_free: return err; } -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG /** * paranoid_vtbl_check - check volume table. @@ -878,10 +878,13 @@ out_free: */ static void paranoid_vtbl_check(const struct ubi_device *ubi) { + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return; + if (vtbl_check(ubi, ubi->vtbl)) { ubi_err("paranoid check failed"); BUG(); } } -#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ +#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 655bbbe..4e55290 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -161,7 +161,7 @@ struct ubi_work { int torture; }; -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec); static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root); @@ -1561,7 +1561,7 @@ void ubi_wl_close(struct ubi_device *ubi) kfree(ubi->lookuptbl); } -#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID +#ifdef CONFIG_MTD_UBI_DEBUG /** * paranoid_check_ec - make sure that the erase counter of a PEB is correct. @@ -1578,6 +1578,9 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec) long long read_ec; struct ubi_ec_hdr *ec_hdr; + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return 0; + ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS); if (!ec_hdr) return -ENOMEM; @@ -1614,6 +1617,9 @@ out_free: static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e, struct rb_root *root) { + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return 0; + if (in_wl_tree(e, root)) return 0; @@ -1636,6 +1642,9 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e) struct ubi_wl_entry *p; int i; + if (!(ubi_chk_flags & UBI_CHK_GEN)) + return 0; + for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i) list_for_each_entry(p, &ubi->pq[i], u.list) if (p == e) @@ -1646,4 +1655,5 @@ static int paranoid_check_in_pq(struct ubi_device *ubi, struct ubi_wl_entry *e) ubi_dbg_dump_stack(); return -EINVAL; } -#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */ + +#endif /* CONFIG_MTD_UBI_DEBUG */ -- cgit v1.1 From 28237e4583604818294dc1ce7881db5f53377b9c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 15 Mar 2011 10:30:40 +0200 Subject: UBI: make tests modes dynamic Similarly to the debugging checks and message, make the test modes be dynamically selected via the "debug_tsts" module parameter or via the "/sys/module/ubi/parameters/debug_tsts" sysfs file. This is consistent with UBIFS as well. And now, since all the Kconfig knobs became dynamic, we can remove the Kconfig.debug file completely. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/Kconfig | 8 ++++++- drivers/mtd/ubi/Kconfig.debug | 37 ---------------------------- drivers/mtd/ubi/build.c | 3 +-- drivers/mtd/ubi/debug.c | 3 +++ drivers/mtd/ubi/debug.h | 56 +++++++++++++++++++++++++++---------------- drivers/mtd/ubi/wl.c | 4 ++-- 6 files changed, 49 insertions(+), 62 deletions(-) delete mode 100644 drivers/mtd/ubi/Kconfig.debug (limited to 'drivers/mtd/ubi') diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 3cf193f..6abeb4f 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -52,6 +52,12 @@ config MTD_UBI_GLUEBI work on top of UBI. Do not enable this unless you use legacy software. -source "drivers/mtd/ubi/Kconfig.debug" +config MTD_UBI_DEBUG + bool "UBI debugging" + depends on SYSFS + select DEBUG_FS + select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL + help + This option enables UBI debugging. endif # MTD_UBI diff --git a/drivers/mtd/ubi/Kconfig.debug b/drivers/mtd/ubi/Kconfig.debug deleted file mode 100644 index d8d33dd..0000000 --- a/drivers/mtd/ubi/Kconfig.debug +++ /dev/null @@ -1,37 +0,0 @@ -comment "UBI debugging options" - -config MTD_UBI_DEBUG - bool "UBI debugging" - depends on SYSFS - select DEBUG_FS - select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL - help - This option enables UBI debugging. - -if MTD_UBI_DEBUG - -config MTD_UBI_DEBUG_DISABLE_BGT - bool "Do not enable the UBI background thread" - help - This option switches the background thread off by default. The thread - may be also be enabled/disabled via UBI sysfs. - -config MTD_UBI_DEBUG_EMULATE_BITFLIPS - bool "Emulate flash bit-flips" - help - This option emulates bit-flips with probability 1/50, which in turn - causes scrubbing. Useful for debugging and stressing UBI. - -config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES - bool "Emulate flash write failures" - help - This option emulates write failures with probability 1/100. Useful for - debugging and testing how UBI handlines errors. - -config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES - bool "Emulate flash erase failures" - help - This option emulates erase failures with probability 1/100. Useful for - debugging and testing how UBI handlines errors. - -endif # MTD_UBI_DEBUG diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 3a04719..a801ea6 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -986,8 +986,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) * checks @ubi->thread_enabled. Otherwise we may fail to wake it up. */ spin_lock(&ubi->wl_lock); - if (!DBG_DISABLE_BGT) - ubi->thread_enabled = 1; + ubi->thread_enabled = 1; wake_up_process(ubi->bgt_thread); spin_unlock(&ubi->wl_lock); diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 4c7a3f6..d4d07e5 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -32,12 +32,15 @@ unsigned int ubi_msg_flags; unsigned int ubi_chk_flags; +unsigned int ubi_tst_flags; module_param_named(debug_msgs, ubi_msg_flags, uint, S_IRUGO | S_IWUSR); module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR); +module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug_msgs, "Debug message type flags"); MODULE_PARM_DESC(debug_chks, "Debug check flags"); +MODULE_PARM_DESC(debug_tsts, "Debug special test flags"); /** * ubi_dbg_dump_ec_hdr - dump an erase counter header. diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 2511b58..0b0c288 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -116,13 +116,34 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len); -#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT -#define DBG_DISABLE_BGT 1 -#else -#define DBG_DISABLE_BGT 0 -#endif +extern unsigned int ubi_tst_flags; + +/* + * Special testing flags. + * + * UBIFS_TST_DISABLE_BGT: disable the background thread + * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips + * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures + * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures + */ +enum { + UBI_TST_DISABLE_BGT = 0x1, + UBI_TST_EMULATE_BITFLIPS = 0x2, + UBI_TST_EMULATE_WRITE_FAILURES = 0x4, + UBI_TST_EMULATE_ERASE_FAILURES = 0x8, +}; + +/** + * ubi_dbg_is_bgt_disabled - if the background thread is disabled. + * + * Returns non-zero if the UBI background thread is disabled for testing + * purposes. + */ +static inline int ubi_dbg_is_bgt_disabled(void) +{ + return ubi_tst_flags & UBI_TST_DISABLE_BGT; +} -#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS /** * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip. * @@ -130,13 +151,11 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, */ static inline int ubi_dbg_is_bitflip(void) { - return !(random32() % 200); + if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS) + return !(random32() % 200); + return 0; } -#else -#define ubi_dbg_is_bitflip() 0 -#endif -#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES /** * ubi_dbg_is_write_failure - if it is time to emulate a write failure. * @@ -145,13 +164,11 @@ static inline int ubi_dbg_is_bitflip(void) */ static inline int ubi_dbg_is_write_failure(void) { - return !(random32() % 500); + if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES) + return !(random32() % 500); + return 0; } -#else -#define ubi_dbg_is_write_failure() 0 -#endif -#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES /** * ubi_dbg_is_erase_failure - if its time to emulate an erase failure. * @@ -160,11 +177,10 @@ static inline int ubi_dbg_is_write_failure(void) */ static inline int ubi_dbg_is_erase_failure(void) { + if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES) return !(random32() % 400); + return 0; } -#else -#define ubi_dbg_is_erase_failure() 0 -#endif #else @@ -187,7 +203,7 @@ static inline int ubi_dbg_is_erase_failure(void) #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({}) #define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a) ({}) -#define DBG_DISABLE_BGT 0 +#define ubi_dbg_is_bgt_disabled() 0 #define ubi_dbg_is_bitflip() 0 #define ubi_dbg_is_write_failure() 0 #define ubi_dbg_is_erase_failure() 0 diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 4e55290..b4cf57d 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -613,7 +613,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) list_add_tail(&wrk->list, &ubi->works); ubi_assert(ubi->works_count >= 0); ubi->works_count += 1; - if (ubi->thread_enabled) + if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled()) wake_up_process(ubi->bgt_thread); spin_unlock(&ubi->wl_lock); } @@ -1364,7 +1364,7 @@ int ubi_thread(void *u) spin_lock(&ubi->wl_lock); if (list_empty(&ubi->works) || ubi->ro_mode || - !ubi->thread_enabled) { + !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) { set_current_state(TASK_INTERRUPTIBLE); spin_unlock(&ubi->wl_lock); schedule(); -- cgit v1.1