diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/ubi/Kconfig | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/Makefile | 5 | ||||
-rw-r--r-- | drivers/mtd/ubi/attach.c (renamed from drivers/mtd/ubi/scan.c) | 970 | ||||
-rw-r--r-- | drivers/mtd/ubi/build.c | 85 | ||||
-rw-r--r-- | drivers/mtd/ubi/cdev.c | 36 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.c | 137 | ||||
-rw-r--r-- | drivers/mtd/ubi/debug.h | 98 | ||||
-rw-r--r-- | drivers/mtd/ubi/eba.c | 68 | ||||
-rw-r--r-- | drivers/mtd/ubi/gluebi.c | 2 | ||||
-rw-r--r-- | drivers/mtd/ubi/io.c | 211 | ||||
-rw-r--r-- | drivers/mtd/ubi/kapi.c | 61 | ||||
-rw-r--r-- | drivers/mtd/ubi/scan.h | 174 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi-media.h | 8 | ||||
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 179 | ||||
-rw-r--r-- | drivers/mtd/ubi/upd.c | 16 | ||||
-rw-r--r-- | drivers/mtd/ubi/vmt.c | 62 | ||||
-rw-r--r-- | drivers/mtd/ubi/vtbl.c | 228 | ||||
-rw-r--r-- | drivers/mtd/ubi/wl.c | 260 |
18 files changed, 1198 insertions, 1410 deletions
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 4dcc752a0c0b..738ee8dc16cd 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -52,12 +52,4 @@ config MTD_UBI_GLUEBI work on top of UBI. Do not enable this unless you use legacy software. -config MTD_UBI_DEBUG - bool "UBI debugging" - depends on SYSFS - select DEBUG_FS - select KALLSYMS - help - This option enables UBI debugging. - endif # MTD_UBI diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile index c9302a5452b0..a0803ac74712 100644 --- a/drivers/mtd/ubi/Makefile +++ b/drivers/mtd/ubi/Makefile @@ -1,7 +1,6 @@ obj-$(CONFIG_MTD_UBI) += ubi.o -ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o scan.o -ubi-y += misc.o +ubi-y += vtbl.o vmt.o upd.o build.o cdev.o kapi.o eba.o io.o wl.o attach.o +ubi-y += misc.o debug.o -ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/attach.c index 12c43b44f815..bd27cbbb4066 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/attach.c @@ -19,21 +19,21 @@ */ /* - * UBI scanning sub-system. + * UBI attaching sub-system. * - * This sub-system is responsible for scanning the flash media, checking UBI - * headers and providing complete information about the UBI flash image. + * This sub-system is responsible for attaching MTD devices and it also + * implements flash media scanning. * - * The scanning information is represented by a &struct ubi_scan_info' object. - * Information about found volumes is represented by &struct ubi_scan_volume + * The attaching information is represented by a &struct ubi_attach_info' + * object. Information about volumes is represented by &struct ubi_ainf_volume * objects which are kept in volume RB-tree with root at the @volumes field. * The RB-tree is indexed by the volume ID. * - * Scanned logical eraseblocks are represented by &struct ubi_scan_leb objects. - * These objects are kept in per-volume RB-trees with the root at the - * corresponding &struct ubi_scan_volume object. To put it differently, we keep - * an RB-tree of per-volume objects and each of these objects is the root of - * RB-tree of per-eraseblock objects. + * Logical eraseblocks are represented by &struct ubi_ainf_peb objects. These + * objects are kept in per-volume RB-trees with the root at the corresponding + * &struct ubi_ainf_volume object. To put it differently, we keep an RB-tree of + * per-volume objects and each of these objects is the root of RB-tree of + * per-LEB objects. * * Corrupted physical eraseblocks are put to the @corr list, free physical * eraseblocks are put to the @free list and the physical eraseblock to be @@ -51,28 +51,29 @@ * * 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). + * error messages. The idea is that we do not lose important data in these + * cases - we may lose only the data which were 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. + * attaching, 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 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 + * corruptions and UBI's strategy is as follows (in case of attaching by + * scanning). 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 (e.g., ECC errors in case of NAND) 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 are 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 @@ -88,11 +89,7 @@ #include <linux/random.h> #include "ubi.h" -#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 -#endif +static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai); /* Temporary variables used during scanning */ static struct ubi_ec_hdr *ech; @@ -100,13 +97,18 @@ static struct ubi_vid_hdr *vidh; /** * add_to_list - add physical eraseblock to a list. - * @si: scanning information + * @ai: attaching information * @pnum: physical eraseblock number to add + * @vol_id: the last used volume id for the PEB + * @lnum: the last used LEB number for the PEB * @ec: erase counter of the physical eraseblock * @to_head: if not zero, add to the head of the list * @list: the list to add to * - * This function adds physical eraseblock @pnum to free, erase, or alien lists. + * This function allocates a 'struct ubi_ainf_peb' object for physical + * eraseblock @pnum and adds it to the "free", "erase", or "alien" lists. + * It stores the @lnum and @vol_id alongside, which can both be + * %UBI_UNKNOWN if they are not available, not readable, or not assigned. * If @to_head is not zero, PEB will be added to the head of the list, which * basically means it will be processed first later. E.g., we add corrupted * PEBs (corrupted due to power cuts) to the head of the erase list to make @@ -114,65 +116,68 @@ static struct ubi_vid_hdr *vidh; * returns zero in case of success and a negative error code in case of * failure. */ -static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, int to_head, - struct list_head *list) +static int add_to_list(struct ubi_attach_info *ai, int pnum, int vol_id, + int lnum, int ec, int to_head, struct list_head *list) { - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; - if (list == &si->free) { + if (list == &ai->free) { dbg_bld("add to free: PEB %d, EC %d", pnum, ec); - } else if (list == &si->erase) { + } else if (list == &ai->erase) { dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); - } else if (list == &si->alien) { + } else if (list == &ai->alien) { dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); - si->alien_peb_count += 1; + ai->alien_peb_count += 1; } else BUG(); - seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); - if (!seb) + aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); + if (!aeb) return -ENOMEM; - seb->pnum = pnum; - seb->ec = ec; + aeb->pnum = pnum; + aeb->vol_id = vol_id; + aeb->lnum = lnum; + aeb->ec = ec; if (to_head) - list_add(&seb->u.list, list); + list_add(&aeb->u.list, list); else - list_add_tail(&seb->u.list, list); + list_add_tail(&aeb->u.list, list); return 0; } /** * add_corrupted - add a corrupted physical eraseblock. - * @si: scanning information + * @ai: attaching information * @pnum: physical eraseblock number to add * @ec: erase counter of the physical eraseblock * - * This function adds corrupted physical eraseblock @pnum to the 'corr' list. - * The corruption was presumably not caused by a power cut. Returns zero in - * case of success and a negative error code in case of failure. + * This function allocates a 'struct ubi_ainf_peb' object for a corrupted + * physical eraseblock @pnum and adds it to the 'corr' list. The corruption + * was presumably not caused by a power cut. Returns zero in case of success + * and a negative error code in case of failure. */ -static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) +static int add_corrupted(struct ubi_attach_info *ai, int pnum, int ec) { - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); - if (!seb) + aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); + if (!aeb) return -ENOMEM; - si->corr_peb_count += 1; - seb->pnum = pnum; - seb->ec = ec; - list_add(&seb->u.list, &si->corr); + ai->corr_peb_count += 1; + aeb->pnum = pnum; + aeb->ec = ec; + list_add(&aeb->u.list, &ai->corr); return 0; } /** * validate_vid_hdr - check volume identifier header. * @vid_hdr: the volume identifier header to check - * @sv: information about the volume this logical eraseblock belongs to + * @av: information about the volume this logical eraseblock belongs to * @pnum: physical eraseblock number the VID header came from * * This function checks that data stored in @vid_hdr is consistent. Returns @@ -184,15 +189,15 @@ static int add_corrupted(struct ubi_scan_info *si, int pnum, int ec) * headers of the same volume. */ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, - const struct ubi_scan_volume *sv, int pnum) + const struct ubi_ainf_volume *av, int pnum) { int vol_type = vid_hdr->vol_type; int vol_id = be32_to_cpu(vid_hdr->vol_id); int used_ebs = be32_to_cpu(vid_hdr->used_ebs); int data_pad = be32_to_cpu(vid_hdr->data_pad); - if (sv->leb_count != 0) { - int sv_vol_type; + if (av->leb_count != 0) { + int av_vol_type; /* * This is not the first logical eraseblock belonging to this @@ -200,28 +205,28 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, * to the data in previous logical eraseblock headers. */ - if (vol_id != sv->vol_id) { - dbg_err("inconsistent vol_id"); + if (vol_id != av->vol_id) { + ubi_err("inconsistent vol_id"); goto bad; } - if (sv->vol_type == UBI_STATIC_VOLUME) - sv_vol_type = UBI_VID_STATIC; + if (av->vol_type == UBI_STATIC_VOLUME) + av_vol_type = UBI_VID_STATIC; else - sv_vol_type = UBI_VID_DYNAMIC; + av_vol_type = UBI_VID_DYNAMIC; - if (vol_type != sv_vol_type) { - dbg_err("inconsistent vol_type"); + if (vol_type != av_vol_type) { + ubi_err("inconsistent vol_type"); goto bad; } - if (used_ebs != sv->used_ebs) { - dbg_err("inconsistent used_ebs"); + if (used_ebs != av->used_ebs) { + ubi_err("inconsistent used_ebs"); goto bad; } - if (data_pad != sv->data_pad) { - dbg_err("inconsistent data_pad"); + if (data_pad != av->data_pad) { + ubi_err("inconsistent data_pad"); goto bad; } } @@ -230,74 +235,74 @@ static int validate_vid_hdr(const struct ubi_vid_hdr *vid_hdr, bad: ubi_err("inconsistent VID header at PEB %d", pnum); - ubi_dbg_dump_vid_hdr(vid_hdr); - ubi_dbg_dump_sv(sv); + ubi_dump_vid_hdr(vid_hdr); + ubi_dump_av(av); return -EINVAL; } /** - * add_volume - add volume to the scanning information. - * @si: scanning information + * add_volume - add volume to the attaching information. + * @ai: attaching information * @vol_id: ID of the volume to add * @pnum: physical eraseblock number * @vid_hdr: volume identifier header * * If the volume corresponding to the @vid_hdr logical eraseblock is already - * present in the scanning information, this function does nothing. Otherwise - * it adds corresponding volume to the scanning information. Returns a pointer - * to the scanning volume object in case of success and a negative error code - * in case of failure. + * present in the attaching information, this function does nothing. Otherwise + * it adds corresponding volume to the attaching information. Returns a pointer + * to the allocated "av" object in case of success and a negative error code in + * case of failure. */ -static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, - int pnum, +static struct ubi_ainf_volume *add_volume(struct ubi_attach_info *ai, + int vol_id, int pnum, const struct ubi_vid_hdr *vid_hdr) { - struct ubi_scan_volume *sv; - struct rb_node **p = &si->volumes.rb_node, *parent = NULL; + struct ubi_ainf_volume *av; + struct rb_node **p = &ai->volumes.rb_node, *parent = NULL; ubi_assert(vol_id == be32_to_cpu(vid_hdr->vol_id)); /* Walk the volume RB-tree to look if this volume is already present */ while (*p) { parent = *p; - sv = rb_entry(parent, struct ubi_scan_volume, rb); + av = rb_entry(parent, struct ubi_ainf_volume, rb); - if (vol_id == sv->vol_id) - return sv; + if (vol_id == av->vol_id) + return av; - if (vol_id > sv->vol_id) + if (vol_id > av->vol_id) p = &(*p)->rb_left; else p = &(*p)->rb_right; } /* The volume is absent - add it */ - sv = kmalloc(sizeof(struct ubi_scan_volume), GFP_KERNEL); - if (!sv) + av = kmalloc(sizeof(struct ubi_ainf_volume), GFP_KERNEL); + if (!av) return ERR_PTR(-ENOMEM); - sv->highest_lnum = sv->leb_count = 0; - sv->vol_id = vol_id; - sv->root = RB_ROOT; - sv->used_ebs = be32_to_cpu(vid_hdr->used_ebs); - sv->data_pad = be32_to_cpu(vid_hdr->data_pad); - sv->compat = vid_hdr->compat; - sv->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME + av->highest_lnum = av->leb_count = 0; + av->vol_id = vol_id; + av->root = RB_ROOT; + av->used_ebs = be32_to_cpu(vid_hdr->used_ebs); + av->data_pad = be32_to_cpu(vid_hdr->data_pad); + av->compat = vid_hdr->compat; + av->vol_type = vid_hdr->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; - if (vol_id > si->highest_vol_id) - si->highest_vol_id = vol_id; + if (vol_id > ai->highest_vol_id) + ai->highest_vol_id = vol_id; - rb_link_node(&sv->rb, parent, p); - rb_insert_color(&sv->rb, &si->volumes); - si->vols_found += 1; + rb_link_node(&av->rb, parent, p); + rb_insert_color(&av->rb, &ai->volumes); + ai->vols_found += 1; dbg_bld("added volume %d", vol_id); - return sv; + return av; } /** * compare_lebs - find out which logical eraseblock is newer. * @ubi: UBI device description object - * @seb: first logical eraseblock to compare + * @aeb: first logical eraseblock to compare * @pnum: physical eraseblock number of the second logical eraseblock to * compare * @vid_hdr: volume identifier header of the second logical eraseblock @@ -306,7 +311,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, * case of success this function returns a positive value, in case of failure, a * negative error code is returned. The success return codes use the following * bits: - * o bit 0 is cleared: the first PEB (described by @seb) is newer than the + * o bit 0 is cleared: the first PEB (described by @aeb) is newer than the * second PEB (described by @pnum and @vid_hdr); * o bit 0 is set: the second PEB is newer; * o bit 1 is cleared: no bit-flips were detected in the newer LEB; @@ -314,7 +319,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, * o bit 2 is cleared: the older LEB is not corrupted; * o bit 2 is set: the older LEB is corrupted. */ -static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, +static int compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, int pnum, const struct ubi_vid_hdr *vid_hdr) { void *buf; @@ -323,7 +328,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, struct ubi_vid_hdr *vh = NULL; unsigned long long sqnum2 = be64_to_cpu(vid_hdr->sqnum); - if (sqnum2 == seb->sqnum) { + if (sqnum2 == aeb->sqnum) { /* * This must be a really ancient UBI image which has been * created before sequence numbers support has been added. At @@ -337,7 +342,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, } /* Obviously the LEB with lower sequence counter is older */ - second_is_newer = !!(sqnum2 > seb->sqnum); + second_is_newer = (sqnum2 > aeb->sqnum); /* * Now we know which copy is newer. If the copy flag of the PEB with @@ -356,7 +361,7 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, return 1; } } else { - if (!seb->copy_flag) { + if (!aeb->copy_flag) { /* It is not a copy, so it is newer */ dbg_bld("first PEB %d is newer, copy_flag is unset", pnum); @@ -367,13 +372,13 @@ static int compare_lebs(struct ubi_device *ubi, const struct ubi_scan_leb *seb, if (!vh) return -ENOMEM; - pnum = seb->pnum; + pnum = aeb->pnum; err = ubi_io_read_vid_hdr(ubi, pnum, vh, 0); if (err) { if (err == UBI_IO_BITFLIPS) bitflips = 1; else { - dbg_err("VID of PEB %d header is bad, but it " + ubi_err("VID of PEB %d header is bad, but it " "was OK earlier, err %d", pnum, err); if (err > 0) err = -EIO; @@ -429,9 +434,9 @@ out_free_vidh: } /** - * ubi_scan_add_used - add physical eraseblock to the scanning information. + * ubi_add_to_av - add used physical eraseblock to the attaching information. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * @pnum: the physical eraseblock number * @ec: erase counter * @vid_hdr: the volume identifier header @@ -444,14 +449,13 @@ out_free_vidh: * to be picked, while the older one has to be dropped. This function returns * zero in case of success and a negative error code in case of failure. */ -int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, - int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, - int bitflips) +int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, + int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips) { int err, vol_id, lnum; unsigned long long sqnum; - struct ubi_scan_volume *sv; - struct ubi_scan_leb *seb; + struct ubi_ainf_volume *av; + struct ubi_ainf_peb *aeb; struct rb_node **p, *parent = NULL; vol_id = be32_to_cpu(vid_hdr->vol_id); @@ -461,25 +465,25 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, dbg_bld("PEB %d, LEB %d:%d, EC %d, sqnum %llu, bitflips %d", pnum, vol_id, lnum, ec, sqnum, bitflips); - sv = add_volume(si, vol_id, pnum, vid_hdr); - if (IS_ERR(sv)) - return PTR_ERR(sv); + av = add_volume(ai, vol_id, pnum, vid_hdr); + if (IS_ERR(av)) + return PTR_ERR(av); - if (si->max_sqnum < sqnum) - si->max_sqnum = sqnum; + if (ai->max_sqnum < sqnum) + ai->max_sqnum = sqnum; /* * Walk the RB-tree of logical eraseblocks of volume @vol_id to look * if this is the first instance of this logical eraseblock or not. */ - p = &sv->root.rb_node; + p = &av->root.rb_node; while (*p) { int cmp_res; parent = *p; - seb = rb_entry(parent, struct ubi_scan_leb, u.rb); - if (lnum != seb->lnum) { - if (lnum < seb->lnum) + aeb = rb_entry(parent, struct ubi_ainf_peb, u.rb); + if (lnum != aeb->lnum) { + if (lnum < aeb->lnum) p = &(*p)->rb_left; else p = &(*p)->rb_right; @@ -491,8 +495,8 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * logical eraseblock present. */ - dbg_bld("this LEB already exists: PEB %d, sqnum %llu, " - "EC %d", seb->pnum, seb->sqnum, seb->ec); + dbg_bld("this LEB already exists: PEB %d, sqnum %llu, EC %d", + aeb->pnum, aeb->sqnum, aeb->ec); /* * Make sure that the logical eraseblocks have different @@ -507,11 +511,11 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * images, but refuse attaching old images with duplicated * logical eraseblocks because there was an unclean reboot. */ - if (seb->sqnum == sqnum && sqnum != 0) { + if (aeb->sqnum == sqnum && sqnum != 0) { ubi_err("two LEBs with same sequence number %llu", sqnum); - ubi_dbg_dump_seb(seb, 0); - ubi_dbg_dump_vid_hdr(vid_hdr); + ubi_dump_aeb(aeb, 0); + ubi_dump_vid_hdr(vid_hdr); return -EINVAL; } @@ -519,7 +523,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * Now we have to drop the older one and preserve the newer * one. */ - cmp_res = compare_lebs(ubi, seb, pnum, vid_hdr); + cmp_res = compare_lebs(ubi, aeb, pnum, vid_hdr); if (cmp_res < 0) return cmp_res; @@ -528,23 +532,26 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * This logical eraseblock is newer than the one * found earlier. */ - err = validate_vid_hdr(vid_hdr, sv, pnum); + err = validate_vid_hdr(vid_hdr, av, pnum); if (err) return err; - err = add_to_list(si, seb->pnum, seb->ec, cmp_res & 4, - &si->erase); + err = add_to_list(ai, aeb->pnum, aeb->vol_id, + aeb->lnum, aeb->ec, cmp_res & 4, + &ai->erase); if (err) return err; - seb->ec = ec; - seb->pnum = pnum; - seb->scrub = ((cmp_res & 2) || bitflips); - seb->copy_flag = vid_hdr->copy_flag; - seb->sqnum = sqnum; + aeb->ec = ec; + aeb->pnum = pnum; + aeb->vol_id = vol_id; + aeb->lnum = lnum; + aeb->scrub = ((cmp_res & 2) || bitflips); + aeb->copy_flag = vid_hdr->copy_flag; + aeb->sqnum = sqnum; - if (sv->highest_lnum == lnum) - sv->last_data_size = + if (av->highest_lnum == lnum) + av->last_data_size = be32_to_cpu(vid_hdr->data_size); return 0; @@ -553,92 +560,64 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, * This logical eraseblock is older than the one found * previously. */ - return add_to_list(si, pnum, ec, cmp_res & 4, - &si->erase); + return add_to_list(ai, pnum, vol_id, lnum, ec, + cmp_res & 4, &ai->erase); } } /* * We've met this logical eraseblock for the first time, add it to the - * scanning information. + * attaching information. */ - err = validate_vid_hdr(vid_hdr, sv, pnum); + err = validate_vid_hdr(vid_hdr, av, pnum); if (err) return err; - seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL); - if (!seb) + aeb = kmem_cache_alloc(ai->aeb_slab_cache, GFP_KERNEL); + if (!aeb) return -ENOMEM; - seb->ec = ec; - seb->pnum = pnum; - seb->lnum = lnum; - seb->scrub = bitflips; - seb->copy_flag = vid_hdr->copy_flag; - seb->sqnum = sqnum; - - if (sv->highest_lnum <= lnum) { - sv->highest_lnum = lnum; - sv->last_data_size = be32_to_cpu(vid_hdr->data_size); + aeb->ec = ec; + aeb->pnum = pnum; + aeb->vol_id = vol_id; + aeb->lnum = lnum; + aeb->scrub = bitflips; + aeb->copy_flag = vid_hdr->copy_flag; + aeb->sqnum = sqnum; + + if (av->highest_lnum <= lnum) { + av->highest_lnum = lnum; + av->last_data_size = be32_to_cpu(vid_hdr->data_size); } - sv->leb_count += 1; - rb_link_node(&seb->u.rb, parent, p); - rb_insert_color(&seb->u.rb, &sv->root); + av->leb_count += 1; + rb_link_node(&aeb->u.rb, parent, p); + rb_insert_color(&aeb->u.rb, &av->root); return 0; } /** - * ubi_scan_find_sv - find volume in the scanning information. - * @si: scanning information + * ubi_find_av - find volume in the attaching information. + * @ai: attaching information * @vol_id: the requested volume ID * * This function returns a pointer to the volume description or %NULL if there - * are no data about this volume in the scanning information. - */ -struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, - int vol_id) -{ - struct ubi_scan_volume *sv; - struct rb_node *p = si->volumes.rb_node; - - while (p) { - sv = rb_entry(p, struct ubi_scan_volume, rb); - - if (vol_id == sv->vol_id) - return sv; - - if (vol_id > sv->vol_id) - p = p->rb_left; - else - p = p->rb_right; - } - - return NULL; -} - -/** - * ubi_scan_find_seb - find LEB in the volume scanning information. - * @sv: a pointer to the volume scanning information - * @lnum: the requested logical eraseblock - * - * This function returns a pointer to the scanning logical eraseblock or %NULL - * if there are no data about it in the scanning volume information. + * are no data about this volume in the attaching information. */ -struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv, - int lnum) +struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, + int vol_id) { - struct ubi_scan_leb *seb; - struct rb_node *p = sv->root.rb_node; + struct ubi_ainf_volume *av; + struct rb_node *p = ai->volumes.rb_node; while (p) { - seb = rb_entry(p, struct ubi_scan_leb, u.rb); + av = rb_entry(p, struct ubi_ainf_volume, rb); - if (lnum == seb->lnum) - return seb; + if (vol_id == av->vol_id) + return av; - if (lnum > seb->lnum) + if (vol_id > av->vol_id) p = p->rb_left; else p = p->rb_right; @@ -648,34 +627,34 @@ struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv, } /** - * ubi_scan_rm_volume - delete scanning information about a volume. - * @si: scanning information - * @sv: the volume scanning information to delete + * ubi_remove_av - delete attaching information about a volume. + * @ai: attaching information + * @av: the volume attaching information to delete */ -void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv) +void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) { struct rb_node *rb; - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; - dbg_bld("remove scanning information about volume %d", sv->vol_id); + dbg_bld("remove attaching information about volume %d", av->vol_id); - while ((rb = rb_first(&sv->root))) { - seb = rb_entry(rb, struct ubi_scan_leb, u.rb); - rb_erase(&seb->u.rb, &sv->root); - list_add_tail(&seb->u.list, &si->erase); + while ((rb = rb_first(&av->root))) { + aeb = rb_entry(rb, struct ubi_ainf_peb, u.rb); + rb_erase(&aeb->u.rb, &av->root); + list_add_tail(&aeb->u.list, &ai->erase); } - rb_erase(&sv->rb, &si->volumes); - kfree(sv); - si->vols_found -= 1; + rb_erase(&av->rb, &ai->volumes); + kfree(av); + ai->vols_found -= 1; } /** - * ubi_scan_erase_peb - erase a physical eraseblock. + * early_erase_peb - erase a physical eraseblock. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * @pnum: physical eraseblock number to erase; - * @ec: erase counter value to write (%UBI_SCAN_UNKNOWN_EC if it is unknown) + * @ec: erase counter value to write (%UBI_UNKNOWN if it is unknown) * * This function erases physical eraseblock 'pnum', and writes the erase * counter header to it. This function should only be used on UBI device @@ -683,8 +662,8 @@ void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv) * This function returns zero in case of success and a negative error code in * case of failure. */ -int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, - int pnum, int ec) +static int early_erase_peb(struct ubi_device *ubi, + const struct ubi_attach_info *ai, int pnum, int ec) { int err; struct ubi_ec_hdr *ec_hdr; @@ -716,9 +695,9 @@ out_free: } /** - * ubi_scan_get_free_peb - get a free physical eraseblock. + * ubi_early_get_peb - get a free physical eraseblock. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * This function returns a free physical eraseblock. It is supposed to be * called on the UBI initialization stages when the wear-leveling sub-system is @@ -726,20 +705,20 @@ out_free: * the lists, writes the EC header if it is needed, and removes it from the * list. * - * This function returns scanning physical eraseblock information in case of - * success and an error code in case of failure. + * This function returns a pointer to the "aeb" of the found free PEB in case + * of success and an error code in case of failure. */ -struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, - struct ubi_scan_info *si) +struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, + struct ubi_attach_info *ai) { int err = 0; - struct ubi_scan_leb *seb, *tmp_seb; + struct ubi_ainf_peb *aeb, *tmp_aeb; - if (!list_empty(&si->free)) { - seb = list_entry(si->free.next, struct ubi_scan_leb, u.list); - list_del(&seb->u.list); - dbg_bld("return free PEB %d, EC %d", seb->pnum, seb->ec); - return seb; + if (!list_empty(&ai->free)) { + aeb = list_entry(ai->free.next, struct ubi_ainf_peb, u.list); + list_del(&aeb->u.list); + dbg_bld("return free PEB %d, EC %d", aeb->pnum, aeb->ec); + return aeb; } /* @@ -748,18 +727,18 @@ struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, * so forth. We don't want to take care about bad eraseblocks here - * they'll be handled later. */ - list_for_each_entry_safe(seb, tmp_seb, &si->erase, u.list) { - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + list_for_each_entry_safe(aeb, tmp_aeb, &ai->erase, u.list) { + if (aeb->ec == UBI_UNKNOWN) + aeb->ec = ai->mean_ec; - err = ubi_scan_erase_peb(ubi, si, seb->pnum, seb->ec+1); + err = early_erase_peb(ubi, ai, aeb->pnum, aeb->ec+1); if (err) continue; - seb->ec += 1; - list_del(&seb->u.list); - dbg_bld("return PEB %d, EC %d", seb->pnum, seb->ec); - return seb; + aeb->ec += 1; + list_del(&aeb->u.list); + dbg_bld("return PEB %d, EC %d", aeb->pnum, aeb->ec); + return aeb; } ubi_err("no free eraseblocks"); @@ -814,7 +793,7 @@ static int check_corruption(struct ubi_device *ubi, struct ubi_vid_hdr *vid_hdr, ubi_err("PEB %d contains corrupted VID header, and the data does not " "contain all 0xFF, this may be a non-UBI PEB or a severe VID " "header corruption which requires manual inspection", pnum); - ubi_dbg_dump_vid_hdr(vid_hdr); + ubi_dump_vid_hdr(vid_hdr); dbg_msg("hexdump of PEB %d offset %d, length %d", pnum, ubi->leb_start, ubi->leb_size); ubi_dbg_print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, @@ -827,16 +806,18 @@ out_unlock: } /** - * process_eb - read, check UBI headers, and add them to scanning information. + * scan_peb - scan and process UBI headers of a PEB. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * @pnum: the physical eraseblock number * - * This function returns a zero if the physical eraseblock was successfully - * handled and a negative error code in case of failure. + * This function reads UBI headers of PEB @pnum, checks them, and adds + * information about this PEB to the corresponding list or RB-tree in the + * "attaching info" structure. Returns zero if the physical eraseblock was + * successfully handled and a negative error code in case of failure. */ -static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, - int pnum) +static int scan_peb(struct ubi_device *ubi, struct ubi_attach_info *ai, + int pnum) { long long uninitialized_var(ec); int err, bitflips = 0, vol_id, ec_err = 0; @@ -848,12 +829,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, if (err < 0) return err; else if (err) { - /* - * FIXME: this is actually duty of the I/O sub-system to - * initialize this, but MTD does not provide enough - * information. - */ - si->bad_peb_count += 1; + ai->bad_peb_count += 1; return 0; } @@ -867,13 +843,13 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; break; case UBI_IO_FF: - si->empty_peb_count += 1; - return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 0, - &si->erase); + ai->empty_peb_count += 1; + return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, + UBI_UNKNOWN, 0, &ai->erase); case UBI_IO_FF_BITFLIPS: - si->empty_peb_count += 1; - return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, 1, - &si->erase); + ai->empty_peb_count += 1; + return add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, + UBI_UNKNOWN, 1, &ai->erase); case UBI_IO_BAD_HDR_EBADMSG: case UBI_IO_BAD_HDR: /* @@ -882,7 +858,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, * moved and EC be re-created. */ ec_err = err; - ec = UBI_SCAN_UNKNOWN_EC; + ec = UBI_UNKNOWN; bitflips = 1; break; default: @@ -911,7 +887,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, */ ubi_err("erase counter overflow, max is %d", UBI_MAX_ERASECOUNTER); - ubi_dbg_dump_ec_hdr(ech); + ubi_dump_ec_hdr(ech); return -EINVAL; } @@ -933,7 +909,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, ubi->image_seq != image_seq) { ubi_err("bad image sequence number %d in PEB %d, " "expected %d", image_seq, pnum, ubi->image_seq); - ubi_dbg_dump_ec_hdr(ech); + ubi_dump_ec_hdr(ech); return -EINVAL; } } @@ -957,7 +933,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, * PEB, bit it is not marked as bad yet. This may also * be a result of power cut during erasure. */ - si->maybe_bad_peb_count += 1; + ai->maybe_bad_peb_count += 1; case UBI_IO_BAD_HDR: if (ec_err) /* @@ -984,23 +960,27 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; else if (!err) /* This corruption is caused by a power cut */ - err = add_to_list(si, pnum, ec, 1, &si->erase); + err = add_to_list(ai, pnum, UBI_UNKNOWN, + UBI_UNKNOWN, ec, 1, &ai->erase); else /* This is an unexpected corruption */ - err = add_corrupted(si, pnum, ec); + err = add_corrupted(ai, pnum, ec); if (err) return err; goto adjust_mean_ec; case UBI_IO_FF_BITFLIPS: - err = add_to_list(si, pnum, ec, 1, &si->erase); + err = add_to_list(ai, pnum, UBI_UNKNOWN, UBI_UNKNOWN, + ec, 1, &ai->erase); if (err) return err; goto adjust_mean_ec; case UBI_IO_FF: if (ec_err) - err = add_to_list(si, pnum, ec, 1, &si->erase); + err = add_to_list(ai, pnum, UBI_UNKNOWN, + UBI_UNKNOWN, ec, 1, &ai->erase); else - err = add_to_list(si, pnum, ec, 0, &si->free); + err = add_to_list(ai, pnum, UBI_UNKNOWN, + UBI_UNKNOWN, ec, 0, &ai->free); if (err) return err; goto adjust_mean_ec; @@ -1019,7 +999,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_DELETE: ubi_msg("\"delete\" compatible internal volume %d:%d" " found, will remove it", vol_id, lnum); - err = add_to_list(si, pnum, ec, 1, &si->erase); + err = add_to_list(ai, pnum, vol_id, lnum, + ec, 1, &ai->erase); if (err) return err; return 0; @@ -1034,7 +1015,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, case UBI_COMPAT_PRESERVE: ubi_msg("\"preserve\" compatible internal volume %d:%d" " found", vol_id, lnum); - err = add_to_list(si, pnum, ec, 0, &si->alien); + err = add_to_list(ai, pnum, vol_id, lnum, + ec, 0, &ai->alien); if (err) return err; return 0; @@ -1049,40 +1031,40 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, if (ec_err) ubi_warn("valid VID header but corrupted EC header at PEB %d", pnum); - err = ubi_scan_add_used(ubi, si, pnum, ec, vidh, bitflips); + err = ubi_add_to_av(ubi, ai, pnum, ec, vidh, bitflips); if (err) return err; adjust_mean_ec: if (!ec_err) { - si->ec_sum += ec; - si->ec_count += 1; - if (ec > si->max_ec) - si->max_ec = ec; - if (ec < si->min_ec) - si->min_ec = ec; + ai->ec_sum += ec; + ai->ec_count += 1; + if (ec > ai->max_ec) + ai->max_ec = ec; + if (ec < ai->min_ec) + ai->min_ec = ec; } return 0; } /** - * check_what_we_have - check what PEB were found by scanning. + * late_analysis - analyze the overall situation with PEB. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * - * This is a helper function which takes a look what PEBs were found by - * scanning, and decides whether the flash is empty and should be formatted and - * whether there are too many corrupted PEBs and we should not attach this - * MTD device. Returns zero if we should proceed with attaching the MTD device, - * and %-EINVAL if we should not. + * This is a helper function which takes a look what PEBs we have after we + * gather information about all of them ("ai" is compete). It decides whether + * the flash is empty and should be formatted of whether there are too many + * corrupted PEBs and we should not attach this MTD device. Returns zero if we + * should proceed with attaching the MTD device, and %-EINVAL if we should not. */ -static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) +static int late_analysis(struct ubi_device *ubi, struct ubi_attach_info *ai) { - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; int max_corr, peb_count; - peb_count = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; + peb_count = ubi->peb_count - ai->bad_peb_count - ai->alien_peb_count; max_corr = peb_count / 20 ?: 8; /* @@ -1090,25 +1072,25 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) * unclean reboots. However, many of them may indicate some problems * with the flash HW or driver. */ - if (si->corr_peb_count) { + if (ai->corr_peb_count) { ubi_err("%d PEBs are corrupted and preserved", - si->corr_peb_count); + ai->corr_peb_count); printk(KERN_ERR "Corrupted PEBs are:"); - list_for_each_entry(seb, &si->corr, u.list) - printk(KERN_CONT " %d", seb->pnum); + list_for_each_entry(aeb, &ai->corr, u.list) + printk(KERN_CONT " %d", aeb->pnum); printk(KERN_CONT "\n"); /* * If too many PEBs are corrupted, we refuse attaching, * otherwise, only print a warning. */ - if (si->corr_peb_count >= max_corr) { + if (ai->corr_peb_count >= max_corr) { ubi_err("too many corrupted PEBs, refusing"); return -EINVAL; } } - if (si->empty_peb_count + si->maybe_bad_peb_count == peb_count) { + if (ai->empty_peb_count + ai->maybe_bad_peb_count == peb_count) { /* * All PEBs are empty, or almost all - a couple PEBs look like * they may be bad PEBs which were not marked as bad yet. @@ -1124,8 +1106,8 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) * 2. Flash contains non-UBI data and we do not want to format * it and destroy possibly important information. */ - if (si->maybe_bad_peb_count <= 2) { - si->is_empty = 1; + if (ai->maybe_bad_peb_count <= 2) { + ai->is_empty = 1; ubi_msg("empty MTD device detected"); get_random_bytes(&ubi->image_seq, sizeof(ubi->image_seq)); @@ -1141,40 +1123,41 @@ static int check_what_we_have(struct ubi_device *ubi, struct ubi_scan_info *si) } /** - * ubi_scan - scan an MTD device. + * scan_all - scan entire MTD device. * @ubi: UBI device description object * * This function does full scanning of an MTD device and returns complete - * information about it. In case of failure, an error code is returned. + * information about it in form of a "struct ubi_attach_info" object. In case + * of failure, an error code is returned. */ -struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) +static struct ubi_attach_info *scan_all(struct ubi_device *ubi) { int err, pnum; struct rb_node *rb1, *rb2; - struct ubi_scan_volume *sv; - struct ubi_scan_leb *seb; - struct ubi_scan_info *si; + struct ubi_ainf_volume *av; + struct ubi_ainf_peb *aeb; + struct ubi_attach_info *ai; - si = kzalloc(sizeof(struct ubi_scan_info), GFP_KERNEL); - if (!si) + ai = kzalloc(sizeof(struct ubi_attach_info), GFP_KERNEL); + if (!ai) return ERR_PTR(-ENOMEM); - INIT_LIST_HEAD(&si->corr); - INIT_LIST_HEAD(&si->free); - INIT_LIST_HEAD(&si->erase); - INIT_LIST_HEAD(&si->alien); - si->volumes = RB_ROOT; + INIT_LIST_HEAD(&ai->corr); + INIT_LIST_HEAD(&ai->free); + INIT_LIST_HEAD(&ai->erase); + INIT_LIST_HEAD(&ai->alien); + ai->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; + ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache", + sizeof(struct ubi_ainf_peb), + 0, 0, NULL); + if (!ai->aeb_slab_cache) + goto out_ai; ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); if (!ech) - goto out_si; + goto out_ai; vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL); if (!vidh) @@ -1184,7 +1167,7 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) cond_resched(); dbg_gen("process PEB %d", pnum); - err = process_eb(ubi, si, pnum); + err = scan_peb(ubi, ai, pnum); if (err < 0) goto out_vidh; } @@ -1192,10 +1175,10 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) dbg_msg("scanning is finished"); /* Calculate mean erase counter */ - if (si->ec_count) - si->mean_ec = div_u64(si->ec_sum, si->ec_count); + if (ai->ec_count) + ai->mean_ec = div_u64(ai->ec_sum, ai->ec_count); - err = check_what_we_have(ubi, si); + err = late_analysis(ubi, ai); if (err) goto out_vidh; @@ -1203,55 +1186,102 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) * In case of unknown erase counter we use the mean erase counter * value. */ - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { - ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) + if (aeb->ec == UBI_UNKNOWN) + aeb->ec = ai->mean_ec; } - list_for_each_entry(seb, &si->free, u.list) { - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + list_for_each_entry(aeb, &ai->free, u.list) { + if (aeb->ec == UBI_UNKNOWN) + aeb->ec = ai->mean_ec; } - list_for_each_entry(seb, &si->corr, u.list) - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + list_for_each_entry(aeb, &ai->corr, u.list) + if (aeb->ec == UBI_UNKNOWN) + aeb->ec = ai->mean_ec; - list_for_each_entry(seb, &si->erase, u.list) - if (seb->ec == UBI_SCAN_UNKNOWN_EC) - seb->ec = si->mean_ec; + list_for_each_entry(aeb, &ai->erase, u.list) + if (aeb->ec == UBI_UNKNOWN) + aeb->ec = ai->mean_ec; - err = paranoid_check_si(ubi, si); + err = self_check_ai(ubi, ai); if (err) goto out_vidh; ubi_free_vid_hdr(ubi, vidh); kfree(ech); - return si; + return ai; out_vidh: ubi_free_vid_hdr(ubi, vidh); out_ech: kfree(ech); -out_si: - ubi_scan_destroy_si(si); +out_ai: + ubi_destroy_ai(ai); return ERR_PTR(err); } /** - * destroy_sv - free the scanning volume information - * @sv: scanning volume information - * @si: scanning information + * ubi_attach - attach an MTD device. + * @ubi: UBI device descriptor * - * This function destroys the volume RB-tree (@sv->root) and the scanning - * volume information. + * This function returns zero in case of success and a negative error code in + * case of failure. */ -static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv) +int ubi_attach(struct ubi_device *ubi) { - struct ubi_scan_leb *seb; - struct rb_node *this = sv->root.rb_node; + int err; + struct ubi_attach_info *ai; + + ai = scan_all(ubi); + if (IS_ERR(ai)) + return PTR_ERR(ai); + + ubi->bad_peb_count = ai->bad_peb_count; + ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; + ubi->corr_peb_count = ai->corr_peb_count; + ubi->max_ec = ai->max_ec; + ubi->mean_ec = ai->mean_ec; + ubi_msg("max. sequence number: %llu", ai->max_sqnum); + + err = ubi_read_volume_table(ubi, ai); + if (err) + goto out_ai; + + err = ubi_wl_init(ubi, ai); + if (err) + goto out_vtbl; + + err = ubi_eba_init(ubi, ai); + if (err) + goto out_wl; + + ubi_destroy_ai(ai); + return 0; + +out_wl: + ubi_wl_close(ubi); +out_vtbl: + ubi_free_internal_volumes(ubi); + vfree(ubi->vtbl); +out_ai: + ubi_destroy_ai(ai); + return err; +} + +/** + * destroy_av - free volume attaching information. + * @av: volume attaching information + * @ai: attaching information + * + * This function destroys the volume attaching information. + */ +static void destroy_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av) +{ + struct ubi_ainf_peb *aeb; + struct rb_node *this = av->root.rb_node; while (this) { if (this->rb_left) @@ -1259,224 +1289,222 @@ static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv) else if (this->rb_right) this = this->rb_right; else { - seb = rb_entry(this, struct ubi_scan_leb, u.rb); + aeb = rb_entry(this, struct ubi_ainf_peb, u.rb); this = rb_parent(this); if (this) { - if (this->rb_left == &seb->u.rb) + if (this->rb_left == &aeb->u.rb) this->rb_left = NULL; else this->rb_right = NULL; } - kmem_cache_free(si->scan_leb_slab, seb); + kmem_cache_free(ai->aeb_slab_cache, aeb); } } - kfree(sv); + kfree(av); } /** - * ubi_scan_destroy_si - destroy scanning information. - * @si: scanning information + * ubi_destroy_ai - destroy attaching information. + * @ai: attaching information */ -void ubi_scan_destroy_si(struct ubi_scan_info *si) +void ubi_destroy_ai(struct ubi_attach_info *ai) { - struct ubi_scan_leb *seb, *seb_tmp; - struct ubi_scan_volume *sv; + struct ubi_ainf_peb *aeb, *aeb_tmp; + struct ubi_ainf_volume *av; struct rb_node *rb; - list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) { - list_del(&seb->u.list); - kmem_cache_free(si->scan_leb_slab, seb); + list_for_each_entry_safe(aeb, aeb_tmp, &ai->alien, u.list) { + list_del(&aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, aeb); } - list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) { - list_del(&seb->u.list); - kmem_cache_free(si->scan_leb_slab, seb); + list_for_each_entry_safe(aeb, aeb_tmp, &ai->erase, u.list) { + list_del(&aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, aeb); } - list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) { - list_del(&seb->u.list); - kmem_cache_free(si->scan_leb_slab, seb); + list_for_each_entry_safe(aeb, aeb_tmp, &ai->corr, u.list) { + list_del(&aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, aeb); } - list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) { - list_del(&seb->u.list); - kmem_cache_free(si->scan_leb_slab, seb); + list_for_each_entry_safe(aeb, aeb_tmp, &ai->free, u.list) { + list_del(&aeb->u.list); + kmem_cache_free(ai->aeb_slab_cache, aeb); } /* Destroy the volume RB-tree */ - rb = si->volumes.rb_node; + rb = ai->volumes.rb_node; while (rb) { if (rb->rb_left) rb = rb->rb_left; else if (rb->rb_right) rb = rb->rb_right; else { - sv = rb_entry(rb, struct ubi_scan_volume, rb); + av = rb_entry(rb, struct ubi_ainf_volume, rb); rb = rb_parent(rb); if (rb) { - if (rb->rb_left == &sv->rb) + if (rb->rb_left == &av->rb) rb->rb_left = NULL; else rb->rb_right = NULL; } - destroy_sv(si, sv); + destroy_av(ai, av); } } - if (si->scan_leb_slab) - kmem_cache_destroy(si->scan_leb_slab); + if (ai->aeb_slab_cache) + kmem_cache_destroy(ai->aeb_slab_cache); - kfree(si); + kfree(ai); } -#ifdef CONFIG_MTD_UBI_DEBUG - /** - * paranoid_check_si - check the scanning information. + * self_check_ai - check the attaching information. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * - * This function returns zero if the scanning information is all right, and a + * This function returns zero if the attaching information is all right, and a * negative error code if not or if an error occurred. */ -static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) +static int self_check_ai(struct ubi_device *ubi, struct ubi_attach_info *ai) { int pnum, err, vols_found = 0; struct rb_node *rb1, *rb2; - struct ubi_scan_volume *sv; - struct ubi_scan_leb *seb, *last_seb; + struct ubi_ainf_volume *av; + struct ubi_ainf_peb *aeb, *last_aeb; uint8_t *buf; if (!ubi->dbg->chk_gen) return 0; /* - * At first, check that scanning information is OK. + * At first, check that attaching information is OK. */ - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { int leb_count = 0; cond_resched(); vols_found += 1; - if (si->is_empty) { + if (ai->is_empty) { ubi_err("bad is_empty flag"); - goto bad_sv; + goto bad_av; } - if (sv->vol_id < 0 || sv->highest_lnum < 0 || - sv->leb_count < 0 || sv->vol_type < 0 || sv->used_ebs < 0 || - sv->data_pad < 0 || sv->last_data_size < 0) { + if (av->vol_id < 0 || av->highest_lnum < 0 || + av->leb_count < 0 || av->vol_type < 0 || av->used_ebs < 0 || + av->data_pad < 0 || av->last_data_size < 0) { ubi_err("negative values"); - goto bad_sv; + goto bad_av; } - if (sv->vol_id >= UBI_MAX_VOLUMES && - sv->vol_id < UBI_INTERNAL_VOL_START) { + if (av->vol_id >= UBI_MAX_VOLUMES && + av->vol_id < UBI_INTERNAL_VOL_START) { ubi_err("bad vol_id"); - goto bad_sv; + goto bad_av; } - if (sv->vol_id > si->highest_vol_id) { + if (av->vol_id > ai->highest_vol_id) { ubi_err("highest_vol_id is %d, but vol_id %d is there", - si->highest_vol_id, sv->vol_id); + ai->highest_vol_id, av->vol_id); goto out; } - if (sv->vol_type != UBI_DYNAMIC_VOLUME && - sv->vol_type != UBI_STATIC_VOLUME) { + if (av->vol_type != UBI_DYNAMIC_VOLUME && + av->vol_type != UBI_STATIC_VOLUME) { ubi_err("bad vol_type"); - goto bad_sv; + goto bad_av; } - if (sv->data_pad > ubi->leb_size / 2) { + if (av->data_pad > ubi->leb_size / 2) { ubi_err("bad data_pad"); - goto bad_sv; + goto bad_av; } - last_seb = NULL; - ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { + last_aeb = NULL; + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) { cond_resched(); - last_seb = seb; + last_aeb = aeb; leb_count += 1; - if (seb->pnum < 0 || seb->ec < 0) { + if (aeb->pnum < 0 || aeb->ec < 0) { ubi_err("negative values"); - goto bad_seb; + goto bad_aeb; } - if (seb->ec < si->min_ec) { - ubi_err("bad si->min_ec (%d), %d found", - si->min_ec, seb->ec); - goto bad_seb; + if (aeb->ec < ai->min_ec) { + ubi_err("bad ai->min_ec (%d), %d found", + ai->min_ec, aeb->ec); + goto bad_aeb; } - if (seb->ec > si->max_ec) { - ubi_err("bad si->max_ec (%d), %d found", - si->max_ec, seb->ec); - goto bad_seb; + if (aeb->ec > ai->max_ec) { + ubi_err("bad ai->max_ec (%d), %d found", + ai->max_ec, aeb->ec); + goto bad_aeb; } - if (seb->pnum >= ubi->peb_count) { + if (aeb->pnum >= ubi->peb_count) { ubi_err("too high PEB number %d, total PEBs %d", - seb->pnum, ubi->peb_count); - goto bad_seb; + aeb->pnum, ubi->peb_count); + goto bad_aeb; } - if (sv->vol_type == UBI_STATIC_VOLUME) { - if (seb->lnum >= sv->used_ebs) { + if (av->vol_type == UBI_STATIC_VOLUME) { + if (aeb->lnum >= av->used_ebs) { ubi_err("bad lnum or used_ebs"); - goto bad_seb; + goto bad_aeb; } } else { - if (sv->used_ebs != 0) { + if (av->used_ebs != 0) { ubi_err("non-zero used_ebs"); - goto bad_seb; + goto bad_aeb; } } - if (seb->lnum > sv->highest_lnum) { + if (aeb->lnum > av->highest_lnum) { ubi_err("incorrect highest_lnum or lnum"); - goto bad_seb; + goto bad_aeb; } } - if (sv->leb_count != leb_count) { + if (av->leb_count != leb_count) { ubi_err("bad leb_count, %d objects in the tree", leb_count); - goto bad_sv; + goto bad_av; } - if (!last_seb) + if (!last_aeb) continue; - seb = last_seb; + aeb = last_aeb; - if (seb->lnum != sv->highest_lnum) { + if (aeb->lnum != av->highest_lnum) { ubi_err("bad highest_lnum"); - goto bad_seb; + goto bad_aeb; } } - if (vols_found != si->vols_found) { - ubi_err("bad si->vols_found %d, should be %d", - si->vols_found, vols_found); + if (vols_found != ai->vols_found) { + ubi_err("bad ai->vols_found %d, should be %d", + ai->vols_found, vols_found); goto out; } - /* Check that scanning information is correct */ - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { - last_seb = NULL; - ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { + /* Check that attaching information is correct */ + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { + last_aeb = NULL; + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) { int vol_type; cond_resched(); - last_seb = seb; + last_aeb = aeb; - err = ubi_io_read_vid_hdr(ubi, seb->pnum, vidh, 1); + err = ubi_io_read_vid_hdr(ubi, aeb->pnum, vidh, 1); if (err && err != UBI_IO_BITFLIPS) { ubi_err("VID header is not OK (%d)", err); if (err > 0) @@ -1486,52 +1514,52 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) vol_type = vidh->vol_type == UBI_VID_DYNAMIC ? UBI_DYNAMIC_VOLUME : UBI_STATIC_VOLUME; - if (sv->vol_type != vol_type) { + if (av->vol_type != vol_type) { ubi_err("bad vol_type"); goto bad_vid_hdr; } - if (seb->sqnum != be64_to_cpu(vidh->sqnum)) { - ubi_err("bad sqnum %llu", seb->sqnum); + if (aeb->sqnum != be64_to_cpu(vidh->sqnum)) { + ubi_err("bad sqnum %llu", aeb->sqnum); goto bad_vid_hdr; } - if (sv->vol_id != be32_to_cpu(vidh->vol_id)) { - ubi_err("bad vol_id %d", sv->vol_id); + if (av->vol_id != be32_to_cpu(vidh->vol_id)) { + ubi_err("bad vol_id %d", av->vol_id); goto bad_vid_hdr; } - if (sv->compat != vidh->compat) { + if (av->compat != vidh->compat) { ubi_err("bad compat %d", vidh->compat); goto bad_vid_hdr; } - if (seb->lnum != be32_to_cpu(vidh->lnum)) { - ubi_err("bad lnum %d", seb->lnum); + if (aeb->lnum != be32_to_cpu(vidh->lnum)) { + ubi_err("bad lnum %d", aeb->lnum); goto bad_vid_hdr; } - if (sv->used_ebs != be32_to_cpu(vidh->used_ebs)) { - ubi_err("bad used_ebs %d", sv->used_ebs); + if (av->used_ebs != be32_to_cpu(vidh->used_ebs)) { + ubi_err("bad used_ebs %d", av->used_ebs); goto bad_vid_hdr; } - if (sv->data_pad != be32_to_cpu(vidh->data_pad)) { - ubi_err("bad data_pad %d", sv->data_pad); + if (av->data_pad != be32_to_cpu(vidh->data_pad)) { + ubi_err("bad data_pad %d", av->data_pad); goto bad_vid_hdr; } } - if (!last_seb) + if (!last_aeb) continue; - if (sv->highest_lnum != be32_to_cpu(vidh->lnum)) { - ubi_err("bad highest_lnum %d", sv->highest_lnum); + if (av->highest_lnum != be32_to_cpu(vidh->lnum)) { + ubi_err("bad highest_lnum %d", av->highest_lnum); goto bad_vid_hdr; } - if (sv->last_data_size != be32_to_cpu(vidh->data_size)) { - ubi_err("bad last_data_size %d", sv->last_data_size); + if (av->last_data_size != be32_to_cpu(vidh->data_size)) { + ubi_err("bad last_data_size %d", av->last_data_size); goto bad_vid_hdr; } } @@ -1553,21 +1581,21 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) buf[pnum] = 1; } - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) - ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) - buf[seb->pnum] = 1; + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) + buf[aeb->pnum] = 1; - list_for_each_entry(seb, &si->free, u.list) - buf[seb->pnum] = 1; + list_for_each_entry(aeb, &ai->free, u.list) + buf[aeb->pnum] = 1; - list_for_each_entry(seb, &si->corr, u.list) - buf[seb->pnum] = 1; + list_for_each_entry(aeb, &ai->corr, u.list) + buf[aeb->pnum] = 1; - list_for_each_entry(seb, &si->erase, u.list) - buf[seb->pnum] = 1; + list_for_each_entry(aeb, &ai->erase, u.list) + buf[aeb->pnum] = 1; - list_for_each_entry(seb, &si->alien, u.list) - buf[seb->pnum] = 1; + list_for_each_entry(aeb, &ai->alien, u.list) + buf[aeb->pnum] = 1; err = 0; for (pnum = 0; pnum < ubi->peb_count; pnum++) @@ -1581,25 +1609,23 @@ static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si) goto out; return 0; -bad_seb: - ubi_err("bad scanning information about LEB %d", seb->lnum); - ubi_dbg_dump_seb(seb, 0); - ubi_dbg_dump_sv(sv); +bad_aeb: + ubi_err("bad attaching information about LEB %d", aeb->lnum); + ubi_dump_aeb(aeb, 0); + ubi_dump_av(av); goto out; -bad_sv: - ubi_err("bad scanning information about volume %d", sv->vol_id); - ubi_dbg_dump_sv(sv); +bad_av: + ubi_err("bad attaching information about volume %d", av->vol_id); + ubi_dump_av(av); goto out; bad_vid_hdr: - ubi_err("bad scanning information about volume %d", sv->vol_id); - ubi_dbg_dump_sv(sv); - ubi_dbg_dump_vid_hdr(vidh); + ubi_err("bad attaching information about volume %d", av->vol_id); + ubi_dump_av(av); + ubi_dump_vid_hdr(vidh); out: - ubi_dbg_dump_stack(); + dump_stack(); return -EINVAL; } - -#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 0fde9fc7d2e5..2c5ed5ca9c33 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -27,10 +27,6 @@ * module load parameters or the kernel boot parameters. If MTD devices were * specified, UBI does not attach any MTD device, but it is possible to do * later using the "UBI control device". - * - * At the moment we only attach UBI devices by scanning, which will become a - * bottleneck when flashes reach certain large size. Then one may improve UBI - * and add other methods, although it does not seem to be easy to do. */ #include <linux/err.h> @@ -554,10 +550,10 @@ static void uif_close(struct ubi_device *ubi) } /** - * free_internal_volumes - free internal volumes. + * ubi_free_internal_volumes - free internal volumes. * @ubi: UBI device description object */ -static void free_internal_volumes(struct ubi_device *ubi) +void ubi_free_internal_volumes(struct ubi_device *ubi) { int i; @@ -569,59 +565,6 @@ static void free_internal_volumes(struct ubi_device *ubi) } /** - * attach_by_scanning - attach an MTD device using scanning method. - * @ubi: UBI device descriptor - * - * This function returns zero in case of success and a negative error code in - * case of failure. - * - * Note, currently this is the only method to attach UBI devices. Hopefully in - * the future we'll have more scalable attaching methods and avoid full media - * scanning. But even in this case scanning will be needed as a fall-back - * attaching method if there are some on-flash table corruptions. - */ -static int attach_by_scanning(struct ubi_device *ubi) -{ - int err; - struct ubi_scan_info *si; - - si = ubi_scan(ubi); - if (IS_ERR(si)) - return PTR_ERR(si); - - ubi->bad_peb_count = si->bad_peb_count; - ubi->good_peb_count = ubi->peb_count - ubi->bad_peb_count; - ubi->corr_peb_count = si->corr_peb_count; - ubi->max_ec = si->max_ec; - ubi->mean_ec = si->mean_ec; - ubi_msg("max. sequence number: %llu", si->max_sqnum); - - err = ubi_read_volume_table(ubi, si); - if (err) - goto out_si; - - err = ubi_wl_init_scan(ubi, si); - if (err) - goto out_vtbl; - - err = ubi_eba_init_scan(ubi, si); - if (err) - goto out_wl; - - ubi_scan_destroy_si(si); - return 0; - -out_wl: - ubi_wl_close(ubi); -out_vtbl: - free_internal_volumes(ubi); - vfree(ubi->vtbl); -out_si: - ubi_scan_destroy_si(si); - return err; -} - -/** * io_init - initialize I/O sub-system for a given UBI device. * @ubi: UBI device description object * @@ -790,11 +733,11 @@ static int io_init(struct ubi_device *ubi) ubi_msg("data offset: %d", ubi->leb_start); /* - * Note, ideally, we have to initialize ubi->bad_peb_count here. But + * Note, ideally, we have to initialize @ubi->bad_peb_count here. But * unfortunately, MTD does not provide this information. We should loop * over all physical eraseblocks and invoke mtd->block_is_bad() for - * each physical eraseblock. So, we skip ubi->bad_peb_count - * uninitialized and initialize it after scanning. + * each physical eraseblock. So, we leave @ubi->bad_peb_count + * uninitialized so far. */ return 0; @@ -805,7 +748,7 @@ static int io_init(struct ubi_device *ubi) * @ubi: UBI device description object * @vol_id: ID of the volume to re-size * - * This function re-sizes the volume marked by the @UBI_VTBL_AUTORESIZE_FLG in + * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in * the volume table to the largest possible size. See comments in ubi-header.h * for more description of the flag. Returns zero in case of success and a * negative error code in case of failure. @@ -881,7 +824,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) for (i = 0; i < UBI_MAX_DEVICES; i++) { ubi = ubi_devices[i]; if (ubi && mtd->index == ubi->mtd->index) { - dbg_err("mtd%d is already attached to ubi%d", + ubi_err("mtd%d is already attached to ubi%d", mtd->index, i); return -EEXIST; } @@ -907,7 +850,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) if (!ubi_devices[ubi_num]) break; if (ubi_num == UBI_MAX_DEVICES) { - dbg_err("only %d UBI devices may be created", + ubi_err("only %d UBI devices may be created", UBI_MAX_DEVICES); return -ENFILE; } @@ -917,7 +860,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) /* Make sure ubi_num is not busy */ if (ubi_devices[ubi_num]) { - dbg_err("ubi%d already exists", ubi_num); + ubi_err("ubi%d already exists", ubi_num); return -EEXIST; } } @@ -937,7 +880,7 @@ 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_ainf_peb) %zu", sizeof(struct ubi_ainf_peb)); dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry)); err = io_init(ubi); @@ -953,9 +896,9 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) if (err) goto out_free; - err = attach_by_scanning(ubi); + err = ubi_attach(ubi); if (err) { - dbg_err("failed to attach by scanning, error %d", err); + ubi_err("failed to attach mtd%d, error %d", mtd->index, err); goto out_debugging; } @@ -1020,7 +963,7 @@ out_uif: uif_close(ubi); out_detach: ubi_wl_close(ubi); - free_internal_volumes(ubi); + ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); out_debugging: ubi_debugging_exit_dev(ubi); @@ -1092,7 +1035,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway) ubi_debugfs_exit_dev(ubi); uif_close(ubi); ubi_wl_close(ubi); - free_internal_volumes(ubi); + ubi_free_internal_volumes(ubi); vfree(ubi->vtbl); put_mtd_device(ubi->mtd); ubi_debugging_exit_dev(ubi); diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index ad76592fb2f4..acec85deb6af 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -63,7 +63,7 @@ static int get_exclusive(struct ubi_volume_desc *desc) users = vol->readers + vol->writers + vol->exclusive; ubi_assert(users > 0); if (users > 1) { - dbg_err("%d users for volume %d", users, vol->vol_id); + ubi_err("%d users for volume %d", users, vol->vol_id); err = -EBUSY; } else { vol->readers = vol->writers = 0; @@ -159,7 +159,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) if (vol->updating) { /* Update is in progress, seeking is prohibited */ - dbg_err("updating"); + ubi_err("updating"); return -EBUSY; } @@ -178,7 +178,7 @@ static loff_t vol_cdev_llseek(struct file *file, loff_t offset, int origin) } if (new_offset < 0 || new_offset > vol->used_bytes) { - dbg_err("bad seek %lld", new_offset); + ubi_err("bad seek %lld", new_offset); return -EINVAL; } @@ -216,11 +216,11 @@ static ssize_t vol_cdev_read(struct file *file, __user char *buf, size_t count, count, *offp, vol->vol_id); if (vol->updating) { - dbg_err("updating"); + ubi_err("updating"); return -EBUSY; } if (vol->upd_marker) { - dbg_err("damaged volume, update marker is set"); + ubi_err("damaged volume, update marker is set"); return -EBADF; } if (*offp == vol->used_bytes || count == 0) @@ -300,7 +300,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, lnum = div_u64_rem(*offp, vol->usable_leb_size, &off); if (off & (ubi->min_io_size - 1)) { - dbg_err("unaligned position"); + ubi_err("unaligned position"); return -EINVAL; } @@ -309,7 +309,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, /* We can write only in fractions of the minimum I/O unit */ if (count & (ubi->min_io_size - 1)) { - dbg_err("unaligned write length"); + ubi_err("unaligned write length"); return -EINVAL; } @@ -334,8 +334,7 @@ static ssize_t vol_cdev_direct_write(struct file *file, const char __user *buf, break; } - err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len, - UBI_UNKNOWN); + err = ubi_eba_write_leb(ubi, vol, lnum, tbuf, off, len); if (err) break; @@ -477,9 +476,6 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, if (req.lnum < 0 || req.lnum >= vol->reserved_pebs || req.bytes < 0 || req.lnum >= vol->usable_leb_size) break; - if (req.dtype != UBI_LONGTERM && req.dtype != UBI_SHORTTERM && - req.dtype != UBI_UNKNOWN) - break; err = get_exclusive(desc); if (err < 0) @@ -518,7 +514,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, if (err) break; - err = ubi_wl_flush(ubi); + err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL); break; } @@ -532,7 +528,7 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, err = -EFAULT; break; } - err = ubi_leb_map(desc, req.lnum, req.dtype); + err = ubi_leb_map(desc, req.lnum); break; } @@ -647,8 +643,8 @@ static int verify_mkvol_req(const struct ubi_device *ubi, return 0; bad: - dbg_err("bad volume creation request"); - ubi_dbg_dump_mkvol_req(req); + ubi_err("bad volume creation request"); + ubi_dump_mkvol_req(req); return err; } @@ -713,12 +709,12 @@ static int rename_volumes(struct ubi_device *ubi, for (i = 0; i < req->count - 1; i++) { for (n = i + 1; n < req->count; n++) { if (req->ents[i].vol_id == req->ents[n].vol_id) { - dbg_err("duplicated volume id %d", + ubi_err("duplicated volume id %d", req->ents[i].vol_id); return -EINVAL; } if (!strcmp(req->ents[i].name, req->ents[n].name)) { - dbg_err("duplicated volume name \"%s\"", + ubi_err("duplicated volume name \"%s\"", req->ents[i].name); return -EINVAL; } @@ -741,7 +737,7 @@ static int rename_volumes(struct ubi_device *ubi, re->desc = ubi_open_volume(ubi->ubi_num, vol_id, UBI_EXCLUSIVE); if (IS_ERR(re->desc)) { err = PTR_ERR(re->desc); - dbg_err("cannot open volume %d, error %d", vol_id, err); + ubi_err("cannot open volume %d, error %d", vol_id, err); kfree(re); goto out_free; } @@ -800,7 +796,7 @@ static int rename_volumes(struct ubi_device *ubi, continue; /* The volume exists but busy, or an error occurred */ - dbg_err("cannot open volume \"%s\", error %d", + ubi_err("cannot open volume \"%s\", error %d", re->new_name, err); goto out_free; } diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index 61af9bb560ab..9f957c2d48e9 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -18,24 +18,49 @@ * Author: Artem Bityutskiy (Битюцкий Артём) */ -/* - * Here we keep all the UBI debugging stuff which should normally be disabled - * and compiled-out, but it is extremely helpful when hunting bugs or doing big - * changes. - */ - -#ifdef CONFIG_MTD_UBI_DEBUG - #include "ubi.h" #include <linux/debugfs.h> #include <linux/uaccess.h> #include <linux/module.h> + +/** + * ubi_dump_flash - dump a region of flash. + * @ubi: UBI device description object + * @pnum: the physical eraseblock number to dump + * @offset: the starting offset within the physical eraseblock to dump + * @len: the length of the region to dump + */ +void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) +{ + int err; + size_t read; + void *buf; + loff_t addr = (loff_t)pnum * ubi->peb_size + offset; + + buf = vmalloc(len); + if (!buf) + return; + err = 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 out; + } + + ubi_msg("dumping %d bytes of data from PEB %d, offset %d", + len, pnum, offset); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1); +out: + vfree(buf); + return; +} + /** - * ubi_dbg_dump_ec_hdr - dump an erase counter header. + * ubi_dump_ec_hdr - dump an erase counter header. * @ec_hdr: the erase counter header to dump */ -void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) +void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { printk(KERN_DEBUG "Erase counter header dump:\n"); printk(KERN_DEBUG "\tmagic %#08x\n", @@ -57,10 +82,10 @@ void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) } /** - * ubi_dbg_dump_vid_hdr - dump a volume identifier header. + * ubi_dump_vid_hdr - dump a volume identifier header. * @vid_hdr: the volume identifier header to dump */ -void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) +void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { printk(KERN_DEBUG "Volume identifier header dump:\n"); printk(KERN_DEBUG "\tmagic %08x\n", be32_to_cpu(vid_hdr->magic)); @@ -82,10 +107,10 @@ void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) } /** - * ubi_dbg_dump_vol_info- dump volume information. + * ubi_dump_vol_info - dump volume information. * @vol: UBI volume description object */ -void ubi_dbg_dump_vol_info(const struct ubi_volume *vol) +void ubi_dump_vol_info(const struct ubi_volume *vol) { printk(KERN_DEBUG "Volume information dump:\n"); printk(KERN_DEBUG "\tvol_id %d\n", vol->vol_id); @@ -112,11 +137,11 @@ void ubi_dbg_dump_vol_info(const struct ubi_volume *vol) } /** - * ubi_dbg_dump_vtbl_record - dump a &struct ubi_vtbl_record object. + * ubi_dump_vtbl_record - dump a &struct ubi_vtbl_record object. * @r: the object to dump * @idx: volume table index */ -void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) +void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { int name_len = be16_to_cpu(r->name_len); @@ -146,44 +171,44 @@ void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) } /** - * ubi_dbg_dump_sv - dump a &struct ubi_scan_volume object. - * @sv: the object to dump + * ubi_dump_av - dump a &struct ubi_ainf_volume object. + * @av: the object to dump */ -void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) +void ubi_dump_av(const struct ubi_ainf_volume *av) { - printk(KERN_DEBUG "Volume scanning information dump:\n"); - printk(KERN_DEBUG "\tvol_id %d\n", sv->vol_id); - printk(KERN_DEBUG "\thighest_lnum %d\n", sv->highest_lnum); - printk(KERN_DEBUG "\tleb_count %d\n", sv->leb_count); - printk(KERN_DEBUG "\tcompat %d\n", sv->compat); - printk(KERN_DEBUG "\tvol_type %d\n", sv->vol_type); - printk(KERN_DEBUG "\tused_ebs %d\n", sv->used_ebs); - printk(KERN_DEBUG "\tlast_data_size %d\n", sv->last_data_size); - printk(KERN_DEBUG "\tdata_pad %d\n", sv->data_pad); + printk(KERN_DEBUG "Volume attaching information dump:\n"); + printk(KERN_DEBUG "\tvol_id %d\n", av->vol_id); + printk(KERN_DEBUG "\thighest_lnum %d\n", av->highest_lnum); + printk(KERN_DEBUG "\tleb_count %d\n", av->leb_count); + printk(KERN_DEBUG "\tcompat %d\n", av->compat); + printk(KERN_DEBUG "\tvol_type %d\n", av->vol_type); + printk(KERN_DEBUG "\tused_ebs %d\n", av->used_ebs); + printk(KERN_DEBUG "\tlast_data_size %d\n", av->last_data_size); + printk(KERN_DEBUG "\tdata_pad %d\n", av->data_pad); } /** - * ubi_dbg_dump_seb - dump a &struct ubi_scan_leb object. - * @seb: the object to dump + * ubi_dump_aeb - dump a &struct ubi_ainf_peb object. + * @aeb: the object to dump * @type: object type: 0 - not corrupted, 1 - corrupted */ -void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, int type) +void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type) { - printk(KERN_DEBUG "eraseblock scanning information dump:\n"); - printk(KERN_DEBUG "\tec %d\n", seb->ec); - printk(KERN_DEBUG "\tpnum %d\n", seb->pnum); + printk(KERN_DEBUG "eraseblock attaching information dump:\n"); + printk(KERN_DEBUG "\tec %d\n", aeb->ec); + printk(KERN_DEBUG "\tpnum %d\n", aeb->pnum); if (type == 0) { - printk(KERN_DEBUG "\tlnum %d\n", seb->lnum); - printk(KERN_DEBUG "\tscrub %d\n", seb->scrub); - printk(KERN_DEBUG "\tsqnum %llu\n", seb->sqnum); + printk(KERN_DEBUG "\tlnum %d\n", aeb->lnum); + printk(KERN_DEBUG "\tscrub %d\n", aeb->scrub); + printk(KERN_DEBUG "\tsqnum %llu\n", aeb->sqnum); } } /** - * ubi_dbg_dump_mkvol_req - dump a &struct ubi_mkvol_req object. + * ubi_dump_mkvol_req - dump a &struct ubi_mkvol_req object. * @req: the object to dump */ -void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) +void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req) { char nm[17]; @@ -200,38 +225,6 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) } /** - * ubi_dbg_dump_flash - dump a region of flash. - * @ubi: UBI device description object - * @pnum: the physical eraseblock number to dump - * @offset: the starting offset within the physical eraseblock to dump - * @len: the length of the region to dump - */ -void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len) -{ - int err; - size_t read; - void *buf; - loff_t addr = (loff_t)pnum * ubi->peb_size + offset; - - buf = vmalloc(len); - if (!buf) - return; - err = 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 out; - } - - dbg_msg("dumping %d bytes of data from PEB %d, offset %d", - len, pnum, offset); - print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1); -out: - vfree(buf); - return; -} - -/** * ubi_debugging_init_dev - initialize debugging for an UBI device. * @ubi: UBI device description object * @@ -479,5 +472,3 @@ void ubi_debugfs_exit_dev(struct ubi_device *ubi) { debugfs_remove_recursive(ubi->dbg->dfs_dir); } - -#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index ead2cd16ba75..d5d2645b51a7 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -21,21 +21,20 @@ #ifndef __UBI_DEBUG_H__ #define __UBI_DEBUG_H__ -#ifdef CONFIG_MTD_UBI_DEBUG +void ubi_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); +void ubi_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr); +void ubi_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr); + #include <linux/random.h> #define ubi_assert(expr) do { \ if (unlikely(!(expr))) { \ printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \ __func__, __LINE__, current->pid); \ - ubi_dbg_dump_stack(); \ + dump_stack(); \ } \ } while (0) -#define dbg_err(fmt, ...) ubi_err(fmt, ##__VA_ARGS__) - -#define ubi_dbg_dump_stack() dump_stack() - #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) @@ -58,17 +57,13 @@ /* Initialization and build messages */ #define dbg_bld(fmt, ...) ubi_dbg_msg("bld", fmt, ##__VA_ARGS__) -void ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr); -void ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr); -void ubi_dbg_dump_vol_info(const struct ubi_volume *vol); -void ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx); -void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv); -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); -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); +void ubi_dump_vol_info(const struct ubi_volume *vol); +void ubi_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx); +void ubi_dump_av(const struct ubi_ainf_volume *av); +void ubi_dump_aeb(const struct ubi_ainf_peb *aeb, int type); +void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req); +int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, + int len); int ubi_debugging_init_dev(struct ubi_device *ubi); void ubi_debugging_exit_dev(struct ubi_device *ubi); int ubi_debugfs_init(void); @@ -167,73 +162,4 @@ static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi) return 0; } -#else - -/* Use "if (0)" to make compiler check arguments even if debugging is off */ -#define ubi_assert(expr) do { \ - if (0) { \ - printk(KERN_CRIT "UBI assert failed in %s at %u (pid %d)\n", \ - __func__, __LINE__, current->pid); \ - } \ -} while (0) - -#define dbg_err(fmt, ...) do { \ - if (0) \ - ubi_err(fmt, ##__VA_ARGS__); \ -} while (0) - -#define ubi_dbg_msg(fmt, ...) do { \ - if (0) \ - printk(KERN_DEBUG fmt "\n", ##__VA_ARGS__); \ -} while (0) - -#define dbg_msg(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_gen(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_eba(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_wl(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_io(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) -#define dbg_bld(fmt, ...) ubi_dbg_msg(fmt, ##__VA_ARGS__) - -static inline void ubi_dbg_dump_stack(void) { return; } -static inline void -ubi_dbg_dump_ec_hdr(const struct ubi_ec_hdr *ec_hdr) { return; } -static inline void -ubi_dbg_dump_vid_hdr(const struct ubi_vid_hdr *vid_hdr) { return; } -static inline void -ubi_dbg_dump_vol_info(const struct ubi_volume *vol) { return; } -static inline void -ubi_dbg_dump_vtbl_record(const struct ubi_vtbl_record *r, int idx) { return; } -static inline void ubi_dbg_dump_sv(const struct ubi_scan_volume *sv) { return; } -static inline void ubi_dbg_dump_seb(const struct ubi_scan_leb *seb, - int type) { return; } -static inline void -ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req) { return; } -static inline void ubi_dbg_dump_flash(struct ubi_device *ubi, - int pnum, int offset, int len) { return; } -static inline void -ubi_dbg_print_hex_dump(const char *l, const char *ps, int pt, int r, - int g, const void *b, size_t len, bool a) { return; } -static inline int ubi_dbg_check_all_ff(struct ubi_device *ubi, - int pnum, int offset, - int len) { return 0; } -static inline int ubi_dbg_check_write(struct ubi_device *ubi, - const void *buf, int pnum, - int offset, int len) { return 0; } - -static inline int ubi_debugging_init_dev(struct ubi_device *ubi) { return 0; } -static inline void ubi_debugging_exit_dev(struct ubi_device *ubi) { return; } -static inline int ubi_debugfs_init(void) { return 0; } -static inline void ubi_debugfs_exit(void) { return; } -static inline int ubi_debugfs_init_dev(struct ubi_device *ubi) { return 0; } -static inline void ubi_debugfs_exit_dev(struct ubi_device *ubi) { return; } - -static inline int -ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi) { return 0; } -static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi) { return 0; } -static inline int -ubi_dbg_is_write_failure(const struct ubi_device *ubi) { return 0; } -static inline int -ubi_dbg_is_erase_failure(const struct ubi_device *ubi) { return 0; } - -#endif /* !CONFIG_MTD_UBI_DEBUG */ #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 2455d620d96b..b703ac7729cf 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -341,7 +341,7 @@ 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); vol->eba_tbl[lnum] = UBI_LEB_UNMAPPED; - err = ubi_wl_put_peb(ubi, pnum, 0); + err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 0); out_unlock: leb_write_unlock(ubi, vol_id, lnum); @@ -507,7 +507,7 @@ static int recover_peb(struct ubi_device *ubi, int pnum, int vol_id, int lnum, return -ENOMEM; retry: - new_pnum = ubi_wl_get_peb(ubi, UBI_UNKNOWN); + new_pnum = ubi_wl_get_peb(ubi); if (new_pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); return new_pnum; @@ -550,7 +550,7 @@ retry: ubi_free_vid_hdr(ubi, vid_hdr); vol->eba_tbl[lnum] = new_pnum; - ubi_wl_put_peb(ubi, pnum, 1); + ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); ubi_msg("data was successfully recovered"); return 0; @@ -558,7 +558,7 @@ retry: out_unlock: mutex_unlock(&ubi->buf_mutex); out_put: - ubi_wl_put_peb(ubi, new_pnum, 1); + ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -568,7 +568,7 @@ write_error: * get another one. */ ubi_warn("failed to write to PEB %d", new_pnum); - ubi_wl_put_peb(ubi, new_pnum, 1); + ubi_wl_put_peb(ubi, vol_id, lnum, new_pnum, 1); if (++tries > UBI_IO_RETRIES) { ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -585,7 +585,6 @@ write_error: * @buf: the data to write * @offset: offset within the logical eraseblock where to write * @len: how many bytes to write - * @dtype: data type * * This function writes data to logical eraseblock @lnum of a dynamic volume * @vol. Returns zero in case of success and a negative error code in case @@ -593,7 +592,7 @@ write_error: * written to the flash media, but may be some garbage. */ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, - const void *buf, int offset, int len, int dtype) + const void *buf, int offset, int len) { int err, pnum, tries = 0, vol_id = vol->vol_id; struct ubi_vid_hdr *vid_hdr; @@ -641,7 +640,7 @@ int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, vid_hdr->data_pad = cpu_to_be32(vol->data_pad); retry: - pnum = ubi_wl_get_peb(ubi, dtype); + pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); @@ -687,7 +686,7 @@ write_error: * eraseblock, so just put it and request a new one. We assume that if * this physical eraseblock went bad, the erase code will handle that. */ - err = ubi_wl_put_peb(ubi, pnum, 1); + err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); if (err || ++tries > UBI_IO_RETRIES) { ubi_ro_mode(ubi); leb_write_unlock(ubi, vol_id, lnum); @@ -707,7 +706,6 @@ write_error: * @lnum: logical eraseblock number * @buf: data to write * @len: how many bytes to write - * @dtype: data type * @used_ebs: how many logical eraseblocks will this volume contain * * This function writes data to logical eraseblock @lnum of static volume @@ -724,8 +722,7 @@ write_error: * code in case of failure. */ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, - int lnum, const void *buf, int len, int dtype, - int used_ebs) + int lnum, const void *buf, int len, int used_ebs) { int err, pnum, tries = 0, data_size = len, vol_id = vol->vol_id; struct ubi_vid_hdr *vid_hdr; @@ -763,7 +760,7 @@ int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, vid_hdr->data_crc = cpu_to_be32(crc); retry: - pnum = ubi_wl_get_peb(ubi, dtype); + pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { ubi_free_vid_hdr(ubi, vid_hdr); leb_write_unlock(ubi, vol_id, lnum); @@ -807,7 +804,7 @@ write_error: return err; } - err = ubi_wl_put_peb(ubi, pnum, 1); + err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); if (err || ++tries > UBI_IO_RETRIES) { ubi_ro_mode(ubi); leb_write_unlock(ubi, vol_id, lnum); @@ -827,7 +824,6 @@ write_error: * @lnum: logical eraseblock number * @buf: data to write * @len: how many bytes to write - * @dtype: data type * * This function changes the contents of a logical eraseblock atomically. @buf * has to contain new logical eraseblock data, and @len - the length of the @@ -839,7 +835,7 @@ write_error: * LEB change may be done at a time. This is ensured by @ubi->alc_mutex. */ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, - int lnum, const void *buf, int len, int dtype) + int lnum, const void *buf, int len) { int err, pnum, tries = 0, vol_id = vol->vol_id; struct ubi_vid_hdr *vid_hdr; @@ -856,7 +852,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, err = ubi_eba_unmap_leb(ubi, vol, lnum); if (err) return err; - return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype); + return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); } vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); @@ -881,7 +877,7 @@ int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, vid_hdr->data_crc = cpu_to_be32(crc); retry: - pnum = ubi_wl_get_peb(ubi, dtype); + pnum = ubi_wl_get_peb(ubi); if (pnum < 0) { err = pnum; goto out_leb_unlock; @@ -905,7 +901,7 @@ retry: } if (vol->eba_tbl[lnum] >= 0) { - err = ubi_wl_put_peb(ubi, vol->eba_tbl[lnum], 0); + err = ubi_wl_put_peb(ubi, vol_id, lnum, vol->eba_tbl[lnum], 0); if (err) goto out_leb_unlock; } @@ -930,7 +926,7 @@ write_error: goto out_leb_unlock; } - err = ubi_wl_put_peb(ubi, pnum, 1); + err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1); if (err || ++tries > UBI_IO_RETRIES) { ubi_ro_mode(ubi); goto out_leb_unlock; @@ -1171,7 +1167,7 @@ out_unlock_leb: * print_rsvd_warning - warn about not having enough reserved PEBs. * @ubi: UBI device description object * - * This is a helper function for 'ubi_eba_init_scan()' which is called when UBI + * This is a helper function for 'ubi_eba_init()' which is called when UBI * cannot reserve enough PEBs for bad block handling. This function makes a * decision whether we have to print a warning or not. The algorithm is as * follows: @@ -1186,13 +1182,13 @@ out_unlock_leb: * reported by real users. */ static void print_rsvd_warning(struct ubi_device *ubi, - struct ubi_scan_info *si) + struct ubi_attach_info *ai) { /* * The 1 << 18 (256KiB) number is picked randomly, just a reasonably * large number to distinguish between newly flashed and used images. */ - if (si->max_sqnum > (1 << 18)) { + if (ai->max_sqnum > (1 << 18)) { int min = ubi->beb_rsvd_level / 10; if (!min) @@ -1209,19 +1205,19 @@ static void print_rsvd_warning(struct ubi_device *ubi, } /** - * ubi_eba_init_scan - initialize the EBA sub-system using scanning information. + * ubi_eba_init - initialize the EBA sub-system using attaching information. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * This function returns zero in case of success and a negative error code in * case of failure. */ -int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) +int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai) { int i, j, err, num_volumes; - struct ubi_scan_volume *sv; + struct ubi_ainf_volume *av; struct ubi_volume *vol; - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; struct rb_node *rb; dbg_eba("initialize EBA sub-system"); @@ -1230,7 +1226,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) mutex_init(&ubi->alc_mutex); ubi->ltree = RB_ROOT; - ubi->global_sqnum = si->max_sqnum + 1; + ubi->global_sqnum = ai->max_sqnum + 1; num_volumes = ubi->vtbl_slots + UBI_INT_VOL_COUNT; for (i = 0; i < num_volumes; i++) { @@ -1250,18 +1246,18 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) for (j = 0; j < vol->reserved_pebs; j++) vol->eba_tbl[j] = UBI_LEB_UNMAPPED; - sv = ubi_scan_find_sv(si, idx2vol_id(ubi, i)); - if (!sv) + av = ubi_find_av(ai, idx2vol_id(ubi, i)); + if (!av) continue; - ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { - if (seb->lnum >= vol->reserved_pebs) + ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) { + if (aeb->lnum >= vol->reserved_pebs) /* * This may happen in case of an unclean reboot * during re-size. */ - ubi_scan_move_to_list(sv, seb, &si->erase); - vol->eba_tbl[seb->lnum] = seb->pnum; + ubi_move_aeb_to_list(av, aeb, &ai->erase); + vol->eba_tbl[aeb->lnum] = aeb->pnum; } } @@ -1283,7 +1279,7 @@ int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) if (ubi->avail_pebs < ubi->beb_rsvd_level) { /* No enough free physical eraseblocks */ ubi->beb_rsvd_pebs = ubi->avail_pebs; - print_rsvd_warning(ubi, si); + print_rsvd_warning(ubi, ai); } else ubi->beb_rsvd_pebs = ubi->beb_rsvd_level; diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index 90b98822d9a4..4e44bee4c564 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c @@ -227,7 +227,7 @@ static int gluebi_write(struct mtd_info *mtd, loff_t to, size_t len, if (to_write > total_written) to_write = total_written; - err = ubi_write(gluebi->desc, lnum, buf, offs, to_write); + err = ubi_leb_write(gluebi->desc, lnum, buf, offs, to_write); if (err) break; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 43f1a0011a55..a8d523794b52 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -91,21 +91,15 @@ #include <linux/slab.h> #include "ubi.h" -#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, - const struct ubi_ec_hdr *ec_hdr); -static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); -static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, - const struct ubi_vid_hdr *vid_hdr); -#else -#define paranoid_check_not_bad(ubi, pnum) 0 -#define paranoid_check_peb_ec_hdr(ubi, pnum) 0 -#define paranoid_check_ec_hdr(ubi, pnum, ec_hdr) 0 -#define paranoid_check_peb_vid_hdr(ubi, pnum) 0 -#define paranoid_check_vid_hdr(ubi, pnum, vid_hdr) 0 -#endif +static int self_check_not_bad(const struct ubi_device *ubi, int pnum); +static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum); +static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum, + const struct ubi_ec_hdr *ec_hdr); +static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum); +static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum, + const struct ubi_vid_hdr *vid_hdr); +static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, + int offset, int len); /** * ubi_io_read - read data from a physical eraseblock. @@ -142,7 +136,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, ubi_assert(offset >= 0 && offset + len <= ubi->peb_size); ubi_assert(len > 0); - err = paranoid_check_not_bad(ubi, pnum); + err = self_check_not_bad(ubi, pnum); if (err) return err; @@ -189,16 +183,16 @@ retry: } 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); + ubi_warn("error %d%s while reading %d bytes from PEB " + "%d:%d, read only %zd bytes, retry", + err, errstr, len, pnum, offset, read); yield(); goto retry; } ubi_err("error %d%s while reading %d bytes from PEB %d:%d, " "read %zd bytes", err, errstr, len, pnum, offset, read); - ubi_dbg_dump_stack(); + dump_stack(); /* * The driver should never return -EBADMSG if it failed to read @@ -257,14 +251,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, return -EROFS; } - /* The below has to be compiled out if paranoid checks are disabled */ - - err = paranoid_check_not_bad(ubi, pnum); + err = self_check_not_bad(ubi, pnum); if (err) return err; /* The area we are writing to has to contain all 0xFF bytes */ - err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); + err = ubi_self_check_all_ff(ubi, pnum, offset, len); if (err) return err; @@ -273,18 +265,18 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, * We write to the data area of the physical eraseblock. Make * sure it has valid EC and VID headers. */ - err = paranoid_check_peb_ec_hdr(ubi, pnum); + err = self_check_peb_ec_hdr(ubi, pnum); if (err) return err; - err = paranoid_check_peb_vid_hdr(ubi, pnum); + err = self_check_peb_vid_hdr(ubi, pnum); if (err) return err; } if (ubi_dbg_is_write_failure(ubi)) { - dbg_err("cannot write %d bytes to PEB %d:%d " + ubi_err("cannot write %d bytes to PEB %d:%d " "(emulated)", len, pnum, offset); - ubi_dbg_dump_stack(); + dump_stack(); return -EIO; } @@ -293,13 +285,13 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, if (err) { ubi_err("error %d while writing %d bytes to PEB %d:%d, written " "%zd bytes", err, len, pnum, offset, written); - ubi_dbg_dump_stack(); - ubi_dbg_dump_flash(ubi, pnum, offset, len); + dump_stack(); + ubi_dump_flash(ubi, pnum, offset, len); } else ubi_assert(written == len); if (!err) { - err = ubi_dbg_check_write(ubi, buf, pnum, offset, len); + err = self_check_write(ubi, buf, pnum, offset, len); if (err) return err; @@ -310,7 +302,7 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, offset += len; len = ubi->peb_size - offset; if (len) - err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); + err = ubi_self_check_all_ff(ubi, pnum, offset, len); } return err; @@ -364,13 +356,13 @@ retry: err = mtd_erase(ubi->mtd, &ei); if (err) { if (retries++ < UBI_IO_RETRIES) { - dbg_io("error %d while erasing PEB %d, retry", - err, pnum); + ubi_warn("error %d while erasing PEB %d, retry", + err, pnum); yield(); goto retry; } ubi_err("cannot erase PEB %d, error %d", pnum, err); - ubi_dbg_dump_stack(); + dump_stack(); return err; } @@ -383,21 +375,21 @@ retry: if (ei.state == MTD_ERASE_FAILED) { if (retries++ < UBI_IO_RETRIES) { - dbg_io("error while erasing PEB %d, retry", pnum); + ubi_warn("error while erasing PEB %d, retry", pnum); yield(); goto retry; } ubi_err("cannot erase PEB %d", pnum); - ubi_dbg_dump_stack(); + dump_stack(); return -EIO; } - err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); + err = ubi_self_check_all_ff(ubi, pnum, 0, ubi->peb_size); if (err) return err; if (ubi_dbg_is_erase_failure(ubi)) { - dbg_err("cannot erase PEB %d (emulated)", pnum); + ubi_err("cannot erase PEB %d (emulated)", pnum); return -EIO; } @@ -521,8 +513,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) * It is important to first invalidate the EC header, and then the VID * header. Otherwise a power cut may lead to valid EC header and * invalid VID header, in which case UBI will treat this PEB as - * corrupted and will try to preserve it, and print scary warnings (see - * the header comment in scan.c for more information). + * corrupted and will try to preserve it, and print scary warnings. */ addr = (loff_t)pnum * ubi->peb_size; err = mtd_write(ubi->mtd, addr, 4, &written, (void *)&data); @@ -563,7 +554,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) */ ubi_err("cannot invalidate PEB %d, write returned %d read returned %d", pnum, err, err1); - ubi_dbg_dump_flash(ubi, pnum, 0, ubi->peb_size); + ubi_dump_flash(ubi, pnum, 0, ubi->peb_size); return -EIO; } @@ -589,7 +580,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) ubi_assert(pnum >= 0 && pnum < ubi->peb_count); - err = paranoid_check_not_bad(ubi, pnum); + err = self_check_not_bad(ubi, pnum); if (err != 0) return err; @@ -721,8 +712,8 @@ static int validate_ec_hdr(const struct ubi_device *ubi, bad: ubi_err("bad EC header"); - ubi_dbg_dump_ec_hdr(ec_hdr); - ubi_dbg_dump_stack(); + ubi_dump_ec_hdr(ec_hdr); + dump_stack(); return 1; } @@ -803,7 +794,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (verbose) { 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); + ubi_dump_ec_hdr(ec_hdr); } dbg_bld("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_EC_HDR_MAGIC); @@ -817,7 +808,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, if (verbose) { ubi_warn("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); - ubi_dbg_dump_ec_hdr(ec_hdr); + ubi_dump_ec_hdr(ec_hdr); } dbg_bld("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); @@ -874,7 +865,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); ec_hdr->hdr_crc = cpu_to_be32(crc); - err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr); + err = self_check_ec_hdr(ubi, pnum, ec_hdr); if (err) return err; @@ -905,40 +896,40 @@ static int validate_vid_hdr(const struct ubi_device *ubi, int usable_leb_size = ubi->leb_size - data_pad; if (copy_flag != 0 && copy_flag != 1) { - dbg_err("bad copy_flag"); + ubi_err("bad copy_flag"); goto bad; } if (vol_id < 0 || lnum < 0 || data_size < 0 || used_ebs < 0 || data_pad < 0) { - dbg_err("negative values"); + ubi_err("negative values"); goto bad; } if (vol_id >= UBI_MAX_VOLUMES && vol_id < UBI_INTERNAL_VOL_START) { - dbg_err("bad vol_id"); + ubi_err("bad vol_id"); goto bad; } if (vol_id < UBI_INTERNAL_VOL_START && compat != 0) { - dbg_err("bad compat"); + ubi_err("bad compat"); goto bad; } if (vol_id >= UBI_INTERNAL_VOL_START && compat != UBI_COMPAT_DELETE && compat != UBI_COMPAT_RO && compat != UBI_COMPAT_PRESERVE && compat != UBI_COMPAT_REJECT) { - dbg_err("bad compat"); + ubi_err("bad compat"); goto bad; } if (vol_type != UBI_VID_DYNAMIC && vol_type != UBI_VID_STATIC) { - dbg_err("bad vol_type"); + ubi_err("bad vol_type"); goto bad; } if (data_pad >= ubi->leb_size / 2) { - dbg_err("bad data_pad"); + ubi_err("bad data_pad"); goto bad; } @@ -950,45 +941,45 @@ static int validate_vid_hdr(const struct ubi_device *ubi, * mapped logical eraseblocks. */ if (used_ebs == 0) { - dbg_err("zero used_ebs"); + ubi_err("zero used_ebs"); goto bad; } if (data_size == 0) { - dbg_err("zero data_size"); + ubi_err("zero data_size"); goto bad; } if (lnum < used_ebs - 1) { if (data_size != usable_leb_size) { - dbg_err("bad data_size"); + ubi_err("bad data_size"); goto bad; } } else if (lnum == used_ebs - 1) { if (data_size == 0) { - dbg_err("bad data_size at last LEB"); + ubi_err("bad data_size at last LEB"); goto bad; } } else { - dbg_err("too high lnum"); + ubi_err("too high lnum"); goto bad; } } else { if (copy_flag == 0) { if (data_crc != 0) { - dbg_err("non-zero data CRC"); + ubi_err("non-zero data CRC"); goto bad; } if (data_size != 0) { - dbg_err("non-zero data_size"); + ubi_err("non-zero data_size"); goto bad; } } else { if (data_size == 0) { - dbg_err("zero data_size of copy"); + ubi_err("zero data_size of copy"); goto bad; } } if (used_ebs != 0) { - dbg_err("bad used_ebs"); + ubi_err("bad used_ebs"); goto bad; } } @@ -997,8 +988,8 @@ static int validate_vid_hdr(const struct ubi_device *ubi, bad: ubi_err("bad VID header"); - ubi_dbg_dump_vid_hdr(vid_hdr); - ubi_dbg_dump_stack(); + ubi_dump_vid_hdr(vid_hdr); + dump_stack(); return 1; } @@ -1054,7 +1045,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, if (verbose) { 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); + ubi_dump_vid_hdr(vid_hdr); } dbg_bld("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); @@ -1068,7 +1059,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, if (verbose) { ubi_warn("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); - ubi_dbg_dump_vid_hdr(vid_hdr); + ubi_dump_vid_hdr(vid_hdr); } dbg_bld("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); @@ -1112,7 +1103,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, dbg_io("write VID header to PEB %d", pnum); ubi_assert(pnum >= 0 && pnum < ubi->peb_count); - err = paranoid_check_peb_ec_hdr(ubi, pnum); + err = self_check_peb_ec_hdr(ubi, pnum); if (err) return err; @@ -1121,7 +1112,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); vid_hdr->hdr_crc = cpu_to_be32(crc); - err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); + err = self_check_vid_hdr(ubi, pnum, vid_hdr); if (err) return err; @@ -1131,17 +1122,15 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, return err; } -#ifdef CONFIG_MTD_UBI_DEBUG - /** - * paranoid_check_not_bad - ensure that a physical eraseblock is not bad. + * self_check_not_bad - ensure that a physical eraseblock is not bad. * @ubi: UBI device description object * @pnum: physical eraseblock number to check * * This function returns zero if the physical eraseblock is good, %-EINVAL if * it is bad and a negative error code if an error occurred. */ -static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) +static int self_check_not_bad(const struct ubi_device *ubi, int pnum) { int err; @@ -1152,13 +1141,13 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) if (!err) return err; - ubi_err("paranoid check failed for PEB %d", pnum); - ubi_dbg_dump_stack(); + ubi_err("self-check failed for PEB %d", pnum); + dump_stack(); return err > 0 ? -EINVAL : err; } /** - * paranoid_check_ec_hdr - check if an erase counter header is all right. + * self_check_ec_hdr - check if an erase counter header is all right. * @ubi: UBI device description object * @pnum: physical eraseblock number the erase counter header belongs to * @ec_hdr: the erase counter header to check @@ -1166,8 +1155,8 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) * This function returns zero if the erase counter header contains valid * values, and %-EINVAL if not. */ -static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, - const struct ubi_ec_hdr *ec_hdr) +static int self_check_ec_hdr(const struct ubi_device *ubi, int pnum, + const struct ubi_ec_hdr *ec_hdr) { int err; uint32_t magic; @@ -1184,27 +1173,27 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, err = validate_ec_hdr(ubi, ec_hdr); if (err) { - ubi_err("paranoid check failed for PEB %d", pnum); + ubi_err("self-check failed for PEB %d", pnum); goto fail; } return 0; fail: - ubi_dbg_dump_ec_hdr(ec_hdr); - ubi_dbg_dump_stack(); + ubi_dump_ec_hdr(ec_hdr); + dump_stack(); return -EINVAL; } /** - * paranoid_check_peb_ec_hdr - check erase counter header. + * self_check_peb_ec_hdr - check erase counter header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * * This function returns zero if the erase counter header is all right and and * a negative error code if not or if an error occurred. */ -static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) +static int self_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) { int err; uint32_t crc, hdr_crc; @@ -1225,14 +1214,14 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) hdr_crc = be32_to_cpu(ec_hdr->hdr_crc); if (hdr_crc != crc) { ubi_err("bad CRC, calculated %#08x, read %#08x", crc, hdr_crc); - ubi_err("paranoid check failed for PEB %d", pnum); - ubi_dbg_dump_ec_hdr(ec_hdr); - ubi_dbg_dump_stack(); + ubi_err("self-check failed for PEB %d", pnum); + ubi_dump_ec_hdr(ec_hdr); + dump_stack(); err = -EINVAL; goto exit; } - err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr); + err = self_check_ec_hdr(ubi, pnum, ec_hdr); exit: kfree(ec_hdr); @@ -1240,7 +1229,7 @@ exit: } /** - * paranoid_check_vid_hdr - check that a volume identifier header is all right. + * self_check_vid_hdr - check that a volume identifier header is all right. * @ubi: UBI device description object * @pnum: physical eraseblock number the volume identifier header belongs to * @vid_hdr: the volume identifier header to check @@ -1248,8 +1237,8 @@ exit: * This function returns zero if the volume identifier header is all right, and * %-EINVAL if not. */ -static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, - const struct ubi_vid_hdr *vid_hdr) +static int self_check_vid_hdr(const struct ubi_device *ubi, int pnum, + const struct ubi_vid_hdr *vid_hdr) { int err; uint32_t magic; @@ -1266,29 +1255,29 @@ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, err = validate_vid_hdr(ubi, vid_hdr); if (err) { - ubi_err("paranoid check failed for PEB %d", pnum); + ubi_err("self-check failed for PEB %d", pnum); goto fail; } return err; fail: - ubi_err("paranoid check failed for PEB %d", pnum); - ubi_dbg_dump_vid_hdr(vid_hdr); - ubi_dbg_dump_stack(); + ubi_err("self-check failed for PEB %d", pnum); + ubi_dump_vid_hdr(vid_hdr); + dump_stack(); return -EINVAL; } /** - * paranoid_check_peb_vid_hdr - check volume identifier header. + * self_check_peb_vid_hdr - check volume identifier header. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * * This function returns zero if the volume identifier header is all right, * and a negative error code if not or if an error occurred. */ -static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) +static int self_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) { int err; uint32_t crc, hdr_crc; @@ -1313,14 +1302,14 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) if (hdr_crc != crc) { ubi_err("bad VID header CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); - ubi_err("paranoid check failed for PEB %d", pnum); - ubi_dbg_dump_vid_hdr(vid_hdr); - ubi_dbg_dump_stack(); + ubi_err("self-check failed for PEB %d", pnum); + ubi_dump_vid_hdr(vid_hdr); + dump_stack(); err = -EINVAL; goto exit; } - err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); + err = self_check_vid_hdr(ubi, pnum, vid_hdr); exit: ubi_free_vid_hdr(ubi, vid_hdr); @@ -1328,7 +1317,7 @@ exit: } /** - * ubi_dbg_check_write - make sure write succeeded. + * self_check_write - make sure write succeeded. * @ubi: UBI device description object * @buf: buffer with data which were written * @pnum: physical eraseblock number the data were written to @@ -1339,8 +1328,8 @@ exit: * the original data buffer - the data have to match. Returns zero if the data * match and a negative error code if not or in case of failure. */ -int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, - int offset, int len) +static int self_check_write(struct ubi_device *ubi, const void *buf, int pnum, + int offset, int len) { int err, i; size_t read; @@ -1368,7 +1357,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, if (c == c1) continue; - ubi_err("paranoid check failed for PEB %d:%d, len %d", + ubi_err("self-check failed for PEB %d:%d, len %d", pnum, offset, len); ubi_msg("data differ at position %d", i); dump_len = max_t(int, 128, len - i); @@ -1380,7 +1369,7 @@ int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, i, i + dump_len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf1 + i, dump_len, 1); - ubi_dbg_dump_stack(); + dump_stack(); err = -EINVAL; goto out_free; } @@ -1394,7 +1383,7 @@ out_free: } /** - * ubi_dbg_check_all_ff - check that a region of flash is empty. + * ubi_self_check_all_ff - check that a region of flash is empty. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @offset: the starting offset within the physical eraseblock to check @@ -1404,7 +1393,7 @@ out_free: * @offset of the physical eraseblock @pnum, and a negative error code if not * or if an error occurred. */ -int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) +int ubi_self_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) { size_t read; int err; @@ -1438,14 +1427,12 @@ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) return 0; fail: - ubi_err("paranoid check failed for PEB %d", pnum); + ubi_err("self-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, buf, len, 1); err = -EINVAL; error: - ubi_dbg_dump_stack(); + dump_stack(); vfree(buf); return err; } - -#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 9fdb35367fe0..3aac1acceeb4 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -221,7 +221,7 @@ out_free: kfree(desc); out_put_ubi: ubi_put_device(ubi); - dbg_err("cannot open device %d, volume %d, error %d", + ubi_err("cannot open device %d, volume %d, error %d", ubi_num, vol_id, err); return ERR_PTR(err); } @@ -426,11 +426,9 @@ EXPORT_SYMBOL_GPL(ubi_leb_read); * @buf: data to write * @offset: offset within the logical eraseblock where to write * @len: how many bytes to write - * @dtype: expected data type * * This function writes @len bytes of data from @buf to offset @offset of - * logical eraseblock @lnum. The @dtype argument describes expected lifetime of - * the data. + * logical eraseblock @lnum. * * This function takes care of physical eraseblock write failures. If write to * the physical eraseblock write operation fails, the logical eraseblock is @@ -447,7 +445,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_read); * returns immediately with %-EBADF code. */ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, - int offset, int len, int dtype) + int offset, int len) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; @@ -466,17 +464,13 @@ int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, offset & (ubi->min_io_size - 1) || len & (ubi->min_io_size - 1)) return -EINVAL; - if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && - dtype != UBI_UNKNOWN) - return -EINVAL; - if (vol->upd_marker) return -EBADF; if (len == 0) return 0; - return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype); + return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len); } EXPORT_SYMBOL_GPL(ubi_leb_write); @@ -486,7 +480,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); * @lnum: logical eraseblock number to change * @buf: data to write * @len: how many bytes to write - * @dtype: expected data type * * This function changes the contents of a logical eraseblock atomically. @buf * has to contain new logical eraseblock data, and @len - the length of the @@ -497,7 +490,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); * code in case of failure. */ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, - int len, int dtype) + int len) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; @@ -515,17 +508,13 @@ int ubi_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf, len > vol->usable_leb_size || len & (ubi->min_io_size - 1)) return -EINVAL; - if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && - dtype != UBI_UNKNOWN) - return -EINVAL; - if (vol->upd_marker) return -EBADF; if (len == 0) return 0; - return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len, dtype); + return ubi_eba_atomic_leb_change(ubi, vol, lnum, buf, len); } EXPORT_SYMBOL_GPL(ubi_leb_change); @@ -562,7 +551,7 @@ int ubi_leb_erase(struct ubi_volume_desc *desc, int lnum) if (err) return err; - return ubi_wl_flush(ubi); + return ubi_wl_flush(ubi, vol->vol_id, lnum); } EXPORT_SYMBOL_GPL(ubi_leb_erase); @@ -626,7 +615,6 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap); * ubi_leb_map - map logical eraseblock to a physical eraseblock. * @desc: volume descriptor * @lnum: logical eraseblock number - * @dtype: expected data type * * This function maps an un-mapped logical eraseblock @lnum to a physical * eraseblock. This means, that after a successful invocation of this @@ -639,7 +627,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_unmap); * eraseblock is already mapped, and other negative error codes in case of * other failures. */ -int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) +int ubi_leb_map(struct ubi_volume_desc *desc, int lnum) { struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; @@ -652,17 +640,13 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype) if (lnum < 0 || lnum >= vol->reserved_pebs) return -EINVAL; - if (dtype != UBI_LONGTERM && dtype != UBI_SHORTTERM && - dtype != UBI_UNKNOWN) - return -EINVAL; - if (vol->upd_marker) return -EBADF; if (vol->eba_tbl[lnum] >= 0) return -EBADMSG; - return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0, dtype); + return ubi_eba_write_leb(ubi, vol, lnum, NULL, 0, 0); } EXPORT_SYMBOL_GPL(ubi_leb_map); @@ -720,6 +704,33 @@ int ubi_sync(int ubi_num) } EXPORT_SYMBOL_GPL(ubi_sync); +/** + * ubi_flush - flush UBI work queue. + * @ubi_num: UBI device to flush work queue + * @vol_id: volume id to flush for + * @lnum: logical eraseblock number to flush for + * + * This function executes all pending works for a particular volume id / logical + * eraseblock number pair. If either value is set to %UBI_ALL, then it acts as + * a wildcard for all of the corresponding volume numbers or logical + * eraseblock numbers. It returns zero in case of success and a negative error + * code in case of failure. + */ +int ubi_flush(int ubi_num, int vol_id, int lnum) +{ + struct ubi_device *ubi; + int err = 0; + + ubi = ubi_get_device(ubi_num); + if (!ubi) + return -ENODEV; + + err = ubi_wl_flush(ubi, vol_id, lnum); + ubi_put_device(ubi); + return err; +} +EXPORT_SYMBOL_GPL(ubi_flush); + BLOCKING_NOTIFIER_HEAD(ubi_notifiers); /** diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h deleted file mode 100644 index d48aef15ab5d..000000000000 --- a/drivers/mtd/ubi/scan.h +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) International Business Machines Corp., 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Artem Bityutskiy (Битюцкий Артём) - */ - -#ifndef __UBI_SCAN_H__ -#define __UBI_SCAN_H__ - -/* The erase counter value for this physical eraseblock is unknown */ -#define UBI_SCAN_UNKNOWN_EC (-1) - -/** - * struct ubi_scan_leb - scanning information about a physical eraseblock. - * @ec: erase counter (%UBI_SCAN_UNKNOWN_EC if it is unknown) - * @pnum: physical eraseblock number - * @lnum: logical eraseblock number - * @scrub: if this physical eraseblock needs scrubbing - * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB) - * @sqnum: sequence number - * @u: unions RB-tree or @list links - * @u.rb: link in the per-volume RB-tree of &struct ubi_scan_leb objects - * @u.list: link in one of the eraseblock lists - * - * One object of this type is allocated for each physical eraseblock during - * scanning. - */ -struct ubi_scan_leb { - int ec; - int pnum; - int lnum; - unsigned int scrub:1; - unsigned int copy_flag:1; - unsigned long long sqnum; - union { - struct rb_node rb; - struct list_head list; - } u; -}; - -/** - * struct ubi_scan_volume - scanning information about a volume. - * @vol_id: volume ID - * @highest_lnum: highest logical eraseblock number in this volume - * @leb_count: number of logical eraseblocks in this volume - * @vol_type: volume type - * @used_ebs: number of used logical eraseblocks in this volume (only for - * static volumes) - * @last_data_size: amount of data in the last logical eraseblock of this - * volume (always equivalent to the usable logical eraseblock - * size in case of dynamic volumes) - * @data_pad: how many bytes at the end of logical eraseblocks of this volume - * are not used (due to volume alignment) - * @compat: compatibility flags of this volume - * @rb: link in the volume RB-tree - * @root: root of the RB-tree containing all the eraseblock belonging to this - * volume (&struct ubi_scan_leb objects) - * - * One object of this type is allocated for each volume during scanning. - */ -struct ubi_scan_volume { - int vol_id; - int highest_lnum; - int leb_count; - int vol_type; - int used_ebs; - int last_data_size; - int data_pad; - int compat; - struct rb_node rb; - struct rb_root root; -}; - -/** - * struct ubi_scan_info - UBI scanning information. - * @volumes: root of the volume RB-tree - * @corr: list of corrupted physical eraseblocks - * @free: list of free physical eraseblocks - * @erase: list of physical eraseblocks which have to be erased - * @alien: list of physical eraseblocks which should not be used by UBI (e.g., - * those belonging to "preserve"-compatible internal volumes) - * @corr_peb_count: count of PEBs in the @corr list - * @empty_peb_count: count of PEBs which are presumably empty (contain only - * 0xFF bytes) - * @alien_peb_count: count of PEBs in the @alien list - * @bad_peb_count: count of bad physical eraseblocks - * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked - * as bad yet, but which look like bad - * @vols_found: number of volumes found during scanning - * @highest_vol_id: highest volume ID - * @is_empty: flag indicating whether the MTD device is empty or not - * @min_ec: lowest erase counter value - * @max_ec: highest erase counter value - * @max_sqnum: highest sequence number value - * @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 - * and so on. - */ -struct ubi_scan_info { - struct rb_root volumes; - struct list_head corr; - struct list_head free; - struct list_head erase; - struct list_head alien; - int corr_peb_count; - int empty_peb_count; - int alien_peb_count; - int bad_peb_count; - int maybe_bad_peb_count; - int vols_found; - int highest_vol_id; - int is_empty; - int min_ec; - int max_ec; - unsigned long long max_sqnum; - int mean_ec; - uint64_t ec_sum; - int ec_count; - struct kmem_cache *scan_leb_slab; -}; - -struct ubi_device; -struct ubi_vid_hdr; - -/* - * ubi_scan_move_to_list - move a PEB from the volume tree to a list. - * - * @sv: volume scanning information - * @seb: scanning eraseblock information - * @list: the list to move to - */ -static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv, - struct ubi_scan_leb *seb, - struct list_head *list) -{ - rb_erase(&seb->u.rb, &sv->root); - list_add_tail(&seb->u.list, list); -} - -int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, - int pnum, int ec, const struct ubi_vid_hdr *vid_hdr, - int bitflips); -struct ubi_scan_volume *ubi_scan_find_sv(const struct ubi_scan_info *si, - int vol_id); -struct ubi_scan_leb *ubi_scan_find_seb(const struct ubi_scan_volume *sv, - int lnum); -void ubi_scan_rm_volume(struct ubi_scan_info *si, struct ubi_scan_volume *sv); -struct ubi_scan_leb *ubi_scan_get_free_peb(struct ubi_device *ubi, - struct ubi_scan_info *si); -int ubi_scan_erase_peb(struct ubi_device *ubi, const struct ubi_scan_info *si, - int pnum, int ec); -struct ubi_scan_info *ubi_scan(struct ubi_device *ubi); -void ubi_scan_destroy_si(struct ubi_scan_info *si); - -#endif /* !__UBI_SCAN_H__ */ diff --git a/drivers/mtd/ubi/ubi-media.h b/drivers/mtd/ubi/ubi-media.h index 6fb8ec2174a5..468ffbc0eabd 100644 --- a/drivers/mtd/ubi/ubi-media.h +++ b/drivers/mtd/ubi/ubi-media.h @@ -149,10 +149,10 @@ enum { * The @image_seq field is used to validate a UBI image that has been prepared * for a UBI device. The @image_seq value can be any value, but it must be the * same on all eraseblocks. UBI will ensure that all new erase counter headers - * also contain this value, and will check the value when scanning at start-up. + * also contain this value, and will check the value when attaching the flash. * One way to make use of @image_seq is to increase its value by one every time * an image is flashed over an existing image, then, if the flashing does not - * complete, UBI will detect the error when scanning. + * complete, UBI will detect the error when attaching the media. */ struct ubi_ec_hdr { __be32 magic; @@ -298,8 +298,8 @@ struct ubi_vid_hdr { #define UBI_INT_VOL_COUNT 1 /* - * Starting ID of internal volumes. There is reserved room for 4096 internal - * volumes. + * Starting ID of internal volumes: 0x7fffefff. + * There is reserved room for 4096 internal volumes. */ #define UBI_INTERNAL_VOL_START (0x7FFFFFFF - 4096) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index b162790790a9..a1a81c9ea8ce 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -43,7 +43,6 @@ #include <asm/pgtable.h> #include "ubi-media.h" -#include "scan.h" /* Maximum number of supported UBI devices */ #define UBI_MAX_DEVICES 32 @@ -66,7 +65,10 @@ /* Background thread name pattern */ #define UBI_BGT_NAME_PATTERN "ubi_bgt%dd" -/* This marker in the EBA table means that the LEB is um-mapped */ +/* + * This marker in the EBA table means that the LEB is um-mapped. + * NOTE! It has to have the same value as %UBI_ALL. + */ #define UBI_LEB_UNMAPPED -1 /* @@ -82,6 +84,9 @@ */ #define UBI_PROT_QUEUE_LEN 10 +/* The volume ID/LEB number/erase counter is unknown */ +#define UBI_UNKNOWN -1 + /* * Error codes returned by the I/O sub-system. * @@ -222,8 +227,6 @@ struct ubi_volume_desc; * @upd_ebs: how many eraseblocks are expected to be updated * @ch_lnum: LEB number which is being changing by the atomic LEB change * operation - * @ch_dtype: data persistency type which is being changing by the atomic LEB - * change operation * @upd_bytes: how many bytes are expected to be received for volume update or * atomic LEB change * @upd_received: how many bytes were already received for volume update or @@ -270,7 +273,6 @@ struct ubi_volume { int upd_ebs; int ch_lnum; - int ch_dtype; long long upd_bytes; long long upd_received; void *upd_buf; @@ -477,6 +479,124 @@ struct ubi_device { struct ubi_debug_info *dbg; }; +/** + * struct ubi_ainf_peb - attach information about a physical eraseblock. + * @ec: erase counter (%UBI_UNKNOWN if it is unknown) + * @pnum: physical eraseblock number + * @vol_id: ID of the volume this LEB belongs to + * @lnum: logical eraseblock number + * @scrub: if this physical eraseblock needs scrubbing + * @copy_flag: this LEB is a copy (@copy_flag is set in VID header of this LEB) + * @sqnum: sequence number + * @u: unions RB-tree or @list links + * @u.rb: link in the per-volume RB-tree of &struct ubi_ainf_peb objects + * @u.list: link in one of the eraseblock lists + * + * One object of this type is allocated for each physical eraseblock when + * attaching an MTD device. Note, if this PEB does not belong to any LEB / + * volume, the @vol_id and @lnum fields are initialized to %UBI_UNKNOWN. + */ +struct ubi_ainf_peb { + int ec; + int pnum; + int vol_id; + int lnum; + unsigned int scrub:1; + unsigned int copy_flag:1; + unsigned long long sqnum; + union { + struct rb_node rb; + struct list_head list; + } u; +}; + +/** + * struct ubi_ainf_volume - attaching information about a volume. + * @vol_id: volume ID + * @highest_lnum: highest logical eraseblock number in this volume + * @leb_count: number of logical eraseblocks in this volume + * @vol_type: volume type + * @used_ebs: number of used logical eraseblocks in this volume (only for + * static volumes) + * @last_data_size: amount of data in the last logical eraseblock of this + * volume (always equivalent to the usable logical eraseblock + * size in case of dynamic volumes) + * @data_pad: how many bytes at the end of logical eraseblocks of this volume + * are not used (due to volume alignment) + * @compat: compatibility flags of this volume + * @rb: link in the volume RB-tree + * @root: root of the RB-tree containing all the eraseblock belonging to this + * volume (&struct ubi_ainf_peb objects) + * + * One object of this type is allocated for each volume when attaching an MTD + * device. + */ +struct ubi_ainf_volume { + int vol_id; + int highest_lnum; + int leb_count; + int vol_type; + int used_ebs; + int last_data_size; + int data_pad; + int compat; + struct rb_node rb; + struct rb_root root; +}; + +/** + * struct ubi_attach_info - MTD device attaching information. + * @volumes: root of the volume RB-tree + * @corr: list of corrupted physical eraseblocks + * @free: list of free physical eraseblocks + * @erase: list of physical eraseblocks which have to be erased + * @alien: list of physical eraseblocks which should not be used by UBI (e.g., + * those belonging to "preserve"-compatible internal volumes) + * @corr_peb_count: count of PEBs in the @corr list + * @empty_peb_count: count of PEBs which are presumably empty (contain only + * 0xFF bytes) + * @alien_peb_count: count of PEBs in the @alien list + * @bad_peb_count: count of bad physical eraseblocks + * @maybe_bad_peb_count: count of bad physical eraseblocks which are not marked + * as bad yet, but which look like bad + * @vols_found: number of volumes found + * @highest_vol_id: highest volume ID + * @is_empty: flag indicating whether the MTD device is empty or not + * @min_ec: lowest erase counter value + * @max_ec: highest erase counter value + * @max_sqnum: highest sequence number value + * @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 + * @aeb_slab_cache: slab cache for &struct ubi_ainf_peb objects + * + * 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 + * error-recovery and so on. + */ +struct ubi_attach_info { + struct rb_root volumes; + struct list_head corr; + struct list_head free; + struct list_head erase; + struct list_head alien; + int corr_peb_count; + int empty_peb_count; + int alien_peb_count; + int bad_peb_count; + int maybe_bad_peb_count; + int vols_found; + int highest_vol_id; + int is_empty; + int min_ec; + int max_ec; + unsigned long long max_sqnum; + int mean_ec; + uint64_t ec_sum; + int ec_count; + struct kmem_cache *aeb_slab_cache; +}; + #include "debug.h" extern struct kmem_cache *ubi_wl_entry_slab; @@ -487,12 +607,23 @@ extern struct class *ubi_class; extern struct mutex ubi_devices_mutex; extern struct blocking_notifier_head ubi_notifiers; +/* scan.c */ +int ubi_add_to_av(struct ubi_device *ubi, struct ubi_attach_info *ai, int pnum, + int ec, const struct ubi_vid_hdr *vid_hdr, int bitflips); +struct ubi_ainf_volume *ubi_find_av(const struct ubi_attach_info *ai, + int vol_id); +void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av); +struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi, + struct ubi_attach_info *ai); +int ubi_attach(struct ubi_device *ubi); +void ubi_destroy_ai(struct ubi_attach_info *ai); + /* vtbl.c */ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, struct ubi_vtbl_record *vtbl_rec); int ubi_vtbl_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list); -int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si); +int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai); /* vmt.c */ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req); @@ -525,22 +656,22 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, void *buf, int offset, int len, int check); int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, - const void *buf, int offset, int len, int dtype); + const void *buf, int offset, int len); int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, - int lnum, const void *buf, int len, int dtype, - int used_ebs); + int lnum, const void *buf, int len, int used_ebs); int ubi_eba_atomic_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, - int lnum, const void *buf, int len, int dtype); + int lnum, const void *buf, int len); int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, struct ubi_vid_hdr *vid_hdr); -int ubi_eba_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); +int ubi_eba_init(struct ubi_device *ubi, struct ubi_attach_info *ai); /* wl.c */ -int ubi_wl_get_peb(struct ubi_device *ubi, int dtype); -int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture); -int ubi_wl_flush(struct ubi_device *ubi); +int ubi_wl_get_peb(struct ubi_device *ubi); +int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, + int pnum, int torture); +int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum); int ubi_wl_scrub_peb(struct ubi_device *ubi, int pnum); -int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si); +int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai); void ubi_wl_close(struct ubi_device *ubi); int ubi_thread(void *u); @@ -573,6 +704,7 @@ int ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb); int ubi_enumerate_volumes(struct notifier_block *nb); +void ubi_free_internal_volumes(struct ubi_device *ubi); /* kapi.c */ void ubi_do_get_device_info(struct ubi_device *ubi, struct ubi_device_info *di); @@ -593,6 +725,21 @@ void ubi_do_get_volume_info(struct ubi_device *ubi, struct ubi_volume *vol, rb = rb_next(rb), \ pos = (rb ? container_of(rb, typeof(*pos), member) : NULL)) +/* + * ubi_move_aeb_to_list - move a PEB from the volume tree to a list. + * + * @av: volume attaching information + * @aeb: attaching eraseblock information + * @list: the list to move to + */ +static inline void ubi_move_aeb_to_list(struct ubi_ainf_volume *av, + struct ubi_ainf_peb *aeb, + struct list_head *list) +{ + rb_erase(&aeb->u.rb, &av->root); + list_add_tail(&aeb->u.list, list); +} + /** * ubi_zalloc_vid_hdr - allocate a volume identifier header object. * @ubi: UBI device description object @@ -667,7 +814,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi) if (!ubi->ro_mode) { ubi->ro_mode = 1; ubi_warn("switch to read-only mode"); - ubi_dbg_dump_stack(); + dump_stack(); } } diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 425bf5a3edd4..9f2ebd8750e7 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -147,7 +147,7 @@ int ubi_start_update(struct ubi_device *ubi, struct ubi_volume *vol, } if (bytes == 0) { - err = ubi_wl_flush(ubi); + err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL); if (err) return err; @@ -186,14 +186,12 @@ int ubi_start_leb_change(struct ubi_device *ubi, struct ubi_volume *vol, dbg_gen("start changing LEB %d:%d, %u bytes", vol->vol_id, req->lnum, req->bytes); if (req->bytes == 0) - return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0, - req->dtype); + return ubi_eba_atomic_leb_change(ubi, vol, req->lnum, NULL, 0); vol->upd_bytes = req->bytes; vol->upd_received = 0; vol->changing_leb = 1; vol->ch_lnum = req->lnum; - vol->ch_dtype = req->dtype; vol->upd_buf = vmalloc(req->bytes); if (!vol->upd_buf) @@ -246,8 +244,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, return 0; } - err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len, - UBI_UNKNOWN); + err = ubi_eba_write_leb(ubi, vol, lnum, buf, 0, len); } else { /* * When writing static volume, and this is the last logical @@ -259,8 +256,7 @@ static int write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, * contain zeros, not random trash. */ memset(buf + len, 0, vol->usable_leb_size - len); - err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, - UBI_UNKNOWN, used_ebs); + err = ubi_eba_write_leb_st(ubi, vol, lnum, buf, len, used_ebs); } return err; @@ -365,7 +361,7 @@ int ubi_more_update_data(struct ubi_device *ubi, struct ubi_volume *vol, ubi_assert(vol->upd_received <= vol->upd_bytes); if (vol->upd_received == vol->upd_bytes) { - err = ubi_wl_flush(ubi); + err = ubi_wl_flush(ubi, UBI_ALL, UBI_ALL); if (err) return err; /* The update is finished, clear the update marker */ @@ -421,7 +417,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol, len - vol->upd_bytes); len = ubi_calc_data_len(ubi, vol->upd_buf, len); err = ubi_eba_atomic_leb_change(ubi, vol, vol->ch_lnum, - vol->upd_buf, len, UBI_UNKNOWN); + vol->upd_buf, len); if (err) return err; } diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 863835f4aefe..0669cff8ac3c 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -29,11 +29,7 @@ #include <linux/export.h> #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG -static int paranoid_check_volumes(struct ubi_device *ubi); -#else -#define paranoid_check_volumes(ubi) 0 -#endif +static int self_check_volumes(struct ubi_device *ubi); static ssize_t vol_attribute_show(struct device *dev, struct device_attribute *attr, char *buf); @@ -227,7 +223,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) } if (vol_id == UBI_VOL_NUM_AUTO) { - dbg_err("out of volume IDs"); + ubi_err("out of volume IDs"); err = -ENFILE; goto out_unlock; } @@ -241,7 +237,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) /* Ensure that this volume does not exist */ err = -EEXIST; if (ubi->volumes[vol_id]) { - dbg_err("volume %d already exists", vol_id); + ubi_err("volume %d already exists", vol_id); goto out_unlock; } @@ -250,7 +246,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) if (ubi->volumes[i] && ubi->volumes[i]->name_len == req->name_len && !strcmp(ubi->volumes[i]->name, req->name)) { - dbg_err("volume \"%s\" exists (ID %d)", req->name, i); + ubi_err("volume \"%s\" exists (ID %d)", req->name, i); goto out_unlock; } @@ -261,9 +257,9 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) /* Reserve physical eraseblocks */ if (vol->reserved_pebs > ubi->avail_pebs) { - dbg_err("not enough PEBs, only %d available", ubi->avail_pebs); + ubi_err("not enough PEBs, only %d available", ubi->avail_pebs); if (ubi->corr_peb_count) - dbg_err("%d PEBs are corrupted and not used", + ubi_err("%d PEBs are corrupted and not used", ubi->corr_peb_count); err = -ENOSPC; goto out_unlock; @@ -284,7 +280,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) * Finish all pending erases because there may be some LEBs belonging * to the same volume ID. */ - err = ubi_wl_flush(ubi); + err = ubi_wl_flush(ubi, vol_id, UBI_ALL); if (err) goto out_acc; @@ -360,8 +356,7 @@ int ubi_create_volume(struct ubi_device *ubi, struct ubi_mkvol_req *req) spin_unlock(&ubi->volumes_lock); ubi_volume_notify(ubi, vol, UBI_VOLUME_ADDED); - if (paranoid_check_volumes(ubi)) - dbg_err("check failed while creating volume %d", vol_id); + self_check_volumes(ubi); return err; out_sysfs: @@ -461,8 +456,8 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) spin_unlock(&ubi->volumes_lock); ubi_volume_notify(ubi, vol, UBI_VOLUME_REMOVED); - if (!no_vtbl && paranoid_check_volumes(ubi)) - dbg_err("check failed while removing volume %d", vol_id); + if (!no_vtbl) + self_check_volumes(ubi); return err; @@ -500,7 +495,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) if (vol->vol_type == UBI_STATIC_VOLUME && reserved_pebs < vol->used_ebs) { - dbg_err("too small size %d, %d LEBs contain data", + ubi_err("too small size %d, %d LEBs contain data", reserved_pebs, vol->used_ebs); return -EINVAL; } @@ -529,10 +524,10 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) if (pebs > 0) { spin_lock(&ubi->volumes_lock); if (pebs > ubi->avail_pebs) { - dbg_err("not enough PEBs: requested %d, available %d", + ubi_err("not enough PEBs: requested %d, available %d", pebs, ubi->avail_pebs); if (ubi->corr_peb_count) - dbg_err("%d PEBs are corrupted and not used", + ubi_err("%d PEBs are corrupted and not used", ubi->corr_peb_count); spin_unlock(&ubi->volumes_lock); err = -ENOSPC; @@ -588,8 +583,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs) } ubi_volume_notify(ubi, vol, UBI_VOLUME_RESIZED); - if (paranoid_check_volumes(ubi)) - dbg_err("check failed while re-sizing volume %d", vol_id); + self_check_volumes(ubi); return err; out_acc: @@ -638,8 +632,8 @@ int ubi_rename_volumes(struct ubi_device *ubi, struct list_head *rename_list) } } - if (!err && paranoid_check_volumes(ubi)) - ; + if (!err) + self_check_volumes(ubi); return err; } @@ -686,8 +680,7 @@ int ubi_add_volume(struct ubi_device *ubi, struct ubi_volume *vol) return err; } - if (paranoid_check_volumes(ubi)) - dbg_err("check failed while adding volume %d", vol_id); + self_check_volumes(ubi); return err; out_cdev: @@ -712,16 +705,14 @@ void ubi_free_volume(struct ubi_device *ubi, struct ubi_volume *vol) volume_sysfs_close(vol); } -#ifdef CONFIG_MTD_UBI_DEBUG - /** - * paranoid_check_volume - check volume information. + * self_check_volume - check volume information. * @ubi: UBI device description object * @vol_id: volume ID * * Returns zero if volume is all right and a a negative error code if not. */ -static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) +static int self_check_volume(struct ubi_device *ubi, int vol_id) { int idx = vol_id2idx(ubi, vol_id); int reserved_pebs, alignment, data_pad, vol_type, name_len, upd_marker; @@ -771,7 +762,7 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) } if (vol->upd_marker && vol->corrupted) { - dbg_err("update marker and corrupted simultaneously"); + ubi_err("update marker and corrupted simultaneously"); goto fail; } @@ -853,22 +844,22 @@ static int paranoid_check_volume(struct ubi_device *ubi, int vol_id) return 0; fail: - ubi_err("paranoid check failed for volume %d", vol_id); + ubi_err("self-check failed for volume %d", vol_id); if (vol) - ubi_dbg_dump_vol_info(vol); - ubi_dbg_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); + ubi_dump_vol_info(vol); + ubi_dump_vtbl_record(&ubi->vtbl[vol_id], vol_id); dump_stack(); spin_unlock(&ubi->volumes_lock); return -EINVAL; } /** - * paranoid_check_volumes - check information about all volumes. + * self_check_volumes - check information about all volumes. * @ubi: UBI device description object * * Returns zero if volumes are all right and a a negative error code if not. */ -static int paranoid_check_volumes(struct ubi_device *ubi) +static int self_check_volumes(struct ubi_device *ubi) { int i, err = 0; @@ -876,11 +867,10 @@ static int paranoid_check_volumes(struct ubi_device *ubi) return 0; for (i = 0; i < ubi->vtbl_slots; i++) { - err = paranoid_check_volume(ubi, i); + err = self_check_volume(ubi, i); if (err) break; } return err; } -#endif diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index 17cec0c01544..437bc193e170 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -37,16 +37,15 @@ * LEB 1. This scheme guarantees recoverability from unclean reboots. * * In this UBI implementation the on-flash volume table does not contain any - * information about how many data static volumes contain. This information may - * be found from the scanning data. + * information about how much data static volumes contain. * * But it would still be beneficial to store this information in the volume * table. For example, suppose we have a static volume X, and all its physical * eraseblocks became bad for some reasons. Suppose we are attaching the - * corresponding MTD device, the scanning has found no logical eraseblocks + * corresponding MTD device, for some reason we find no logical eraseblocks * corresponding to the volume X. According to the volume table volume X does * exist. So we don't know whether it is just empty or all its physical - * eraseblocks went bad. So we cannot alarm the user about this corruption. + * eraseblocks went bad. So we cannot alarm the user properly. * * The volume table also stores so-called "update marker", which is used for * volume updates. Before updating the volume, the update marker is set, and @@ -62,11 +61,7 @@ #include <asm/div64.h> #include "ubi.h" -#ifdef CONFIG_MTD_UBI_DEBUG -static void paranoid_vtbl_check(const struct ubi_device *ubi); -#else -#define paranoid_vtbl_check(ubi) -#endif +static void self_vtbl_check(const struct ubi_device *ubi); /* Empty volume table record */ static struct ubi_vtbl_record empty_vtbl_record; @@ -106,12 +101,12 @@ int ubi_change_vtbl_record(struct ubi_device *ubi, int idx, return err; err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, - ubi->vtbl_size, UBI_LONGTERM); + ubi->vtbl_size); if (err) return err; } - paranoid_vtbl_check(ubi); + self_vtbl_check(ubi); return 0; } @@ -158,7 +153,7 @@ int ubi_vtbl_rename_volumes(struct ubi_device *ubi, return err; err = ubi_eba_write_leb(ubi, layout_vol, i, ubi->vtbl, 0, - ubi->vtbl_size, UBI_LONGTERM); + ubi->vtbl_size); if (err) return err; } @@ -197,7 +192,7 @@ static int vtbl_check(const struct ubi_device *ubi, if (be32_to_cpu(vtbl[i].crc) != crc) { ubi_err("bad CRC at record %u: %#08x, not %#08x", i, crc, be32_to_cpu(vtbl[i].crc)); - ubi_dbg_dump_vtbl_record(&vtbl[i], i); + ubi_dump_vtbl_record(&vtbl[i], i); return 1; } @@ -229,7 +224,7 @@ static int vtbl_check(const struct ubi_device *ubi, n = ubi->leb_size % alignment; if (data_pad != n) { - dbg_err("bad data_pad, has to be %d", n); + ubi_err("bad data_pad, has to be %d", n); err = 6; goto bad; } @@ -245,7 +240,7 @@ static int vtbl_check(const struct ubi_device *ubi, } if (reserved_pebs > ubi->good_peb_count) { - dbg_err("too large reserved_pebs %d, good PEBs %d", + ubi_err("too large reserved_pebs %d, good PEBs %d", reserved_pebs, ubi->good_peb_count); err = 9; goto bad; @@ -277,8 +272,8 @@ static int vtbl_check(const struct ubi_device *ubi, !strncmp(vtbl[i].name, vtbl[n].name, len1)) { ubi_err("volumes %d and %d have the same name" " \"%s\"", i, n, vtbl[i].name); - ubi_dbg_dump_vtbl_record(&vtbl[i], i); - ubi_dbg_dump_vtbl_record(&vtbl[n], n); + ubi_dump_vtbl_record(&vtbl[i], i); + ubi_dump_vtbl_record(&vtbl[n], n); return -EINVAL; } } @@ -288,26 +283,26 @@ static int vtbl_check(const struct ubi_device *ubi, bad: ubi_err("volume table check failed: record %d, error %d", i, err); - ubi_dbg_dump_vtbl_record(&vtbl[i], i); + ubi_dump_vtbl_record(&vtbl[i], i); return -EINVAL; } /** * create_vtbl - create a copy of volume table. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * @copy: number of the volume table copy * @vtbl: contents of the volume table * * This function returns zero in case of success and a negative error code in * case of failure. */ -static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, +static int create_vtbl(struct ubi_device *ubi, struct ubi_attach_info *ai, int copy, void *vtbl) { int err, tries = 0; struct ubi_vid_hdr *vid_hdr; - struct ubi_scan_leb *new_seb; + struct ubi_ainf_peb *new_aeb; ubi_msg("create volume table (copy #%d)", copy + 1); @@ -316,9 +311,9 @@ static int create_vtbl(struct ubi_device *ubi, struct ubi_scan_info *si, return -ENOMEM; retry: - new_seb = ubi_scan_get_free_peb(ubi, si); - if (IS_ERR(new_seb)) { - err = PTR_ERR(new_seb); + new_aeb = ubi_early_get_peb(ubi, ai); + if (IS_ERR(new_aeb)) { + err = PTR_ERR(new_aeb); goto out_free; } @@ -328,25 +323,24 @@ retry: vid_hdr->data_size = vid_hdr->used_ebs = vid_hdr->data_pad = cpu_to_be32(0); vid_hdr->lnum = cpu_to_be32(copy); - vid_hdr->sqnum = cpu_to_be64(++si->max_sqnum); + vid_hdr->sqnum = cpu_to_be64(++ai->max_sqnum); /* The EC header is already there, write the VID header */ - err = ubi_io_write_vid_hdr(ubi, new_seb->pnum, vid_hdr); + err = ubi_io_write_vid_hdr(ubi, new_aeb->pnum, vid_hdr); if (err) goto write_error; /* Write the layout volume contents */ - err = ubi_io_write_data(ubi, vtbl, new_seb->pnum, 0, ubi->vtbl_size); + err = ubi_io_write_data(ubi, vtbl, new_aeb->pnum, 0, ubi->vtbl_size); if (err) goto write_error; /* - * And add it to the scanning information. Don't delete the old version - * of this LEB as it will be deleted and freed in 'ubi_scan_add_used()'. + * And add it to the attaching information. Don't delete the old version + * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'. */ - err = ubi_scan_add_used(ubi, si, new_seb->pnum, new_seb->ec, - vid_hdr, 0); - kfree(new_seb); + err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0); + kfree(new_aeb); ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -356,10 +350,10 @@ write_error: * Probably this physical eraseblock went bad, try to pick * another one. */ - list_add(&new_seb->u.list, &si->erase); + list_add(&new_aeb->u.list, &ai->erase); goto retry; } - kfree(new_seb); + kfree(new_aeb); out_free: ubi_free_vid_hdr(ubi, vid_hdr); return err; @@ -369,20 +363,20 @@ out_free: /** * process_lvol - process the layout volume. * @ubi: UBI device description object - * @si: scanning information - * @sv: layout volume scanning information + * @ai: attaching information + * @av: layout volume attaching information * * This function is responsible for reading the layout volume, ensuring it is * not corrupted, and recovering from corruptions if needed. Returns volume * table in case of success and a negative error code in case of failure. */ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, - struct ubi_scan_info *si, - struct ubi_scan_volume *sv) + struct ubi_attach_info *ai, + struct ubi_ainf_volume *av) { int err; struct rb_node *rb; - struct ubi_scan_leb *seb; + struct ubi_ainf_peb *aeb; struct ubi_vtbl_record *leb[UBI_LAYOUT_VOLUME_EBS] = { NULL, NULL }; int leb_corrupted[UBI_LAYOUT_VOLUME_EBS] = {1, 1}; @@ -414,14 +408,14 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, dbg_gen("check layout volume"); /* Read both LEB 0 and LEB 1 into memory */ - ubi_rb_for_each_entry(rb, seb, &sv->root, u.rb) { - leb[seb->lnum] = vzalloc(ubi->vtbl_size); - if (!leb[seb->lnum]) { + ubi_rb_for_each_entry(rb, aeb, &av->root, u.rb) { + leb[aeb->lnum] = vzalloc(ubi->vtbl_size); + if (!leb[aeb->lnum]) { err = -ENOMEM; goto out_free; } - err = ubi_io_read_data(ubi, leb[seb->lnum], seb->pnum, 0, + err = ubi_io_read_data(ubi, leb[aeb->lnum], aeb->pnum, 0, ubi->vtbl_size); if (err == UBI_IO_BITFLIPS || mtd_is_eccerr(err)) /* @@ -429,12 +423,12 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, * uncorrectable ECC error, but we have our own CRC and * the data will be checked later. If the data is OK, * the PEB will be scrubbed (because we set - * seb->scrub). If the data is not OK, the contents of + * aeb->scrub). If the data is not OK, the contents of * the PEB will be recovered from the second copy, and - * seb->scrub will be cleared in - * 'ubi_scan_add_used()'. + * aeb->scrub will be cleared in + * 'ubi_add_to_av()'. */ - seb->scrub = 1; + aeb->scrub = 1; else if (err) goto out_free; } @@ -453,7 +447,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, ubi->vtbl_size); if (leb_corrupted[1]) { ubi_warn("volume table copy #2 is corrupted"); - err = create_vtbl(ubi, si, 1, leb[0]); + err = create_vtbl(ubi, ai, 1, leb[0]); if (err) goto out_free; ubi_msg("volume table was restored"); @@ -476,7 +470,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, } ubi_warn("volume table copy #1 is corrupted"); - err = create_vtbl(ubi, si, 0, leb[1]); + err = create_vtbl(ubi, ai, 0, leb[1]); if (err) goto out_free; ubi_msg("volume table was restored"); @@ -494,13 +488,13 @@ out_free: /** * create_empty_lvol - create empty layout volume. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * This function returns volume table contents in case of success and a * negative error code in case of failure. */ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, - struct ubi_scan_info *si) + struct ubi_attach_info *ai) { int i; struct ubi_vtbl_record *vtbl; @@ -515,7 +509,7 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, for (i = 0; i < UBI_LAYOUT_VOLUME_EBS; i++) { int err; - err = create_vtbl(ubi, si, i, vtbl); + err = create_vtbl(ubi, ai, i, vtbl); if (err) { vfree(vtbl); return ERR_PTR(err); @@ -528,18 +522,19 @@ static struct ubi_vtbl_record *create_empty_lvol(struct ubi_device *ubi, /** * init_volumes - initialize volume information for existing volumes. * @ubi: UBI device description object - * @si: scanning information + * @ai: scanning information * @vtbl: volume table * * This function allocates volume description objects for existing volumes. * Returns zero in case of success and a negative error code in case of * failure. */ -static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, +static int init_volumes(struct ubi_device *ubi, + const struct ubi_attach_info *ai, const struct ubi_vtbl_record *vtbl) { int i, reserved_pebs = 0; - struct ubi_scan_volume *sv; + struct ubi_ainf_volume *av; struct ubi_volume *vol; for (i = 0; i < ubi->vtbl_slots; i++) { @@ -595,8 +590,8 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, } /* Static volumes only */ - sv = ubi_scan_find_sv(si, i); - if (!sv) { + av = ubi_find_av(ai, i); + if (!av) { /* * No eraseblocks belonging to this volume found. We * don't actually know whether this static volume is @@ -608,22 +603,22 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, continue; } - if (sv->leb_count != sv->used_ebs) { + if (av->leb_count != av->used_ebs) { /* * We found a static volume which misses several * eraseblocks. Treat it as corrupted. */ ubi_warn("static volume %d misses %d LEBs - corrupted", - sv->vol_id, sv->used_ebs - sv->leb_count); + av->vol_id, av->used_ebs - av->leb_count); vol->corrupted = 1; continue; } - vol->used_ebs = sv->used_ebs; + vol->used_ebs = av->used_ebs; vol->used_bytes = (long long)(vol->used_ebs - 1) * vol->usable_leb_size; - vol->used_bytes += sv->last_data_size; - vol->last_eb_bytes = sv->last_data_size; + vol->used_bytes += av->last_data_size; + vol->last_eb_bytes = av->last_data_size; } /* And add the layout volume */ @@ -664,105 +659,104 @@ static int init_volumes(struct ubi_device *ubi, const struct ubi_scan_info *si, } /** - * check_sv - check volume scanning information. + * check_av - check volume attaching information. * @vol: UBI volume description object - * @sv: volume scanning information + * @av: volume attaching information * - * This function returns zero if the volume scanning information is consistent + * This function returns zero if the volume attaching information is consistent * to the data read from the volume tabla, and %-EINVAL if not. */ -static int check_sv(const struct ubi_volume *vol, - const struct ubi_scan_volume *sv) +static int check_av(const struct ubi_volume *vol, + const struct ubi_ainf_volume *av) { int err; - if (sv->highest_lnum >= vol->reserved_pebs) { + if (av->highest_lnum >= vol->reserved_pebs) { err = 1; goto bad; } - if (sv->leb_count > vol->reserved_pebs) { + if (av->leb_count > vol->reserved_pebs) { err = 2; goto bad; } - if (sv->vol_type != vol->vol_type) { + if (av->vol_type != vol->vol_type) { err = 3; goto bad; } - if (sv->used_ebs > vol->reserved_pebs) { + if (av->used_ebs > vol->reserved_pebs) { err = 4; goto bad; } - if (sv->data_pad != vol->data_pad) { + if (av->data_pad != vol->data_pad) { err = 5; goto bad; } return 0; bad: - ubi_err("bad scanning information, error %d", err); - ubi_dbg_dump_sv(sv); - ubi_dbg_dump_vol_info(vol); + ubi_err("bad attaching information, error %d", err); + ubi_dump_av(av); + ubi_dump_vol_info(vol); return -EINVAL; } /** - * check_scanning_info - check that scanning information. + * check_attaching_info - check that attaching information. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * Even though we protect on-flash data by CRC checksums, we still don't trust - * the media. This function ensures that scanning information is consistent to - * the information read from the volume table. Returns zero if the scanning + * the media. This function ensures that attaching information is consistent to + * the information read from the volume table. Returns zero if the attaching * information is OK and %-EINVAL if it is not. */ -static int check_scanning_info(const struct ubi_device *ubi, - struct ubi_scan_info *si) +static int check_attaching_info(const struct ubi_device *ubi, + struct ubi_attach_info *ai) { int err, i; - struct ubi_scan_volume *sv; + struct ubi_ainf_volume *av; struct ubi_volume *vol; - if (si->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) { - ubi_err("scanning found %d volumes, maximum is %d + %d", - si->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots); + if (ai->vols_found > UBI_INT_VOL_COUNT + ubi->vtbl_slots) { + ubi_err("found %d volumes while attaching, maximum is %d + %d", + ai->vols_found, UBI_INT_VOL_COUNT, ubi->vtbl_slots); return -EINVAL; } - if (si->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && - si->highest_vol_id < UBI_INTERNAL_VOL_START) { - ubi_err("too large volume ID %d found by scanning", - si->highest_vol_id); + if (ai->highest_vol_id >= ubi->vtbl_slots + UBI_INT_VOL_COUNT && + ai->highest_vol_id < UBI_INTERNAL_VOL_START) { + ubi_err("too large volume ID %d found", ai->highest_vol_id); return -EINVAL; } for (i = 0; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { cond_resched(); - sv = ubi_scan_find_sv(si, i); + av = ubi_find_av(ai, i); vol = ubi->volumes[i]; if (!vol) { - if (sv) - ubi_scan_rm_volume(si, sv); + if (av) + ubi_remove_av(ai, av); continue; } if (vol->reserved_pebs == 0) { ubi_assert(i < ubi->vtbl_slots); - if (!sv) + if (!av) continue; /* - * During scanning we found a volume which does not + * During attaching we found a volume which does not * exist according to the information in the volume * table. This must have happened due to an unclean * reboot while the volume was being removed. Discard * these eraseblocks. */ - ubi_msg("finish volume %d removal", sv->vol_id); - ubi_scan_rm_volume(si, sv); - } else if (sv) { - err = check_sv(vol, sv); + ubi_msg("finish volume %d removal", av->vol_id); + ubi_remove_av(ai, av); + } else if (av) { + err = check_av(vol, av); if (err) return err; } @@ -774,16 +768,16 @@ static int check_scanning_info(const struct ubi_device *ubi, /** * ubi_read_volume_table - read the volume table. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * This function reads volume table, checks it, recover from errors if needed, * or creates it if needed. Returns zero in case of success and a negative * error code in case of failure. */ -int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) +int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_attach_info *ai) { int i, err; - struct ubi_scan_volume *sv; + struct ubi_ainf_volume *av; empty_vtbl_record.crc = cpu_to_be32(0xf116c36b); @@ -798,8 +792,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) ubi->vtbl_size = ubi->vtbl_slots * UBI_VTBL_RECORD_SIZE; ubi->vtbl_size = ALIGN(ubi->vtbl_size, ubi->min_io_size); - sv = ubi_scan_find_sv(si, UBI_LAYOUT_VOLUME_ID); - if (!sv) { + av = ubi_find_av(ai, UBI_LAYOUT_VOLUME_ID); + if (!av) { /* * No logical eraseblocks belonging to the layout volume were * found. This could mean that the flash is just empty. In @@ -808,8 +802,8 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) * But if flash is not empty this must be a corruption or the * MTD device just contains garbage. */ - if (si->is_empty) { - ubi->vtbl = create_empty_lvol(ubi, si); + if (ai->is_empty) { + ubi->vtbl = create_empty_lvol(ubi, ai); if (IS_ERR(ubi->vtbl)) return PTR_ERR(ubi->vtbl); } else { @@ -817,14 +811,14 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) return -EINVAL; } } else { - if (sv->leb_count > UBI_LAYOUT_VOLUME_EBS) { + if (av->leb_count > UBI_LAYOUT_VOLUME_EBS) { /* This must not happen with proper UBI images */ - dbg_err("too many LEBs (%d) in layout volume", - sv->leb_count); + ubi_err("too many LEBs (%d) in layout volume", + av->leb_count); return -EINVAL; } - ubi->vtbl = process_lvol(ubi, si, sv); + ubi->vtbl = process_lvol(ubi, ai, av); if (IS_ERR(ubi->vtbl)) return PTR_ERR(ubi->vtbl); } @@ -835,15 +829,15 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) * The layout volume is OK, initialize the corresponding in-RAM data * structures. */ - err = init_volumes(ubi, si, ubi->vtbl); + err = init_volumes(ubi, ai, ubi->vtbl); if (err) goto out_free; /* - * Make sure that the scanning information is consistent to the + * Make sure that the attaching information is consistent to the * information stored in the volume table. */ - err = check_scanning_info(ubi, si); + err = check_attaching_info(ubi, ai); if (err) goto out_free; @@ -858,21 +852,17 @@ out_free: return err; } -#ifdef CONFIG_MTD_UBI_DEBUG - /** - * paranoid_vtbl_check - check volume table. + * self_vtbl_check - check volume table. * @ubi: UBI device description object */ -static void paranoid_vtbl_check(const struct ubi_device *ubi) +static void self_vtbl_check(const struct ubi_device *ubi) { if (!ubi->dbg->chk_gen) return; if (vtbl_check(ubi, ubi->vtbl)) { - ubi_err("paranoid check failed"); + ubi_err("self-check failed"); BUG(); } } - -#endif /* CONFIG_MTD_UBI_DEBUG */ diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 7c1a9bf8ac86..9df100a4ec38 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -41,12 +41,6 @@ * physical eraseblocks with low erase counter to free physical eraseblocks * with high erase counter. * - * The 'ubi_wl_get_peb()' function accepts data type hints which help to pick - * an "optimal" physical eraseblock. For example, when it is known that the - * physical eraseblock will be "put" soon because it contains short-term data, - * the WL sub-system may pick a free physical eraseblock with low erase - * counter, and so forth. - * * If the WL sub-system fails to erase a physical eraseblock, it marks it as * bad. * @@ -70,8 +64,7 @@ * to the user; instead, we first want to let users fill them up with data; * * o there is a chance that the user will put the physical eraseblock very - * soon, so it makes sense not to move it for some time, but wait; this is - * especially important in case of "short term" physical eraseblocks. + * soon, so it makes sense not to move it for some time, but wait. * * Physical eraseblocks stay protected only for limited time. But the "time" is * measured in erase cycles in this case. This is implemented with help of the @@ -147,6 +140,8 @@ * @list: a link in the list of pending works * @func: worker function * @e: physical eraseblock to erase + * @vol_id: the volume ID on which this erasure is being performed + * @lnum: the logical eraseblock number * @torture: if the physical eraseblock has to be tortured * * The @func pointer points to the worker function. If the @cancel argument is @@ -159,21 +154,16 @@ struct ubi_work { 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 vol_id; + int lnum; int torture; }; -#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(const struct ubi_device *ubi, - struct ubi_wl_entry *e, - struct rb_root *root); -static int paranoid_check_in_pq(const struct ubi_device *ubi, - struct ubi_wl_entry *e); -#else -#define paranoid_check_ec(ubi, pnum, ec) 0 -#define paranoid_check_in_wl_tree(ubi, e, root) -#define paranoid_check_in_pq(ubi, e) 0 -#endif +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); /** * wl_tree_add - add a wear-leveling entry to a WL RB-tree. @@ -383,19 +373,15 @@ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int diff) /** * ubi_wl_get_peb - get a physical eraseblock. * @ubi: UBI device description object - * @dtype: type of data which will be stored in this physical eraseblock * * This function returns a physical eraseblock in case of success and a * negative error code in case of failure. Might sleep. */ -int ubi_wl_get_peb(struct ubi_device *ubi, int dtype) +int ubi_wl_get_peb(struct ubi_device *ubi) { int err; struct ubi_wl_entry *e, *first, *last; - ubi_assert(dtype == UBI_LONGTERM || dtype == UBI_SHORTTERM || - dtype == UBI_UNKNOWN); - retry: spin_lock(&ubi->wl_lock); if (!ubi->free.rb_node) { @@ -413,45 +399,15 @@ retry: goto retry; } - switch (dtype) { - case UBI_LONGTERM: - /* - * For long term data we pick a physical eraseblock with high - * erase counter. But the highest erase counter we can pick is - * bounded by the the lowest erase counter plus - * %WL_FREE_MAX_DIFF. - */ - e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); - break; - case UBI_UNKNOWN: - /* - * For unknown data we pick a physical eraseblock with medium - * erase counter. But we by no means can pick a physical - * eraseblock with erase counter greater or equivalent than the - * lowest erase counter plus %WL_FREE_MAX_DIFF/2. - */ - first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, - u.rb); - last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb); - - if (last->ec - first->ec < WL_FREE_MAX_DIFF) - e = rb_entry(ubi->free.rb_node, - struct ubi_wl_entry, u.rb); - else - e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2); - break; - case UBI_SHORTTERM: - /* - * For short term data we pick a physical eraseblock with the - * lowest erase counter as we expect it will be erased soon. - */ - e = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb); - break; - default: - BUG(); - } + first = rb_entry(rb_first(&ubi->free), struct ubi_wl_entry, u.rb); + last = rb_entry(rb_last(&ubi->free), struct ubi_wl_entry, u.rb); + + if (last->ec - first->ec < WL_FREE_MAX_DIFF) + e = rb_entry(ubi->free.rb_node, struct ubi_wl_entry, u.rb); + else + e = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF/2); - paranoid_check_in_wl_tree(ubi, e, &ubi->free); + self_check_in_wl_tree(ubi, e, &ubi->free); /* * Move the physical eraseblock to the protection queue where it will @@ -462,8 +418,8 @@ retry: prot_queue_add(ubi, e); spin_unlock(&ubi->wl_lock); - err = ubi_dbg_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, - ubi->peb_size - ubi->vid_hdr_aloffset); + err = ubi_self_check_all_ff(ubi, e->pnum, ubi->vid_hdr_aloffset, + ubi->peb_size - ubi->vid_hdr_aloffset); if (err) { ubi_err("new PEB %d does not contain all 0xFF bytes", e->pnum); return err; @@ -488,7 +444,7 @@ static int prot_queue_del(struct ubi_device *ubi, int pnum) if (!e) return -ENODEV; - if (paranoid_check_in_pq(ubi, e)) + if (self_check_in_pq(ubi, e)) return -ENODEV; list_del(&e->u.list); @@ -514,7 +470,7 @@ static int sync_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, dbg_wl("erase PEB %d, old EC %llu", e->pnum, ec); - err = paranoid_check_ec(ubi, e->pnum, e->ec); + err = self_check_ec(ubi, e->pnum, e->ec); if (err) return -EINVAL; @@ -627,13 +583,15 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, * schedule_erase - schedule an erase work. * @ubi: UBI device description object * @e: the WL entry of the physical eraseblock to erase + * @vol_id: the volume ID that last used this PEB + * @lnum: the last used logical eraseblock number for the PEB * @torture: if the physical eraseblock has to be tortured * * This function returns zero in case of success and a %-ENOMEM in case of * failure. */ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, - int torture) + int vol_id, int lnum, int torture) { struct ubi_work *wl_wrk; @@ -646,6 +604,8 @@ static int schedule_erase(struct ubi_device *ubi, struct ubi_wl_entry *e, wl_wrk->func = &erase_worker; wl_wrk->e = e; + wl_wrk->vol_id = vol_id; + wl_wrk->lnum = lnum; wl_wrk->torture = torture; schedule_ubi_work(ubi, wl_wrk); @@ -714,7 +674,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, e1->ec, e2->ec); goto out_cancel; } - paranoid_check_in_wl_tree(ubi, e1, &ubi->used); + self_check_in_wl_tree(ubi, e1, &ubi->used); rb_erase(&e1->u.rb, &ubi->used); dbg_wl("move PEB %d EC %d to PEB %d EC %d", e1->pnum, e1->ec, e2->pnum, e2->ec); @@ -723,12 +683,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, scrubbing = 1; e1 = rb_entry(rb_first(&ubi->scrub), struct ubi_wl_entry, u.rb); e2 = find_wl_entry(&ubi->free, WL_FREE_MAX_DIFF); - paranoid_check_in_wl_tree(ubi, e1, &ubi->scrub); + self_check_in_wl_tree(ubi, e1, &ubi->scrub); rb_erase(&e1->u.rb, &ubi->scrub); dbg_wl("scrub PEB %d to PEB %d", e1->pnum, e2->pnum); } - paranoid_check_in_wl_tree(ubi, e2, &ubi->free); + self_check_in_wl_tree(ubi, e2, &ubi->free); rb_erase(&e2->u.rb, &ubi->free); ubi->move_from = e1; ubi->move_to = e2; @@ -846,7 +806,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, ubi->move_to_put = ubi->wl_scheduled = 0; spin_unlock(&ubi->wl_lock); - err = schedule_erase(ubi, e1, 0); + err = schedule_erase(ubi, e1, vol_id, lnum, 0); if (err) { kmem_cache_free(ubi_wl_entry_slab, e1); if (e2) @@ -861,7 +821,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, */ dbg_wl("PEB %d (LEB %d:%d) was put meanwhile, erase", e2->pnum, vol_id, lnum); - err = schedule_erase(ubi, e2, 0); + err = schedule_erase(ubi, e2, vol_id, lnum, 0); if (err) { kmem_cache_free(ubi_wl_entry_slab, e2); goto out_ro; @@ -900,7 +860,7 @@ out_not_moved: spin_unlock(&ubi->wl_lock); ubi_free_vid_hdr(ubi, vid_hdr); - err = schedule_erase(ubi, e2, torture); + err = schedule_erase(ubi, e2, vol_id, lnum, torture); if (err) { kmem_cache_free(ubi_wl_entry_slab, e2); goto out_ro; @@ -1019,6 +979,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, { struct ubi_wl_entry *e = wl_wrk->e; int pnum = e->pnum, err, need; + int vol_id = wl_wrk->vol_id; + int lnum = wl_wrk->lnum; if (cancel) { dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); @@ -1027,7 +989,8 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, return 0; } - dbg_wl("erase PEB %d EC %d", pnum, e->ec); + dbg_wl("erase PEB %d EC %d LEB %d:%d", + pnum, e->ec, wl_wrk->vol_id, wl_wrk->lnum); err = sync_erase(ubi, e, wl_wrk->torture); if (!err) { @@ -1057,7 +1020,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, int err1; /* Re-schedule the LEB for erasure */ - err1 = schedule_erase(ubi, e, 0); + err1 = schedule_erase(ubi, e, vol_id, lnum, 0); if (err1) { err = err1; goto out_ro; @@ -1125,6 +1088,8 @@ out_ro: /** * ubi_wl_put_peb - return a PEB to the wear-leveling sub-system. * @ubi: UBI device description object + * @vol_id: the volume ID that last used this PEB + * @lnum: the last used logical eraseblock number for the PEB * @pnum: physical eraseblock to return * @torture: if this physical eraseblock has to be tortured * @@ -1133,7 +1098,8 @@ out_ro: * occurred to this @pnum and it has to be tested. This function returns zero * in case of success, and a negative error code in case of failure. */ -int ubi_wl_put_peb(struct ubi_device *ubi, int pnum, int torture) +int ubi_wl_put_peb(struct ubi_device *ubi, int vol_id, int lnum, + int pnum, int torture) { int err; struct ubi_wl_entry *e; @@ -1175,13 +1141,13 @@ retry: return 0; } else { if (in_wl_tree(e, &ubi->used)) { - paranoid_check_in_wl_tree(ubi, e, &ubi->used); + self_check_in_wl_tree(ubi, e, &ubi->used); rb_erase(&e->u.rb, &ubi->used); } else if (in_wl_tree(e, &ubi->scrub)) { - paranoid_check_in_wl_tree(ubi, e, &ubi->scrub); + self_check_in_wl_tree(ubi, e, &ubi->scrub); rb_erase(&e->u.rb, &ubi->scrub); } else if (in_wl_tree(e, &ubi->erroneous)) { - paranoid_check_in_wl_tree(ubi, e, &ubi->erroneous); + self_check_in_wl_tree(ubi, e, &ubi->erroneous); rb_erase(&e->u.rb, &ubi->erroneous); ubi->erroneous_peb_count -= 1; ubi_assert(ubi->erroneous_peb_count >= 0); @@ -1199,7 +1165,7 @@ retry: } spin_unlock(&ubi->wl_lock); - err = schedule_erase(ubi, e, torture); + err = schedule_erase(ubi, e, vol_id, lnum, torture); if (err) { spin_lock(&ubi->wl_lock); wl_tree_add(e, &ubi->used); @@ -1248,7 +1214,7 @@ retry: } if (in_wl_tree(e, &ubi->used)) { - paranoid_check_in_wl_tree(ubi, e, &ubi->used); + self_check_in_wl_tree(ubi, e, &ubi->used); rb_erase(&e->u.rb, &ubi->used); } else { int err; @@ -1275,44 +1241,55 @@ retry: /** * ubi_wl_flush - flush all pending works. * @ubi: UBI device description object + * @vol_id: the volume id to flush for + * @lnum: the logical eraseblock number to flush for * - * This function returns zero in case of success and a negative error code in - * case of failure. + * This function executes all pending works for a particular volume id / + * logical eraseblock number pair. If either value is set to %UBI_ALL, then it + * acts as a wildcard for all of the corresponding volume numbers or logical + * eraseblock numbers. It returns zero in case of success and a negative error + * code in case of failure. */ -int ubi_wl_flush(struct ubi_device *ubi) +int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) { - int err; + int err = 0; + int found = 1; /* * Erase while the pending works queue is not empty, but not more than * the number of currently pending works. */ - dbg_wl("flush (%d pending works)", ubi->works_count); - while (ubi->works_count) { - err = do_work(ubi); - if (err) - return err; - } + dbg_wl("flush pending work for LEB %d:%d (%d pending works)", + vol_id, lnum, ubi->works_count); - /* - * Make sure all the works which have been done in parallel are - * finished. - */ down_write(&ubi->work_sem); - up_write(&ubi->work_sem); + while (found) { + struct ubi_work *wrk; + found = 0; - /* - * And in case last was the WL worker and it canceled the LEB - * movement, flush again. - */ - while (ubi->works_count) { - dbg_wl("flush more (%d pending works)", ubi->works_count); - err = do_work(ubi); - if (err) - return err; + spin_lock(&ubi->wl_lock); + list_for_each_entry(wrk, &ubi->works, list) { + if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) && + (lnum == UBI_ALL || wrk->lnum == lnum)) { + list_del(&wrk->list); + ubi->works_count -= 1; + ubi_assert(ubi->works_count >= 0); + spin_unlock(&ubi->wl_lock); + + err = wrk->func(ubi, wrk, 0); + if (err) + goto out; + spin_lock(&ubi->wl_lock); + found = 1; + break; + } + } + spin_unlock(&ubi->wl_lock); } - return 0; +out: + up_write(&ubi->work_sem); + return err; } /** @@ -1421,26 +1398,26 @@ static void cancel_pending(struct ubi_device *ubi) } /** - * ubi_wl_init_scan - initialize the WL sub-system using scanning information. + * ubi_wl_init - initialize the WL sub-system using attaching information. * @ubi: UBI device description object - * @si: scanning information + * @ai: attaching information * * This function returns zero in case of success, and a negative error code in * case of failure. */ -int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) +int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) { int err, i; struct rb_node *rb1, *rb2; - struct ubi_scan_volume *sv; - struct ubi_scan_leb *seb, *tmp; + struct ubi_ainf_volume *av; + struct ubi_ainf_peb *aeb, *tmp; struct ubi_wl_entry *e; ubi->used = ubi->erroneous = ubi->free = ubi->scrub = RB_ROOT; spin_lock_init(&ubi->wl_lock); mutex_init(&ubi->move_mutex); init_rwsem(&ubi->work_sem); - ubi->max_ec = si->max_ec; + ubi->max_ec = ai->max_ec; INIT_LIST_HEAD(&ubi->works); sprintf(ubi->bgt_name, UBI_BGT_NAME_PATTERN, ubi->ubi_num); @@ -1454,48 +1431,48 @@ int ubi_wl_init_scan(struct ubi_device *ubi, struct ubi_scan_info *si) INIT_LIST_HEAD(&ubi->pq[i]); ubi->pq_head = 0; - list_for_each_entry_safe(seb, tmp, &si->erase, u.list) { + list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) { cond_resched(); e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); if (!e) goto out_free; - e->pnum = seb->pnum; - e->ec = seb->ec; + e->pnum = aeb->pnum; + e->ec = aeb->ec; ubi->lookuptbl[e->pnum] = e; - if (schedule_erase(ubi, e, 0)) { + if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0)) { kmem_cache_free(ubi_wl_entry_slab, e); goto out_free; } } - list_for_each_entry(seb, &si->free, u.list) { + list_for_each_entry(aeb, &ai->free, u.list) { cond_resched(); e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); if (!e) goto out_free; - e->pnum = seb->pnum; - e->ec = seb->ec; + e->pnum = aeb->pnum; + e->ec = aeb->ec; ubi_assert(e->ec >= 0); wl_tree_add(e, &ubi->free); ubi->lookuptbl[e->pnum] = e; } - ubi_rb_for_each_entry(rb1, sv, &si->volumes, rb) { - ubi_rb_for_each_entry(rb2, seb, &sv->root, u.rb) { + ubi_rb_for_each_entry(rb1, av, &ai->volumes, rb) { + ubi_rb_for_each_entry(rb2, aeb, &av->root, u.rb) { cond_resched(); e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL); if (!e) goto out_free; - e->pnum = seb->pnum; - e->ec = seb->ec; + e->pnum = aeb->pnum; + e->ec = aeb->ec; ubi->lookuptbl[e->pnum] = e; - if (!seb->scrub) { + if (!aeb->scrub) { dbg_wl("add PEB %d EC %d to the used tree", e->pnum, e->ec); wl_tree_add(e, &ubi->used); @@ -1567,10 +1544,8 @@ void ubi_wl_close(struct ubi_device *ubi) kfree(ubi->lookuptbl); } -#ifdef CONFIG_MTD_UBI_DEBUG - /** - * paranoid_check_ec - make sure that the erase counter of a PEB is correct. + * self_check_ec - make sure that the erase counter of a PEB is correct. * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * @ec: the erase counter to check @@ -1579,7 +1554,7 @@ void ubi_wl_close(struct ubi_device *ubi) * is equivalent to @ec, and a negative error code if not or if an error * occurred. */ -static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec) +static int self_check_ec(struct ubi_device *ubi, int pnum, int ec) { int err; long long read_ec; @@ -1601,9 +1576,9 @@ static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec) read_ec = be64_to_cpu(ec_hdr->ec); if (ec != read_ec) { - ubi_err("paranoid check failed for PEB %d", pnum); + ubi_err("self-check failed for PEB %d", pnum); ubi_err("read EC is %lld, should be %d", read_ec, ec); - ubi_dbg_dump_stack(); + dump_stack(); err = 1; } else err = 0; @@ -1614,7 +1589,7 @@ out_free: } /** - * paranoid_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree. + * self_check_in_wl_tree - check that wear-leveling entry is in WL RB-tree. * @ubi: UBI device description object * @e: the wear-leveling entry to check * @root: the root of the tree @@ -1622,9 +1597,8 @@ out_free: * This function returns zero if @e is in the @root RB-tree and %-EINVAL if it * is not. */ -static int paranoid_check_in_wl_tree(const struct ubi_device *ubi, - struct ubi_wl_entry *e, - struct rb_root *root) +static int self_check_in_wl_tree(const struct ubi_device *ubi, + struct ubi_wl_entry *e, struct rb_root *root) { if (!ubi->dbg->chk_gen) return 0; @@ -1632,22 +1606,22 @@ static int paranoid_check_in_wl_tree(const struct ubi_device *ubi, if (in_wl_tree(e, root)) return 0; - ubi_err("paranoid check failed for PEB %d, EC %d, RB-tree %p ", + ubi_err("self-check failed for PEB %d, EC %d, RB-tree %p ", e->pnum, e->ec, root); - ubi_dbg_dump_stack(); + dump_stack(); return -EINVAL; } /** - * paranoid_check_in_pq - check if wear-leveling entry is in the protection + * self_check_in_pq - check if wear-leveling entry is in the protection * queue. * @ubi: UBI device description object * @e: the wear-leveling entry to check * * This function returns zero if @e is in @ubi->pq and %-EINVAL if it is not. */ -static int paranoid_check_in_pq(const struct ubi_device *ubi, - struct ubi_wl_entry *e) +static int self_check_in_pq(const struct ubi_device *ubi, + struct ubi_wl_entry *e) { struct ubi_wl_entry *p; int i; @@ -1660,10 +1634,8 @@ static int paranoid_check_in_pq(const struct ubi_device *ubi, if (p == e) return 0; - ubi_err("paranoid check failed for PEB %d, EC %d, Protect queue", + ubi_err("self-check failed for PEB %d, EC %d, Protect queue", e->pnum, e->ec); - ubi_dbg_dump_stack(); + dump_stack(); return -EINVAL; } - -#endif /* CONFIG_MTD_UBI_DEBUG */ |