From 052c28073ff26f771d44ef33952a41d18dadd255 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 29 Jun 2014 17:00:45 +0300 Subject: [PATCH 01/17] UBIFS: fix a race condition Hu (hujianyang@huawei.com) discovered a race condition which may lead to a situation when UBIFS is unable to mount the file-system after an unclean reboot. The problem is theoretical, though. In UBIFS, we have the log, which basically a set of LEBs in a certain area. The log has the tail and the head. Every time user writes data to the file-system, the UBIFS journal grows, and the log grows as well, because we append new reference nodes to the head of the log. So the head moves forward all the time, while the log tail stays at the same position. At any time, the UBIFS master node points to the tail of the log. When we mount the file-system, we scan the log, and we always start from its tail, because this is where the master node points to. The only occasion when the tail of the log changes is the commit operation. The commit operation has 2 phases - "commit start" and "commit end". The former is relatively short, and does not involve much I/O. During this phase we mostly just build various in-memory lists of the things which have to be written to the flash media during "commit end" phase. During the commit start phase, what we do is we "clean" the log. Indeed, the commit operation will index all the data in the journal, so the entire journal "disappears", and therefore the data in the log become unneeded. So we just move the head of the log to the next LEB, and write the CS node there. This LEB will be the tail of the new log when the commit operation finishes. When the "commit start" phase finishes, users may write more data to the file-system, in parallel with the ongoing "commit end" operation. At this point the log tail was not changed yet, it is the same as it had been before we started the commit. The log head keeps moving forward, though. The commit operation now needs to write the new master node, and the new master node should point to the new log tail. After this the LEBs between the old log tail and the new log tail can be unmapped and re-used again. And here is the possible problem. We do 2 operations: (a) We first update the log tail position in memory (see 'ubifs_log_end_commit()'). (b) And then we write the master node (see the big lock of code in 'do_commit()'). But nothing prevents the log head from moving forward between (a) and (b), and the log head may "wrap" now to the old log tail. And when the "wrap" happens, the contends of the log tail gets erased. Now a power cut happens and we are in trouble. We end up with the old master node pointing to the old tail, which was erased. And replay fails because it expects the master node to point to the correct log tail at all times. This patch merges the abovementioned (a) and (b) operations by moving the master node change code to the 'ubifs_log_end_commit()' function, so that it runs with the log mutex locked, which will prevent the log from being changed benween operations (a) and (b). Cc: stable@vger.kernel.org # 07e19df UBIFS: remove mst_mutex Cc: stable@vger.kernel.org Reported-by: hujianyang Tested-by: hujianyang Signed-off-by: Artem Bityutskiy --- fs/ubifs/commit.c | 8 +++----- fs/ubifs/log.c | 11 ++++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index aa13ad053b14..26b69b2d4a45 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c @@ -164,10 +164,6 @@ static int do_commit(struct ubifs_info *c) if (err) goto out; err = ubifs_orphan_end_commit(c); - if (err) - goto out; - old_ltail_lnum = c->ltail_lnum; - err = ubifs_log_end_commit(c, new_ltail_lnum); if (err) goto out; err = dbg_check_old_index(c, &zroot); @@ -202,7 +198,9 @@ static int do_commit(struct ubifs_info *c) c->mst_node->flags |= cpu_to_le32(UBIFS_MST_NO_ORPHS); else c->mst_node->flags &= ~cpu_to_le32(UBIFS_MST_NO_ORPHS); - err = ubifs_write_master(c); + + old_ltail_lnum = c->ltail_lnum; + err = ubifs_log_end_commit(c, new_ltail_lnum); if (err) goto out; diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index a47ddfc9be6b..9bd4aafd5c6f 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c @@ -447,9 +447,9 @@ out: * @ltail_lnum: new log tail LEB number * * This function is called on when the commit operation was finished. It - * moves log tail to new position and unmaps LEBs which contain obsolete data. - * Returns zero in case of success and a negative error code in case of - * failure. + * moves log tail to new position and updates the master node so that it stores + * the new log tail LEB number. Returns zero in case of success and a negative + * error code in case of failure. */ int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) { @@ -477,7 +477,12 @@ int ubifs_log_end_commit(struct ubifs_info *c, int ltail_lnum) spin_unlock(&c->buds_lock); err = dbg_check_bud_bytes(c); + if (err) + goto out; + err = ubifs_write_master(c); + +out: mutex_unlock(&c->log_mutex); return err; } From ba29e721eb2df6df8f33c1f248388bb037a47914 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 16 Jul 2014 15:22:29 +0300 Subject: [PATCH 02/17] UBIFS: fix free log space calculation Hu (hujianyang ) discovered an issue in the 'empty_log_bytes()' function, which calculates how many bytes are left in the log: " If 'c->lhead_lnum + 1 == c->ltail_lnum' and 'c->lhead_offs == c->leb_size', 'h' would equalent to 't' and 'empty_log_bytes()' would return 'c->log_bytes' instead of 0. " At this point it is not clear what would be the consequences of this, and whether this may lead to any problems, but this patch addresses the issue just in case. Cc: stable@vger.kernel.org Tested-by: hujianyang Reported-by: hujianyang Signed-off-by: Artem Bityutskiy --- fs/ubifs/log.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c index 9bd4aafd5c6f..c14628fbeee2 100644 --- a/fs/ubifs/log.c +++ b/fs/ubifs/log.c @@ -106,10 +106,14 @@ static inline long long empty_log_bytes(const struct ubifs_info *c) h = (long long)c->lhead_lnum * c->leb_size + c->lhead_offs; t = (long long)c->ltail_lnum * c->leb_size; - if (h >= t) + if (h > t) return c->log_bytes - h + t; - else + else if (h != t) return t - h; + else if (c->lhead_lnum != c->ltail_lnum) + return 0; + else + return c->log_bytes; } /** From 1bf1890e86869032099b539bc83b098be12fc5a7 Mon Sep 17 00:00:00 2001 From: Richard Genoud Date: Tue, 9 Sep 2014 14:25:01 +0200 Subject: [PATCH 03/17] UBI: add missing kmem_cache_free() in process_pool_aeb error path I ran into this error after a ubiupdatevol, because I forgot to backport e9110361a9a4 UBI: fix the volumes tree sorting criteria. UBI error: process_pool_aeb: orphaned volume in fastmap pool UBI error: ubi_scan_fastmap: Attach by fastmap failed, doing a full scan! kmem_cache_destroy ubi_ainf_peb_slab: Slab cache still has objects CPU: 0 PID: 1 Comm: swapper Not tainted 3.14.18-00053-gf05cac8dbf85 #1 [] (unwind_backtrace) from [] (show_stack+0x10/0x14) [] (show_stack) from [] (destroy_ai+0x230/0x244) [] (destroy_ai) from [] (ubi_attach+0x98/0x1ec) [] (ubi_attach) from [] (ubi_attach_mtd_dev+0x2b8/0x868) [] (ubi_attach_mtd_dev) from [] (ubi_init+0x1dc/0x2ac) [] (ubi_init) from [] (do_one_initcall+0x94/0x140) [] (do_one_initcall) from [] (kernel_init_freeable+0xe8/0x1b0) [] (kernel_init_freeable) from [] (kernel_init+0x8/0xe4) [] (kernel_init) from [] (ret_from_fork+0x14/0x24) UBI: scanning is finished Freeing the cache in the error path fixes the Slab error. Tested on at91sam9g35 (3.14.18+fastmap backports) Signed-off-by: Richard Genoud Cc: stable # 3.10+ --- drivers/mtd/ubi/fastmap.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 0431b46d9fd9..c701369090fb 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -330,6 +330,7 @@ static int process_pool_aeb(struct ubi_device *ubi, struct ubi_attach_info *ai, av = tmp_av; else { ubi_err("orphaned volume in fastmap pool!"); + kmem_cache_free(ai->aeb_slab_cache, new_aeb); return UBI_BAD_FASTMAP; } From 3df770725339c41d1cd9be4da4ca0d968119d8ad Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 20 Aug 2014 10:19:38 +0100 Subject: [PATCH 04/17] UBI: block: fix dereference on uninitialized dev commit 4df38926f337 ("UBI: block: Avoid disk size integer overflow") introduced a dereference on dev (which is not initialized at that point) when printing a warning message. Re-order disk_capacity check after the dev is found. Found by cppcheck: [drivers/mtd/ubi/block.c:509]: (error) Uninitialized variable: dev Artem: tweak the error message a bit Signed-off-by: Colin Ian King Acked-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/block.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 33c64955d4d7..518792b7634d 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -504,11 +504,6 @@ static int ubiblock_resize(struct ubi_volume_info *vi) struct ubiblock *dev; u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9; - if ((sector_t)disk_capacity != disk_capacity) { - ubi_warn("%s: the volume is too big, cannot resize (%d LEBs)", - dev->gd->disk_name, vi->size); - return -EFBIG; - } /* * Need to lock the device list until we stop using the device, * otherwise the device struct might get released in @@ -520,6 +515,12 @@ static int ubiblock_resize(struct ubi_volume_info *vi) mutex_unlock(&devices_mutex); return -ENODEV; } + if ((sector_t)disk_capacity != disk_capacity) { + mutex_unlock(&devices_mutex); + ubi_warn("%s: the volume is too big (%d LEBs), cannot resize", + dev->gd->disk_name, vi->size); + return -EFBIG; + } mutex_lock(&dev->dev_mutex); set_capacity(dev->gd, disk_capacity); From 978d6496758d19de2431ebf163337fc7b92f8c45 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 29 Aug 2014 18:42:28 -0300 Subject: [PATCH 05/17] UBI: block: Fix block device size setting We are currently taking the block device size from the ubi_volume_info.size field. However, this is not the amount of data in the volume, but the number of reserved physical eraseblocks, and hence leads to an incorrect representation of the volume. In particular, this produces I/O errors on static volumes as the block interface may attempt to read unmapped PEBs: $ cat /dev/ubiblock0_0 > /dev/null UBI error: ubiblock_read_to_buf: ubiblock0_0 ubi_read error -22 end_request: I/O error, dev ubiblock0_0, sector 9536 Buffer I/O error on device ubiblock0_0, logical block 2384 [snip] Fix this by using the ubi_volume_info.used_bytes field which is set to the actual number of data bytes for both static and dynamic volumes. While here, improve the error message to be less stupid and more useful: UBI error: ubiblock_read_to_buf: ubiblock0_1 ubi_read error -9 on LEB=0, off=15872, len=512 It's worth noticing that the 512-byte sector representation of the volume is only correct if the volume size is multiple of 512-bytes. This is true for virtually any NAND device, given eraseblocks and pages are 512-byte multiple and hence so is the LEB size. Artem: tweak the error message and make it look more like other UBI error messages. Fixes: 9d54c8a33eec ("UBI: R/O block driver on top of UBI volumes") Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy Cc: stable@vger.kernel.org # v3.15+ --- drivers/mtd/ubi/block.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 518792b7634d..581784485376 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -188,8 +188,9 @@ static int ubiblock_read_to_buf(struct ubiblock *dev, char *buffer, ret = ubi_read(dev->desc, leb, buffer, offset, len); if (ret) { - ubi_err("%s ubi_read error %d", - dev->gd->disk_name, ret); + ubi_err("%s: error %d while reading from LEB %d (offset %d, " + "length %d)", dev->gd->disk_name, ret, leb, offset, + len); return ret; } return 0; @@ -378,7 +379,7 @@ int ubiblock_create(struct ubi_volume_info *vi) { struct ubiblock *dev; struct gendisk *gd; - u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9; + u64 disk_capacity = vi->used_bytes >> 9; int ret; if ((sector_t)disk_capacity != disk_capacity) @@ -502,7 +503,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) static int ubiblock_resize(struct ubi_volume_info *vi) { struct ubiblock *dev; - u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9; + u64 disk_capacity = vi->used_bytes >> 9; /* * Need to lock the device list until we stop using the device, @@ -524,7 +525,7 @@ static int ubiblock_resize(struct ubi_volume_info *vi) mutex_lock(&dev->dev_mutex); set_capacity(dev->gd, disk_capacity); - ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size); + ubi_msg("%s resized to %lld bytes", dev->gd->disk_name, vi->used_bytes); mutex_unlock(&dev->dev_mutex); mutex_unlock(&devices_mutex); return 0; From 06d9c2905f745c8b1920a335cbb366ba6b0fc754 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 29 Aug 2014 18:42:29 -0300 Subject: [PATCH 06/17] UBI: block: Add support for the UBI_VOLUME_UPDATED notification Static volumes can change its 'used_bytes' when they get updated, and so the block interface must listen to the UBI_VOLUME_UPDATED notification to resize the block device accordingly. Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy Cc: stable@vger.kernel.org # v3.15+ --- drivers/mtd/ubi/block.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 581784485376..8876c7d3d712 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -524,8 +524,12 @@ static int ubiblock_resize(struct ubi_volume_info *vi) } mutex_lock(&dev->dev_mutex); - set_capacity(dev->gd, disk_capacity); - ubi_msg("%s resized to %lld bytes", dev->gd->disk_name, vi->used_bytes); + + if (get_capacity(dev->gd) != disk_capacity) { + set_capacity(dev->gd, disk_capacity); + ubi_msg("%s resized to %lld bytes", dev->gd->disk_name, + vi->used_bytes); + } mutex_unlock(&dev->dev_mutex); mutex_unlock(&devices_mutex); return 0; @@ -549,6 +553,14 @@ static int ubiblock_notify(struct notifier_block *nb, case UBI_VOLUME_RESIZED: ubiblock_resize(&nt->vi); break; + case UBI_VOLUME_UPDATED: + /* + * If the volume is static, a content update might mean the + * size (i.e. used_bytes) was also changed. + */ + if (nt->vi.vol_type == UBI_STATIC_VOLUME) + ubiblock_resize(&nt->vi); + break; default: break; } From fda322a1b3b9e8ee231913c500f73c6988b1aff5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Fri, 29 Aug 2014 18:42:30 -0300 Subject: [PATCH 07/17] UBI: Dispatch update notification if the volume is updated The UBI_IOCVOLUP ioctl is used to start an update and also to truncate a volume. In the first case, a "volume updated" notification is dispatched when the update is done. This commit adds the "volume updated" notification to be also sent when the volume is truncated. This is required for UBI block and gluebi to get notified about the new volume size. Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy Cc: stable@vger.kernel.org # v3.15+ --- drivers/mtd/ubi/cdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 7646220ca6e2..20aeb277d8d4 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -425,8 +425,10 @@ static long vol_cdev_ioctl(struct file *file, unsigned int cmd, break; err = ubi_start_update(ubi, vol, bytes); - if (bytes == 0) + if (bytes == 0) { + ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); revoke_exclusive(desc, UBI_READWRITE); + } break; } From d577bc104f2c01928d586358663de6d0a950130f Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 19 Sep 2014 11:48:46 +0200 Subject: [PATCH 08/17] UBIFS: Remove bogus assert This assertion was only correct before UBIFS had xattr support. Now with xattr support also a directory node can carry data and can act as host node. Suggested-by: Artem Bityutskiy Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- fs/ubifs/journal.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 0e045e75abd8..fb166e204441 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -546,15 +546,14 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, int aligned_dlen, aligned_ilen, sync = IS_DIRSYNC(dir); int last_reference = !!(deletion && inode->i_nlink == 0); struct ubifs_inode *ui = ubifs_inode(inode); - struct ubifs_inode *dir_ui = ubifs_inode(dir); + struct ubifs_inode *host_ui = ubifs_inode(dir); struct ubifs_dent_node *dent; struct ubifs_ino_node *ino; union ubifs_key dent_key, ino_key; dbg_jnl("ino %lu, dent '%.*s', data len %d in dir ino %lu", inode->i_ino, nm->len, nm->name, ui->data_len, dir->i_ino); - ubifs_assert(dir_ui->data_len == 0); - ubifs_assert(mutex_is_locked(&dir_ui->ui_mutex)); + ubifs_assert(mutex_is_locked(&host_ui->ui_mutex)); dlen = UBIFS_DENT_NODE_SZ + nm->len + 1; ilen = UBIFS_INO_NODE_SZ; @@ -658,7 +657,7 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, ui->synced_i_size = ui->ui_size; spin_unlock(&ui->ui_lock); mark_inode_clean(c, ui); - mark_inode_clean(c, dir_ui); + mark_inode_clean(c, host_ui); return 0; out_finish: From adfe83be973dc990f3763de3667c4cd004e6e4f7 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 19 Sep 2014 11:48:47 +0200 Subject: [PATCH 09/17] UBI: Improve comment on work_sem Make clear what work_sem really does. Suggested-by: Artem Bityutskiy Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/ubi.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 7bf416329c19..f2933df15f9c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -439,7 +439,8 @@ struct ubi_debug_info { * @move_to, @move_to_put @erase_pending, @wl_scheduled, @works, * @erroneous, and @erroneous_peb_count fields * @move_mutex: serializes eraseblock moves - * @work_sem: synchronizes the WL worker with use tasks + * @work_sem: used to wait for all the scheduled works to finish and prevent + * new works from being submitted * @wl_scheduled: non-zero if the wear-leveling was scheduled * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any * physical eraseblock From 7fbbd05799976c0611dcb229649260504b2bdef5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 19 Sep 2014 13:56:56 +0300 Subject: [PATCH 10/17] UBI: return on error in rename_volumes() I noticed this during a code review. We are checking that the strlen() of ->name is not less than the ->name_len which the user gave us. I believe this bug is harmless but clearly we meant to return here instead of setting an error code and then not using it. Signed-off-by: Dan Carpenter Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c index 20aeb277d8d4..59de69a24e40 100644 --- a/drivers/mtd/ubi/cdev.c +++ b/drivers/mtd/ubi/cdev.c @@ -701,7 +701,7 @@ static int rename_volumes(struct ubi_device *ubi, req->ents[i].name[req->ents[i].name_len] = '\0'; n = strlen(req->ents[i].name); if (n != req->ents[i].name_len) - err = -EINVAL; + return -EINVAL; } /* Make sure volume IDs and names are unique */ From b91671bb23a79c32a23b0ad5d6e6ad292bb21bdf Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Fri, 19 Sep 2014 17:37:56 +0200 Subject: [PATCH 11/17] UBI: Fix livelock in produce_free_peb() The while loop in produce_free_peb() assumes that each work will produce a free PEB. This is not true. If ubi->works_count is 1 and the only scheduled work is the wear_leveling_worker() produce_free_peb() can loop forever in case nobody schedules an erase work. Fix this issue by checking in the while loop whether work is scheduled. Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 20f491713145..32b3c1486a05 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -272,7 +272,7 @@ static int produce_free_peb(struct ubi_device *ubi) { int err; - while (!ubi->free.rb_node) { + while (!ubi->free.rb_node && ubi->works_count) { spin_unlock(&ubi->wl_lock); dbg_wl("do one work synchronously"); From 4b1a43eab1ab0b1d05bc0c2aa823262da2445a7f Mon Sep 17 00:00:00 2001 From: hujianyang Date: Sat, 20 Sep 2014 14:55:11 +0800 Subject: [PATCH 12/17] UBIFS: Align the dump messages of SB_NODE I found the dump messages of UBIFS_SB_NODE is not aligned. This patch remove the extra space from the line which is retracted. Signed-off-by: hujianyang Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index 177b0152fef4..d0bcf9290ea4 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -334,9 +334,9 @@ void ubifs_dump_node(const struct ubifs_info *c, const void *node) pr_err("\tkey_fmt %d (%s)\n", (int)sup->key_fmt, get_key_fmt(sup->key_fmt)); pr_err("\tflags %#x\n", sup_flags); - pr_err("\t big_lpt %u\n", + pr_err("\tbig_lpt %u\n", !!(sup_flags & UBIFS_FLG_BIGLPT)); - pr_err("\t space_fixup %u\n", + pr_err("\tspace_fixup %u\n", !!(sup_flags & UBIFS_FLG_SPACE_FIXUP)); pr_err("\tmin_io_size %u\n", le32_to_cpu(sup->min_io_size)); pr_err("\tleb_size %u\n", le32_to_cpu(sup->leb_size)); From 170505f58f01d89dea2667d484cb5da18fb9ffd9 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 22 Sep 2014 10:45:34 +0200 Subject: [PATCH 13/17] UBI: ubi_eba_read_leb: Remove in vain variable assignment There is no need to set err, it will be overwritten in any case later at: if (scrub) err = ubi_wl_scrub_peb(ubi, pnum); Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 0e11671dadc4..2402d3b50171 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -441,10 +441,9 @@ retry: err = ubi_io_read_data(ubi, buf, pnum, offset, len); if (err) { - if (err == UBI_IO_BITFLIPS) { + if (err == UBI_IO_BITFLIPS) scrub = 1; - err = 0; - } else if (mtd_is_eccerr(err)) { + else if (mtd_is_eccerr(err)) { if (vol->vol_type == UBI_DYNAMIC_VOLUME) goto out_unlock; scrub = 1; From 849271a4e4b723c521df0f55d67614d8ffd5e125 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 22 Sep 2014 10:45:35 +0200 Subject: [PATCH 14/17] UBI: wl: Rename cancel flag to shutdown It confused me more than once that the cancel flag of the work function does not indicate the cancellation of a single work. In fact it indicates the WL sub-system shutdown and therefore worker functions have to free their wl_entries too. That's why you cannot cancel a single work, you can only shutdown all works. Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/ubi.h | 9 +++++---- drivers/mtd/ubi/wl.c | 24 +++++++++++++----------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index f2933df15f9c..320fc38fa2a1 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -714,14 +714,15 @@ struct ubi_attach_info { * @torture: if the physical eraseblock has to be tortured * @anchor: produce a anchor PEB to by used by fastmap * - * The @func pointer points to the worker function. If the @cancel argument is - * not zero, the worker has to free the resources and exit immediately. The - * worker has to return zero in case of success and a negative error code in + * The @func pointer points to the worker function. If the @shutdown argument is + * not zero, the worker has to free the resources and exit immediately as the + * WL sub-system is shutting down. + * The worker has to return zero in case of success and a negative error code in * case of failure. */ struct ubi_work { struct list_head list; - int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel); + int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int shutdown); /* The below fields are only relevant to erasure works */ struct ubi_wl_entry *e; int vol_id; diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 32b3c1486a05..c04b7f62fae5 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -864,7 +864,7 @@ static void schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) } static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, - int cancel); + int shutdown); #ifdef CONFIG_MTD_UBI_FASTMAP /** @@ -990,14 +990,15 @@ int ubi_wl_put_fm_peb(struct ubi_device *ubi, struct ubi_wl_entry *fm_e, * wear_leveling_worker - wear-leveling worker function. * @ubi: UBI device description object * @wrk: the work object - * @cancel: non-zero if the worker has to free memory and exit + * @shutdown: non-zero if the worker has to free memory and exit + * because the WL-subsystem is shutting down * * This function copies a more worn out physical eraseblock to a less worn out * one. Returns zero in case of success and a negative error code in case of * failure. */ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, - int cancel) + int shutdown) { int err, scrubbing = 0, torture = 0, protect = 0, erroneous = 0; int vol_id = -1, uninitialized_var(lnum); @@ -1008,7 +1009,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk, struct ubi_vid_hdr *vid_hdr; kfree(wrk); - if (cancel) + if (shutdown) return 0; vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS); @@ -1407,7 +1408,8 @@ int ubi_ensure_anchor_pebs(struct ubi_device *ubi) * erase_worker - physical eraseblock erase worker function. * @ubi: UBI device description object * @wl_wrk: the work object - * @cancel: non-zero if the worker has to free memory and exit + * @shutdown: non-zero if the worker has to free memory and exit + * because the WL sub-system is shutting down * * This function erases a physical eraseblock and perform torture testing if * needed. It also takes care about marking the physical eraseblock bad if @@ -1415,7 +1417,7 @@ int ubi_ensure_anchor_pebs(struct ubi_device *ubi) * failure. */ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, - int cancel) + int shutdown) { struct ubi_wl_entry *e = wl_wrk->e; int pnum = e->pnum; @@ -1423,7 +1425,7 @@ static int erase_worker(struct ubi_device *ubi, struct ubi_work *wl_wrk, int lnum = wl_wrk->lnum; int err, available_consumed = 0; - if (cancel) { + if (shutdown) { dbg_wl("cancel erasure of PEB %d EC %d", pnum, e->ec); kfree(wl_wrk); kmem_cache_free(ubi_wl_entry_slab, e); @@ -1845,10 +1847,10 @@ int ubi_thread(void *u) } /** - * cancel_pending - cancel all pending works. + * shutdown_work - shutdown all pending works. * @ubi: UBI device description object */ -static void cancel_pending(struct ubi_device *ubi) +static void shutdown_work(struct ubi_device *ubi) { while (!list_empty(&ubi->works)) { struct ubi_work *wrk; @@ -1997,7 +1999,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) return 0; out_free: - cancel_pending(ubi); + shutdown_work(ubi); tree_destroy(&ubi->used); tree_destroy(&ubi->free); tree_destroy(&ubi->scrub); @@ -2029,7 +2031,7 @@ static void protection_queue_destroy(struct ubi_device *ubi) void ubi_wl_close(struct ubi_device *ubi) { dbg_wl("close the WL sub-system"); - cancel_pending(ubi); + shutdown_work(ubi); protection_queue_destroy(ubi); tree_destroy(&ubi->used); tree_destroy(&ubi->erroneous); From e3e00445d478f63f42a306e549f7358b6612110b Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 16 Sep 2014 15:30:35 +0200 Subject: [PATCH 15/17] UBI: Fix trivial typo in __schedule_ubi_work s/of/if/ Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/wl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index c04b7f62fae5..6654f191868e 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -835,7 +835,7 @@ repeat: * @wrk: the work to schedule * * This function adds a work defined by @wrk to the tail of the pending works - * list. Can only be used of ubi->work_sem is already held in read mode! + * list. Can only be used if ubi->work_sem is already held in read mode! */ static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) { From 443b39cdd5c37661bf681858b327418c3a5b9d76 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 16 Sep 2014 15:30:36 +0200 Subject: [PATCH 16/17] UBIFS: Fix trivial typo in power_cut_emulated() s/withing/within/ Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- fs/ubifs/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index d0bcf9290ea4..7ed13e1e216a 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -2462,7 +2462,7 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write) if (chance(1, 2)) { d->pc_delay = 1; - /* Fail withing 1 minute */ + /* Fail within 1 minute */ delay = prandom_u32() % 60000; d->pc_timeout = jiffies; d->pc_timeout += msecs_to_jiffies(delay); From 91401a34038e614076dbfb5c4969a052e72fb296 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 30 Sep 2014 00:20:46 +0200 Subject: [PATCH 17/17] UBI: Fastmap: Calc fastmap size correctly We need to add fm_sb too. Signed-off-by: Richard Weinberger Reviewed-by: Tanya Brokhman Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/fastmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index c701369090fb..cfd5b5e90156 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -24,7 +24,8 @@ size_t ubi_calc_fm_size(struct ubi_device *ubi) { size_t size; - size = sizeof(struct ubi_fm_hdr) + \ + size = sizeof(struct ubi_fm_sb) + \ + sizeof(struct ubi_fm_hdr) + \ sizeof(struct ubi_fm_scan_pool) + \ sizeof(struct ubi_fm_scan_pool) + \ (ubi->peb_count * sizeof(struct ubi_fm_ec)) + \