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

Commit d820cb63 authored by Theodore Ts'o's avatar Theodore Ts'o Committed by Greg Kroah-Hartman
Browse files

ext4: don't use the orphan list when migrating an inode



commit 6eeaf88fd586f05aaf1d48cb3a139d2a5c6eb055 upstream.

We probably want to remove the indirect block to extents migration
feature after a deprecation window, but until then, let's fix a
potential data loss problem caused by the fact that we put the
tmp_inode on the orphan list.  In the unlikely case where we crash and
do a journal recovery, the data blocks belonging to the inode being
migrated are also represented in the tmp_inode on the orphan list ---
and so its data blocks will get marked unallocated, and available for
reuse.

Instead, stop putting the tmp_inode on the oprhan list.  So in the
case where we crash while migrating the inode, we'll leak an inode,
which is not a disaster.  It will be easily fixed the next time we run
fsck, and it's better than potentially having blocks getting claimed
by two different files, and losing data as a result.

Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
Reviewed-by: default avatarLukas Czerner <lczerner@redhat.com>
Cc: stable@kernel.org
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 85c121cf
Loading
Loading
Loading
Loading
+4 −15
Original line number Diff line number Diff line
@@ -455,12 +455,12 @@ int ext4_ext_migrate(struct inode *inode)
	percpu_down_write(&sbi->s_writepages_rwsem);

	/*
	 * Worst case we can touch the allocation bitmaps, a bgd
	 * block, and a block to link in the orphan list.  We do need
	 * need to worry about credits for modifying the quota inode.
	 * Worst case we can touch the allocation bitmaps and a block
	 * group descriptor block.  We do need need to worry about
	 * credits for modifying the quota inode.
	 */
	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE,
		4 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));
		3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb));

	if (IS_ERR(handle)) {
		retval = PTR_ERR(handle);
@@ -481,10 +481,6 @@ int ext4_ext_migrate(struct inode *inode)
	 * Use the correct seed for checksum (i.e. the seed from 'inode').  This
	 * is so that the metadata blocks will have the correct checksum after
	 * the migration.
	 *
	 * Note however that, if a crash occurs during the migration process,
	 * the recovery process is broken because the tmp_inode checksums will
	 * be wrong and the orphans cleanup will fail.
	 */
	ei = EXT4_I(inode);
	EXT4_I(tmp_inode)->i_csum_seed = ei->i_csum_seed;
@@ -496,7 +492,6 @@ int ext4_ext_migrate(struct inode *inode)
	clear_nlink(tmp_inode);

	ext4_ext_tree_init(handle, tmp_inode);
	ext4_orphan_add(handle, tmp_inode);
	ext4_journal_stop(handle);

	/*
@@ -521,12 +516,6 @@ int ext4_ext_migrate(struct inode *inode)

	handle = ext4_journal_start(inode, EXT4_HT_MIGRATE, 1);
	if (IS_ERR(handle)) {
		/*
		 * It is impossible to update on-disk structures without
		 * a handle, so just rollback in-core changes and live other
		 * work to orphan_list_cleanup()
		 */
		ext4_orphan_del(NULL, tmp_inode);
		retval = PTR_ERR(handle);
		goto out_tmp_inode;
	}