From e8c235b065ec07cd1c63c0e0bfbfc718d438baba Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Tue, 8 Jul 2014 16:04:44 +0200 Subject: UBI: init_volumes: Ignore volumes with no LEBs UBI assumes that ubi_attach_info will only contain ubi_ainf_volume structures for volumes with at least one LEB. In scanning mode this is true because UBI can nicely create a ubi_ainf_volume on demand while creating the EBA table. For fastmap this is not true, the fastmap on-flash structure has a list of all volumes, the ubi_ainf_volume structures are created from this list. So it can happen that an empty volume ends up in init_volumes(). We can easely deal with that by looking into ->leb_count too. Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/vtbl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index d77b1c1d7c72..07cac5f9ffb8 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -591,7 +591,7 @@ static int init_volumes(struct ubi_device *ubi, /* Static volumes only */ av = ubi_find_av(ai, i); - if (!av) { + if (!av || !av->leb_count) { /* * No eraseblocks belonging to this volume found. We * don't actually know whether this static volume is -- cgit v1.2.3-70-g09d2 From 495f2bf6c4ed2da5dcadac96312f71da2a5af949 Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 5 May 2014 07:11:52 -0300 Subject: UBI: block: Make ubiblock_resize return something Currently, ubiblock_resize() can fail if the device is not found in the list. This commit changes the return type, so the function can return something meaningful on error paths. Reported-by: kbuild test robot Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/block.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 8457df7ec5af..52cefae01887 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -498,7 +498,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) return 0; } -static void ubiblock_resize(struct ubi_volume_info *vi) +static int ubiblock_resize(struct ubi_volume_info *vi) { struct ubiblock *dev; int disk_capacity; @@ -512,7 +512,7 @@ static void ubiblock_resize(struct ubi_volume_info *vi) dev = find_dev_nolock(vi->ubi_num, vi->vol_id); if (!dev) { mutex_unlock(&devices_mutex); - return; + return -ENODEV; } mutex_lock(&dev->dev_mutex); @@ -521,6 +521,7 @@ static void ubiblock_resize(struct ubi_volume_info *vi) ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size); mutex_unlock(&dev->dev_mutex); mutex_unlock(&devices_mutex); + return 0; } static int ubiblock_notify(struct notifier_block *nb, -- cgit v1.2.3-70-g09d2 From 0a3d571bb8940a189322cc5f51466bdab044a48b Mon Sep 17 00:00:00 2001 From: Ezequiel Garcia Date: Mon, 5 May 2014 07:11:53 -0300 Subject: UBI: block: Set disk_capacity out of the mutex There's no need to set the disk capacity with the mutex held, so this commit takes the variable setting out of the mutex. This simplifies the disk capacity fix for very large volumes in a follow up commit. Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/block.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 52cefae01887..043919ad35e4 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -378,7 +378,7 @@ int ubiblock_create(struct ubi_volume_info *vi) { struct ubiblock *dev; struct gendisk *gd; - int disk_capacity; + int disk_capacity = (vi->size * vi->usable_leb_size) >> 9; int ret; /* Check that the volume isn't already handled */ @@ -412,7 +412,6 @@ int ubiblock_create(struct ubi_volume_info *vi) gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id; gd->private_data = dev; sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); - disk_capacity = (vi->size * vi->usable_leb_size) >> 9; set_capacity(gd, disk_capacity); dev->gd = gd; @@ -501,7 +500,7 @@ int ubiblock_remove(struct ubi_volume_info *vi) static int ubiblock_resize(struct ubi_volume_info *vi) { struct ubiblock *dev; - int disk_capacity; + int disk_capacity = (vi->size * vi->usable_leb_size) >> 9; /* * Need to lock the device list until we stop using the device, @@ -516,7 +515,6 @@ static int ubiblock_resize(struct ubi_volume_info *vi) } mutex_lock(&dev->dev_mutex); - disk_capacity = (vi->size * vi->usable_leb_size) >> 9; set_capacity(dev->gd, disk_capacity); ubi_msg("%s resized to %d LEBs", dev->gd->disk_name, vi->size); mutex_unlock(&dev->dev_mutex); -- cgit v1.2.3-70-g09d2 From 4df38926f337ff4de49a8fb512aa4a55df0c502d Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Mon, 5 May 2014 07:11:54 -0300 Subject: UBI: block: Avoid disk size integer overflow This patch fixes the issue that on very large UBI volumes UBI block does not work correctly. Signed-off-by: Richard Weinberger Signed-off-by: Ezequiel Garcia Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/block.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index 043919ad35e4..33c64955d4d7 100644 --- a/drivers/mtd/ubi/block.c +++ b/drivers/mtd/ubi/block.c @@ -378,9 +378,11 @@ int ubiblock_create(struct ubi_volume_info *vi) { struct ubiblock *dev; struct gendisk *gd; - int disk_capacity = (vi->size * vi->usable_leb_size) >> 9; + u64 disk_capacity = ((u64)vi->size * vi->usable_leb_size) >> 9; int ret; + if ((sector_t)disk_capacity != disk_capacity) + return -EFBIG; /* Check that the volume isn't already handled */ mutex_lock(&devices_mutex); if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { @@ -500,8 +502,13 @@ int ubiblock_remove(struct ubi_volume_info *vi) static int ubiblock_resize(struct ubi_volume_info *vi) { struct ubiblock *dev; - int disk_capacity = (vi->size * vi->usable_leb_size) >> 9; + 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 -- cgit v1.2.3-70-g09d2 From 49e236bc4a2639af0e77b3a05460e8367e3187a4 Mon Sep 17 00:00:00 2001 From: Richard Weinberger Date: Sun, 27 Jul 2014 09:35:48 +0200 Subject: UBI: bugfix in ubi_wl_flush() Use the _safe variant because we're iterating over a list where items get deleted and freed. Signed-off-by: Richard Weinberger Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/wl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/mtd') diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index 0f3425dac910..20f491713145 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -1718,12 +1718,12 @@ int ubi_wl_flush(struct ubi_device *ubi, int vol_id, int lnum) vol_id, lnum, ubi->works_count); while (found) { - struct ubi_work *wrk; + struct ubi_work *wrk, *tmp; found = 0; down_read(&ubi->work_sem); spin_lock(&ubi->wl_lock); - list_for_each_entry(wrk, &ubi->works, list) { + list_for_each_entry_safe(wrk, tmp, &ubi->works, list) { if ((vol_id == UBI_ALL || wrk->vol_id == vol_id) && (lnum == UBI_ALL || wrk->lnum == lnum)) { list_del(&wrk->list); -- cgit v1.2.3-70-g09d2