Merge tag 'ubifs-for-linus-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 May 2023 01:58:59 +0000 (18:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 4 May 2023 01:58:59 +0000 (18:58 -0700)
Pull UBI and UBIFS updates from Richard Weinberger:
 "UBI:

   - Fix error value for try_write_vid_and_data()

   - Minor cleanups

  UBIFS:

   - Fixes for various memory leaks

   - Minor cleanups"

* tag 'ubifs-for-linus-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs:
  ubifs: Fix memleak when insert_old_idx() failed
  Revert "ubifs: dirty_cow_znode: Fix memleak in error handling path"
  ubifs: Fix memory leak in do_rename
  ubifs: Free memory for tmpfile name
  ubi: Fix return value overwrite issue in try_write_vid_and_data()
  ubifs: Remove return in compr_exit()
  ubi: Simplify bool conversion

drivers/mtd/ubi/build.c
drivers/mtd/ubi/eba.c
fs/ubifs/compress.c
fs/ubifs/dir.c
fs/ubifs/tnc.c

index 9cd565daad36851e7631ce88d0c8b575f5f7435a..8b91a55ec0d28827d57fbfb42d405402f738ab71 100644 (file)
@@ -1266,7 +1266,7 @@ static int __init ubi_init(void)
                mutex_lock(&ubi_devices_mutex);
                err = ubi_attach_mtd_dev(mtd, p->ubi_num,
                                         p->vid_hdr_offs, p->max_beb_per1024,
-                                        p->enable_fm == 0 ? true : false);
+                                        p->enable_fm == 0);
                mutex_unlock(&ubi_devices_mutex);
                if (err < 0) {
                        pr_err("UBI error: cannot attach mtd%d\n",
index 403b79d6efd5ad56868e35f7e10e5903ec7fb7b5..655ff41863e2be4e7d5169bb374ca3e365582c71 100644 (file)
@@ -946,7 +946,7 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
                                  int offset, int len)
 {
        struct ubi_device *ubi = vol->ubi;
-       int pnum, opnum, err, vol_id = vol->vol_id;
+       int pnum, opnum, err, err2, vol_id = vol->vol_id;
 
        pnum = ubi_wl_get_peb(ubi);
        if (pnum < 0) {
@@ -981,10 +981,19 @@ static int try_write_vid_and_data(struct ubi_volume *vol, int lnum,
 out_put:
        up_read(&ubi->fm_eba_sem);
 
-       if (err && pnum >= 0)
-               err = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
-       else if (!err && opnum >= 0)
-               err = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0);
+       if (err && pnum >= 0) {
+               err2 = ubi_wl_put_peb(ubi, vol_id, lnum, pnum, 1);
+               if (err2) {
+                       ubi_warn(ubi, "failed to return physical eraseblock %d, error %d",
+                                pnum, err2);
+               }
+       } else if (!err && opnum >= 0) {
+               err2 = ubi_wl_put_peb(ubi, vol_id, lnum, opnum, 0);
+               if (err2) {
+                       ubi_warn(ubi, "failed to return physical eraseblock %d, error %d",
+                                opnum, err2);
+               }
+       }
 
        return err;
 }
index 3a92e6af69b2296347c97adece77e85a2224e0ef..75461777c466b1c93c24cbf05ae942bf0beae573 100644 (file)
@@ -217,7 +217,6 @@ static void compr_exit(struct ubifs_compressor *compr)
 {
        if (compr->capi_name)
                crypto_free_comp(compr->cc);
-       return;
 }
 
 /**
index 1505539f6fe974ae73990e57773a8c96628136f4..ef0499edc248f2a21380398273dd4777203e5286 100644 (file)
@@ -358,7 +358,6 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry)
        umode_t mode = S_IFCHR | WHITEOUT_MODE;
        struct inode *inode;
        struct ubifs_info *c = dir->i_sb->s_fs_info;
-       struct fscrypt_name nm;
 
        /*
         * Create an inode('nlink = 1') for whiteout without updating journal,
@@ -369,10 +368,6 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry)
        dbg_gen("dent '%pd', mode %#hx in dir ino %lu",
                dentry, mode, dir->i_ino);
 
-       err = fscrypt_setup_filename(dir, &dentry->d_name, 0, &nm);
-       if (err)
-               return ERR_PTR(err);
-
        inode = ubifs_new_inode(c, dir, mode, false);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
@@ -395,7 +390,6 @@ out_inode:
        make_bad_inode(inode);
        iput(inode);
 out_free:
-       fscrypt_free_filename(&nm);
        ubifs_err(c, "cannot create whiteout file, error %d", err);
        return ERR_PTR(err);
 }
@@ -492,6 +486,7 @@ static int ubifs_tmpfile(struct mnt_idmap *idmap, struct inode *dir,
        unlock_2_inodes(dir, inode);
 
        ubifs_release_budget(c, &req);
+       fscrypt_free_filename(&nm);
 
        return finish_open_simple(file, 0);
 
index 2469f72eeaabb16867c6485b8acb745c36f969f5..6b7d95b65f4b635709f31d0c37c2e1e9a45cba48 100644 (file)
@@ -44,6 +44,33 @@ enum {
        NOT_ON_MEDIA = 3,
 };
 
+static void do_insert_old_idx(struct ubifs_info *c,
+                             struct ubifs_old_idx *old_idx)
+{
+       struct ubifs_old_idx *o;
+       struct rb_node **p, *parent = NULL;
+
+       p = &c->old_idx.rb_node;
+       while (*p) {
+               parent = *p;
+               o = rb_entry(parent, struct ubifs_old_idx, rb);
+               if (old_idx->lnum < o->lnum)
+                       p = &(*p)->rb_left;
+               else if (old_idx->lnum > o->lnum)
+                       p = &(*p)->rb_right;
+               else if (old_idx->offs < o->offs)
+                       p = &(*p)->rb_left;
+               else if (old_idx->offs > o->offs)
+                       p = &(*p)->rb_right;
+               else {
+                       ubifs_err(c, "old idx added twice!");
+                       kfree(old_idx);
+               }
+       }
+       rb_link_node(&old_idx->rb, parent, p);
+       rb_insert_color(&old_idx->rb, &c->old_idx);
+}
+
 /**
  * insert_old_idx - record an index node obsoleted since the last commit start.
  * @c: UBIFS file-system description object
@@ -69,35 +96,15 @@ enum {
  */
 static int insert_old_idx(struct ubifs_info *c, int lnum, int offs)
 {
-       struct ubifs_old_idx *old_idx, *o;
-       struct rb_node **p, *parent = NULL;
+       struct ubifs_old_idx *old_idx;
 
        old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
        if (unlikely(!old_idx))
                return -ENOMEM;
        old_idx->lnum = lnum;
        old_idx->offs = offs;
+       do_insert_old_idx(c, old_idx);
 
-       p = &c->old_idx.rb_node;
-       while (*p) {
-               parent = *p;
-               o = rb_entry(parent, struct ubifs_old_idx, rb);
-               if (lnum < o->lnum)
-                       p = &(*p)->rb_left;
-               else if (lnum > o->lnum)
-                       p = &(*p)->rb_right;
-               else if (offs < o->offs)
-                       p = &(*p)->rb_left;
-               else if (offs > o->offs)
-                       p = &(*p)->rb_right;
-               else {
-                       ubifs_err(c, "old idx added twice!");
-                       kfree(old_idx);
-                       return 0;
-               }
-       }
-       rb_link_node(&old_idx->rb, parent, p);
-       rb_insert_color(&old_idx->rb, &c->old_idx);
        return 0;
 }
 
@@ -199,23 +206,6 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
        __set_bit(DIRTY_ZNODE, &zn->flags);
        __clear_bit(COW_ZNODE, &zn->flags);
 
-       ubifs_assert(c, !ubifs_zn_obsolete(znode));
-       __set_bit(OBSOLETE_ZNODE, &znode->flags);
-
-       if (znode->level != 0) {
-               int i;
-               const int n = zn->child_cnt;
-
-               /* The children now have new parent */
-               for (i = 0; i < n; i++) {
-                       struct ubifs_zbranch *zbr = &zn->zbranch[i];
-
-                       if (zbr->znode)
-                               zbr->znode->parent = zn;
-               }
-       }
-
-       atomic_long_inc(&c->dirty_zn_cnt);
        return zn;
 }
 
@@ -233,6 +223,42 @@ static int add_idx_dirt(struct ubifs_info *c, int lnum, int dirt)
        return ubifs_add_dirt(c, lnum, dirt);
 }
 
+/**
+ * replace_znode - replace old znode with new znode.
+ * @c: UBIFS file-system description object
+ * @new_zn: new znode
+ * @old_zn: old znode
+ * @zbr: the branch of parent znode
+ *
+ * Replace old znode with new znode in TNC.
+ */
+static void replace_znode(struct ubifs_info *c, struct ubifs_znode *new_zn,
+                         struct ubifs_znode *old_zn, struct ubifs_zbranch *zbr)
+{
+       ubifs_assert(c, !ubifs_zn_obsolete(old_zn));
+       __set_bit(OBSOLETE_ZNODE, &old_zn->flags);
+
+       if (old_zn->level != 0) {
+               int i;
+               const int n = new_zn->child_cnt;
+
+               /* The children now have new parent */
+               for (i = 0; i < n; i++) {
+                       struct ubifs_zbranch *child = &new_zn->zbranch[i];
+
+                       if (child->znode)
+                               child->znode->parent = new_zn;
+               }
+       }
+
+       zbr->znode = new_zn;
+       zbr->lnum = 0;
+       zbr->offs = 0;
+       zbr->len = 0;
+
+       atomic_long_inc(&c->dirty_zn_cnt);
+}
+
 /**
  * dirty_cow_znode - ensure a znode is not being committed.
  * @c: UBIFS file-system description object
@@ -265,28 +291,32 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
                return zn;
 
        if (zbr->len) {
-               err = insert_old_idx(c, zbr->lnum, zbr->offs);
-               if (unlikely(err))
-                       /*
-                        * Obsolete znodes will be freed by tnc_destroy_cnext()
-                        * or free_obsolete_znodes(), copied up znodes should
-                        * be added back to tnc and freed by
-                        * ubifs_destroy_tnc_subtree().
-                        */
+               struct ubifs_old_idx *old_idx;
+
+               old_idx = kmalloc(sizeof(struct ubifs_old_idx), GFP_NOFS);
+               if (unlikely(!old_idx)) {
+                       err = -ENOMEM;
                        goto out;
+               }
+               old_idx->lnum = zbr->lnum;
+               old_idx->offs = zbr->offs;
+
                err = add_idx_dirt(c, zbr->lnum, zbr->len);
-       } else
-               err = 0;
+               if (err) {
+                       kfree(old_idx);
+                       goto out;
+               }
 
-out:
-       zbr->znode = zn;
-       zbr->lnum = 0;
-       zbr->offs = 0;
-       zbr->len = 0;
+               do_insert_old_idx(c, old_idx);
+       }
+
+       replace_znode(c, zn, znode, zbr);
 
-       if (unlikely(err))
-               return ERR_PTR(err);
        return zn;
+
+out:
+       kfree(zn);
+       return ERR_PTR(err);
 }
 
 /**