From: Sasha Levin Date: Sat, 14 Jan 2023 14:23:27 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v4.14.303~63^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1fb49a2afa13b326999bbabb1a295885b20d78d9;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/asoc-intel-bytcr_rt5640-add-quirk-for-the-advantech-.patch-10536 b/queue-5.4/asoc-intel-bytcr_rt5640-add-quirk-for-the-advantech-.patch-10536 new file mode 100644 index 00000000000..b99524bf186 --- /dev/null +++ b/queue-5.4/asoc-intel-bytcr_rt5640-add-quirk-for-the-advantech-.patch-10536 @@ -0,0 +1,59 @@ +From 43a94a0cc3625f6dfd83b1894c093e4d08402520 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 13 Dec 2022 13:32:46 +0100 +Subject: ASoC: Intel: bytcr_rt5640: Add quirk for the Advantech MICA-071 + tablet + +From: Hans de Goede + +[ Upstream commit a1dec9d70b6ad97087b60b81d2492134a84208c6 ] + +The Advantech MICA-071 tablet deviates from the defaults for +a non CR Bay Trail based tablet in several ways: + +1. It uses an analog MIC on IN3 rather then using DMIC1 +2. It only has 1 speaker +3. It needs the OVCD current threshold to be set to 1500uA instead of + the default 2000uA to reliable differentiate between headphones vs + headsets + +Add a quirk with these settings for this tablet. + +Signed-off-by: Hans de Goede +Acked-by: Pierre-Louis Bossart +Link: https://lore.kernel.org/r/20221213123246.11226-1-hdegoede@redhat.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + sound/soc/intel/boards/bytcr_rt5640.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c +index 6a8edb0a559d..6da730636a85 100644 +--- a/sound/soc/intel/boards/bytcr_rt5640.c ++++ b/sound/soc/intel/boards/bytcr_rt5640.c +@@ -453,6 +453,21 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, ++ { ++ /* Advantech MICA-071 */ ++ .matches = { ++ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Advantech"), ++ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "MICA-071"), ++ }, ++ /* OVCD Th = 1500uA to reliable detect head-phones vs -set */ ++ .driver_data = (void *)(BYT_RT5640_IN3_MAP | ++ BYT_RT5640_JD_SRC_JD2_IN4N | ++ BYT_RT5640_OVCD_TH_1500UA | ++ BYT_RT5640_OVCD_SF_0P75 | ++ BYT_RT5640_MONO_SPEAKER | ++ BYT_RT5640_DIFF_MIC | ++ BYT_RT5640_MCLK_EN), ++ }, + { + .matches = { + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "ARCHOS"), +-- +2.35.1 + diff --git a/queue-5.4/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch b/queue-5.4/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch new file mode 100644 index 00000000000..217b6a06eb6 --- /dev/null +++ b/queue-5.4/ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch @@ -0,0 +1,114 @@ +From c002f4c6ba2b250e85c059413a39df931f1263d7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Oct 2022 12:23:07 +0800 +Subject: ext4: fix bug_on in __es_tree_search caused by bad quota inode + +From: Baokun Li + +[ Upstream commit d323877484765aaacbb2769b06e355c2041ed115 ] + +We got a issue as fllows: +================================================================== + kernel BUG at fs/ext4/extents_status.c:202! + invalid opcode: 0000 [#1] PREEMPT SMP + CPU: 1 PID: 810 Comm: mount Not tainted 6.1.0-rc1-next-g9631525255e3 #352 + RIP: 0010:__es_tree_search.isra.0+0xb8/0xe0 + RSP: 0018:ffffc90001227900 EFLAGS: 00010202 + RAX: 0000000000000000 RBX: 0000000077512a0f RCX: 0000000000000000 + RDX: 0000000000000002 RSI: 0000000000002a10 RDI: ffff8881004cd0c8 + RBP: ffff888177512ac8 R08: 47ffffffffffffff R09: 0000000000000001 + R10: 0000000000000001 R11: 00000000000679af R12: 0000000000002a10 + R13: ffff888177512d88 R14: 0000000077512a10 R15: 0000000000000000 + FS: 00007f4bd76dbc40(0000)GS:ffff88842fd00000(0000)knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00005653bf993cf8 CR3: 000000017bfdf000 CR4: 00000000000006e0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + + ext4_es_cache_extent+0xe2/0x210 + ext4_cache_extents+0xd2/0x110 + ext4_find_extent+0x5d5/0x8c0 + ext4_ext_map_blocks+0x9c/0x1d30 + ext4_map_blocks+0x431/0xa50 + ext4_getblk+0x82/0x340 + ext4_bread+0x14/0x110 + ext4_quota_read+0xf0/0x180 + v2_read_header+0x24/0x90 + v2_check_quota_file+0x2f/0xa0 + dquot_load_quota_sb+0x26c/0x760 + dquot_load_quota_inode+0xa5/0x190 + ext4_enable_quotas+0x14c/0x300 + __ext4_fill_super+0x31cc/0x32c0 + ext4_fill_super+0x115/0x2d0 + get_tree_bdev+0x1d2/0x360 + ext4_get_tree+0x19/0x30 + vfs_get_tree+0x26/0xe0 + path_mount+0x81d/0xfc0 + do_mount+0x8d/0xc0 + __x64_sys_mount+0xc0/0x160 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +================================================================== + +Above issue may happen as follows: +------------------------------------- +ext4_fill_super + ext4_orphan_cleanup + ext4_enable_quotas + ext4_quota_enable + ext4_iget --> get error inode <5> + ext4_ext_check_inode --> Wrong imode makes it escape inspection + make_bad_inode(inode) --> EXT4_BOOT_LOADER_INO set imode + dquot_load_quota_inode + vfs_setup_quota_inode --> check pass + dquot_load_quota_sb + v2_check_quota_file + v2_read_header + ext4_quota_read + ext4_bread + ext4_getblk + ext4_map_blocks + ext4_ext_map_blocks + ext4_find_extent + ext4_cache_extents + ext4_es_cache_extent + __es_tree_search.isra.0 + ext4_es_end --> Wrong extents trigger BUG_ON + +In the above issue, s_usr_quota_inum is set to 5, but inode<5> contains +incorrect imode and disordered extents. Because 5 is EXT4_BOOT_LOADER_INO, +the ext4_ext_check_inode check in the ext4_iget function can be bypassed, +finally, the extents that are not checked trigger the BUG_ON in the +__es_tree_search function. To solve this issue, check whether the inode is +bad_inode in vfs_setup_quota_inode(). + +Signed-off-by: Baokun Li +Reviewed-by: Chaitanya Kulkarni +Reviewed-by: Jason Yan +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221026042310.3839669-2-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/quota/dquot.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index 84f61ab05890..1d652af48f0b 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2311,6 +2311,8 @@ static int vfs_setup_quota_inode(struct inode *inode, int type) + struct super_block *sb = inode->i_sb; + struct quota_info *dqopt = sb_dqopt(sb); + ++ if (is_bad_inode(inode)) ++ return -EUCLEAN; + if (!S_ISREG(inode->i_mode)) + return -EACCES; + if (IS_RDONLY(inode)) +-- +2.35.1 + diff --git a/queue-5.4/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch b/queue-5.4/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch new file mode 100644 index 00000000000..cf9ef58a13a --- /dev/null +++ b/queue-5.4/ext4-fix-uninititialized-value-in-ext4_evict_inode.patch @@ -0,0 +1,97 @@ +From 85f6be5c405641d72662bd1dd4bc2530ed6d26d6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 17 Nov 2022 15:36:03 +0800 +Subject: ext4: fix uninititialized value in 'ext4_evict_inode' + +From: Ye Bin + +[ Upstream commit 7ea71af94eaaaf6d9aed24bc94a05b977a741cb9 ] + +Syzbot found the following issue: +===================================================== +BUG: KMSAN: uninit-value in ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180 + ext4_evict_inode+0xdd/0x26b0 fs/ext4/inode.c:180 + evict+0x365/0x9a0 fs/inode.c:664 + iput_final fs/inode.c:1747 [inline] + iput+0x985/0xdd0 fs/inode.c:1773 + __ext4_new_inode+0xe54/0x7ec0 fs/ext4/ialloc.c:1361 + ext4_mknod+0x376/0x840 fs/ext4/namei.c:2844 + vfs_mknod+0x79d/0x830 fs/namei.c:3914 + do_mknodat+0x47d/0xaa0 + __do_sys_mknodat fs/namei.c:3992 [inline] + __se_sys_mknodat fs/namei.c:3989 [inline] + __ia32_sys_mknodat+0xeb/0x150 fs/namei.c:3989 + do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline] + __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178 + do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203 + do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246 + entry_SYSENTER_compat_after_hwframe+0x70/0x82 + +Uninit was created at: + __alloc_pages+0x9f1/0xe80 mm/page_alloc.c:5578 + alloc_pages+0xaae/0xd80 mm/mempolicy.c:2285 + alloc_slab_page mm/slub.c:1794 [inline] + allocate_slab+0x1b5/0x1010 mm/slub.c:1939 + new_slab mm/slub.c:1992 [inline] + ___slab_alloc+0x10c3/0x2d60 mm/slub.c:3180 + __slab_alloc mm/slub.c:3279 [inline] + slab_alloc_node mm/slub.c:3364 [inline] + slab_alloc mm/slub.c:3406 [inline] + __kmem_cache_alloc_lru mm/slub.c:3413 [inline] + kmem_cache_alloc_lru+0x6f3/0xb30 mm/slub.c:3429 + alloc_inode_sb include/linux/fs.h:3117 [inline] + ext4_alloc_inode+0x5f/0x860 fs/ext4/super.c:1321 + alloc_inode+0x83/0x440 fs/inode.c:259 + new_inode_pseudo fs/inode.c:1018 [inline] + new_inode+0x3b/0x430 fs/inode.c:1046 + __ext4_new_inode+0x2a7/0x7ec0 fs/ext4/ialloc.c:959 + ext4_mkdir+0x4d5/0x1560 fs/ext4/namei.c:2992 + vfs_mkdir+0x62a/0x870 fs/namei.c:4035 + do_mkdirat+0x466/0x7b0 fs/namei.c:4060 + __do_sys_mkdirat fs/namei.c:4075 [inline] + __se_sys_mkdirat fs/namei.c:4073 [inline] + __ia32_sys_mkdirat+0xc4/0x120 fs/namei.c:4073 + do_syscall_32_irqs_on arch/x86/entry/common.c:112 [inline] + __do_fast_syscall_32+0xa2/0x100 arch/x86/entry/common.c:178 + do_fast_syscall_32+0x33/0x70 arch/x86/entry/common.c:203 + do_SYSENTER_32+0x1b/0x20 arch/x86/entry/common.c:246 + entry_SYSENTER_compat_after_hwframe+0x70/0x82 + +CPU: 1 PID: 4625 Comm: syz-executor.2 Not tainted 6.1.0-rc4-syzkaller-62821-gcb231e2f67ec #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/26/2022 +===================================================== + +Now, 'ext4_alloc_inode()' didn't init 'ei->i_flags'. If new inode failed +before set 'ei->i_flags' in '__ext4_new_inode()', then do 'iput()'. As after +6bc0d63dad7f commit will access 'ei->i_flags' in 'ext4_evict_inode()' which +will lead to access uninit-value. +To solve above issue just init 'ei->i_flags' in 'ext4_alloc_inode()'. + +Reported-by: syzbot+57b25da729eb0b88177d@syzkaller.appspotmail.com +Signed-off-by: Ye Bin +Fixes: 6bc0d63dad7f ("ext4: remove EA inode entry from mbcache on inode eviction") +Reviewed-by: Jan Kara +Reviewed-by: Eric Biggers +Link: https://lore.kernel.org/r/20221117073603.2598882-1-yebin@huaweicloud.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/ext4/super.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/fs/ext4/super.c b/fs/ext4/super.c +index 4c014d67dfaf..789a9f6a2ec6 100644 +--- a/fs/ext4/super.c ++++ b/fs/ext4/super.c +@@ -1085,6 +1085,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) + return NULL; + + inode_set_iversion(&ei->vfs_inode, 1); ++ ei->i_flags = 0; + spin_lock_init(&ei->i_raw_lock); + INIT_LIST_HEAD(&ei->i_prealloc_list); + spin_lock_init(&ei->i_prealloc_lock); +-- +2.35.1 + diff --git a/queue-5.4/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch b/queue-5.4/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch new file mode 100644 index 00000000000..d771c628376 --- /dev/null +++ b/queue-5.4/ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch @@ -0,0 +1,80 @@ +From 6f96c33700f094419c8c7019a3f988ef1ece0ad7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 2 Nov 2022 16:06:33 +0800 +Subject: ext4: fix use-after-free in ext4_orphan_cleanup + +From: Baokun Li + +[ Upstream commit a71248b1accb2b42e4980afef4fa4a27fa0e36f5 ] + +I caught a issue as follows: +================================================================== + BUG: KASAN: use-after-free in __list_add_valid+0x28/0x1a0 + Read of size 8 at addr ffff88814b13f378 by task mount/710 + + CPU: 1 PID: 710 Comm: mount Not tainted 6.1.0-rc3-next #370 + Call Trace: + + dump_stack_lvl+0x73/0x9f + print_report+0x25d/0x759 + kasan_report+0xc0/0x120 + __asan_load8+0x99/0x140 + __list_add_valid+0x28/0x1a0 + ext4_orphan_cleanup+0x564/0x9d0 [ext4] + __ext4_fill_super+0x48e2/0x5300 [ext4] + ext4_fill_super+0x19f/0x3a0 [ext4] + get_tree_bdev+0x27b/0x450 + ext4_get_tree+0x19/0x30 [ext4] + vfs_get_tree+0x49/0x150 + path_mount+0xaae/0x1350 + do_mount+0xe2/0x110 + __x64_sys_mount+0xf0/0x190 + do_syscall_64+0x35/0x80 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + + [...] +================================================================== + +Above issue may happen as follows: +------------------------------------- +ext4_fill_super + ext4_orphan_cleanup + --- loop1: assume last_orphan is 12 --- + list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan) + ext4_truncate --> return 0 + ext4_inode_attach_jinode --> return -ENOMEM + iput(inode) --> free inode<12> + --- loop2: last_orphan is still 12 --- + list_add(&EXT4_I(inode)->i_orphan, &EXT4_SB(sb)->s_orphan); + // use inode<12> and trigger UAF + +To solve this issue, we need to propagate the return value of +ext4_inode_attach_jinode() appropriately. + +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20221102080633.1630225-1-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index 5eb1d9ac269c..0830a4de47bc 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4530,7 +4530,8 @@ int ext4_truncate(struct inode *inode) + + /* If we zero-out tail of the page, we have to create jinode for jbd2 */ + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) { +- if (ext4_inode_attach_jinode(inode) < 0) ++ err = ext4_inode_attach_jinode(inode); ++ if (err) + goto out_trace; + } + +-- +2.35.1 + diff --git a/queue-5.4/ext4-jbd2-provide-accessor-function-for-handle-credi.patch b/queue-5.4/ext4-jbd2-provide-accessor-function-for-handle-credi.patch new file mode 100644 index 00000000000..6c2ed4b794d --- /dev/null +++ b/queue-5.4/ext4-jbd2-provide-accessor-function-for-handle-credi.patch @@ -0,0 +1,124 @@ +From da383a89ea15bc937f28cf199eeee546d82be16a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:17 +0100 +Subject: ext4, jbd2: Provide accessor function for handle credits + +From: Jan Kara + +[ Upstream commit a9a8344ee1714f835ba394077e8c13d751e2f148 ] + +Provide accessor function to get number of credits available in a handle +and use it from ext4. Later, computation of available credits won't be +so straightforward. + +Reviewed-by: Theodore Ts'o +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-11-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4_jbd2.c | 13 +++++++------ + fs/ext4/ext4_jbd2.h | 7 ------- + fs/ext4/xattr.c | 2 +- + include/linux/jbd2.h | 6 ++++++ + 4 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index 2b98d893cda9..731bbfdbce5b 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -119,8 +119,8 @@ handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line, + return ext4_get_nojournal(); + + sb = handle->h_journal->j_private; +- trace_ext4_journal_start_reserved(sb, handle->h_buffer_credits, +- _RET_IP_); ++ trace_ext4_journal_start_reserved(sb, ++ jbd2_handle_buffer_credits(handle), _RET_IP_); + err = ext4_journal_check_start(sb); + if (err < 0) { + jbd2_journal_free_reserved(handle); +@@ -138,10 +138,10 @@ int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, + { + if (!ext4_handle_valid(handle)) + return 0; +- if (handle->h_buffer_credits >= check_cred) ++ if (jbd2_handle_buffer_credits(handle) >= check_cred) + return 0; + return ext4_journal_extend(handle, +- extend_cred - handle->h_buffer_credits); ++ extend_cred - jbd2_handle_buffer_credits(handle)); + } + + static void ext4_journal_abort_handle(const char *caller, unsigned int line, +@@ -289,7 +289,7 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, + handle->h_type, + handle->h_line_no, + handle->h_requested_credits, +- handle->h_buffer_credits, err); ++ jbd2_handle_buffer_credits(handle), err); + return err; + } + ext4_error_inode(inode, where, line, +@@ -300,7 +300,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, + handle->h_type, + handle->h_line_no, + handle->h_requested_credits, +- handle->h_buffer_credits, err); ++ jbd2_handle_buffer_credits(handle), ++ err); + } + } else { + if (inode) +diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h +index 481bf770a374..a4b980eae4da 100644 +--- a/fs/ext4/ext4_jbd2.h ++++ b/fs/ext4/ext4_jbd2.h +@@ -288,13 +288,6 @@ static inline int ext4_handle_is_aborted(handle_t *handle) + return 0; + } + +-static inline int ext4_handle_has_enough_credits(handle_t *handle, int needed) +-{ +- if (ext4_handle_valid(handle) && handle->h_buffer_credits < needed) +- return 0; +- return 1; +-} +- + #define ext4_journal_start_sb(sb, type, nblocks) \ + __ext4_journal_start_sb((sb), __LINE__, (type), (nblocks), 0) + +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index cf1af6a4a567..40f76cf6d031 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -2330,7 +2330,7 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, + flags & XATTR_CREATE); + brelse(bh); + +- if (!ext4_handle_has_enough_credits(handle, credits)) { ++ if (jbd2_handle_buffer_credits(handle) < credits) { + error = -ENOSPC; + goto cleanup; + } +diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h +index b0e97e5de8ca..a0768a4b3e84 100644 +--- a/include/linux/jbd2.h ++++ b/include/linux/jbd2.h +@@ -1644,6 +1644,12 @@ static inline tid_t jbd2_get_latest_transaction(journal_t *journal) + return tid; + } + ++ ++static inline int jbd2_handle_buffer_credits(handle_t *handle) ++{ ++ return handle->h_buffer_credits; ++} ++ + #ifdef __KERNEL__ + + #define buffer_trace_init(bh) do {} while (0) +-- +2.35.1 + diff --git a/queue-5.4/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch b/queue-5.4/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch new file mode 100644 index 00000000000..b477bda8e6b --- /dev/null +++ b/queue-5.4/ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch @@ -0,0 +1,79 @@ +From 9bd6f19f9a8ea9041eadb1d5e259e647a34705a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 1 Jul 2020 16:30:27 +0800 +Subject: ext4: lost matching-pair of trace in ext4_truncate + +From: zhengliang + +[ Upstream commit 9a5d265fed014115f35e598022c956e5d2fb863e ] + +It should call trace exit in all return path for ext4_truncate. + +Signed-off-by: zhengliang +Reviewed-by: Andreas Dilger +Reviewed-by: Ritesh Harjani +Link: https://lore.kernel.org/r/20200701083027.45996-1-zhengliang6@huawei.com +Signed-off-by: Theodore Ts'o +Stable-dep-of: a71248b1accb ("ext4: fix use-after-free in ext4_orphan_cleanup") +Signed-off-by: Sasha Levin +--- + fs/ext4/inode.c | 17 +++++++++-------- + 1 file changed, 9 insertions(+), 8 deletions(-) + +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index a39567e03580..5eb1d9ac269c 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -4513,7 +4513,7 @@ int ext4_truncate(struct inode *inode) + trace_ext4_truncate_enter(inode); + + if (!ext4_can_truncate(inode)) +- return 0; ++ goto out_trace; + + ext4_clear_inode_flag(inode, EXT4_INODE_EOFBLOCKS); + +@@ -4524,16 +4524,14 @@ int ext4_truncate(struct inode *inode) + int has_inline = 1; + + err = ext4_inline_data_truncate(inode, &has_inline); +- if (err) +- return err; +- if (has_inline) +- return 0; ++ if (err || has_inline) ++ goto out_trace; + } + + /* If we zero-out tail of the page, we have to create jinode for jbd2 */ + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) { + if (ext4_inode_attach_jinode(inode) < 0) +- return 0; ++ goto out_trace; + } + + if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) +@@ -4542,8 +4540,10 @@ int ext4_truncate(struct inode *inode) + credits = ext4_blocks_for_truncate(inode); + + handle = ext4_journal_start(inode, EXT4_HT_TRUNCATE, credits); +- if (IS_ERR(handle)) +- return PTR_ERR(handle); ++ if (IS_ERR(handle)) { ++ err = PTR_ERR(handle); ++ goto out_trace; ++ } + + if (inode->i_size & (inode->i_sb->s_blocksize - 1)) + ext4_block_truncate_page(handle, mapping, inode->i_size); +@@ -4592,6 +4592,7 @@ int ext4_truncate(struct inode *inode) + ext4_mark_inode_dirty(handle, inode); + ext4_journal_stop(handle); + ++out_trace: + trace_ext4_truncate_exit(inode); + return err; + } +-- +2.35.1 + diff --git a/queue-5.4/ext4-provide-function-to-handle-transaction-restarts.patch b/queue-5.4/ext4-provide-function-to-handle-transaction-restarts.patch new file mode 100644 index 00000000000..b17bfcc7822 --- /dev/null +++ b/queue-5.4/ext4-provide-function-to-handle-transaction-restarts.patch @@ -0,0 +1,799 @@ +From 629cf5472a71183744208ab6d8ee4305367bb86b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:16 +0100 +Subject: ext4: Provide function to handle transaction restarts + +From: Jan Kara + +[ Upstream commit a413036791d040e33badcc634453a4d0c0705499 ] + +Provide ext4_journal_ensure_credits_fn() function to ensure transaction +has given amount of credits and call helper function to prepare for +restarting a transaction. This allows to remove some boilerplate code +from various places, add proper error handling for the case where +transaction extension or restart fails, and reduces following changes +needed for proper revoke record reservation tracking. + +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-10-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/ext4/ext4.h | 4 +- + fs/ext4/ext4_jbd2.c | 11 ++++++ + fs/ext4/ext4_jbd2.h | 48 +++++++++++++++++++++++ + fs/ext4/extents.c | 68 +++++++++++++++++++------------- + fs/ext4/indirect.c | 93 +++++++++++++++++++++++++------------------- + fs/ext4/inode.c | 26 ------------- + fs/ext4/migrate.c | 95 +++++++++++++++++---------------------------- + fs/ext4/resize.c | 46 +++++----------------- + fs/ext4/xattr.c | 90 ++++++++++++++++-------------------------- + 9 files changed, 234 insertions(+), 247 deletions(-) + +diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h +index 946804c3c4b1..6017a55b3834 100644 +--- a/fs/ext4/ext4.h ++++ b/fs/ext4/ext4.h +@@ -2634,7 +2634,6 @@ extern int ext4_can_truncate(struct inode *inode); + extern int ext4_truncate(struct inode *); + extern int ext4_break_layouts(struct inode *); + extern int ext4_punch_hole(struct inode *inode, loff_t offset, loff_t length); +-extern int ext4_truncate_restart_trans(handle_t *, struct inode *, int nblocks); + extern void ext4_set_inode_flags(struct inode *); + extern int ext4_alloc_da_blocks(struct inode *inode); + extern void ext4_set_aops(struct inode *inode); +@@ -3327,6 +3326,9 @@ extern int ext4_swap_extents(handle_t *handle, struct inode *inode1, + ext4_lblk_t lblk2, ext4_lblk_t count, + int mark_unwritten,int *err); + extern int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu); ++extern int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode, ++ int check_cred, int restart_cred); ++ + + /* move_extent.c */ + extern void ext4_double_down_write_data_sem(struct inode *first, +diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c +index 7c70b08d104c..2b98d893cda9 100644 +--- a/fs/ext4/ext4_jbd2.c ++++ b/fs/ext4/ext4_jbd2.c +@@ -133,6 +133,17 @@ handle_t *__ext4_journal_start_reserved(handle_t *handle, unsigned int line, + return handle; + } + ++int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, ++ int extend_cred) ++{ ++ if (!ext4_handle_valid(handle)) ++ return 0; ++ if (handle->h_buffer_credits >= check_cred) ++ return 0; ++ return ext4_journal_extend(handle, ++ extend_cred - handle->h_buffer_credits); ++} ++ + static void ext4_journal_abort_handle(const char *caller, unsigned int line, + const char *err_fn, + struct buffer_head *bh, +diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h +index ef8fcf7d0d3b..481bf770a374 100644 +--- a/fs/ext4/ext4_jbd2.h ++++ b/fs/ext4/ext4_jbd2.h +@@ -346,6 +346,54 @@ static inline int ext4_journal_restart(handle_t *handle, int nblocks) + return 0; + } + ++int __ext4_journal_ensure_credits(handle_t *handle, int check_cred, ++ int extend_cred); ++ ++ ++/* ++ * Ensure @handle has at least @check_creds credits available. If not, ++ * transaction will be extended or restarted to contain at least @extend_cred ++ * credits. Before restarting transaction @fn is executed to allow for cleanup ++ * before the transaction is restarted. ++ * ++ * The return value is < 0 in case of error, 0 in case the handle has enough ++ * credits or transaction extension succeeded, 1 in case transaction had to be ++ * restarted. ++ */ ++#define ext4_journal_ensure_credits_fn(handle, check_cred, extend_cred, fn) \ ++({ \ ++ __label__ __ensure_end; \ ++ int err = __ext4_journal_ensure_credits((handle), (check_cred), \ ++ (extend_cred)); \ ++ \ ++ if (err <= 0) \ ++ goto __ensure_end; \ ++ err = (fn); \ ++ if (err < 0) \ ++ goto __ensure_end; \ ++ err = ext4_journal_restart((handle), (extend_cred)); \ ++ if (err == 0) \ ++ err = 1; \ ++__ensure_end: \ ++ err; \ ++}) ++ ++/* ++ * Ensure given handle has at least requested amount of credits available, ++ * possibly restarting transaction if needed. ++ */ ++static inline int ext4_journal_ensure_credits(handle_t *handle, int credits) ++{ ++ return ext4_journal_ensure_credits_fn(handle, credits, credits, 0); ++} ++ ++static inline int ext4_journal_ensure_credits_batch(handle_t *handle, ++ int credits) ++{ ++ return ext4_journal_ensure_credits_fn(handle, credits, ++ EXT4_MAX_TRANS_DATA, 0); ++} ++ + static inline int ext4_journal_blocks_per_page(struct inode *inode) + { + if (EXT4_JOURNAL(inode) != NULL) +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 27760c39f70e..81226addfefe 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -100,29 +100,40 @@ static int ext4_split_extent_at(handle_t *handle, + static int ext4_find_delayed_extent(struct inode *inode, + struct extent_status *newes); + +-static int ext4_ext_truncate_extend_restart(handle_t *handle, +- struct inode *inode, +- int needed) ++static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped) + { +- int err; +- +- if (!ext4_handle_valid(handle)) +- return 0; +- if (handle->h_buffer_credits >= needed) +- return 0; + /* +- * If we need to extend the journal get a few extra blocks +- * while we're at it for efficiency's sake. ++ * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this ++ * moment, get_block can be called only for blocks inside i_size since ++ * page cache has been already dropped and writes are blocked by ++ * i_mutex. So we can safely drop the i_data_sem here. + */ +- needed += 3; +- err = ext4_journal_extend(handle, needed - handle->h_buffer_credits); +- if (err <= 0) +- return err; +- err = ext4_truncate_restart_trans(handle, inode, needed); +- if (err == 0) +- err = -EAGAIN; ++ BUG_ON(EXT4_JOURNAL(inode) == NULL); ++ ext4_discard_preallocations(inode); ++ up_write(&EXT4_I(inode)->i_data_sem); ++ *dropped = 1; ++ return 0; ++} + +- return err; ++/* ++ * Make sure 'handle' has at least 'check_cred' credits. If not, restart ++ * transaction with 'restart_cred' credits. The function drops i_data_sem ++ * when restarting transaction and gets it after transaction is restarted. ++ * ++ * The function returns 0 on success, 1 if transaction had to be restarted, ++ * and < 0 in case of fatal error. ++ */ ++int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode, ++ int check_cred, int restart_cred) ++{ ++ int ret; ++ int dropped = 0; ++ ++ ret = ext4_journal_ensure_credits_fn(handle, check_cred, restart_cred, ++ ext4_ext_trunc_restart_fn(inode, &dropped)); ++ if (dropped) ++ down_write(&EXT4_I(inode)->i_data_sem); ++ return ret; + } + + /* +@@ -2868,9 +2879,13 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, + } + credits += EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); + +- err = ext4_ext_truncate_extend_restart(handle, inode, credits); +- if (err) ++ err = ext4_datasem_ensure_credits(handle, inode, credits, ++ credits); ++ if (err) { ++ if (err > 0) ++ err = -EAGAIN; + goto out; ++ } + + err = ext4_ext_get_access(handle, inode, path + depth); + if (err) +@@ -5259,13 +5274,10 @@ ext4_access_path(handle_t *handle, struct inode *inode, + * descriptor) for each block group; assume two block + * groups + */ +- if (handle->h_buffer_credits < 7) { +- credits = ext4_writepage_trans_blocks(inode); +- err = ext4_ext_truncate_extend_restart(handle, inode, credits); +- /* EAGAIN is success */ +- if (err && err != -EAGAIN) +- return err; +- } ++ credits = ext4_writepage_trans_blocks(inode); ++ err = ext4_datasem_ensure_credits(handle, inode, 7, credits); ++ if (err < 0) ++ return err; + + err = ext4_ext_get_access(handle, inode, path); + return err; +diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c +index a131d2781342..9e13e31a1a22 100644 +--- a/fs/ext4/indirect.c ++++ b/fs/ext4/indirect.c +@@ -696,27 +696,62 @@ int ext4_ind_trans_blocks(struct inode *inode, int nrblocks) + return DIV_ROUND_UP(nrblocks, EXT4_ADDR_PER_BLOCK(inode->i_sb)) + 4; + } + ++static int ext4_ind_trunc_restart_fn(handle_t *handle, struct inode *inode, ++ struct buffer_head *bh, int *dropped) ++{ ++ int err; ++ ++ if (bh) { ++ BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); ++ err = ext4_handle_dirty_metadata(handle, inode, bh); ++ if (unlikely(err)) ++ return err; ++ } ++ err = ext4_mark_inode_dirty(handle, inode); ++ if (unlikely(err)) ++ return err; ++ /* ++ * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this ++ * moment, get_block can be called only for blocks inside i_size since ++ * page cache has been already dropped and writes are blocked by ++ * i_mutex. So we can safely drop the i_data_sem here. ++ */ ++ BUG_ON(EXT4_JOURNAL(inode) == NULL); ++ ext4_discard_preallocations(inode); ++ up_write(&EXT4_I(inode)->i_data_sem); ++ *dropped = 1; ++ return 0; ++} ++ + /* + * Truncate transactions can be complex and absolutely huge. So we need to + * be able to restart the transaction at a conventient checkpoint to make + * sure we don't overflow the journal. + * + * Try to extend this transaction for the purposes of truncation. If +- * extend fails, we need to propagate the failure up and restart the +- * transaction in the top-level truncate loop. --sct +- * +- * Returns 0 if we managed to create more room. If we can't create more +- * room, and the transaction must be restarted we return 1. ++ * extend fails, we restart transaction. + */ +-static int try_to_extend_transaction(handle_t *handle, struct inode *inode) ++static int ext4_ind_truncate_ensure_credits(handle_t *handle, ++ struct inode *inode, ++ struct buffer_head *bh) + { +- if (!ext4_handle_valid(handle)) +- return 0; +- if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1)) +- return 0; +- if (!ext4_journal_extend(handle, ext4_blocks_for_truncate(inode))) +- return 0; +- return 1; ++ int ret; ++ int dropped = 0; ++ ++ ret = ext4_journal_ensure_credits_fn(handle, EXT4_RESERVE_TRANS_BLOCKS, ++ ext4_blocks_for_truncate(inode), ++ ext4_ind_trunc_restart_fn(handle, inode, bh, &dropped)); ++ if (dropped) ++ down_write(&EXT4_I(inode)->i_data_sem); ++ if (ret <= 0) ++ return ret; ++ if (bh) { ++ BUFFER_TRACE(bh, "retaking write access"); ++ ret = ext4_journal_get_write_access(handle, bh); ++ if (unlikely(ret)) ++ return ret; ++ } ++ return 0; + } + + /* +@@ -851,27 +886,9 @@ static int ext4_clear_blocks(handle_t *handle, struct inode *inode, + return 1; + } + +- if (try_to_extend_transaction(handle, inode)) { +- if (bh) { +- BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); +- err = ext4_handle_dirty_metadata(handle, inode, bh); +- if (unlikely(err)) +- goto out_err; +- } +- err = ext4_mark_inode_dirty(handle, inode); +- if (unlikely(err)) +- goto out_err; +- err = ext4_truncate_restart_trans(handle, inode, +- ext4_blocks_for_truncate(inode)); +- if (unlikely(err)) +- goto out_err; +- if (bh) { +- BUFFER_TRACE(bh, "retaking write access"); +- err = ext4_journal_get_write_access(handle, bh); +- if (unlikely(err)) +- goto out_err; +- } +- } ++ err = ext4_ind_truncate_ensure_credits(handle, inode, bh); ++ if (err < 0) ++ goto out_err; + + for (p = first; p < last; p++) + *p = 0; +@@ -1054,11 +1071,9 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, + */ + if (ext4_handle_is_aborted(handle)) + return; +- if (try_to_extend_transaction(handle, inode)) { +- ext4_mark_inode_dirty(handle, inode); +- ext4_truncate_restart_trans(handle, inode, +- ext4_blocks_for_truncate(inode)); +- } ++ if (ext4_ind_truncate_ensure_credits(handle, inode, ++ NULL) < 0) ++ return; + + /* + * The forget flag here is critical because if +diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c +index b38427b8d083..a39567e03580 100644 +--- a/fs/ext4/inode.c ++++ b/fs/ext4/inode.c +@@ -163,32 +163,6 @@ int ext4_inode_is_fast_symlink(struct inode *inode) + (inode->i_size < EXT4_N_BLOCKS * 4); + } + +-/* +- * Restart the transaction associated with *handle. This does a commit, +- * so before we call here everything must be consistently dirtied against +- * this transaction. +- */ +-int ext4_truncate_restart_trans(handle_t *handle, struct inode *inode, +- int nblocks) +-{ +- int ret; +- +- /* +- * Drop i_data_sem to avoid deadlock with ext4_map_blocks. At this +- * moment, get_block can be called only for blocks inside i_size since +- * page cache has been already dropped and writes are blocked by +- * i_mutex. So we can safely drop the i_data_sem here. +- */ +- BUG_ON(EXT4_JOURNAL(inode) == NULL); +- jbd_debug(2, "restarting handle %p\n", handle); +- up_write(&EXT4_I(inode)->i_data_sem); +- ret = ext4_journal_restart(handle, nblocks); +- down_write(&EXT4_I(inode)->i_data_sem); +- ext4_discard_preallocations(inode); +- +- return ret; +-} +- + /* + * Called at the last iput() if i_nlink is zero. + */ +diff --git a/fs/ext4/migrate.c b/fs/ext4/migrate.c +index dbba3c3a2f06..6d1243819ab3 100644 +--- a/fs/ext4/migrate.c ++++ b/fs/ext4/migrate.c +@@ -50,29 +50,9 @@ static int finish_range(handle_t *handle, struct inode *inode, + needed = ext4_ext_calc_credits_for_single_extent(inode, + lb->last_block - lb->first_block + 1, path); + +- /* +- * Make sure the credit we accumalated is not really high +- */ +- if (needed && ext4_handle_has_enough_credits(handle, +- EXT4_RESERVE_TRANS_BLOCKS)) { +- up_write((&EXT4_I(inode)->i_data_sem)); +- retval = ext4_journal_restart(handle, needed); +- down_write((&EXT4_I(inode)->i_data_sem)); +- if (retval) +- goto err_out; +- } else if (needed) { +- retval = ext4_journal_extend(handle, needed); +- if (retval) { +- /* +- * IF not able to extend the journal restart the journal +- */ +- up_write((&EXT4_I(inode)->i_data_sem)); +- retval = ext4_journal_restart(handle, needed); +- down_write((&EXT4_I(inode)->i_data_sem)); +- if (retval) +- goto err_out; +- } +- } ++ retval = ext4_datasem_ensure_credits(handle, inode, needed, needed); ++ if (retval < 0) ++ goto err_out; + retval = ext4_ext_insert_extent(handle, inode, &path, &newext, 0); + err_out: + up_write((&EXT4_I(inode)->i_data_sem)); +@@ -196,26 +176,6 @@ static int update_tind_extent_range(handle_t *handle, struct inode *inode, + + } + +-static int extend_credit_for_blkdel(handle_t *handle, struct inode *inode) +-{ +- int retval = 0, needed; +- +- if (ext4_handle_has_enough_credits(handle, EXT4_RESERVE_TRANS_BLOCKS+1)) +- return 0; +- /* +- * We are freeing a blocks. During this we touch +- * superblock, group descriptor and block bitmap. +- * So allocate a credit of 3. We may update +- * quota (user and group). +- */ +- needed = 3 + EXT4_MAXQUOTAS_TRANS_BLOCKS(inode->i_sb); +- +- if (ext4_journal_extend(handle, needed) != 0) +- retval = ext4_journal_restart(handle, needed); +- +- return retval; +-} +- + static int free_dind_blocks(handle_t *handle, + struct inode *inode, __le32 i_data) + { +@@ -223,6 +183,7 @@ static int free_dind_blocks(handle_t *handle, + __le32 *tmp_idata; + struct buffer_head *bh; + unsigned long max_entries = inode->i_sb->s_blocksize >> 2; ++ int err; + + bh = ext4_sb_bread(inode->i_sb, le32_to_cpu(i_data), 0); + if (IS_ERR(bh)) +@@ -231,7 +192,12 @@ static int free_dind_blocks(handle_t *handle, + tmp_idata = (__le32 *)bh->b_data; + for (i = 0; i < max_entries; i++) { + if (tmp_idata[i]) { +- extend_credit_for_blkdel(handle, inode); ++ err = ext4_journal_ensure_credits(handle, ++ EXT4_RESERVE_TRANS_BLOCKS); ++ if (err < 0) { ++ put_bh(bh); ++ return err; ++ } + ext4_free_blocks(handle, inode, NULL, + le32_to_cpu(tmp_idata[i]), 1, + EXT4_FREE_BLOCKS_METADATA | +@@ -239,7 +205,9 @@ static int free_dind_blocks(handle_t *handle, + } + } + put_bh(bh); +- extend_credit_for_blkdel(handle, inode); ++ err = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS); ++ if (err < 0) ++ return err; + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); +@@ -270,7 +238,9 @@ static int free_tind_blocks(handle_t *handle, + } + } + put_bh(bh); +- extend_credit_for_blkdel(handle, inode); ++ retval = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS); ++ if (retval < 0) ++ return retval; + ext4_free_blocks(handle, inode, NULL, le32_to_cpu(i_data), 1, + EXT4_FREE_BLOCKS_METADATA | + EXT4_FREE_BLOCKS_FORGET); +@@ -283,7 +253,10 @@ static int free_ind_block(handle_t *handle, struct inode *inode, __le32 *i_data) + + /* ei->i_data[EXT4_IND_BLOCK] */ + if (i_data[0]) { +- extend_credit_for_blkdel(handle, inode); ++ retval = ext4_journal_ensure_credits(handle, ++ EXT4_RESERVE_TRANS_BLOCKS); ++ if (retval < 0) ++ return retval; + ext4_free_blocks(handle, inode, NULL, + le32_to_cpu(i_data[0]), 1, + EXT4_FREE_BLOCKS_METADATA | +@@ -318,12 +291,9 @@ static int ext4_ext_swap_inode_data(handle_t *handle, struct inode *inode, + * One credit accounted for writing the + * i_data field of the original inode + */ +- retval = ext4_journal_extend(handle, 1); +- if (retval) { +- retval = ext4_journal_restart(handle, 1); +- if (retval) +- goto err_out; +- } ++ retval = ext4_journal_ensure_credits(handle, 1); ++ if (retval < 0) ++ goto err_out; + + i_data[0] = ei->i_data[EXT4_IND_BLOCK]; + i_data[1] = ei->i_data[EXT4_DIND_BLOCK]; +@@ -391,15 +361,19 @@ static int free_ext_idx(handle_t *handle, struct inode *inode, + ix = EXT_FIRST_INDEX(eh); + for (i = 0; i < le16_to_cpu(eh->eh_entries); i++, ix++) { + retval = free_ext_idx(handle, inode, ix); +- if (retval) +- break; ++ if (retval) { ++ put_bh(bh); ++ return retval; ++ } + } + } + put_bh(bh); +- extend_credit_for_blkdel(handle, inode); ++ retval = ext4_journal_ensure_credits(handle, EXT4_RESERVE_TRANS_BLOCKS); ++ if (retval < 0) ++ return retval; + ext4_free_blocks(handle, inode, NULL, block, 1, + EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET); +- return retval; ++ return 0; + } + + /* +@@ -578,9 +552,9 @@ int ext4_ext_migrate(struct inode *inode) + } + + /* We mark the tmp_inode dirty via ext4_ext_tree_init. */ +- if (ext4_journal_extend(handle, 1) != 0) +- ext4_journal_restart(handle, 1); +- ++ retval = ext4_journal_ensure_credits(handle, 1); ++ if (retval < 0) ++ goto out_stop; + /* + * Mark the tmp_inode as of size zero + */ +@@ -599,6 +573,7 @@ int ext4_ext_migrate(struct inode *inode) + + /* Reset the extent details */ + ext4_ext_tree_init(handle, tmp_inode); ++out_stop: + ext4_journal_stop(handle); + out_tmp_inode: + unlock_new_inode(tmp_inode); +diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c +index 880307ba0f27..44b52921f7f4 100644 +--- a/fs/ext4/resize.c ++++ b/fs/ext4/resize.c +@@ -430,30 +430,6 @@ static struct buffer_head *bclean(handle_t *handle, struct super_block *sb, + return bh; + } + +-/* +- * If we have fewer than thresh credits, extend by EXT4_MAX_TRANS_DATA. +- * If that fails, restart the transaction & regain write access for the +- * buffer head which is used for block_bitmap modifications. +- */ +-static int extend_or_restart_transaction(handle_t *handle, int thresh) +-{ +- int err; +- +- if (ext4_handle_has_enough_credits(handle, thresh)) +- return 0; +- +- err = ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA); +- if (err < 0) +- return err; +- if (err) { +- err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA); +- if (err) +- return err; +- } +- +- return 0; +-} +- + /* + * set_flexbg_block_bitmap() mark clusters [@first_cluster, @last_cluster] used. + * +@@ -493,8 +469,8 @@ static int set_flexbg_block_bitmap(struct super_block *sb, handle_t *handle, + continue; + } + +- err = extend_or_restart_transaction(handle, 1); +- if (err) ++ err = ext4_journal_ensure_credits_batch(handle, 1); ++ if (err < 0) + return err; + + bh = sb_getblk(sb, flex_gd->groups[group].block_bitmap); +@@ -586,8 +562,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb, + struct buffer_head *gdb; + + ext4_debug("update backup group %#04llx\n", block); +- err = extend_or_restart_transaction(handle, 1); +- if (err) ++ err = ext4_journal_ensure_credits_batch(handle, 1); ++ if (err < 0) + goto out; + + gdb = sb_getblk(sb, block); +@@ -644,8 +620,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb, + + /* Initialize block bitmap of the @group */ + block = group_data[i].block_bitmap; +- err = extend_or_restart_transaction(handle, 1); +- if (err) ++ err = ext4_journal_ensure_credits_batch(handle, 1); ++ if (err < 0) + goto out; + + bh = bclean(handle, sb, block); +@@ -673,8 +649,8 @@ static int setup_new_flex_group_blocks(struct super_block *sb, + + /* Initialize inode bitmap of the @group */ + block = group_data[i].inode_bitmap; +- err = extend_or_restart_transaction(handle, 1); +- if (err) ++ err = ext4_journal_ensure_credits_batch(handle, 1); ++ if (err < 0) + goto out; + /* Mark unused entries in inode bitmap used */ + bh = bclean(handle, sb, block); +@@ -1157,10 +1133,8 @@ static void update_backups(struct super_block *sb, sector_t blk_off, char *data, + ext4_fsblk_t backup_block; + + /* Out of journal space, and can't get more - abort - so sad */ +- if (ext4_handle_valid(handle) && +- handle->h_buffer_credits == 0 && +- ext4_journal_extend(handle, EXT4_MAX_TRANS_DATA) && +- (err = ext4_journal_restart(handle, EXT4_MAX_TRANS_DATA))) ++ err = ext4_journal_ensure_credits_batch(handle, 1); ++ if (err < 0) + break; + + if (meta_bg == 0) +diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c +index 78df2d65998e..cf1af6a4a567 100644 +--- a/fs/ext4/xattr.c ++++ b/fs/ext4/xattr.c +@@ -982,55 +982,6 @@ int __ext4_xattr_set_credits(struct super_block *sb, struct inode *inode, + return credits; + } + +-static int ext4_xattr_ensure_credits(handle_t *handle, struct inode *inode, +- int credits, struct buffer_head *bh, +- bool dirty, bool block_csum) +-{ +- int error; +- +- if (!ext4_handle_valid(handle)) +- return 0; +- +- if (handle->h_buffer_credits >= credits) +- return 0; +- +- error = ext4_journal_extend(handle, credits - handle->h_buffer_credits); +- if (!error) +- return 0; +- if (error < 0) { +- ext4_warning(inode->i_sb, "Extend journal (error %d)", error); +- return error; +- } +- +- if (bh && dirty) { +- if (block_csum) +- ext4_xattr_block_csum_set(inode, bh); +- error = ext4_handle_dirty_metadata(handle, NULL, bh); +- if (error) { +- ext4_warning(inode->i_sb, "Handle metadata (error %d)", +- error); +- return error; +- } +- } +- +- error = ext4_journal_restart(handle, credits); +- if (error) { +- ext4_warning(inode->i_sb, "Restart journal (error %d)", error); +- return error; +- } +- +- if (bh) { +- error = ext4_journal_get_write_access(handle, bh); +- if (error) { +- ext4_warning(inode->i_sb, +- "Get write access failed (error %d)", +- error); +- return error; +- } +- } +- return 0; +-} +- + static int ext4_xattr_inode_update_ref(handle_t *handle, struct inode *ea_inode, + int ref_change) + { +@@ -1148,6 +1099,24 @@ static int ext4_xattr_inode_inc_ref_all(handle_t *handle, struct inode *parent, + return saved_err; + } + ++static int ext4_xattr_restart_fn(handle_t *handle, struct inode *inode, ++ struct buffer_head *bh, bool block_csum, bool dirty) ++{ ++ int error; ++ ++ if (bh && dirty) { ++ if (block_csum) ++ ext4_xattr_block_csum_set(inode, bh); ++ error = ext4_handle_dirty_metadata(handle, NULL, bh); ++ if (error) { ++ ext4_warning(inode->i_sb, "Handle metadata (error %d)", ++ error); ++ return error; ++ } ++ } ++ return 0; ++} ++ + static void + ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, + struct buffer_head *bh, +@@ -1184,13 +1153,23 @@ ext4_xattr_inode_dec_ref_all(handle_t *handle, struct inode *parent, + continue; + } + +- err = ext4_xattr_ensure_credits(handle, parent, credits, bh, +- dirty, block_csum); +- if (err) { ++ err = ext4_journal_ensure_credits_fn(handle, credits, credits, ++ ext4_xattr_restart_fn(handle, parent, bh, block_csum, ++ dirty)); ++ if (err < 0) { + ext4_warning_inode(ea_inode, "Ensure credits err=%d", + err); + continue; + } ++ if (err > 0) { ++ err = ext4_journal_get_write_access(handle, bh); ++ if (err) { ++ ext4_warning_inode(ea_inode, ++ "Re-get write access err=%d", ++ err); ++ continue; ++ } ++ } + + err = ext4_xattr_inode_dec_ref(handle, ea_inode); + if (err) { +@@ -2879,11 +2858,8 @@ int ext4_xattr_delete_inode(handle_t *handle, struct inode *inode, + struct inode *ea_inode; + int error; + +- error = ext4_xattr_ensure_credits(handle, inode, extra_credits, +- NULL /* bh */, +- false /* dirty */, +- false /* block_csum */); +- if (error) { ++ error = ext4_journal_ensure_credits(handle, extra_credits); ++ if (error < 0) { + EXT4_ERROR_INODE(inode, "ensure credits (error %d)", error); + goto cleanup; + } +-- +2.35.1 + diff --git a/queue-5.4/jbd2-drop-pointless-wakeup-from-jbd2_journal_stop.patch b/queue-5.4/jbd2-drop-pointless-wakeup-from-jbd2_journal_stop.patch new file mode 100644 index 00000000000..08c1e8dbc32 --- /dev/null +++ b/queue-5.4/jbd2-drop-pointless-wakeup-from-jbd2_journal_stop.patch @@ -0,0 +1,50 @@ +From 58a5adc78307d3204ab19ba2ed2eb1cd0929363f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:22 +0100 +Subject: jbd2: Drop pointless wakeup from jbd2_journal_stop() + +From: Jan Kara + +[ Upstream commit 5559b2d81b51de75cb7864bb1fbb82982f7e8fff ] + +When we drop last handle from a transaction and journal->j_barrier_count +> 0, jbd2_journal_stop() wakes up journal->j_wait_transaction_locked +wait queue. This looks pointless - wait for outstanding handles always +happens on journal->j_wait_updates waitqueue. +journal->j_wait_transaction_locked is used to wait for transaction state +changes and by start_this_handle() for waiting until +journal->j_barrier_count drops to 0. The first case is clearly +irrelevant here since only jbd2 thread changes transaction state. The +second case looks related but jbd2_journal_unlock_updates() is +responsible for the wakeup in this case. So just drop the wakeup. + +Reviewed-by: Theodore Ts'o +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-16-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/jbd2/transaction.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index ce66dbbf0f90..6d78648392f0 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1850,11 +1850,8 @@ int jbd2_journal_stop(handle_t *handle) + * once we do this, we must not dereference transaction + * pointer again. + */ +- if (atomic_dec_and_test(&transaction->t_updates)) { ++ if (atomic_dec_and_test(&transaction->t_updates)) + wake_up(&journal->j_wait_updates); +- if (journal->j_barrier_count) +- wake_up(&journal->j_wait_transaction_locked); +- } + + rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); + +-- +2.35.1 + diff --git a/queue-5.4/jbd2-factor-out-common-parts-of-stopping-and-restart.patch b/queue-5.4/jbd2-factor-out-common-parts-of-stopping-and-restart.patch new file mode 100644 index 00000000000..3a9785c2d2e --- /dev/null +++ b/queue-5.4/jbd2-factor-out-common-parts-of-stopping-and-restart.patch @@ -0,0 +1,205 @@ +From 80aa738f12e908dff5edaf9940b57127ba63363b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:23 +0100 +Subject: jbd2: Factor out common parts of stopping and restarting a handle + +From: Jan Kara + +[ Upstream commit ec8b6f600e49dc87a8564807fec4193bf93ee2b5 ] + +jbd2__journal_restart() has quite some code that is common with +jbd2_journal_stop(). Factor this functionality into stop_this_handle() +helper and use it from both functions. Note that this also drops +t_handle_lock protection from jbd2__journal_restart() as +jbd2_journal_stop() does the same thing without it. + +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-17-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/jbd2/transaction.c | 98 ++++++++++++++++++++----------------------- + 1 file changed, 46 insertions(+), 52 deletions(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 6d78648392f0..ee9a778c8fbe 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -514,12 +514,17 @@ handle_t *jbd2_journal_start(journal_t *journal, int nblocks) + } + EXPORT_SYMBOL(jbd2_journal_start); + +-void jbd2_journal_free_reserved(handle_t *handle) ++static void __jbd2_journal_unreserve_handle(handle_t *handle) + { + journal_t *journal = handle->h_journal; + + WARN_ON(!handle->h_reserved); + sub_reserved_credits(journal, handle->h_buffer_credits); ++} ++ ++void jbd2_journal_free_reserved(handle_t *handle) ++{ ++ __jbd2_journal_unreserve_handle(handle); + jbd2_free_handle(handle); + } + EXPORT_SYMBOL(jbd2_journal_free_reserved); +@@ -657,6 +662,28 @@ int jbd2_journal_extend(handle_t *handle, int nblocks) + return result; + } + ++static void stop_this_handle(handle_t *handle) ++{ ++ transaction_t *transaction = handle->h_transaction; ++ journal_t *journal = transaction->t_journal; ++ ++ J_ASSERT(journal_current_handle() == handle); ++ J_ASSERT(atomic_read(&transaction->t_updates) > 0); ++ current->journal_info = NULL; ++ atomic_sub(handle->h_buffer_credits, ++ &transaction->t_outstanding_credits); ++ if (handle->h_rsv_handle) ++ __jbd2_journal_unreserve_handle(handle->h_rsv_handle); ++ if (atomic_dec_and_test(&transaction->t_updates)) ++ wake_up(&journal->j_wait_updates); ++ ++ rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); ++ /* ++ * Scope of the GFP_NOFS context is over here and so we can restore the ++ * original alloc context. ++ */ ++ memalloc_nofs_restore(handle->saved_alloc_context); ++} + + /** + * int jbd2_journal_restart() - restart a handle . +@@ -679,52 +706,34 @@ int jbd2__journal_restart(handle_t *handle, int nblocks, gfp_t gfp_mask) + transaction_t *transaction = handle->h_transaction; + journal_t *journal; + tid_t tid; +- int need_to_start, ret; ++ int need_to_start; + + /* If we've had an abort of any type, don't even think about + * actually doing the restart! */ + if (is_handle_aborted(handle)) + return 0; + journal = transaction->t_journal; ++ tid = transaction->t_tid; + + /* + * First unlink the handle from its current transaction, and start the + * commit on that. + */ +- J_ASSERT(atomic_read(&transaction->t_updates) > 0); +- J_ASSERT(journal_current_handle() == handle); +- +- read_lock(&journal->j_state_lock); +- spin_lock(&transaction->t_handle_lock); +- atomic_sub(handle->h_buffer_credits, +- &transaction->t_outstanding_credits); +- if (handle->h_rsv_handle) { +- sub_reserved_credits(journal, +- handle->h_rsv_handle->h_buffer_credits); +- } +- if (atomic_dec_and_test(&transaction->t_updates)) +- wake_up(&journal->j_wait_updates); +- tid = transaction->t_tid; +- spin_unlock(&transaction->t_handle_lock); ++ jbd_debug(2, "restarting handle %p\n", handle); ++ stop_this_handle(handle); + handle->h_transaction = NULL; +- current->journal_info = NULL; + +- jbd_debug(2, "restarting handle %p\n", handle); ++ /* ++ * TODO: If we use READ_ONCE / WRITE_ONCE for j_commit_request we can ++ * get rid of pointless j_state_lock traffic like this. ++ */ ++ read_lock(&journal->j_state_lock); + need_to_start = !tid_geq(journal->j_commit_request, tid); + read_unlock(&journal->j_state_lock); + if (need_to_start) + jbd2_log_start_commit(journal, tid); +- +- rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); + handle->h_buffer_credits = nblocks; +- /* +- * Restore the original nofs context because the journal restart +- * is basically the same thing as journal stop and start. +- * start_this_handle will start a new nofs context. +- */ +- memalloc_nofs_restore(handle->saved_alloc_context); +- ret = start_this_handle(journal, handle, gfp_mask); +- return ret; ++ return start_this_handle(journal, handle, gfp_mask); + } + EXPORT_SYMBOL(jbd2__journal_restart); + +@@ -1734,16 +1743,12 @@ int jbd2_journal_stop(handle_t *handle) + * Handle is already detached from the transaction so there is + * nothing to do other than free the handle. + */ +- if (handle->h_rsv_handle) +- jbd2_free_handle(handle->h_rsv_handle); ++ memalloc_nofs_restore(handle->saved_alloc_context); + goto free_and_exit; + } + journal = transaction->t_journal; + tid = transaction->t_tid; + +- J_ASSERT(journal_current_handle() == handle); +- J_ASSERT(atomic_read(&transaction->t_updates) > 0); +- + if (is_handle_aborted(handle)) + err = -EIO; + +@@ -1813,9 +1818,6 @@ int jbd2_journal_stop(handle_t *handle) + + if (handle->h_sync) + transaction->t_synchronous_commit = 1; +- current->journal_info = NULL; +- atomic_sub(handle->h_buffer_credits, +- &transaction->t_outstanding_credits); + + /* + * If the handle is marked SYNC, we need to set another commit +@@ -1845,27 +1847,19 @@ int jbd2_journal_stop(handle_t *handle) + } + + /* +- * Once we drop t_updates, if it goes to zero the transaction +- * could start committing on us and eventually disappear. So +- * once we do this, we must not dereference transaction +- * pointer again. ++ * Once stop_this_handle() drops t_updates, the transaction could start ++ * committing on us and eventually disappear. So we must not ++ * dereference transaction pointer again after calling ++ * stop_this_handle(). + */ +- if (atomic_dec_and_test(&transaction->t_updates)) +- wake_up(&journal->j_wait_updates); +- +- rwsem_release(&journal->j_trans_commit_map, 1, _THIS_IP_); ++ stop_this_handle(handle); + + if (wait_for_commit) + err = jbd2_log_wait_commit(journal, tid); + +- if (handle->h_rsv_handle) +- jbd2_journal_free_reserved(handle->h_rsv_handle); + free_and_exit: +- /* +- * Scope of the GFP_NOFS context is over here and so we can restore the +- * original alloc context. +- */ +- memalloc_nofs_restore(handle->saved_alloc_context); ++ if (handle->h_rsv_handle) ++ jbd2_free_handle(handle->h_rsv_handle); + jbd2_free_handle(handle); + return err; + } +-- +2.35.1 + diff --git a/queue-5.4/jbd2-reorganize-jbd2_journal_stop.patch b/queue-5.4/jbd2-reorganize-jbd2_journal_stop.patch new file mode 100644 index 00000000000..31429710160 --- /dev/null +++ b/queue-5.4/jbd2-reorganize-jbd2_journal_stop.patch @@ -0,0 +1,104 @@ +From 6fddfed79a11832d9931d6a0d5aa6b42022a716c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:20 +0100 +Subject: jbd2: Reorganize jbd2_journal_stop() + +From: Jan Kara + +[ Upstream commit dfaf5ffda227be3e867fee7c0f6a66749392fbd0 ] + +Move code in jbd2_journal_stop() around a bit. It removes some +unnecessary code duplication and will make factoring out parts common +with jbd2__journal_restart() easier. + +Reviewed-by: Theodore Ts'o +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-14-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/jbd2/transaction.c | 40 ++++++++++++++++------------------------ + 1 file changed, 16 insertions(+), 24 deletions(-) + +diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c +index 09f4d00fece2..ce66dbbf0f90 100644 +--- a/fs/jbd2/transaction.c ++++ b/fs/jbd2/transaction.c +@@ -1722,41 +1722,34 @@ int jbd2_journal_stop(handle_t *handle) + tid_t tid; + pid_t pid; + ++ if (--handle->h_ref > 0) { ++ jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, ++ handle->h_ref); ++ if (is_handle_aborted(handle)) ++ return -EIO; ++ return 0; ++ } + if (!transaction) { + /* +- * Handle is already detached from the transaction so +- * there is nothing to do other than decrease a refcount, +- * or free the handle if refcount drops to zero ++ * Handle is already detached from the transaction so there is ++ * nothing to do other than free the handle. + */ +- if (--handle->h_ref > 0) { +- jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, +- handle->h_ref); +- return err; +- } else { +- if (handle->h_rsv_handle) +- jbd2_free_handle(handle->h_rsv_handle); +- goto free_and_exit; +- } ++ if (handle->h_rsv_handle) ++ jbd2_free_handle(handle->h_rsv_handle); ++ goto free_and_exit; + } + journal = transaction->t_journal; ++ tid = transaction->t_tid; + + J_ASSERT(journal_current_handle() == handle); ++ J_ASSERT(atomic_read(&transaction->t_updates) > 0); + + if (is_handle_aborted(handle)) + err = -EIO; +- else +- J_ASSERT(atomic_read(&transaction->t_updates) > 0); +- +- if (--handle->h_ref > 0) { +- jbd_debug(4, "h_ref %d -> %d\n", handle->h_ref + 1, +- handle->h_ref); +- return err; +- } + + jbd_debug(4, "Handle %p going down\n", handle); + trace_jbd2_handle_stats(journal->j_fs_dev->bd_dev, +- transaction->t_tid, +- handle->h_type, handle->h_line_no, ++ tid, handle->h_type, handle->h_line_no, + jiffies - handle->h_start_jiffies, + handle->h_sync, handle->h_requested_credits, + (handle->h_requested_credits - +@@ -1841,7 +1834,7 @@ int jbd2_journal_stop(handle_t *handle) + jbd_debug(2, "transaction too old, requesting commit for " + "handle %p\n", handle); + /* This is non-blocking */ +- jbd2_log_start_commit(journal, transaction->t_tid); ++ jbd2_log_start_commit(journal, tid); + + /* + * Special case: JBD2_SYNC synchronous updates require us +@@ -1857,7 +1850,6 @@ int jbd2_journal_stop(handle_t *handle) + * once we do this, we must not dereference transaction + * pointer again. + */ +- tid = transaction->t_tid; + if (atomic_dec_and_test(&transaction->t_updates)) { + wake_up(&journal->j_wait_updates); + if (journal->j_barrier_count) +-- +2.35.1 + diff --git a/queue-5.4/jbd2-use-the-correct-print-format.patch b/queue-5.4/jbd2-use-the-correct-print-format.patch new file mode 100644 index 00000000000..71880138b51 --- /dev/null +++ b/queue-5.4/jbd2-use-the-correct-print-format.patch @@ -0,0 +1,202 @@ +From 61e286eeca71ccf5b54c872b0fd3e27d76f38738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 11 Oct 2022 19:33:44 +0800 +Subject: jbd2: use the correct print format + +From: Bixuan Cui + +[ Upstream commit d87a7b4c77a997d5388566dd511ca8e6b8e8a0a8 ] + +The print format error was found when using ftrace event: + <...>-1406 [000] .... 23599442.895823: jbd2_end_commit: dev 252,8 transaction -1866216965 sync 0 head -1866217368 + <...>-1406 [000] .... 23599442.896299: jbd2_start_commit: dev 252,8 transaction -1866216964 sync 0 + +Use the correct print format for transaction, head and tid. + +Fixes: 879c5e6b7cb4 ('jbd2: convert instrumentation from markers to tracepoints') +Signed-off-by: Bixuan Cui +Reviewed-by: Jason Yan +Link: https://lore.kernel.org/r/1665488024-95172-1-git-send-email-cuibixuan@linux.alibaba.com +Signed-off-by: Theodore Ts'o +Cc: stable@kernel.org +Signed-off-by: Sasha Levin +--- + include/trace/events/jbd2.h | 40 ++++++++++++++++++------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/include/trace/events/jbd2.h b/include/trace/events/jbd2.h +index 2310b259329f..c9fb7b987a3a 100644 +--- a/include/trace/events/jbd2.h ++++ b/include/trace/events/jbd2.h +@@ -40,7 +40,7 @@ DECLARE_EVENT_CLASS(jbd2_commit, + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( char, sync_commit ) +- __field( int, transaction ) ++ __field( tid_t, transaction ) + ), + + TP_fast_assign( +@@ -49,7 +49,7 @@ DECLARE_EVENT_CLASS(jbd2_commit, + __entry->transaction = commit_transaction->t_tid; + ), + +- TP_printk("dev %d,%d transaction %d sync %d", ++ TP_printk("dev %d,%d transaction %u sync %d", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->transaction, __entry->sync_commit) + ); +@@ -97,8 +97,8 @@ TRACE_EVENT(jbd2_end_commit, + TP_STRUCT__entry( + __field( dev_t, dev ) + __field( char, sync_commit ) +- __field( int, transaction ) +- __field( int, head ) ++ __field( tid_t, transaction ) ++ __field( tid_t, head ) + ), + + TP_fast_assign( +@@ -108,7 +108,7 @@ TRACE_EVENT(jbd2_end_commit, + __entry->head = journal->j_tail_sequence; + ), + +- TP_printk("dev %d,%d transaction %d sync %d head %d", ++ TP_printk("dev %d,%d transaction %u sync %d head %u", + MAJOR(__entry->dev), MINOR(__entry->dev), + __entry->transaction, __entry->sync_commit, __entry->head) + ); +@@ -134,14 +134,14 @@ TRACE_EVENT(jbd2_submit_inode_data, + ); + + TRACE_EVENT(jbd2_handle_start, +- TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, ++ TP_PROTO(dev_t dev, tid_t tid, unsigned int type, + unsigned int line_no, int requested_blocks), + + TP_ARGS(dev, tid, type, line_no, requested_blocks), + + TP_STRUCT__entry( + __field( dev_t, dev ) +- __field( unsigned long, tid ) ++ __field( tid_t, tid ) + __field( unsigned int, type ) + __field( unsigned int, line_no ) + __field( int, requested_blocks) +@@ -155,14 +155,14 @@ TRACE_EVENT(jbd2_handle_start, + __entry->requested_blocks = requested_blocks; + ), + +- TP_printk("dev %d,%d tid %lu type %u line_no %u " ++ TP_printk("dev %d,%d tid %u type %u line_no %u " + "requested_blocks %d", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, + __entry->type, __entry->line_no, __entry->requested_blocks) + ); + + TRACE_EVENT(jbd2_handle_extend, +- TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, ++ TP_PROTO(dev_t dev, tid_t tid, unsigned int type, + unsigned int line_no, int buffer_credits, + int requested_blocks), + +@@ -170,7 +170,7 @@ TRACE_EVENT(jbd2_handle_extend, + + TP_STRUCT__entry( + __field( dev_t, dev ) +- __field( unsigned long, tid ) ++ __field( tid_t, tid ) + __field( unsigned int, type ) + __field( unsigned int, line_no ) + __field( int, buffer_credits ) +@@ -186,7 +186,7 @@ TRACE_EVENT(jbd2_handle_extend, + __entry->requested_blocks = requested_blocks; + ), + +- TP_printk("dev %d,%d tid %lu type %u line_no %u " ++ TP_printk("dev %d,%d tid %u type %u line_no %u " + "buffer_credits %d requested_blocks %d", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, + __entry->type, __entry->line_no, __entry->buffer_credits, +@@ -194,7 +194,7 @@ TRACE_EVENT(jbd2_handle_extend, + ); + + TRACE_EVENT(jbd2_handle_stats, +- TP_PROTO(dev_t dev, unsigned long tid, unsigned int type, ++ TP_PROTO(dev_t dev, tid_t tid, unsigned int type, + unsigned int line_no, int interval, int sync, + int requested_blocks, int dirtied_blocks), + +@@ -203,7 +203,7 @@ TRACE_EVENT(jbd2_handle_stats, + + TP_STRUCT__entry( + __field( dev_t, dev ) +- __field( unsigned long, tid ) ++ __field( tid_t, tid ) + __field( unsigned int, type ) + __field( unsigned int, line_no ) + __field( int, interval ) +@@ -223,7 +223,7 @@ TRACE_EVENT(jbd2_handle_stats, + __entry->dirtied_blocks = dirtied_blocks; + ), + +- TP_printk("dev %d,%d tid %lu type %u line_no %u interval %d " ++ TP_printk("dev %d,%d tid %u type %u line_no %u interval %d " + "sync %d requested_blocks %d dirtied_blocks %d", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, + __entry->type, __entry->line_no, __entry->interval, +@@ -232,14 +232,14 @@ TRACE_EVENT(jbd2_handle_stats, + ); + + TRACE_EVENT(jbd2_run_stats, +- TP_PROTO(dev_t dev, unsigned long tid, ++ TP_PROTO(dev_t dev, tid_t tid, + struct transaction_run_stats_s *stats), + + TP_ARGS(dev, tid, stats), + + TP_STRUCT__entry( + __field( dev_t, dev ) +- __field( unsigned long, tid ) ++ __field( tid_t, tid ) + __field( unsigned long, wait ) + __field( unsigned long, request_delay ) + __field( unsigned long, running ) +@@ -265,7 +265,7 @@ TRACE_EVENT(jbd2_run_stats, + __entry->blocks_logged = stats->rs_blocks_logged; + ), + +- TP_printk("dev %d,%d tid %lu wait %u request_delay %u running %u " ++ TP_printk("dev %d,%d tid %u wait %u request_delay %u running %u " + "locked %u flushing %u logging %u handle_count %u " + "blocks %u blocks_logged %u", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, +@@ -280,14 +280,14 @@ TRACE_EVENT(jbd2_run_stats, + ); + + TRACE_EVENT(jbd2_checkpoint_stats, +- TP_PROTO(dev_t dev, unsigned long tid, ++ TP_PROTO(dev_t dev, tid_t tid, + struct transaction_chp_stats_s *stats), + + TP_ARGS(dev, tid, stats), + + TP_STRUCT__entry( + __field( dev_t, dev ) +- __field( unsigned long, tid ) ++ __field( tid_t, tid ) + __field( unsigned long, chp_time ) + __field( __u32, forced_to_close ) + __field( __u32, written ) +@@ -303,7 +303,7 @@ TRACE_EVENT(jbd2_checkpoint_stats, + __entry->dropped = stats->cs_dropped; + ), + +- TP_printk("dev %d,%d tid %lu chp_time %u forced_to_close %u " ++ TP_printk("dev %d,%d tid %u chp_time %u forced_to_close %u " + "written %u dropped %u", + MAJOR(__entry->dev), MINOR(__entry->dev), __entry->tid, + jiffies_to_msecs(__entry->chp_time), +-- +2.35.1 + diff --git a/queue-5.4/ocfs2-use-accessor-function-for-h_buffer_credits.patch b/queue-5.4/ocfs2-use-accessor-function-for-h_buffer_credits.patch new file mode 100644 index 00000000000..ad150bb6fb7 --- /dev/null +++ b/queue-5.4/ocfs2-use-accessor-function-for-h_buffer_credits.patch @@ -0,0 +1,168 @@ +From 332d74ed7afca6f1f88a6eff40c61ee73e68b513 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Nov 2019 17:44:18 +0100 +Subject: ocfs2: Use accessor function for h_buffer_credits + +From: Jan Kara + +[ Upstream commit 9797a902480521dc8e7a478e38f0c896ffff8784 ] + +Use the jbd2 accessor function for h_buffer_credits. + +Reviewed-by: Theodore Ts'o +Signed-off-by: Jan Kara +Link: https://lore.kernel.org/r/20191105164437.32602-12-jack@suse.cz +Signed-off-by: Theodore Ts'o +Stable-dep-of: d87a7b4c77a9 ("jbd2: use the correct print format") +Signed-off-by: Sasha Levin +--- + fs/ocfs2/alloc.c | 32 ++++++++++++++++---------------- + fs/ocfs2/journal.c | 4 ++-- + 2 files changed, 18 insertions(+), 18 deletions(-) + +diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c +index 4db87b26cf7b..9bc3e926b717 100644 +--- a/fs/ocfs2/alloc.c ++++ b/fs/ocfs2/alloc.c +@@ -2288,9 +2288,9 @@ static int ocfs2_extend_rotate_transaction(handle_t *handle, int subtree_depth, + int ret = 0; + int credits = (path->p_tree_depth - subtree_depth) * 2 + 1 + op_credits; + +- if (handle->h_buffer_credits < credits) ++ if (jbd2_handle_buffer_credits(handle) < credits) + ret = ocfs2_extend_trans(handle, +- credits - handle->h_buffer_credits); ++ credits - jbd2_handle_buffer_credits(handle)); + + return ret; + } +@@ -2367,7 +2367,7 @@ static int ocfs2_rotate_tree_right(handle_t *handle, + struct ocfs2_path *right_path, + struct ocfs2_path **ret_left_path) + { +- int ret, start, orig_credits = handle->h_buffer_credits; ++ int ret, start, orig_credits = jbd2_handle_buffer_credits(handle); + u32 cpos; + struct ocfs2_path *left_path = NULL; + struct super_block *sb = ocfs2_metadata_cache_get_super(et->et_ci); +@@ -3148,7 +3148,7 @@ static int ocfs2_rotate_tree_left(handle_t *handle, + struct ocfs2_path *path, + struct ocfs2_cached_dealloc_ctxt *dealloc) + { +- int ret, orig_credits = handle->h_buffer_credits; ++ int ret, orig_credits = jbd2_handle_buffer_credits(handle); + struct ocfs2_path *tmp_path = NULL, *restart_path = NULL; + struct ocfs2_extent_block *eb; + struct ocfs2_extent_list *el; +@@ -3386,8 +3386,8 @@ static int ocfs2_merge_rec_right(struct ocfs2_path *left_path, + right_path); + + ret = ocfs2_extend_rotate_transaction(handle, subtree_index, +- handle->h_buffer_credits, +- right_path); ++ jbd2_handle_buffer_credits(handle), ++ right_path); + if (ret) { + mlog_errno(ret); + goto out; +@@ -3548,8 +3548,8 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path, + right_path); + + ret = ocfs2_extend_rotate_transaction(handle, subtree_index, +- handle->h_buffer_credits, +- left_path); ++ jbd2_handle_buffer_credits(handle), ++ left_path); + if (ret) { + mlog_errno(ret); + goto out; +@@ -3623,7 +3623,7 @@ static int ocfs2_merge_rec_left(struct ocfs2_path *right_path, + le16_to_cpu(el->l_next_free_rec) == 1) { + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + right_path); + if (ret) { + mlog_errno(ret); +@@ -3669,7 +3669,7 @@ static int ocfs2_try_to_merge_extent(handle_t *handle, + if (ctxt->c_split_covers_rec && ctxt->c_has_empty_extent) { + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + path); + if (ret) { + mlog_errno(ret); +@@ -3725,7 +3725,7 @@ static int ocfs2_try_to_merge_extent(handle_t *handle, + + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + path); + if (ret) { + mlog_errno(ret); +@@ -3755,7 +3755,7 @@ static int ocfs2_try_to_merge_extent(handle_t *handle, + + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + path); + if (ret) { + mlog_errno(ret); +@@ -3799,7 +3799,7 @@ static int ocfs2_try_to_merge_extent(handle_t *handle, + if (ctxt->c_split_covers_rec) { + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + path); + if (ret) { + mlog_errno(ret); +@@ -5358,7 +5358,7 @@ static int ocfs2_truncate_rec(handle_t *handle, + if (ocfs2_is_empty_extent(&el->l_recs[0]) && index > 0) { + /* extend credit for ocfs2_remove_rightmost_path */ + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, ++ jbd2_handle_buffer_credits(handle), + path); + if (ret) { + mlog_errno(ret); +@@ -5427,8 +5427,8 @@ static int ocfs2_truncate_rec(handle_t *handle, + } + + ret = ocfs2_extend_rotate_transaction(handle, 0, +- handle->h_buffer_credits, +- path); ++ jbd2_handle_buffer_credits(handle), ++ path); + if (ret) { + mlog_errno(ret); + goto out; +diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c +index da95ed79c12e..595745602f1e 100644 +--- a/fs/ocfs2/journal.c ++++ b/fs/ocfs2/journal.c +@@ -420,7 +420,7 @@ int ocfs2_extend_trans(handle_t *handle, int nblocks) + if (!nblocks) + return 0; + +- old_nblocks = handle->h_buffer_credits; ++ old_nblocks = jbd2_handle_buffer_credits(handle); + + trace_ocfs2_extend_trans(old_nblocks, nblocks); + +@@ -461,7 +461,7 @@ int ocfs2_allocate_extend_trans(handle_t *handle, int thresh) + + BUG_ON(!handle); + +- old_nblks = handle->h_buffer_credits; ++ old_nblks = jbd2_handle_buffer_credits(handle); + trace_ocfs2_allocate_extend_trans(old_nblks, thresh); + + if (old_nblks < thresh) +-- +2.35.1 + diff --git a/queue-5.4/quota-factor-out-setup-of-quota-inode.patch b/queue-5.4/quota-factor-out-setup-of-quota-inode.patch new file mode 100644 index 00000000000..cc40224f332 --- /dev/null +++ b/queue-5.4/quota-factor-out-setup-of-quota-inode.patch @@ -0,0 +1,192 @@ +From ef2b9f063beca969f15a1a39acb5153616b054ea Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Nov 2019 17:45:31 +0100 +Subject: quota: Factor out setup of quota inode + +From: Jan Kara + +[ Upstream commit c7d3d28360fdb3ed3a5aa0bab19315e0fdc994a1 ] + +Factor out setting up of quota inode and eventual error cleanup from +vfs_load_quota_inode(). This will simplify situation for filesystems +that don't have any quota inodes. + +Signed-off-by: Jan Kara +Stable-dep-of: d32387748476 ("ext4: fix bug_on in __es_tree_search caused by bad quota inode") +Signed-off-by: Sasha Levin +--- + fs/quota/dquot.c | 108 ++++++++++++++++++++++++--------------- + include/linux/quotaops.h | 2 + + 2 files changed, 69 insertions(+), 41 deletions(-) + +diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c +index dc5f8654b277..84f61ab05890 100644 +--- a/fs/quota/dquot.c ++++ b/fs/quota/dquot.c +@@ -2306,28 +2306,60 @@ EXPORT_SYMBOL(dquot_quota_off); + * Turn quotas on on a device + */ + +-/* +- * Helper function to turn quotas on when we already have the inode of +- * quota file and no quota information is loaded. +- */ +-static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ++static int vfs_setup_quota_inode(struct inode *inode, int type) ++{ ++ struct super_block *sb = inode->i_sb; ++ struct quota_info *dqopt = sb_dqopt(sb); ++ ++ if (!S_ISREG(inode->i_mode)) ++ return -EACCES; ++ if (IS_RDONLY(inode)) ++ return -EROFS; ++ if (sb_has_quota_loaded(sb, type)) ++ return -EBUSY; ++ ++ dqopt->files[type] = igrab(inode); ++ if (!dqopt->files[type]) ++ return -EIO; ++ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { ++ /* We don't want quota and atime on quota files (deadlocks ++ * possible) Also nobody should write to the file - we use ++ * special IO operations which ignore the immutable bit. */ ++ inode_lock(inode); ++ inode->i_flags |= S_NOQUOTA; ++ inode_unlock(inode); ++ /* ++ * When S_NOQUOTA is set, remove dquot references as no more ++ * references can be added ++ */ ++ __dquot_drop(inode); ++ } ++ return 0; ++} ++ ++static void vfs_cleanup_quota_inode(struct super_block *sb, int type) ++{ ++ struct quota_info *dqopt = sb_dqopt(sb); ++ struct inode *inode = dqopt->files[type]; ++ ++ if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { ++ inode_lock(inode); ++ inode->i_flags &= ~S_NOQUOTA; ++ inode_unlock(inode); ++ } ++ dqopt->files[type] = NULL; ++ iput(inode); ++} ++ ++int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, + unsigned int flags) + { + struct quota_format_type *fmt = find_quota_format(format_id); +- struct super_block *sb = inode->i_sb; + struct quota_info *dqopt = sb_dqopt(sb); + int error; + + if (!fmt) + return -ESRCH; +- if (!S_ISREG(inode->i_mode)) { +- error = -EACCES; +- goto out_fmt; +- } +- if (IS_RDONLY(inode)) { +- error = -EROFS; +- goto out_fmt; +- } + if (!sb->s_op->quota_write || !sb->s_op->quota_read || + (type == PRJQUOTA && sb->dq_op->get_projid == NULL)) { + error = -EINVAL; +@@ -2359,27 +2391,9 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + invalidate_bdev(sb->s_bdev); + } + +- if (!(dqopt->flags & DQUOT_QUOTA_SYS_FILE)) { +- /* We don't want quota and atime on quota files (deadlocks +- * possible) Also nobody should write to the file - we use +- * special IO operations which ignore the immutable bit. */ +- inode_lock(inode); +- inode->i_flags |= S_NOQUOTA; +- inode_unlock(inode); +- /* +- * When S_NOQUOTA is set, remove dquot references as no more +- * references can be added +- */ +- __dquot_drop(inode); +- } +- +- error = -EIO; +- dqopt->files[type] = igrab(inode); +- if (!dqopt->files[type]) +- goto out_file_flags; + error = -EINVAL; + if (!fmt->qf_ops->check_quota_file(sb, type)) +- goto out_file_init; ++ goto out_fmt; + + dqopt->ops[type] = fmt->qf_ops; + dqopt->info[type].dqi_format = fmt; +@@ -2387,7 +2401,7 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); + error = dqopt->ops[type]->read_file_info(sb, type); + if (error < 0) +- goto out_file_init; ++ goto out_fmt; + if (dqopt->flags & DQUOT_QUOTA_SYS_FILE) { + spin_lock(&dq_data_lock); + dqopt->info[type].dqi_flags |= DQF_SYS_FILE; +@@ -2402,18 +2416,30 @@ static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, + dquot_disable(sb, type, flags); + + return error; +-out_file_init: +- dqopt->files[type] = NULL; +- iput(inode); +-out_file_flags: +- inode_lock(inode); +- inode->i_flags &= ~S_NOQUOTA; +- inode_unlock(inode); + out_fmt: + put_quota_format(fmt); + + return error; + } ++EXPORT_SYMBOL(dquot_load_quota_sb); ++ ++/* ++ * Helper function to turn quotas on when we already have the inode of ++ * quota file and no quota information is loaded. ++ */ ++static int vfs_load_quota_inode(struct inode *inode, int type, int format_id, ++ unsigned int flags) ++{ ++ int err; ++ ++ err = vfs_setup_quota_inode(inode, type); ++ if (err < 0) ++ return err; ++ err = dquot_load_quota_sb(inode->i_sb, type, format_id, flags); ++ if (err < 0) ++ vfs_cleanup_quota_inode(inode->i_sb, type); ++ return err; ++} + + /* Reenable quotas on remount RW */ + int dquot_resume(struct super_block *sb, int type) +diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h +index 91e0b7624053..ec10897f7f60 100644 +--- a/include/linux/quotaops.h ++++ b/include/linux/quotaops.h +@@ -99,6 +99,8 @@ int dquot_file_open(struct inode *inode, struct file *file); + + int dquot_enable(struct inode *inode, int type, int format_id, + unsigned int flags); ++int dquot_load_quota_sb(struct super_block *sb, int type, int format_id, ++ unsigned int flags); + int dquot_quota_on(struct super_block *sb, int type, int format_id, + const struct path *path); + int dquot_quota_on_mount(struct super_block *sb, char *qf_name, +-- +2.35.1 + diff --git a/queue-5.4/series b/queue-5.4/series index 31de0b4b2eb..a8091cf0b9a 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -609,3 +609,18 @@ s390-percpu-add-read_once-to-arch_this_cpu_to_op_simple.patch net-ulp-prevent-ulp-without-clone-op-from-entering-the-listen-status.patch alsa-pcm-move-rwsem-lock-inside-snd_ctl_elem_read-to-prevent-uaf.patch alsa-hda-hdmi-add-a-hp-device-0x8715-to-force-connect-list.patch +asoc-intel-bytcr_rt5640-add-quirk-for-the-advantech-.patch-10536 +wifi-wilc1000-sdio-fix-module-autoloading.patch +usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch +ext4-provide-function-to-handle-transaction-restarts.patch +ext4-jbd2-provide-accessor-function-for-handle-credi.patch +ocfs2-use-accessor-function-for-h_buffer_credits.patch +jbd2-reorganize-jbd2_journal_stop.patch +jbd2-drop-pointless-wakeup-from-jbd2_journal_stop.patch +jbd2-factor-out-common-parts-of-stopping-and-restart.patch +jbd2-use-the-correct-print-format.patch +quota-factor-out-setup-of-quota-inode.patch +ext4-fix-bug_on-in-__es_tree_search-caused-by-bad-qu.patch +ext4-lost-matching-pair-of-trace-in-ext4_truncate.patch +ext4-fix-use-after-free-in-ext4_orphan_cleanup.patch +ext4-fix-uninititialized-value-in-ext4_evict_inode.patch diff --git a/queue-5.4/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch b/queue-5.4/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch new file mode 100644 index 00000000000..25a7780b070 --- /dev/null +++ b/queue-5.4/usb-ulpi-defer-ulpi_register-on-ulpi_read_id-timeout.patch @@ -0,0 +1,49 @@ +From bcd06b7e46305eecedfd5f9b87494c1e810d53f2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 5 Dec 2022 21:15:26 +0100 +Subject: usb: ulpi: defer ulpi_register on ulpi_read_id timeout + +From: Ferry Toth + +[ Upstream commit 8a7b31d545d3a15f0e6f5984ae16f0ca4fd76aac ] + +Since commit 0f0101719138 ("usb: dwc3: Don't switch OTG -> peripheral +if extcon is present") Dual Role support on Intel Merrifield platform +broke due to rearranging the call to dwc3_get_extcon(). + +It appears to be caused by ulpi_read_id() on the first test write failing +with -ETIMEDOUT. Currently ulpi_read_id() expects to discover the phy via +DT when the test write fails and returns 0 in that case, even if DT does not +provide the phy. As a result usb probe completes without phy. + +Make ulpi_read_id() return -ETIMEDOUT to its user if the first test write +fails. The user should then handle it appropriately. A follow up patch +will make dwc3_core_init() set -EPROBE_DEFER in this case and bail out. + +Fixes: ef6a7bcfb01c ("usb: ulpi: Support device discovery via DT") +Cc: stable@vger.kernel.org +Acked-by: Heikki Krogerus +Signed-off-by: Ferry Toth +Link: https://lore.kernel.org/r/20221205201527.13525-2-ftoth@exalondelft.nl +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + drivers/usb/common/ulpi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/usb/common/ulpi.c b/drivers/usb/common/ulpi.c +index c42c152bbc33..94700c1d2f6e 100644 +--- a/drivers/usb/common/ulpi.c ++++ b/drivers/usb/common/ulpi.c +@@ -207,7 +207,7 @@ static int ulpi_read_id(struct ulpi *ulpi) + /* Test the interface */ + ret = ulpi_write(ulpi, ULPI_SCRATCH, 0xaa); + if (ret < 0) +- goto err; ++ return ret; + + ret = ulpi_read(ulpi, ULPI_SCRATCH); + if (ret < 0) +-- +2.35.1 + diff --git a/queue-5.4/wifi-wilc1000-sdio-fix-module-autoloading.patch b/queue-5.4/wifi-wilc1000-sdio-fix-module-autoloading.patch new file mode 100644 index 00000000000..4a6526ad599 --- /dev/null +++ b/queue-5.4/wifi-wilc1000-sdio-fix-module-autoloading.patch @@ -0,0 +1,36 @@ +From 2085ee74e78c63cecfc65a826f629e4cc3115b99 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 19:12:21 +0200 +Subject: wifi: wilc1000: sdio: fix module autoloading + +From: Michael Walle + +[ Upstream commit 57d545b5a3d6ce3a8fb6b093f02bfcbb908973f3 ] + +There are no SDIO module aliases included in the driver, therefore, +module autoloading isn't working. Add the proper MODULE_DEVICE_TABLE(). + +Cc: stable@vger.kernel.org +Signed-off-by: Michael Walle +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20221027171221.491937-1-michael@walle.cc +Signed-off-by: Sasha Levin +--- + drivers/staging/wilc1000/wilc_sdio.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/staging/wilc1000/wilc_sdio.c b/drivers/staging/wilc1000/wilc_sdio.c +index c787c5da8f2b..22a30da011e1 100644 +--- a/drivers/staging/wilc1000/wilc_sdio.c ++++ b/drivers/staging/wilc1000/wilc_sdio.c +@@ -20,6 +20,7 @@ static const struct sdio_device_id wilc_sdio_ids[] = { + { SDIO_DEVICE(SDIO_VENDOR_ID_WILC, SDIO_DEVICE_ID_WILC) }, + { }, + }; ++MODULE_DEVICE_TABLE(sdio, wilc_sdio_ids); + + #define WILC_SDIO_BLOCK_SIZE 512 + +-- +2.35.1 +