Commit 5dccdc5a authored by zhangyi (F)'s avatar zhangyi (F) Committed by Theodore Ts'o
Browse files

ext4: do not iput inode under running transaction in ext4_rename()



In ext4_rename(), when RENAME_WHITEOUT failed to add new entry into
directory, it ends up dropping new created whiteout inode under the
running transaction. After commit <9b88f9fb> ("ext4: Do not iput inode
under running transaction"), we follow the assumptions that evict() does
not get called from a transaction context but in ext4_rename() it breaks
this suggestion. Although it's not a real problem, better to obey it, so
this patch add inode to orphan list and stop transaction before final
iput().

Signed-off-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Link: https://lore.kernel.org/r/20210303131703.330415-2-yi.zhang@huawei.com


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent b7ff91fd
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -3799,14 +3799,14 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
	 */
	retval = -ENOENT;
	if (!old.bh || le32_to_cpu(old.de->inode) != old.inode->i_ino)
		goto end_rename;
		goto release_bh;

	new.bh = ext4_find_entry(new.dir, &new.dentry->d_name,
				 &new.de, &new.inlined);
	if (IS_ERR(new.bh)) {
		retval = PTR_ERR(new.bh);
		new.bh = NULL;
		goto end_rename;
		goto release_bh;
	}
	if (new.bh) {
		if (!new.inode) {
@@ -3823,15 +3823,13 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
		handle = ext4_journal_start(old.dir, EXT4_HT_DIR, credits);
		if (IS_ERR(handle)) {
			retval = PTR_ERR(handle);
			handle = NULL;
			goto end_rename;
			goto release_bh;
		}
	} else {
		whiteout = ext4_whiteout_for_rename(mnt_userns, &old, credits, &handle);
		if (IS_ERR(whiteout)) {
			retval = PTR_ERR(whiteout);
			whiteout = NULL;
			goto end_rename;
			goto release_bh;
		}
	}

@@ -3965,16 +3963,18 @@ static int ext4_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
			ext4_resetent(handle, &old,
				      old.inode->i_ino, old_file_type);
			drop_nlink(whiteout);
			ext4_orphan_add(handle, whiteout);
		}
		unlock_new_inode(whiteout);
		ext4_journal_stop(handle);
		iput(whiteout);

	} else {
		ext4_journal_stop(handle);
	}
release_bh:
	brelse(old.dir_bh);
	brelse(old.bh);
	brelse(new.bh);
	if (handle)
		ext4_journal_stop(handle);
	return retval;
}