From 525bab71feb152bccb65054cc2bca1537e3bd2b5 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Thu, 28 Apr 2016 18:13:58 -0300 Subject: [PATCH 1/8] UBI: Add ro-mode sysfs attribute On serious situations, UBI may detect serious device corruption, and switch to read-only mode to protect the data and allow debugging. This commit exposes this ro-mode on sysfs, so it can be obtained by userspace tools. Signed-off-by: Ezequiel Garcia Signed-off-by: Richard Weinberger --- Documentation/ABI/stable/sysfs-class-ubi | 9 +++++++++ drivers/mtd/ubi/build.c | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi index 18d471d9faea..a6b324014692 100644 --- a/Documentation/ABI/stable/sysfs-class-ubi +++ b/Documentation/ABI/stable/sysfs-class-ubi @@ -107,6 +107,15 @@ Contact: Artem Bityutskiy Description: Number of physical eraseblocks reserved for bad block handling. +What: /sys/class/ubi/ubiX/ro_mode +Date: April 2016 +KernelVersion: 4.7 +Contact: linux-mtd@lists.infradead.org +Description: + Contains ASCII "1\n" if the read-only flag is set on this + device, and "0\n" if it is cleared. UBI devices mark themselves + as read-only when they detect an unrecoverable error. + What: /sys/class/ubi/ubiX/total_eraseblocks Date: July 2006 KernelVersion: 2.6.22 diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 22fd19c0c5d3..7091fca0fb44 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -149,6 +149,8 @@ static struct device_attribute dev_bgt_enabled = __ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL); static struct device_attribute dev_mtd_num = __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); +static struct device_attribute dev_ro_mode = + __ATTR(ro_mode, S_IRUGO, dev_attribute_show, NULL); /** * ubi_volume_notify - send a volume change notification. @@ -385,6 +387,8 @@ static ssize_t dev_attribute_show(struct device *dev, ret = sprintf(buf, "%d\n", ubi->thread_enabled); else if (attr == &dev_mtd_num) ret = sprintf(buf, "%d\n", ubi->mtd->index); + else if (attr == &dev_ro_mode) + ret = sprintf(buf, "%d\n", ubi->ro_mode); else ret = -EINVAL; @@ -404,6 +408,7 @@ static struct attribute *ubi_dev_attrs[] = { &dev_min_io_size.attr, &dev_bgt_enabled.attr, &dev_mtd_num.attr, + &dev_ro_mode.attr, NULL }; ATTRIBUTE_GROUPS(ubi_dev); From 1e0a74f10d76021988ecd9e34e6c0c65d1c5403e Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sat, 7 May 2016 18:09:18 +0200 Subject: [PATCH 2/8] UBI: Don't read back all data in ubi_eba_copy_leb() Drop this paranoia check from the old days. If our MTD driver or the flash is so bad that we even cannot trust it to write data we have bigger problems. If one really does not trust the flash and wants write-verify she can enable UBI io checks using debugfs. Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/eba.c | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 5b9834cf2820..61356a9b1303 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -1202,32 +1202,6 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, } cond_resched(); - - /* - * We've written the data and are going to read it back to make - * sure it was written correctly. - */ - memset(ubi->peb_buf, 0xFF, aldata_size); - err = ubi_io_read_data(ubi, ubi->peb_buf, to, 0, aldata_size); - if (err) { - if (err != UBI_IO_BITFLIPS) { - ubi_warn(ubi, "error %d while reading data back from PEB %d", - err, to); - if (is_error_sane(err)) - err = MOVE_TARGET_RD_ERR; - } else - err = MOVE_TARGET_BITFLIPS; - goto out_unlock_buf; - } - - cond_resched(); - - if (crc != crc32(UBI_CRC32_INIT, ubi->peb_buf, data_size)) { - ubi_warn(ubi, "read data back from PEB %d and it is different", - to); - err = -EINVAL; - goto out_unlock_buf; - } } ubi_assert(vol->eba_tbl[lnum] == from); From 960b35d06b6d6b377fd47a8a44e41a96f35ce485 Mon Sep 17 00:00:00 2001 From: z00189512 Date: Wed, 30 Mar 2016 02:41:19 +0800 Subject: [PATCH 3/8] UBI: Modify wrong comment in ubi_leb_map function. Signed-off-by: z00189512 Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/kapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index e844887732fb..cc6fa0115c9a 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -708,7 +708,7 @@ int ubi_leb_map(struct ubi_volume_desc *desc, int lnum) struct ubi_volume *vol = desc->vol; struct ubi_device *ubi = vol->ubi; - dbg_gen("unmap LEB %d:%d", vol->vol_id, lnum); + dbg_gen("map LEB %d:%d", vol->vol_id, lnum); if (desc->mode == UBI_READONLY || vol->vol_type == UBI_STATIC_VOLUME) return -EROFS; From fadb3665bad96be8f696e4899ee0f618536d54c7 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Apr 2016 09:41:26 +0300 Subject: [PATCH 4/8] UBI: Clean up return in ubi_remove_volume() My static checker says that "err" can be uninitialized if "vol->reserved_pebs" is <= 0. I don't think that can happen but returning a literal is cleaner anyway. Signed-off-by: Dan Carpenter Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/vmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c index 1ae17bb9b889..10059dfdc1b6 100644 --- a/drivers/mtd/ubi/vmt.c +++ b/drivers/mtd/ubi/vmt.c @@ -405,7 +405,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl) if (!no_vtbl) self_check_volumes(ubi); - return err; + return 0; out_err: ubi_err(ubi, "cannot remove volume %d, error %d", vol_id, err); From 24663e7281b8fbfaae22467ec2625e2bffe07815 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 13 Apr 2016 09:41:55 +0300 Subject: [PATCH 5/8] UBI: Silence an unintialized variable warning My static checker complains that "val" is uninitialized when kstrtoint() fails. Signed-off-by: Dan Carpenter Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/debug.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c index c4cb15a3098c..f101a4985a7c 100644 --- a/drivers/mtd/ubi/debug.c +++ b/drivers/mtd/ubi/debug.c @@ -352,7 +352,8 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf, } else if (dent == d->dfs_emulate_power_cut) { if (kstrtoint(buf, 0, &val) != 0) count = -EINVAL; - d->emulate_power_cut = val; + else + d->emulate_power_cut = val; goto out; } From 73b0cd57fcd07201b138214f9a2353f76dd9ae2c Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Fri, 22 Apr 2016 12:06:38 +0200 Subject: [PATCH 6/8] UBI: Set free_count to zero before walking through erase list Set free_count to zero before walking through ai->erase list in wl_init(). Found in U-Boot as U-Boot has no workqueue/threads, it immediately calls erase_worker(), which increase for each erased block free_count. Without this patch, free_count gets after this initialized to zero in wl_init(), so the free_count variable always has the maybe wrong value 0 in U-Boot. Signed-off-by: Heiko Schocher Reviewed-by: Boris Brezillon Signed-off-by: Richard Weinberger --- 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 17ec948ac40e..959c7b12e0b1 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1534,6 +1534,7 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) INIT_LIST_HEAD(&ubi->pq[i]); ubi->pq_head = 0; + ubi->free_count = 0; list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) { cond_resched(); @@ -1552,7 +1553,6 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai) found_pebs++; } - ubi->free_count = 0; list_for_each_entry(aeb, &ai->free, u.list) { cond_resched(); From 1900149c835ab5b48bea31a823ea5e5a401fb560 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 26 Apr 2016 16:39:48 +0200 Subject: [PATCH 7/8] UBI: Fix static volume checks when Fastmap is used Ezequiel reported that he's facing UBI going into read-only mode after power cut. It turned out that this behavior happens only when updating a static volume is interrupted and Fastmap is used. A possible trace can look like: ubi0 warning: ubi_io_read_vid_hdr [ubi]: no VID header found at PEB 2323, only 0xFF bytes ubi0 warning: ubi_eba_read_leb [ubi]: switch to read-only mode CPU: 0 PID: 833 Comm: ubiupdatevol Not tainted 4.6.0-rc2-ARCH #4 Hardware name: SAMSUNG ELECTRONICS CO., LTD. 300E4C/300E5C/300E7C/NP300E5C-AD8AR, BIOS P04RAP 10/15/2012 0000000000000286 00000000eba949bd ffff8800c45a7b38 ffffffff8140d841 ffff8801964be000 ffff88018eaa4800 ffff8800c45a7bb8 ffffffffa003abf6 ffffffff850e2ac0 8000000000000163 ffff8801850e2ac0 ffff8801850e2ac0 Call Trace: [] dump_stack+0x63/0x82 [] ubi_eba_read_leb+0x486/0x4a0 [ubi] [] ubi_check_volume+0x83/0xf0 [ubi] [] ubi_open_volume+0x177/0x350 [ubi] [] vol_cdev_open+0x58/0xb0 [ubi] [] chrdev_open+0xae/0x1d0 [] do_dentry_open+0x1ff/0x300 [] ? cdev_put+0x30/0x30 [] vfs_open+0x56/0x60 [] path_openat+0x4f4/0x1190 [] do_filp_open+0x91/0x100 [] ? __alloc_fd+0xc7/0x190 [] do_sys_open+0x13f/0x210 [] SyS_open+0x1e/0x20 [] entry_SYSCALL_64_fastpath+0x1a/0xa4 UBI checks static volumes for data consistency and reads the whole volume upon first open. If the volume is found erroneous users of UBI cannot read from it, but another volume update is possible to fix it. The check is performed by running ubi_eba_read_leb() on every allocated LEB of the volume. For static volumes ubi_eba_read_leb() computes the checksum of all data stored in a LEB. To verify the computed checksum it has to read the LEB's volume header which stores the original checksum. If the volume header is not found UBI treats this as fatal internal error and switches to RO mode. If the UBI device was attached via a full scan the assumption is correct, the volume header has to be present as it had to be there while scanning to get known as mapped. If the attach operation happened via Fastmap the assumption is no longer correct. When attaching via Fastmap UBI learns the mapping table from Fastmap's snapshot of the system state and not via a full scan. It can happen that a LEB got unmapped after a Fastmap was written to the flash. Then UBI can learn the LEB still as mapped and accessing it returns only 0xFF bytes. As UBI is not a FTL it is allowed to have mappings to empty PEBs, it assumes that the layer above takes care of LEB accounting and referencing. UBIFS does so using the LEB property tree (LPT). For static volumes UBI blindly assumes that all LEBs are present and therefore special actions have to be taken. The described situation can happen when updating a static volume is interrupted, either by a user or a power cut. The volume update code first unmaps all LEBs of a volume and then writes LEB by LEB. If the sequence of operations is interrupted UBI detects this either by the absence of LEBs, no volume header present at scan time, or corrupted payload, detected via checksum. In the Fastmap case the former method won't trigger as no scan happened and UBI automatically thinks all LEBs are present. Only by reading data from a LEB it detects that the volume header is missing and incorrectly treats this as fatal error. To deal with the situation ubi_eba_read_leb() from now on checks whether we attached via Fastmap and handles the absence of a volume header like a data corruption error. This way interrupted static volume updates will correctly get detected also when Fastmap is used. Cc: Reported-by: Ezequiel Garcia Tested-by: Ezequiel Garcia Signed-off-by: Richard Weinberger --- drivers/mtd/ubi/eba.c | 21 +++++++++++++++++++-- drivers/mtd/ubi/fastmap.c | 1 + drivers/mtd/ubi/ubi.h | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 61356a9b1303..5780dd1ba79d 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -426,8 +426,25 @@ retry: pnum, vol_id, lnum); err = -EBADMSG; } else { - err = -EINVAL; - ubi_ro_mode(ubi); + /* + * Ending up here in the non-Fastmap case + * is a clear bug as the VID header had to + * be present at scan time to have it referenced. + * With fastmap the story is more complicated. + * Fastmap has the mapping info without the need + * of a full scan. So the LEB could have been + * unmapped, Fastmap cannot know this and keeps + * the LEB referenced. + * This is valid and works as the layer above UBI + * has to do bookkeeping about used/referenced + * LEBs in any case. + */ + if (ubi->fast_attach) { + err = -EBADMSG; + } else { + err = -EINVAL; + ubi_ro_mode(ubi); + } } } goto out_free; diff --git a/drivers/mtd/ubi/fastmap.c b/drivers/mtd/ubi/fastmap.c index 263b439e21a8..990898b9dc72 100644 --- a/drivers/mtd/ubi/fastmap.c +++ b/drivers/mtd/ubi/fastmap.c @@ -1058,6 +1058,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, ubi_msg(ubi, "fastmap WL pool size: %d", ubi->fm_wl_pool.max_size); ubi->fm_disabled = 0; + ubi->fast_attach = 1; ubi_free_vid_hdr(ubi, vh); kfree(ech); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index dadc6a9d5755..61d4e99755a4 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -466,6 +466,7 @@ struct ubi_debug_info { * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes * @fm_work: fastmap work queue * @fm_work_scheduled: non-zero if fastmap work was scheduled + * @fast_attach: non-zero if UBI was attached by fastmap * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks @@ -574,6 +575,7 @@ struct ubi_device { size_t fm_size; struct work_struct fm_work; int fm_work_scheduled; + int fast_attach; /* Wear-leveling sub-system's stuff */ struct rb_root used; From 1112018cefc586cba924770a2b28bff6d2f0aa5c Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Mon, 16 May 2016 21:46:30 +0200 Subject: [PATCH 8/8] ubifs: ubifs_dump_inode: Fix dumping field bulk_read The wrong field (xattr) is dumped here due to a copy-and-paste error. Signed-off-by: Andreas Gruenbacher Signed-off-by: Richard Weinberger --- 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 595ca0debe11..69e287e20732 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c @@ -260,7 +260,7 @@ void ubifs_dump_inode(struct ubifs_info *c, const struct inode *inode) pr_err("\txattr_names %u\n", ui->xattr_names); pr_err("\tdirty %u\n", ui->dirty); pr_err("\txattr %u\n", ui->xattr); - pr_err("\tbulk_read %u\n", ui->xattr); + pr_err("\tbulk_read %u\n", ui->bulk_read); pr_err("\tsynced_i_size %llu\n", (unsigned long long)ui->synced_i_size); pr_err("\tui_size %llu\n",