]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Oct 2022 13:24:08 +0000 (15:24 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 16 Oct 2022 13:24:08 +0000 (15:24 +0200)
added patches:
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-fix-check-for-block-being-out-of-directory-size.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-null-ptr-deref-in-ext4_write_info.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-make-ext4_lazyinit_thread-freezable.patch
ext4-place-buffer-head-allocation-before-handle-start.patch
ext4-update-state-fc_regions_size-after-successful-memory-allocation.patch

12 files changed:
queue-5.15/ext4-don-t-increase-iversion-counter-for-ea_inodes.patch [new file with mode: 0644]
queue-5.15/ext4-ext4_read_bh_lock-should-submit-io-if-the-buffer-isn-t-uptodate.patch [new file with mode: 0644]
queue-5.15/ext4-fix-check-for-block-being-out-of-directory-size.patch [new file with mode: 0644]
queue-5.15/ext4-fix-dir-corruption-when-ext4_dx_add_entry-fails.patch [new file with mode: 0644]
queue-5.15/ext4-fix-miss-release-buffer-head-in-ext4_fc_write_inode.patch [new file with mode: 0644]
queue-5.15/ext4-fix-null-ptr-deref-in-ext4_write_info.patch [new file with mode: 0644]
queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_modified_inode.patch [new file with mode: 0644]
queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_regions.patch [new file with mode: 0644]
queue-5.15/ext4-make-ext4_lazyinit_thread-freezable.patch [new file with mode: 0644]
queue-5.15/ext4-place-buffer-head-allocation-before-handle-start.patch [new file with mode: 0644]
queue-5.15/ext4-update-state-fc_regions_size-after-successful-memory-allocation.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/ext4-don-t-increase-iversion-counter-for-ea_inodes.patch b/queue-5.15/ext4-don-t-increase-iversion-counter-for-ea_inodes.patch
new file mode 100644 (file)
index 0000000..326e9cc
--- /dev/null
@@ -0,0 +1,44 @@
+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 */
diff --git a/queue-5.15/ext4-ext4_read_bh_lock-should-submit-io-if-the-buffer-isn-t-uptodate.patch b/queue-5.15/ext4-ext4_read_bh_lock-should-submit-io-if-the-buffer-isn-t-uptodate.patch
new file mode 100644 (file)
index 0000000..d90957a
--- /dev/null
@@ -0,0 +1,80 @@
+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);
+       }
+ }
diff --git a/queue-5.15/ext4-fix-check-for-block-being-out-of-directory-size.patch b/queue-5.15/ext4-fix-check-for-block-being-out-of-directory-size.patch
new file mode 100644 (file)
index 0000000..89defcb
--- /dev/null
@@ -0,0 +1,36 @@
+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);
diff --git a/queue-5.15/ext4-fix-dir-corruption-when-ext4_dx_add_entry-fails.patch b/queue-5.15/ext4-fix-dir-corruption-when-ext4_dx_add_entry-fails.patch
new file mode 100644 (file)
index 0000000..6080e86
--- /dev/null
@@ -0,0 +1,95 @@
+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,
diff --git a/queue-5.15/ext4-fix-miss-release-buffer-head-in-ext4_fc_write_inode.patch b/queue-5.15/ext4-fix-miss-release-buffer-head-in-ext4_fc_write_inode.patch
new file mode 100644 (file)
index 0000000..f15d7fa
--- /dev/null
@@ -0,0 +1,57 @@
+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;
+ }
+ /*
diff --git a/queue-5.15/ext4-fix-null-ptr-deref-in-ext4_write_info.patch b/queue-5.15/ext4-fix-null-ptr-deref-in-ext4_write_info.patch
new file mode 100644 (file)
index 0000000..6942032
--- /dev/null
@@ -0,0 +1,79 @@
+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);
diff --git a/queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_modified_inode.patch b/queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_modified_inode.patch
new file mode 100644 (file)
index 0000000..a176296
--- /dev/null
@@ -0,0 +1,44 @@
+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;
+       }
diff --git a/queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_regions.patch b/queue-5.15/ext4-fix-potential-memory-leak-in-ext4_fc_record_regions.patch
new file mode 100644 (file)
index 0000000..2cbb662
--- /dev/null
@@ -0,0 +1,49 @@
+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;
diff --git a/queue-5.15/ext4-make-ext4_lazyinit_thread-freezable.patch b/queue-5.15/ext4-make-ext4_lazyinit_thread-freezable.patch
new file mode 100644 (file)
index 0000000..c7925da
--- /dev/null
@@ -0,0 +1,32 @@
+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) {
diff --git a/queue-5.15/ext4-place-buffer-head-allocation-before-handle-start.patch b/queue-5.15/ext4-place-buffer-head-allocation-before-handle-start.patch
new file mode 100644 (file)
index 0000000..6b5a528
--- /dev/null
@@ -0,0 +1,49 @@
+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:
diff --git a/queue-5.15/ext4-update-state-fc_regions_size-after-successful-memory-allocation.patch b/queue-5.15/ext4-update-state-fc_regions_size-after-successful-memory-allocation.patch
new file mode 100644 (file)
index 0000000..24d8a1f
--- /dev/null
@@ -0,0 +1,45 @@
+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++];
index d96a1ceec2e348385b8bc56a4d190c9095a42a4d..b24a6fa68d09fe02a9bf1925c611e3ac9aae77e2 100644 (file)
@@ -90,3 +90,14 @@ jbd2-fix-potential-buffer-head-reference-count-leak.patch
 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