diff options
author | Theodore Ts'o <tytso@mit.edu> | 2022-01-05 23:59:56 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2022-01-27 08:47:40 +0100 |
commit | ab5edcdd0e37f03d2d95f0daef145c700c2a890d (patch) | |
tree | 30f312d85e179327b5f8bf7873c09f4863dcc3a1 | |
parent | 581658a6111b88e9b672c5cfc6e2239c32922603 (diff) | |
download | linux-stable-ab5edcdd0e37f03d2d95f0daef145c700c2a890d.tar.gz linux-stable-ab5edcdd0e37f03d2d95f0daef145c700c2a890d.tar.bz2 linux-stable-ab5edcdd0e37f03d2d95f0daef145c700c2a890d.zip |
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: Theodore Ts'o <tytso@mit.edu>
Reviewed-by: Lukas Czerner <lczerner@redhat.com>
Cc: stable@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | fs/ext4/migrate.c | 19 |
1 files changed, 4 insertions, 15 deletions
diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c index f918accde5ec..6967ab3306e7 100644 --- a/fs/ext4/migrate.c +++ b/fs/ext4/migrate.c @@ -462,12 +462,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); @@ -488,10 +488,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; @@ -503,7 +499,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); /* @@ -528,12 +523,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; } |