This patch set fix some hung task and warning bug:
Long Li (1): xfs: fix hung when transaction commit fail in xfs_inactive_ifree
Ye Bin (2): xfs: fix dead loop when do mount with IO fault injection xfs: fix warning in xfs_vm_writepages()
fs/xfs/xfs_buf_item.c | 20 ++++++++++++++++++++ fs/xfs/xfs_icache.c | 6 ++++++ fs/xfs/xfs_inode.c | 3 ++- fs/xfs/xfs_inode_item.c | 3 ++- fs/xfs/xfs_log.c | 4 +++- 5 files changed, 33 insertions(+), 3 deletions(-)
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8LHTR CVE: NA
--------------------------------
When do IO fault injection, mount maybe hung: blk_update_request: I/O error, dev dm-4, sector 2128216 op 0x0:(READ) flags 0x1000 phys_seg 1 prio class 0 XFS (dm-4): metadata I/O error in "xfs_btree_read_buf_block.constprop.0+0x190/0x200 [xfs]" at daddr 0x207958 len 8 error 5 blk_update_request: I/O error, dev dm-4, sector 2108042 op 0x1:(WRITE) flags 0x29800 phys_seg 1 prio class 0 XFS (dm-4): log I/O error -5 XFS (dm-4): Metadata I/O Error (0x1) detected at xfs_trans_read_buf_map+0x2b6/0x510 [xfs] (fs/xfs/xfs_trans_buf.c:296). Shutting down filesystem. sd 6:0:0:3: [sdh] Synchronizing SCSI cache XFS (dm-4): Please unmount the filesystem and rectify the problem(s) XFS (dm-4): Failed to recover intents XFS (dm-4): Ending recovery (logdev: internal)
PID: 2489297 TASK: ffff8880355c1b00 CPU: 0 COMMAND: "mount" __schedule at ffffffff93aa03c1 schedule at ffffffff93aa0c6f schedule_timeout at ffffffff93aa63c0 xfs_wait_buftarg at ffffffffc1170ff0 [xfs] xfs_log_mount_finish at ffffffffc11bddc4 [xfs] xfs_mountfs at ffffffffc11a4492 [xfs] xfs_fc_fill_super at ffffffffc11ae01c [xfs] get_tree_bdev at ffffffff92c62a79 vfs_get_tree at ffffffff92c60fe0 do_new_mount at ffffffff92caaca0 path_mount at ffffffff92cabf83 __se_sys_mount at ffffffff92cac352 do_syscall_64 at ffffffff93a8b153 entry_SYSCALL_64_after_hwframe at ffffffff93c00099
Ftrace log: mount-2489297 [002] .... 337330.575879: xfs_buf_wait_buftarg: dev 253:4 bno 0x3220 nblks 0x8 hold 2 pincount 0 lock 1 flags DONE|PAGES caller __list_l0
Above issue hapnens as xfs_buf log item is in AIL list, but xlog is already shutdown, so xfs_log_worker() will not wakeup xfsaild to submit AIL list. Then the last 'b_hold' will no chance to be decreased. Then xfs_wait_buftarg() will dead loop to free xfs_buf. To solve above issue there is need to push AIL list before call xfs_wait_buftarg(). As xfs_log_mount_finish() return error, xfs_mountfs() will call xfs_log_mount_cancel() to clean AIL list, and call xfs_wait_buftarg() to make sure all xfs_buf has been reclaimed. So what we need to do is call xfs_wait_buftarg() when 'error == 0' in xfs_log_mount_finish().
Signed-off-by: Ye Bin yebin@huawei.com Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_log.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 51c100c86177..bd167a94a6b3 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c @@ -817,7 +817,9 @@ xfs_log_mount_finish( } else { xfs_info(mp, "Ending clean mount"); } - xfs_buftarg_drain(mp->m_ddev_targp); + + if (!error) + xfs_buftarg_drain(mp->m_ddev_targp);
clear_bit(XLOG_RECOVERY_NEEDED, &log->l_opstate);
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8LHTR CVE: NA
--------------------------------
After running unplug disk test and unmount filesystem, the umount thread hung all the time.
crash> dmesg sd 0:0:0:0: rejecting I/O to offline device XFS (sda): log I/O error -5 XFS (sda): Corruption of in-memory data (0x8) detected at xfs_defer_finish_noroll+0x12e0/0x1cf0 (fs/xfs/libxfs/xfs_defer.c:504). Shutting down filesystem. XFS (sda): Please unmount the filesystem and rectify the problem(s) XFS (sda): xfs_inactive_ifree: xfs_trans_commit returned error -5 XFS (sda): Unmounting Filesystem
crash> bt 3368 PID: 3368 TASK: ffff88801bcd8040 CPU: 3 COMMAND: "umount" #0 [ffffc900086a7ae0] __schedule at ffffffff83d3fd25 #1 [ffffc900086a7be8] schedule at ffffffff83d414dd #2 [ffffc900086a7c10] xfs_ail_push_all_sync at ffffffff8256db24 #3 [ffffc900086a7d18] xfs_unmount_flush_inodes at ffffffff824ee7e2 #4 [ffffc900086a7d28] xfs_unmountfs at ffffffff824f2eff #5 [ffffc900086a7da8] xfs_fs_put_super at ffffffff82503e69 #6 [ffffc900086a7de8] generic_shutdown_super at ffffffff81aeb8cd #7 [ffffc900086a7e10] kill_block_super at ffffffff81aefcfa #8 [ffffc900086a7e30] deactivate_locked_super at ffffffff81aeb2da #9 [ffffc900086a7e48] deactivate_super at ffffffff81aeb639 #10 [ffffc900086a7e68] cleanup_mnt at ffffffff81b6ddd5 #11 [ffffc900086a7ea0] __cleanup_mnt at ffffffff81b6dfdf #12 [ffffc900086a7eb0] task_work_run at ffffffff8126e5cf #13 [ffffc900086a7ef8] exit_to_user_mode_prepare at ffffffff813fa136 #14 [ffffc900086a7f28] syscall_exit_to_user_mode at ffffffff83d25dbb #15 [ffffc900086a7f40] do_syscall_64 at ffffffff83d1f8d9 #16 [ffffc900086a7f50] entry_SYSCALL_64_after_hwframe at ffffffff83e00085
When we free a cluster buffer from xfs_ifree_cluster, all the inodes in cache are marked XFS_ISTALE. On journal commit dirty stale inodes as are handled by both buffer and inode log items, inodes marked as XFS_ISTALE in AIL will be removed from the AIL because the buffer log item will clean it. If the transaction commit fails in the xfs_inactive_ifree(), inodes marked as XFS_ISTALE will be left in AIL due to buf log item is not committed, this will cause the unmount thread above to be blocked all the time. Set inode item abort associated with the buffer that is stale after buf item release, let ail clean up these items, that prevent inode item left in AIL and can not being pushed.
Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_buf_item.c | 20 ++++++++++++++++++++ fs/xfs/xfs_inode.c | 3 ++- fs/xfs/xfs_inode_item.c | 3 ++- 3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 023d4e0385dd..b1a6ef2a1136 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c @@ -645,8 +645,12 @@ xfs_buf_item_put( struct xfs_buf_log_item *bip) { struct xfs_log_item *lip = &bip->bli_item; + struct xfs_buf *bp = bip->bli_buf; + struct xfs_log_item *lp, *n; + struct xfs_inode_log_item *iip; bool aborted; bool dirty; + bool stale = bip->bli_flags & XFS_BLI_STALE_INODE;
/* drop the bli ref and return if it wasn't the last one */ if (!atomic_dec_and_test(&bip->bli_refcount)) @@ -673,6 +677,22 @@ xfs_buf_item_put( if (aborted) xfs_trans_ail_delete(lip, 0); xfs_buf_item_relse(bip->bli_buf); + + /* + * If it is an inode buffer and item marked as stale, abort flushing + * inodes associated with the buf, prevent inode item left in AIL. + */ + if (aborted && stale) { + list_for_each_entry_safe(lp, n, &bp->b_li_list, li_bio_list) { + iip = container_of(lp, struct xfs_inode_log_item, + ili_item); + if (xfs_iflags_test(iip->ili_inode, XFS_ISTALE)) { + set_bit(XFS_LI_ABORTED, &lp->li_flags); + xfs_iflags_clear(iip->ili_inode, XFS_IFLUSHING); + } + } + } + return true; }
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 4d55f58d99b7..30b34a5dc6df 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -3368,7 +3368,8 @@ xfs_iflush_cluster( * once we drop the i_flags_lock. */ spin_lock(&ip->i_flags_lock); - ASSERT(!__xfs_iflags_test(ip, XFS_ISTALE)); + ASSERT(!__xfs_iflags_test(ip, XFS_ISTALE) || + test_bit(XFS_LI_ABORTED, &lip->li_flags)); if (__xfs_iflags_test(ip, XFS_IRECLAIM | XFS_IFLUSHING)) { spin_unlock(&ip->i_flags_lock); continue; diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 127b2410eb20..db0d976e6e4a 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -695,7 +695,8 @@ xfs_inode_item_push( uint rval = XFS_ITEM_SUCCESS; int error;
- if (!bp || (ip->i_flags & XFS_ISTALE)) { + if (!bp || ((ip->i_flags & XFS_ISTALE) && + !(lip->li_flags & XFS_LI_ABORTED))) { /* * Inode item/buffer is being aborted due to cluster * buffer deletion. Trigger a log force to have that operation
From: Ye Bin yebin10@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I8LHTR CVE: NA
--------------------------------
When do BULKSTAT test got issues as follows: WARNING: CPU: 3 PID: 8425 at fs/xfs/xfs_aops.c:509 xfs_vm_writepages+0x184/0x1c0 Modules linked in: CPU: 3 PID: 8425 Comm: xfs_bulkstat Not tainted 6.3.0-next-20230505-00003-gf3329adf5424-dirty #456 RIP: 0010:xfs_vm_writepages+0x184/0x1c0 RSP: 0018:ffffc90014bb7088 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 1ffff92002976e11 RCX: ffff88817aef8000 RDX: 0000000000000000 RSI: ffff88817aef8000 RDI: 0000000000000002 RBP: ffff888267dd2ad8 R08: ffffffff8313f414 R09: ffffed1022377c18 R10: ffff888111bbe0bb R11: ffffed1022377c17 R12: ffff88817aef8000 R13: ffffc90014bb7358 R14: dffffc0000000000 R15: ffffffff8313f290 FS: 00007f9568bb0440(0000) GS:ffff88882fc80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000d7a008 CR3: 000000024e11f000 CR4: 00000000000006e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> do_writepages+0x1a8/0x630 __writeback_single_inode+0x126/0xe00 writeback_single_inode+0x2ae/0x530 write_inode_now+0x16e/0x1e0 iput.part.0+0x46c/0x730 iput+0x60/0x80 xfs_bulkstat_one_int+0xd87/0x1580 xfs_bulkstat_iwalk+0x6e/0xd0 xfs_iwalk_ag_recs+0x449/0x770 xfs_iwalk_run_callbacks+0x305/0x630 xfs_iwalk_ag+0x819/0xae0 xfs_iwalk+0x2d5/0x4e0 xfs_bulkstat+0x358/0x520 xfs_ioc_bulkstat.isra.0+0x242/0x340 xfs_file_ioctl+0x1d6/0x1ba0 __x64_sys_ioctl+0x197/0x210 do_syscall_64+0x39/0xb0 entry_SYSCALL_64_after_hwframe+0x63/0xcd
Above issue may happens as follows: Porcess1 Process2 process3 process4 xfs_bulkstat xfs_trans_alloc_empty xfs_bulkstat_one_int xfs_iget(XFS_IGET_DONTCACHE) ->Get inode from disk and mark inode with I_DONTCACHE
xfs_lookup xfs_iget ->Hold inode refcount xfs_irele
xfs_file_write_iter ->Write file made some dirty pages close file
xfs_bulkstat xfs_trans_alloc_empty xfs_bulkstat_one_int xfs_iget(XFS_IGET_DONTCACHE)
-> process4 close file
******Trigger dentry reclaim, inode refcount is 1****** xfs_irele iput ->Put the last refcount iput_final write_inode_now xfs_vm_writepages WARN_ON_ONCE(current->journal_info) ->Trigger warning
As commit a6343e4d9278 grab an empty transaction when do BULKSTAT. If put the last refcount of inode maybe cause writepages will trigger warning, and also lead to data loss. To solve above issue if xfs_iget_cache_hit() just clear inode's I_DONTCACHE flags.
Fixes: a6343e4d9278 ("xfs: avoid buffer deadlocks when walking fs inodes") Signed-off-by: Ye Bin yebin10@huawei.com Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_icache.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/fs/xfs/xfs_icache.c b/fs/xfs/xfs_icache.c index 3c210ac83713..f4971bd1de05 100644 --- a/fs/xfs/xfs_icache.c +++ b/fs/xfs/xfs_icache.c @@ -557,6 +557,12 @@ xfs_iget_cache_hit( if (!igrab(inode)) goto out_skip;
+ if (!(flags & XFS_IGET_DONTCACHE)) { + spin_lock(&inode->i_lock); + inode->i_state &= ~I_DONTCACHE; + spin_unlock(&inode->i_lock); + } + /* We've got a live one. */ spin_unlock(&ip->i_flags_lock); rcu_read_unlock();
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/3495 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/3495 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/7...