Commit 9f269232 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'ubifs-for-linus-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/ubifs

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
parents fa31fc82 b5fda08e
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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",
+14 −5
Original line number Diff line number Diff line
@@ -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;
}
+0 −1
Original line number Diff line number Diff line
@@ -217,7 +217,6 @@ static void compr_exit(struct ubifs_compressor *compr)
{
	if (compr->capi_name)
		crypto_free_comp(compr->cc);
	return;
}

/**
+1 −6
Original line number Diff line number Diff line
@@ -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 @@ static struct inode *create_whiteout(struct inode *dir, struct dentry *dentry)
	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);

+86 −56
Original line number Diff line number Diff line
@@ -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);
}

/**