FAILED: patch "[PATCH] ext4: Fix reusing stale buffer heads from last failed" failed to apply to 4.19-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.19-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-4.19.y
git checkout FETCH_HEAD
git cherry-pick -x 26fb5290240dc31cae99b8b4dd2af7f46dfcba6b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2023072107-action-steadily-cfc3@gregkh' --subject-prefix 'PATCH 4.19.y' HEAD^..
Possible dependencies:
26fb5290240d ("ext4: Fix reusing stale buffer heads from last failed mounting") ee7ed3aa0f08 ("ext4: rename journal_dev to s_journal_dev inside ext4_sb_info") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570") 4dc5794cf207 ("gpio: pca9570: Add DT bindings for NXP PCA9570")
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 26fb5290240dc31cae99b8b4dd2af7f46dfcba6b Mon Sep 17 00:00:00 2001
From: Zhihao Cheng <[email protected]>
Date: Wed, 15 Mar 2023 09:31:23 +0800
Subject: [PATCH] ext4: Fix reusing stale buffer heads from last failed
mounting
Following process makes ext4 load stale buffer heads from last failed mounting in a new mounting operation:mount_bdev
ext4_fill_super
| ext4_load_and_init_journal
| ext4_load_journal
| jbd2_journal_load
| load_superblock
| journal_get_superblock
| set_buffer_verified(bh) // buffer head is verified
| jbd2_journal_recover // failed caused by EIO
| goto failed_mount3a // skip 'sb->s_root' initialization
deactivate_locked_super
kill_block_super
generic_shutdown_super
if (sb->s_root)
// false, skip ext4_put_super->invalidate_bdev->
// invalidate_mapping_pages->mapping_evict_folio->
// filemap_release_folio->try_to_free_buffers, which
// cannot drop buffer head.
blkdev_put
blkdev_put_whole
if (atomic_dec_and_test(&bdev->bd_openers))
// false, systemd-udev happens to open the device. Then
// blkdev_flush_mapping->kill_bdev->truncate_inode_pages->
// truncate_inode_folio->truncate_cleanup_folio->
// folio_invalidate->block_invalidate_folio->
// filemap_release_folio->try_to_free_buffers will be skipped,
// dropping buffer head is missed again.Second mount:ext4_fill_super
ext4_load_and_init_journal
ext4_load_journal
ext4_get_journal
jbd2_journal_init_inode
journal_init_common
bh = getblk_unmovable
bh = __find_get_block // Found stale bh in last failed mounting
journal->j_sb_buffer = bh
jbd2_journal_load
load_superblock
journal_get_superblock
if (buffer_verified(bh))
// true, skip journal->j_format_version = 2, value is 0
jbd2_journal_recover
do_one_pass
next_log_block += count_tags(journal, bh)
// According to journal_tag_bytes(), 'tag_bytes' calculating is
// affected by jbd2_has_feature_csum3(), jbd2_has_feature_csum3()
// returns false because 'j->j_format_version >= 2' is not true,
// then we get wrong next_log_block. The do_one_pass may exit
// early whenoccuring non JBD2_MAGIC_NUMBER in 'next_log_block'.The filesystem is corrupted here, journal is partially replayed, and new journal sequence number actually is already used by last mounting.
The invalidate_bdev() can drop all buffer heads even racing with bare reading block device(eg. systemd-udev), so we can fix it by invalidating bdev in error handling path in __ext4_fill_super().
Fetch a reproducer in [Link].
fs/ext4/super.c +7 -6
@@ -1128,6 +1128,12 @@ static void ext4_blkdev_remove(struct ext4_sb_info *sbi)struct block_device *bdev; bdev = sbi->s_journal_bdev;if (bdev) { +/* +* Invalidate the journal device's buffers. We don't want them +* floating about in memory - the physical journal device may +* hotswapped, and it breaks the `ro-after' testing code. +*/ +invalidate_bdev (bdev);ext4_blkdev_put (bdev); sbi->s_journal_bdev =NULL ; }
@@ -1328,13 +1334,7 @@ static void ext4_put_super(struct super_block *sb)sync_blockdev (sb->s_bdev);invalidate_bdev (sb->s_bdev);if (sbi->s_journal_bdev && sbi->s_journal_bdev != sb->s_bdev) { -/* -* Invalidate the journal device's buffers. We don't want them -* floating about in memory - the physical journal device may -* hotswapped, and it breaks the `ro-after' testing code. -*/ sync_blockdev (sbi->s_journal_bdev); -invalidate_bdev (sbi->s_journal_bdev);ext4_blkdev_remove (sbi); }
@@ -5655,6 +5655,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)brelse (sbi->s_sbh);ext4_blkdev_remove (sbi); out_fail: +invalidate_bdev (sb->s_bdev); sb->s_fs_info =NULL ;return err; }