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 a7d1febf667a..16baeb51b2bd 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); 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; } diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 5b9834cf2820..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; @@ -1202,32 +1219,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); 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/kapi.c b/drivers/mtd/ubi/kapi.c index 437757c89b9e..348dbbcbedc8 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -705,7 +705,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; 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; 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); 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(); 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",