--- /dev/null
+From 50f094a5580e6297bf10a807d16f0ee23fa576cf Mon Sep 17 00:00:00 2001
+From: Lukas Czerner <lczerner@redhat.com>
+Date: Wed, 24 Aug 2022 18:03:47 +0200
+Subject: ext4: don't increase iversion counter for ea_inodes
+
+From: Lukas Czerner <lczerner@redhat.com>
+
+commit 50f094a5580e6297bf10a807d16f0ee23fa576cf upstream.
+
+ea_inodes are using i_version for storing part of the reference count so
+we really need to leave it alone.
+
+The problem can be reproduced by xfstest ext4/026 when iversion is
+enabled. Fix it by not calling inode_inc_iversion() for EXT4_EA_INODE_FL
+inodes in ext4_mark_iloc_dirty().
+
+Cc: stable@kernel.org
+Signed-off-by: Lukas Czerner <lczerner@redhat.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Jeff Layton <jlayton@kernel.org>
+Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
+Link: https://lore.kernel.org/r/20220824160349.39664-1-lczerner@redhat.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/inode.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -5701,7 +5701,12 @@ int ext4_mark_iloc_dirty(handle_t *handl
+ }
+ ext4_fc_track_inode(handle, inode);
+
+- if (IS_I_VERSION(inode))
++ /*
++ * ea_inodes are using i_version for storing reference count, don't
++ * mess with it
++ */
++ if (IS_I_VERSION(inode) &&
++ !(EXT4_I(inode)->i_flags & EXT4_EA_INODE_FL))
+ inode_inc_iversion(inode);
+
+ /* the do_update_inode consumes one bh->b_count */
--- /dev/null
+From 0b73284c564d3ae4feef4bc920292f004acf4980 Mon Sep 17 00:00:00 2001
+From: Zhang Yi <yi.zhang@huawei.com>
+Date: Wed, 31 Aug 2022 15:46:29 +0800
+Subject: ext4: ext4_read_bh_lock() should submit IO if the buffer isn't uptodate
+
+From: Zhang Yi <yi.zhang@huawei.com>
+
+commit 0b73284c564d3ae4feef4bc920292f004acf4980 upstream.
+
+Recently we notice that ext4 filesystem would occasionally fail to read
+metadata from disk and report error message, but the disk and block
+layer looks fine. After analyse, we lockon commit 88dbcbb3a484
+("blkdev: avoid migration stalls for blkdev pages"). It provide a
+migration method for the bdev, we could move page that has buffers
+without extra users now, but it lock the buffers on the page, which
+breaks the fragile metadata read operation on ext4 filesystem,
+ext4_read_bh_lock() was copied from ll_rw_block(), it depends on the
+assumption of that locked buffer means it is under IO. So it just
+trylock the buffer and skip submit IO if it lock failed, after
+wait_on_buffer() we conclude IO error because the buffer is not
+uptodate.
+
+This issue could be easily reproduced by add some delay just after
+buffer_migrate_lock_buffers() in __buffer_migrate_folio() and do
+fsstress on ext4 filesystem.
+
+ EXT4-fs error (device pmem1): __ext4_find_entry:1658: inode #73193:
+ comm fsstress: reading directory lblock 0
+ EXT4-fs error (device pmem1): __ext4_find_entry:1658: inode #75334:
+ comm fsstress: reading directory lblock 0
+
+Fix it by removing the trylock logic in ext4_read_bh_lock(), just lock
+the buffer and submit IO if it's not uptodate, and also leave over
+readahead helper.
+
+Cc: stable@kernel.org
+Signed-off-by: Zhang Yi <yi.zhang@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220831074629.3755110-1-yi.zhang@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c | 16 +++++-----------
+ 1 file changed, 5 insertions(+), 11 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -186,19 +186,12 @@ int ext4_read_bh(struct buffer_head *bh,
+
+ int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, bool wait)
+ {
+- if (trylock_buffer(bh)) {
+- if (wait)
+- return ext4_read_bh(bh, op_flags, NULL);
++ lock_buffer(bh);
++ if (!wait) {
+ ext4_read_bh_nowait(bh, op_flags, NULL);
+ return 0;
+ }
+- if (wait) {
+- wait_on_buffer(bh);
+- if (buffer_uptodate(bh))
+- return 0;
+- return -EIO;
+- }
+- return 0;
++ return ext4_read_bh(bh, op_flags, NULL);
+ }
+
+ /*
+@@ -245,7 +238,8 @@ void ext4_sb_breadahead_unmovable(struct
+ struct buffer_head *bh = sb_getblk_gfp(sb, block, 0);
+
+ if (likely(bh)) {
+- ext4_read_bh_lock(bh, REQ_RAHEAD, false);
++ if (trylock_buffer(bh))
++ ext4_read_bh_nowait(bh, REQ_RAHEAD, NULL);
+ brelse(bh);
+ }
+ }
--- /dev/null
+From 61a1d87a324ad5e3ed27c6699dfc93218fcf3201 Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Mon, 22 Aug 2022 13:48:32 +0200
+Subject: ext4: fix check for block being out of directory size
+
+From: Jan Kara <jack@suse.cz>
+
+commit 61a1d87a324ad5e3ed27c6699dfc93218fcf3201 upstream.
+
+The check in __ext4_read_dirblock() for block being outside of directory
+size was wrong because it compared block number against directory size
+in bytes. Fix it.
+
+Fixes: 65f8ea4cd57d ("ext4: check if directory block is within i_size")
+CVE: CVE-2022-1184
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Reviewed-by: Lukas Czerner <lczerner@redhat.com>
+Link: https://lore.kernel.org/r/20220822114832.1482-1-jack@suse.cz
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/namei.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -126,7 +126,7 @@ static struct buffer_head *__ext4_read_d
+ struct ext4_dir_entry *dirent;
+ int is_dx_block = 0;
+
+- if (block >= inode->i_size) {
++ if (block >= inode->i_size >> inode->i_blkbits) {
+ ext4_error_inode(inode, func, line, block,
+ "Attempting to read directory block (%u) that is past i_size (%llu)",
+ block, inode->i_size);
--- /dev/null
+From 7177dd009c7c04290891e9a534cd47d1b620bd04 Mon Sep 17 00:00:00 2001
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+Date: Sun, 11 Sep 2022 12:52:04 +0800
+Subject: ext4: fix dir corruption when ext4_dx_add_entry() fails
+
+From: Zhihao Cheng <chengzhihao1@huawei.com>
+
+commit 7177dd009c7c04290891e9a534cd47d1b620bd04 upstream.
+
+Following process may lead to fs corruption:
+1. ext4_create(dir/foo)
+ ext4_add_nondir
+ ext4_add_entry
+ ext4_dx_add_entry
+ a. add_dirent_to_buf
+ ext4_mark_inode_dirty
+ ext4_handle_dirty_metadata // dir inode bh is recorded into journal
+ b. ext4_append // dx_get_count(entries) == dx_get_limit(entries)
+ ext4_bread(EXT4_GET_BLOCKS_CREATE)
+ ext4_getblk
+ ext4_map_blocks
+ ext4_ext_map_blocks
+ ext4_mb_new_blocks
+ dquot_alloc_block
+ dquot_alloc_space_nodirty
+ inode_add_bytes // update dir's i_blocks
+ ext4_ext_insert_extent
+ ext4_ext_dirty // record extent bh into journal
+ ext4_handle_dirty_metadata(bh)
+ // record new block into journal
+ inode->i_size += inode->i_sb->s_blocksize // new size(in mem)
+ c. ext4_handle_dirty_dx_node(bh2)
+ // record dir's new block(dx_node) into journal
+ d. ext4_handle_dirty_dx_node((frame - 1)->bh)
+ e. ext4_handle_dirty_dx_node(frame->bh)
+ f. do_split // ret err!
+ g. add_dirent_to_buf
+ ext4_mark_inode_dirty(dir) // update raw_inode on disk(skipped)
+2. fsck -a /dev/sdb
+ drop last block(dx_node) which beyonds dir's i_size.
+ /dev/sdb: recovering journal
+ /dev/sdb contains a file system with errors, check forced.
+ /dev/sdb: Inode 12, end of extent exceeds allowed value
+ (logical block 128, physical block 3938, len 1)
+3. fsck -fn /dev/sdb
+ dx_node->entry[i].blk > dir->i_size
+ Pass 2: Checking directory structure
+ Problem in HTREE directory inode 12 (/dir): bad block number 128.
+ Clear HTree index? no
+ Problem in HTREE directory inode 12: block #3 has invalid depth (2)
+ Problem in HTREE directory inode 12: block #3 has bad max hash
+ Problem in HTREE directory inode 12: block #3 not referenced
+
+Fix it by marking inode dirty directly inside ext4_append().
+Fetch a reproducer in [Link].
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216466
+Cc: stable@vger.kernel.org
+Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220911045204.516460-1-chengzhihao1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/namei.c | 15 ++++++++++-----
+ 1 file changed, 10 insertions(+), 5 deletions(-)
+
+--- a/fs/ext4/namei.c
++++ b/fs/ext4/namei.c
+@@ -85,15 +85,20 @@ static struct buffer_head *ext4_append(h
+ return bh;
+ inode->i_size += inode->i_sb->s_blocksize;
+ EXT4_I(inode)->i_disksize = inode->i_size;
++ err = ext4_mark_inode_dirty(handle, inode);
++ if (err)
++ goto out;
+ BUFFER_TRACE(bh, "get_write_access");
+ err = ext4_journal_get_write_access(handle, inode->i_sb, bh,
+ EXT4_JTR_NONE);
+- if (err) {
+- brelse(bh);
+- ext4_std_error(inode->i_sb, err);
+- return ERR_PTR(err);
+- }
++ if (err)
++ goto out;
+ return bh;
++
++out:
++ brelse(bh);
++ ext4_std_error(inode->i_sb, err);
++ return ERR_PTR(err);
+ }
+
+ static int ext4_dx_csum_verify(struct inode *inode,
--- /dev/null
+From ccbf8eeb39f2ff00b54726a2b20b35d788c4ecb5 Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Wed, 14 Sep 2022 18:08:59 +0800
+Subject: ext4: fix miss release buffer head in ext4_fc_write_inode
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit ccbf8eeb39f2ff00b54726a2b20b35d788c4ecb5 upstream.
+
+In 'ext4_fc_write_inode' function first call 'ext4_get_inode_loc' get 'iloc',
+after use it miss release 'iloc.bh'.
+So just release 'iloc.bh' before 'ext4_fc_write_inode' return.
+
+Cc: stable@kernel.org
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220914100859.1415196-1-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 15 +++++++++------
+ 1 file changed, 9 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -794,22 +794,25 @@ static int ext4_fc_write_inode(struct in
+ tl.fc_tag = cpu_to_le16(EXT4_FC_TAG_INODE);
+ tl.fc_len = cpu_to_le16(inode_len + sizeof(fc_inode.fc_ino));
+
++ ret = -ECANCELED;
+ dst = ext4_fc_reserve_space(inode->i_sb,
+ sizeof(tl) + inode_len + sizeof(fc_inode.fc_ino), crc);
+ if (!dst)
+- return -ECANCELED;
++ goto err;
+
+ if (!ext4_fc_memcpy(inode->i_sb, dst, &tl, sizeof(tl), crc))
+- return -ECANCELED;
++ goto err;
+ dst += sizeof(tl);
+ if (!ext4_fc_memcpy(inode->i_sb, dst, &fc_inode, sizeof(fc_inode), crc))
+- return -ECANCELED;
++ goto err;
+ dst += sizeof(fc_inode);
+ if (!ext4_fc_memcpy(inode->i_sb, dst, (u8 *)ext4_raw_inode(&iloc),
+ inode_len, crc))
+- return -ECANCELED;
+-
+- return 0;
++ goto err;
++ ret = 0;
++err:
++ brelse(iloc.bh);
++ return ret;
+ }
+
+ /*
--- /dev/null
+From f9c1f248607d5546075d3f731e7607d5571f2b60 Mon Sep 17 00:00:00 2001
+From: Baokun Li <libaokun1@huawei.com>
+Date: Fri, 5 Aug 2022 20:39:47 +0800
+Subject: ext4: fix null-ptr-deref in ext4_write_info
+
+From: Baokun Li <libaokun1@huawei.com>
+
+commit f9c1f248607d5546075d3f731e7607d5571f2b60 upstream.
+
+I caught a null-ptr-deref bug as follows:
+==================================================================
+KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f]
+CPU: 1 PID: 1589 Comm: umount Not tainted 5.10.0-02219-dirty #339
+RIP: 0010:ext4_write_info+0x53/0x1b0
+[...]
+Call Trace:
+ dquot_writeback_dquots+0x341/0x9a0
+ ext4_sync_fs+0x19e/0x800
+ __sync_filesystem+0x83/0x100
+ sync_filesystem+0x89/0xf0
+ generic_shutdown_super+0x79/0x3e0
+ kill_block_super+0xa1/0x110
+ deactivate_locked_super+0xac/0x130
+ deactivate_super+0xb6/0xd0
+ cleanup_mnt+0x289/0x400
+ __cleanup_mnt+0x16/0x20
+ task_work_run+0x11c/0x1c0
+ exit_to_user_mode_prepare+0x203/0x210
+ syscall_exit_to_user_mode+0x5b/0x3a0
+ do_syscall_64+0x59/0x70
+ entry_SYSCALL_64_after_hwframe+0x44/0xa9
+ ==================================================================
+
+Above issue may happen as follows:
+-------------------------------------
+exit_to_user_mode_prepare
+ task_work_run
+ __cleanup_mnt
+ cleanup_mnt
+ deactivate_super
+ deactivate_locked_super
+ kill_block_super
+ generic_shutdown_super
+ shrink_dcache_for_umount
+ dentry = sb->s_root
+ sb->s_root = NULL <--- Here set NULL
+ sync_filesystem
+ __sync_filesystem
+ sb->s_op->sync_fs > ext4_sync_fs
+ dquot_writeback_dquots
+ sb->dq_op->write_info > ext4_write_info
+ ext4_journal_start(d_inode(sb->s_root), EXT4_HT_QUOTA, 2)
+ d_inode(sb->s_root)
+ s_root->d_inode <--- Null pointer dereference
+
+To solve this problem, we use ext4_journal_start_sb directly
+to avoid s_root being used.
+
+Cc: stable@kernel.org
+Signed-off-by: Baokun Li <libaokun1@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220805123947.565152-1-libaokun1@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -6207,7 +6207,7 @@ static int ext4_write_info(struct super_
+ handle_t *handle;
+
+ /* Data block + inode block */
+- handle = ext4_journal_start(d_inode(sb->s_root), EXT4_HT_QUOTA, 2);
++ handle = ext4_journal_start_sb(sb, EXT4_HT_QUOTA, 2);
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ ret = dquot_commit_info(sb, type);
--- /dev/null
+From 9305721a309fa1bd7c194e0d4a2335bf3b29dca4 Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Wed, 21 Sep 2022 14:40:38 +0800
+Subject: ext4: fix potential memory leak in ext4_fc_record_modified_inode()
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit 9305721a309fa1bd7c194e0d4a2335bf3b29dca4 upstream.
+
+As krealloc may return NULL, in this case 'state->fc_modified_inodes'
+may not be freed by krealloc, but 'state->fc_modified_inodes' already
+set NULL. Then will lead to 'state->fc_modified_inodes' memory leak.
+
+Cc: stable@kernel.org
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220921064040.3693255-2-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1414,13 +1414,15 @@ static int ext4_fc_record_modified_inode
+ if (state->fc_modified_inodes[i] == ino)
+ return 0;
+ if (state->fc_modified_inodes_used == state->fc_modified_inodes_size) {
+- state->fc_modified_inodes = krealloc(
+- state->fc_modified_inodes,
++ int *fc_modified_inodes;
++
++ fc_modified_inodes = krealloc(state->fc_modified_inodes,
+ sizeof(int) * (state->fc_modified_inodes_size +
+ EXT4_FC_REPLAY_REALLOC_INCREMENT),
+ GFP_KERNEL);
+- if (!state->fc_modified_inodes)
++ if (!fc_modified_inodes)
+ return -ENOMEM;
++ state->fc_modified_inodes = fc_modified_inodes;
+ state->fc_modified_inodes_size +=
+ EXT4_FC_REPLAY_REALLOC_INCREMENT;
+ }
--- /dev/null
+From 7069d105c1f15c442b68af43f7fde784f3126739 Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Wed, 21 Sep 2022 14:40:39 +0800
+Subject: ext4: fix potential memory leak in ext4_fc_record_regions()
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit 7069d105c1f15c442b68af43f7fde784f3126739 upstream.
+
+As krealloc may return NULL, in this case 'state->fc_regions' may not be
+freed by krealloc, but 'state->fc_regions' already set NULL. Then will
+lead to 'state->fc_regions' memory leak.
+
+Cc: stable@kernel.org
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220921064040.3693255-3-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1607,15 +1607,17 @@ int ext4_fc_record_regions(struct super_
+ if (replay && state->fc_regions_used != state->fc_regions_valid)
+ state->fc_regions_used = state->fc_regions_valid;
+ if (state->fc_regions_used == state->fc_regions_size) {
++ struct ext4_fc_alloc_region *fc_regions;
++
+ state->fc_regions_size +=
+ EXT4_FC_REPLAY_REALLOC_INCREMENT;
+- state->fc_regions = krealloc(
+- state->fc_regions,
+- state->fc_regions_size *
+- sizeof(struct ext4_fc_alloc_region),
+- GFP_KERNEL);
+- if (!state->fc_regions)
++ fc_regions = krealloc(state->fc_regions,
++ state->fc_regions_size *
++ sizeof(struct ext4_fc_alloc_region),
++ GFP_KERNEL);
++ if (!fc_regions)
+ return -ENOMEM;
++ state->fc_regions = fc_regions;
+ }
+ region = &state->fc_regions[state->fc_regions_used++];
+ region->ino = ino;
--- /dev/null
+From 3b575495ab8dbb4dbe85b4ac7f991693c3668ff5 Mon Sep 17 00:00:00 2001
+From: Lalith Rajendran <lalithkraj@google.com>
+Date: Thu, 18 Aug 2022 21:40:49 +0000
+Subject: ext4: make ext4_lazyinit_thread freezable
+
+From: Lalith Rajendran <lalithkraj@google.com>
+
+commit 3b575495ab8dbb4dbe85b4ac7f991693c3668ff5 upstream.
+
+ext4_lazyinit_thread is not set freezable. Hence when the thread calls
+try_to_freeze it doesn't freeze during suspend and continues to send
+requests to the storage during suspend, resulting in suspend failures.
+
+Cc: stable@kernel.org
+Signed-off-by: Lalith Rajendran <lalithkraj@google.com>
+Link: https://lore.kernel.org/r/20220818214049.1519544-1-lalithkraj@google.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/super.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -3377,6 +3377,7 @@ static int ext4_lazyinit_thread(void *ar
+ unsigned long next_wakeup, cur;
+
+ BUG_ON(NULL == eli);
++ set_freezable();
+
+ cont_thread:
+ while (true) {
--- /dev/null
+From d1052d236eddf6aa851434db1897b942e8db9921 Mon Sep 17 00:00:00 2001
+From: Jinke Han <hanjinke.666@bytedance.com>
+Date: Sat, 3 Sep 2022 09:24:29 +0800
+Subject: ext4: place buffer head allocation before handle start
+
+From: Jinke Han <hanjinke.666@bytedance.com>
+
+commit d1052d236eddf6aa851434db1897b942e8db9921 upstream.
+
+In our product environment, we encounter some jbd hung waiting handles to
+stop while several writters were doing memory reclaim for buffer head
+allocation in delay alloc write path. Ext4 do buffer head allocation with
+holding transaction handle which may be blocked too long if the reclaim
+works not so smooth. According to our bcc trace, the reclaim time in
+buffer head allocation can reach 258s and the jbd transaction commit also
+take almost the same time meanwhile. Except for these extreme cases,
+we often see several seconds delays for cgroup memory reclaim on our
+servers. This is more likely to happen considering docker environment.
+
+One thing to note, the allocation of buffer heads is as often as page
+allocation or more often when blocksize less than page size. Just like
+page cache allocation, we should also place the buffer head allocation
+before startting the handle.
+
+Cc: stable@kernel.org
+Signed-off-by: Jinke Han <hanjinke.666@bytedance.com>
+Link: https://lore.kernel.org/r/20220903012429.22555-1-hanjinke.666@bytedance.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/inode.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/fs/ext4/inode.c
++++ b/fs/ext4/inode.c
+@@ -1177,6 +1177,13 @@ retry_grab:
+ page = grab_cache_page_write_begin(mapping, index, flags);
+ if (!page)
+ return -ENOMEM;
++ /*
++ * The same as page allocation, we prealloc buffer heads before
++ * starting the handle.
++ */
++ if (!page_has_buffers(page))
++ create_empty_buffers(page, inode->i_sb->s_blocksize, 0);
++
+ unlock_page(page);
+
+ retry_journal:
--- /dev/null
+From 27cd49780381c6ccbf248798e5e8fd076200ffba Mon Sep 17 00:00:00 2001
+From: Ye Bin <yebin10@huawei.com>
+Date: Wed, 21 Sep 2022 14:40:40 +0800
+Subject: ext4: update 'state->fc_regions_size' after successful memory allocation
+
+From: Ye Bin <yebin10@huawei.com>
+
+commit 27cd49780381c6ccbf248798e5e8fd076200ffba upstream.
+
+To avoid to 'state->fc_regions_size' mismatch with 'state->fc_regions'
+when fail to reallocate 'fc_reqions',only update 'state->fc_regions_size'
+after 'state->fc_regions' is allocated successfully.
+
+Cc: stable@kernel.org
+Signed-off-by: Ye Bin <yebin10@huawei.com>
+Reviewed-by: Jan Kara <jack@suse.cz>
+Link: https://lore.kernel.org/r/20220921064040.3693255-4-yebin10@huawei.com
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/ext4/fast_commit.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/fs/ext4/fast_commit.c
++++ b/fs/ext4/fast_commit.c
+@@ -1609,14 +1609,15 @@ int ext4_fc_record_regions(struct super_
+ if (state->fc_regions_used == state->fc_regions_size) {
+ struct ext4_fc_alloc_region *fc_regions;
+
+- state->fc_regions_size +=
+- EXT4_FC_REPLAY_REALLOC_INCREMENT;
+ fc_regions = krealloc(state->fc_regions,
+- state->fc_regions_size *
+- sizeof(struct ext4_fc_alloc_region),
++ sizeof(struct ext4_fc_alloc_region) *
++ (state->fc_regions_size +
++ EXT4_FC_REPLAY_REALLOC_INCREMENT),
+ GFP_KERNEL);
+ if (!fc_regions)
+ return -ENOMEM;
++ state->fc_regions_size +=
++ EXT4_FC_REPLAY_REALLOC_INCREMENT;
+ state->fc_regions = fc_regions;
+ }
+ region = &state->fc_regions[state->fc_regions_used++];
jbd2-fix-potential-use-after-free-in-jbd2_fc_wait_bufs.patch
jbd2-add-miss-release-buffer-head-in-fc_do_one_pass.patch
ext4-avoid-crash-when-inline-data-creation-follows-dio-write.patch
+ext4-fix-null-ptr-deref-in-ext4_write_info.patch
+ext4-make-ext4_lazyinit_thread-freezable.patch
+ext4-fix-check-for-block-being-out-of-directory-size.patch
+ext4-don-t-increase-iversion-counter-for-ea_inodes.patch
+ext4-ext4_read_bh_lock-should-submit-io-if-the-buffer-isn-t-uptodate.patch
+ext4-place-buffer-head-allocation-before-handle-start.patch
+ext4-fix-dir-corruption-when-ext4_dx_add_entry-fails.patch
+ext4-fix-miss-release-buffer-head-in-ext4_fc_write_inode.patch
+ext4-fix-potential-memory-leak-in-ext4_fc_record_modified_inode.patch
+ext4-fix-potential-memory-leak-in-ext4_fc_record_regions.patch
+ext4-update-state-fc_regions_size-after-successful-memory-allocation.patch