Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 104c0d6b authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull UBI, UBIFS and JFFS2 updates from Richard Weinberger:
 "UBI:
   - Be less stupid when placing a fastmap anchor
   - Try harder to get an empty PEB in case of contention
   - Make ubiblock to warn if image is not a multiple of 512

  UBIFS:
   - Various fixes in error paths

  JFFS2:
   - Various fixes in error paths"

* tag 'upstream-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  jffs2: Fix memory leak in jffs2_scan_eraseblock() error path
  jffs2: Remove jffs2_gc_fetch_page and jffs2_gc_release_page
  jffs2: Fix possible null-pointer dereferences in jffs2_add_frag_to_fragtree()
  ubi: block: Warn if volume size is not multiple of 512
  ubifs: Fix memory leak bug in alloc_ubifs_info() error path
  ubifs: Fix memory leak in __ubifs_node_verify_hmac error path
  ubifs: Fix memory leak in read_znode() error path
  ubi: ubi_wl_get_peb: Increase the number of attempts while getting PEB
  ubi: Don't do anchor move within fastmap area
  ubifs: Remove redundant assignment to pointer fname
parents 9dca3432 6a379f67
Loading
Loading
Loading
Loading
+35 −8
Original line number Diff line number Diff line
@@ -345,15 +345,36 @@ static const struct blk_mq_ops ubiblock_mq_ops = {
	.init_request	= ubiblock_init_request,
};

static int calc_disk_capacity(struct ubi_volume_info *vi, u64 *disk_capacity)
{
	u64 size = vi->used_bytes >> 9;

	if (vi->used_bytes % 512) {
		pr_warn("UBI: block: volume size is not a multiple of 512, "
			"last %llu bytes are ignored!\n",
			vi->used_bytes - (size << 9));
	}

	if ((sector_t)size != size)
		return -EFBIG;

	*disk_capacity = size;

	return 0;
}

int ubiblock_create(struct ubi_volume_info *vi)
{
	struct ubiblock *dev;
	struct gendisk *gd;
	u64 disk_capacity = vi->used_bytes >> 9;
	u64 disk_capacity;
	int ret;

	if ((sector_t)disk_capacity != disk_capacity)
		return -EFBIG;
	ret = calc_disk_capacity(vi, &disk_capacity);
	if (ret) {
		return ret;
	}

	/* Check that the volume isn't already handled */
	mutex_lock(&devices_mutex);
	if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
@@ -507,7 +528,8 @@ int ubiblock_remove(struct ubi_volume_info *vi)
static int ubiblock_resize(struct ubi_volume_info *vi)
{
	struct ubiblock *dev;
	u64 disk_capacity = vi->used_bytes >> 9;
	u64 disk_capacity;
	int ret;

	/*
	 * Need to lock the device list until we stop using the device,
@@ -520,11 +542,16 @@ static int ubiblock_resize(struct ubi_volume_info *vi)
		mutex_unlock(&devices_mutex);
		return -ENODEV;
	}
	if ((sector_t)disk_capacity != disk_capacity) {

	ret = calc_disk_capacity(vi, &disk_capacity);
	if (ret) {
		mutex_unlock(&devices_mutex);
		dev_warn(disk_to_dev(dev->gd), "the volume is too big (%d LEBs), cannot resize",
		if (ret == -EFBIG) {
			dev_warn(disk_to_dev(dev->gd),
				 "the volume is too big (%d LEBs), cannot resize",
				 vi->size);
		return -EFBIG;
		}
		return ret;
	}

	mutex_lock(&dev->dev_mutex);
+3 −3
Original line number Diff line number Diff line
@@ -196,7 +196,7 @@ static int produce_free_peb(struct ubi_device *ubi)
 */
int ubi_wl_get_peb(struct ubi_device *ubi)
{
	int ret, retried = 0;
	int ret, attempts = 0;
	struct ubi_fm_pool *pool = &ubi->fm_pool;
	struct ubi_fm_pool *wl_pool = &ubi->fm_wl_pool;

@@ -221,12 +221,12 @@ int ubi_wl_get_peb(struct ubi_device *ubi)

	if (pool->used == pool->size) {
		spin_unlock(&ubi->wl_lock);
		if (retried) {
		attempts++;
		if (attempts == 10) {
			ubi_err(ubi, "Unable to get a free PEB from user WL pool");
			ret = -ENOSPC;
			goto out;
		}
		retried = 1;
		up_read(&ubi->fm_eba_sem);
		ret = produce_free_peb(ubi);
		if (ret < 0) {
+6 −0
Original line number Diff line number Diff line
@@ -710,6 +710,12 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
		if (!e2)
			goto out_cancel;

		/*
		 * Anchor move within the anchor area is useless.
		 */
		if (e2->pnum < UBI_FM_MAX_START)
			goto out_cancel;

		self_check_in_wl_tree(ubi, e1, &ubi->used);
		rb_erase(&e1->u.rb, &ubi->used);
		dbg_wl("anchor-move PEB %d to PEB %d", e1->pnum, e2->pnum);
+0 −27
Original line number Diff line number Diff line
@@ -682,33 +682,6 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
	return JFFS2_INODE_INFO(inode);
}

unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
				   struct jffs2_inode_info *f,
				   unsigned long offset,
				   unsigned long *priv)
{
	struct inode *inode = OFNI_EDONI_2SFFJ(f);
	struct page *pg;

	pg = read_cache_page(inode->i_mapping, offset >> PAGE_SHIFT,
			     jffs2_do_readpage_unlock, inode);
	if (IS_ERR(pg))
		return (void *)pg;

	*priv = (unsigned long)pg;
	return kmap(pg);
}

void jffs2_gc_release_page(struct jffs2_sb_info *c,
			   unsigned char *ptr,
			   unsigned long *priv)
{
	struct page *pg = (void *)*priv;

	kunmap(pg);
	put_page(pg);
}

static int jffs2_flash_setup(struct jffs2_sb_info *c) {
	int ret = 0;

+13 −8
Original line number Diff line number Diff line
@@ -1165,12 +1165,13 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
				       struct jffs2_inode_info *f, struct jffs2_full_dnode *fn,
				       uint32_t start, uint32_t end)
{
	struct inode *inode = OFNI_EDONI_2SFFJ(f);
	struct jffs2_full_dnode *new_fn;
	struct jffs2_raw_inode ri;
	uint32_t alloclen, offset, orig_end, orig_start;
	int ret = 0;
	unsigned char *comprbuf = NULL, *writebuf;
	unsigned long pg;
	struct page *page;
	unsigned char *pg_ptr;

	memset(&ri, 0, sizeof(ri));
@@ -1325,15 +1326,18 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
	 * end up here trying to GC the *same* page that jffs2_write_begin() is
	 * trying to write out, read_cache_page() will not deadlock. */
	mutex_unlock(&f->sem);
	pg_ptr = jffs2_gc_fetch_page(c, f, start, &pg);
	mutex_lock(&f->sem);

	if (IS_ERR(pg_ptr)) {
	page = read_cache_page(inode->i_mapping, start >> PAGE_SHIFT,
			       jffs2_do_readpage_unlock, inode);
	if (IS_ERR(page)) {
		pr_warn("read_cache_page() returned error: %ld\n",
			PTR_ERR(pg_ptr));
		return PTR_ERR(pg_ptr);
			PTR_ERR(page));
		mutex_lock(&f->sem);
		return PTR_ERR(page);
	}

	pg_ptr = kmap(page);
	mutex_lock(&f->sem);

	offset = start;
	while(offset < orig_end) {
		uint32_t datalen;
@@ -1396,6 +1400,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
		}
	}

	jffs2_gc_release_page(c, pg_ptr, &pg);
	kunmap(page);
	put_page(page);
	return ret;
}
Loading