From 8b765bebb6aecb363031838d394e360bf11bb009 Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Wed, 22 Jun 2016 11:01:57 +0200 Subject: mtd: ubi: Fix endless loop when moving PEB When moving a PEB the leb_write_trylock() function is called. As the function never returns 0 UBI will end up in an endless loop. Noticed the issue when fastmap has been enabled and data is beeing copied several times to a UBI volume. When UBI tries to move the anchor PEB, the issue comes up. The leb_write_trylock() is now equal to the leb_write_lock(). But kept it for easier maintaince in future when syncing with kernel. Signed-off-by: Teresa Remmet Signed-off-by: Sascha Hauer --- drivers/mtd/ubi/eba.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index a7af247953..31dbcd29c3 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -257,16 +257,7 @@ static int leb_write_trylock(struct ubi_device *ubi, int vol_id, int lnum) le = ltree_add_entry(ubi, vol_id, lnum); if (IS_ERR(le)) return PTR_ERR(le); - - /* Contention, cancel */ - le->users -= 1; - ubi_assert(le->users >= 0); - if (le->users == 0) { - rb_erase(&le->rb, &ubi->ltree); - kfree(le); - } - - return 1; + return 0; } /** -- cgit v1.2.3 From 94d8236556338c1e9851a703ef9c89b2fd2f15fe Mon Sep 17 00:00:00 2001 From: Sascha Hauer Date: Fri, 24 Jun 2016 11:38:24 +0200 Subject: mtd: ubi: actually do work in wear leveling code The actual work in the wear leveling code is done in a separate thread. Since we do not have threading so far we did not do any of the queued work. Change this by calling the worker function synchronously. With this barebox now can write a fastmap on a freshly ubiformated device. Signed-off-by: Sascha Hauer --- drivers/mtd/ubi/wl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 4535f2d804..f24c219819 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -183,7 +183,6 @@ static void wl_entry_destroy(struct ubi_device *ubi, struct ubi_wl_entry *e) kfree(e); } -#ifndef CONFIG_MTD_UBI_FASTMAP /** * do_work - do one pending work. * @ubi: UBI device description object @@ -221,7 +220,6 @@ static int do_work(struct ubi_device *ubi) return err; } -#endif /** * in_wl_tree - check if wear-leveling entry is present in a WL RB-tree. @@ -523,8 +521,9 @@ static void __schedule_ubi_work(struct ubi_device *ubi, struct ubi_work *wrk) list_add_tail(&wrk->list, &ubi->works); ubi_assert(ubi->works_count >= 0); ubi->works_count += 1; - if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled(ubi)) - wake_up_process(ubi->bgt_thread); + + /* No threading in barebox, so do work synchronously */ + do_work(ubi); } /** -- cgit v1.2.3 From 2c80865bc1d2b12b74b0546fb1062faafeda85c3 Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Mon, 27 Jun 2016 13:42:17 +0200 Subject: commands: ubimkvol: Add option for static volumes Creating static volumes in barebox already works, only the option was missing. Signed-off-by: Teresa Remmet Signed-off-by: Sascha Hauer --- commands/ubi.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/commands/ubi.c b/commands/ubi.c index 844d75dcb8..dc2b4b502d 100644 --- a/commands/ubi.c +++ b/commands/ubi.c @@ -13,24 +13,41 @@ static int do_ubimkvol(int argc, char *argv[]) { + int opt; struct ubi_mkvol_req req; int fd, ret; uint64_t size; - if (argc != 4) + req.vol_type = UBI_DYNAMIC_VOLUME; + + while ((opt = getopt(argc, argv, "t:")) > 0) { + switch (opt) { + case 't': + if (!strcmp(optarg, "dynamic")) + req.vol_type = UBI_DYNAMIC_VOLUME; + else if (!strcmp(optarg, "static")) + req.vol_type = UBI_STATIC_VOLUME; + else + return COMMAND_ERROR_USAGE; + break; + default: + return COMMAND_ERROR_USAGE; + } + } + + if (argc - optind != 3) return COMMAND_ERROR_USAGE; - size = strtoull_suffix(argv[3], NULL, 0); - req.name_len = min_t(int, strlen(argv[2]), UBI_VOL_NAME_MAX); - strncpy(req.name, argv[2], req.name_len); + size = strtoull_suffix(argv[optind+2], NULL, 0); + req.name_len = min_t(int, strlen(argv[optind+1]), UBI_VOL_NAME_MAX); + strncpy(req.name, argv[optind+1], req.name_len); req.name[req.name_len] = 0; - req.vol_type = UBI_DYNAMIC_VOLUME; req.bytes = size; req.vol_id = UBI_VOL_NUM_AUTO; req.alignment = 1; - fd = open(argv[1], O_WRONLY); + fd = open(argv[optind], O_WRONLY); if (fd < 0) { perror("open"); return 1; @@ -48,12 +65,13 @@ static int do_ubimkvol(int argc, char *argv[]) BAREBOX_CMD_HELP_START(ubimkvol) BAREBOX_CMD_HELP_TEXT("Create an UBI volume on UBIDEV with NAME and SIZE.") BAREBOX_CMD_HELP_TEXT("If SIZE is 0 all available space is used for the volume.") +BAREBOX_CMD_HELP_OPT("-t ", "volume type, default is dynamic") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(ubimkvol) .cmd = do_ubimkvol, BAREBOX_CMD_DESC("create an UBI volume") - BAREBOX_CMD_OPTS("UBIDEV NAME SIZE") + BAREBOX_CMD_OPTS("[-t] UBIDEV NAME SIZE") BAREBOX_CMD_GROUP(CMD_GRP_PART) BAREBOX_CMD_HELP(cmd_ubimkvol_help) BAREBOX_CMD_END -- cgit v1.2.3 From c087e0804f0290e9886899e8a3cccb07c4ce088b Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Mon, 27 Jun 2016 13:42:18 +0200 Subject: mtd: UBI: Add support for updating static volumes Added support to update UBI static volumes in barebox. This is mainly realized with adding the ioctl UBI_IOCVOLUP. Signed-off-by: Teresa Remmet Signed-off-by: Sascha Hauer --- drivers/mtd/ubi/barebox.c | 56 +++++++++++++++++++++++++++++++++++++++++++++-- drivers/mtd/ubi/upd.c | 12 ---------- 2 files changed, 54 insertions(+), 14 deletions(-) diff --git a/drivers/mtd/ubi/barebox.c b/drivers/mtd/ubi/barebox.c index 085e4a76d3..fc60aaeec5 100644 --- a/drivers/mtd/ubi/barebox.c +++ b/drivers/mtd/ubi/barebox.c @@ -65,7 +65,10 @@ static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf, struct ubi_device *ubi = priv->ubi; int err; - if (!priv->written) { + if (!priv->written && !vol->updating) { + if (vol->vol_type == UBI_STATIC_VOLUME) + return -EROFS; + err = ubi_start_update(ubi, vol, vol->used_bytes); if (err < 0) { ubi_err(ubi, "Cannot start volume update"); @@ -104,7 +107,7 @@ static int ubi_volume_cdev_close(struct cdev *cdev) int remaining = vol->usable_leb_size - (priv->written % vol->usable_leb_size); - if (remaining) { + if (remaining && vol->vol_type == UBI_DYNAMIC_VOLUME) { void *buf = kmalloc(remaining, GFP_KERNEL); if (!buf) @@ -122,6 +125,9 @@ static int ubi_volume_cdev_close(struct cdev *cdev) } } + if (vol->vol_type == UBI_STATIC_VOLUME) + cdev->size = priv->written; + err = ubi_finish_update(ubi, vol); if (err) return err; @@ -156,12 +162,54 @@ static loff_t ubi_volume_cdev_lseek(struct cdev *cdev, loff_t ofs) return ofs; } +static int ubi_volume_cdev_ioctl(struct cdev *cdev, int cmd, void *buf) +{ + struct ubi_volume_cdev_priv *priv = cdev->priv; + struct ubi_device *ubi = priv->ubi; + struct ubi_volume *vol = priv->vol; + int err = 0; + + switch (cmd) { + /* Volume update command */ + case UBI_IOCVOLUP: + { + int64_t bytes, rsvd_bytes; + + err = copy_from_user(&bytes, buf, sizeof(int64_t)); + if (err) { + err = -EFAULT; + break; + } + + rsvd_bytes = (long long)vol->reserved_pebs * + ubi->leb_size - vol->data_pad; + + if (bytes < 0 || bytes > rsvd_bytes) { + err = -EINVAL; + break; + } + + err = ubi_start_update(ubi, vol, bytes); + if (bytes == 0) + ubi_volume_notify(ubi, vol, UBI_VOLUME_UPDATED); + + break; + } + + default: + err = -ENOTTY; + break; + } + return err; +} + static struct file_operations ubi_volume_fops = { .open = ubi_volume_cdev_open, .close = ubi_volume_cdev_close, .read = ubi_volume_cdev_read, .write = ubi_volume_cdev_write, .lseek = ubi_volume_cdev_lseek, + .ioctl = ubi_volume_cdev_ioctl, }; int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol) @@ -179,6 +227,10 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol) cdev->name = basprintf("%s.%s", ubi->cdev.name, vol->name); cdev->priv = priv; cdev->size = vol->used_bytes; + + if (vol->vol_type == UBI_STATIC_VOLUME) + cdev->flags = DEVFS_IS_CHARACTER_DEV; + cdev->dev = &vol->dev; ubi_msg(ubi, "registering %s as /dev/%s", vol->name, cdev->name); ret = devfs_create(cdev); diff --git a/drivers/mtd/ubi/upd.c b/drivers/mtd/ubi/upd.c index 33d4dbf0bd..e3deb3e931 100644 --- a/drivers/mtd/ubi/upd.c +++ b/drivers/mtd/ubi/upd.c @@ -368,18 +368,6 @@ 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, UBI_ALL, UBI_ALL); - if (err) - return err; - /* The update is finished, clear the update marker */ - err = clear_update_marker(ubi, vol, vol->upd_bytes); - if (err) - return err; - vol->updating = 0; - err = to_write; - vfree(vol->upd_buf); - } return err; } -- cgit v1.2.3 From f5205bd0922c579959353a56e8e522d40377f74d Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Mon, 27 Jun 2016 13:42:19 +0200 Subject: commands: ubi: Add ubiupdatevol command Add ubiupdatevol command. This is to update static and dynamic volumes. Signed-off-by: Teresa Remmet Signed-off-by: Sascha Hauer --- commands/ubi.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/commands/ubi.c b/commands/ubi.c index dc2b4b502d..65d2d256a8 100644 --- a/commands/ubi.c +++ b/commands/ubi.c @@ -7,10 +7,97 @@ #include #include #include +#include #include #include #include +static int do_ubiupdatevol(int argc, char *argv[]) +{ + int fd_img, fd_vol, ret = 0; + uint64_t size = 0; + struct stat st; + unsigned int count; + void *buf; + + if (argc - optind < 2) + return COMMAND_ERROR_USAGE; + + if (stat(argv[optind + 1], &st)) { + perror("stat image"); + return 1; + } + + size = st.st_size; + + if (size == FILESIZE_MAX) { + printf("%s has unknown filesize, this is not supported\n", + argv[optind + 1]); + return 1; + } + + fd_img = open(argv[optind + 1], O_RDONLY); + if (fd_img < 0) { + perror("open image"); + return 1; + } + + fd_vol = open(argv[optind], O_WRONLY); + if (fd_vol < 0) { + perror("open volume"); + ret = 1; + goto error_img; + } + + ret = ioctl(fd_vol, UBI_IOCVOLUP, &size); + if (ret) { + printf("failed to start update: %s\n", strerror(-ret)); + goto error; + } + + buf = xmalloc(RW_BUF_SIZE); + + while (size) { + + count = read(fd_img, buf, RW_BUF_SIZE); + if (count < 0) { + perror("read"); + ret = 1; + break; + } + + ret = write(fd_vol, buf, count); + if (ret < 0) { + perror("write"); + break; + } + + size -= count; + } + + free(buf); + +error: + close(fd_vol); +error_img: + close(fd_img); + return ret; +} + + +BAREBOX_CMD_HELP_START(ubiupdatevol) +BAREBOX_CMD_HELP_TEXT("Update UBI volume with an image.") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(ubiupdatevol) + .cmd = do_ubiupdatevol, + BAREBOX_CMD_DESC("Update an UBI volume") + BAREBOX_CMD_OPTS("UBIVOL IMAGE") + BAREBOX_CMD_GROUP(CMD_GRP_PART) + BAREBOX_CMD_HELP(cmd_ubiupdatevol_help) +BAREBOX_CMD_END + + static int do_ubimkvol(int argc, char *argv[]) { int opt; -- cgit v1.2.3 From 2c310bd8a9e43e7023fbf7f0cebb2faaed9b03e0 Mon Sep 17 00:00:00 2001 From: Teresa Remmet Date: Mon, 27 Jun 2016 13:42:20 +0200 Subject: ARM: am335x_defconfig: Enable ubi fastmap and ubifs Enable support for ubifs and ubi fastmap. Signed-off-by: Teresa Remmet Signed-off-by: Sascha Hauer --- arch/arm/configs/am335x_defconfig | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig index 96c6699407..382133b8c4 100644 --- a/arch/arm/configs/am335x_defconfig +++ b/arch/arm/configs/am335x_defconfig @@ -22,6 +22,10 @@ CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y CONFIG_MENU=y # CONFIG_TIMESTAMP is not set +CONFIG_BOOTM_SHOW_TYPE=y +CONFIG_BOOTM_VERBOSE=y +CONFIG_BOOTM_INITRD=y +CONFIG_BOOTM_OFTREE=y CONFIG_BLSPEC=y CONFIG_CONSOLE_ACTIVATE_NONE=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y @@ -31,10 +35,6 @@ CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_ARM_MMUINFO=y -CONFIG_BOOTM_SHOW_TYPE=y -CONFIG_BOOTM_VERBOSE=y -CONFIG_BOOTM_INITRD=y -CONFIG_BOOTM_OFTREE=y # CONFIG_CMD_BOOTU is not set CONFIG_CMD_BOOTZ=y CONFIG_CMD_GO=y @@ -108,6 +108,7 @@ CONFIG_MTD_M25P80=y CONFIG_NAND=y CONFIG_NAND_OMAP_GPMC=y CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y CONFIG_USB_HOST=y CONFIG_USB_STORAGE=y CONFIG_USB_GADGET=y @@ -137,3 +138,6 @@ CONFIG_FS_NFS=y CONFIG_FS_FAT=y CONFIG_FS_FAT_WRITE=y CONFIG_FS_FAT_LFN=y +CONFIG_FS_UBIFS=y +CONFIG_FS_UBIFS_COMPRESSION_LZO=y +CONFIG_FS_UBIFS_COMPRESSION_ZLIB=y -- cgit v1.2.3