Merge tag 'upstream-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 18:10:16 +0000 (11:10 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 21 Sep 2019 18:10:16 +0000 (11:10 -0700)
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

12 files changed:
drivers/mtd/ubi/block.c
drivers/mtd/ubi/fastmap-wl.c
drivers/mtd/ubi/wl.c
fs/jffs2/fs.c
fs/jffs2/gc.c
fs/jffs2/nodelist.c
fs/jffs2/os-linux.h
fs/jffs2/scan.c
fs/ubifs/auth.c
fs/ubifs/debug.c
fs/ubifs/super.c
fs/ubifs/tnc_misc.c

index 6025398955a21728b0740659c986287c4549e12d..e1a2ae21dfd31f9dd7b792bdc2659c7e74eedc88 100644 (file)
@@ -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 @@ out_unlock:
 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",
-                        vi->size);
-               return -EFBIG;
+               if (ret == -EFBIG) {
+                       dev_warn(disk_to_dev(dev->gd),
+                                "the volume is too big (%d LEBs), cannot resize",
+                                vi->size);
+               }
+               return ret;
        }
 
        mutex_lock(&dev->dev_mutex);
index d9e2e3a6e105fd4885f3812f8e20a6c10e823846..c44c8470247e1b840245cfc174c3e5e2712f918a 100644 (file)
@@ -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 @@ again:
 
        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) {
index 949700a9bb4bdeeb62d8cb14fcf4235b2e07fbb0..3fcdefe2714d0167770e26fe522db7e5b00bd540 100644 (file)
@@ -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);
index 05fe6cf5f1ac3ba5d2470c43ec38b880c21bfcd3..ab8cdd9e932590ea484f2e45b927e26f244ad2f7 100644 (file)
@@ -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;
 
index 9ed0f26cf0238f2d4c6de247da6121abe9059ea3..373b3b7c9f44570ed523332720e116556805214f 100644 (file)
@@ -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;
 }
index b86c78d178c60a3af10f6ae4c688d6acce8f8dbf..021a4a2190eeb2a1500610b1f8e74a09e83787c4 100644 (file)
@@ -226,7 +226,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r
                lastend = this->ofs + this->size;
        } else {
                dbg_fragtree2("lookup gave no frag\n");
-               lastend = 0;
+               return -EINVAL;
        }
 
        /* See if we ran off the end of the fragtree */
index 21071fc2975de9ab4b28fc92ca6c33bb3de4b15b..ef1cfa61549e6cefa1e98673b4cf0269b1f892fa 100644 (file)
@@ -183,9 +183,6 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c,
                                   struct jffs2_inode_info *f,
                                   unsigned long offset,
                                   unsigned long *priv);
-void jffs2_gc_release_page(struct jffs2_sb_info *c,
-                          unsigned char *pg,
-                          unsigned long *priv);
 void jffs2_flash_cleanup(struct jffs2_sb_info *c);
 
 
index 90431dd613b8db1bd699c6cc1eaff6a5608fde46..5f7e284e0df36112b8881eb592b5cc6e185d4e9d 100644 (file)
@@ -527,8 +527,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
                                        err = jffs2_fill_scan_buf(c, sumptr, 
                                                                  jeb->offset + c->sector_size - sumlen,
                                                                  sumlen - buf_len);                            
-                                       if (err)
+                                       if (err) {
+                                               if (sumlen > buf_size)
+                                                       kfree(sumptr);
                                                return err;
+                                       }
                                }
                        }
 
index d9af2de9084af584e815da014d77614eae145d41..8cdbd53d780ca76af5d7fb1ee5d670decec07dc6 100644 (file)
@@ -479,8 +479,10 @@ int __ubifs_node_verify_hmac(const struct ubifs_info *c, const void *node,
                return -ENOMEM;
 
        err = ubifs_node_calc_hmac(c, node, len, ofs_hmac, hmac);
-       if (err)
+       if (err) {
+               kfree(hmac);
                return err;
+       }
 
        err = crypto_memneq(hmac, node + ofs_hmac, hmac_len);
 
index a5f10d79e0ddf5cae1d1bab53936cbd782bb276b..e4b52783819db9eff1ccbfb99eddb66bc9595d64 100644 (file)
@@ -2817,7 +2817,6 @@ void dbg_debugfs_init_fs(struct ubifs_info *c)
                     c->vi.ubi_num, c->vi.vol_id);
        if (n == UBIFS_DFS_DIR_LEN) {
                /* The array size is too small */
-               fname = UBIFS_DFS_DIR_NAME;
                return;
        }
 
index 5e1e8ec0589eba84dd44b41a4b998df359b4e520..7d4547e5202de4c26b08623f8a229aba999fb0db 100644 (file)
@@ -2267,8 +2267,10 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                }
        } else {
                err = ubifs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
-               if (err)
+               if (err) {
+                       kfree(c);
                        goto out_deact;
+               }
                /* We do not support atime */
                sb->s_flags |= SB_ACTIVE;
                if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT))
index 6f293f662d983afed23d90649134c6b915c4d69a..49cb34c3f3243213446cf75d1d0e4d4c6c7e25e7 100644 (file)
@@ -284,6 +284,7 @@ static int read_znode(struct ubifs_info *c, struct ubifs_zbranch *zzbr,
        err = ubifs_node_check_hash(c, idx, zzbr->hash);
        if (err) {
                ubifs_bad_hash(c, idx, zzbr->hash, lnum, offs);
+               kfree(idx);
                return err;
        }