This patch set fix three bug:
Jiachen Zhang (1): xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real
Long Li (1): iomap: fix warning in xfs_iomap_write_delalloc_release()
Zhang Tianci (1): xfs: update dir3 leaf block metadata after swap
fs/xfs/libxfs/xfs_bmap.c | 76 +++++++++++++++--------------------- fs/xfs/libxfs/xfs_da_btree.c | 7 ++++ fs/xfs/xfs_iomap.c | 2 +- 3 files changed, 40 insertions(+), 45 deletions(-)
hulk inclusion category: bugfix bugzilla: 189317, https://gitee.com/openeuler/kernel/issues/I76JSK CVE: NA
--------------------------------
When fsstress + drop cache test, we get following warning:
CPU: 2 PID: 42297 Comm: fsstress Not tainted 5.10.0-09150-gd7277a187bfc #33 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.14.0-0-g155821a1990b-prebuilt.qemu.org 04/01/2014 RIP: 0010:xfs_iomap_write_delalloc_release fs/xfs/xfs_iomap.c:1272 [inline] RIP: 0010:xfs_iomap_file_buffered_write_punch_delalloc fs/xfs/xfs_iomap.c:1357 [inline] RIP: 0010:xfs_buffered_write_iomap_end+0xa39/0x11b0 fs/xfs/xfs_iomap.c:1373 Code: 08 01 e8 a2 42 9a 02 e8 35 db 13 ff 49 8d 6d ff 48 83 05 c9 1c df 08 01 e9 f7 fb ff ff e8 1f db 13 ff 48 83 05 e7 2f df 08 01 <0f> 0b 48 83 05 e5 2f df 08 01 4c 8b 7c 24 18 4c 89 e6 48 83 05 dd RSP: 0000:ffff88811ab27550 EFLAGS: 00010202 RAX: ffff888110941bc0 RBX: 00000000002cd000 RCX: ffffffff8b454f41 RDX: 0000000000000000 RSI: 00000000002cd000 RDI: 0000000000000006 RBP: 000000000000001f R08: ffff888110941bc0 R09: 0000000000000001 R10: ffffea0004838877 R11: fffff9400090710e R12: 00000000002cd000 R13: ffff88812318fa88 R14: 00000000002c7000 R15: 00000000002d0000 FS: 00007f9474a86740(0000) GS:ffff8881f6900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f09f84c88e0 CR3: 0000000101b32001 CR4: 0000000000370ee0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: iomap_apply+0xff/0xdf0 fs/iomap/apply.c:98 iomap_file_buffered_write+0x164/0x230 fs/iomap/buffered-io.c:852 xfs_file_buffered_aio_write+0x34a/0xc90 fs/xfs/xfs_file.c:736 xfs_file_write_iter+0x375/0x4b0 fs/xfs/xfs_file.c:816 call_write_iter include/linux/fs.h:1970 [inline] do_iter_readv_writev+0x735/0x8b0 fs/read_write.c:735 do_iter_write+0x19d/0x4b0 fs/read_write.c:861 vfs_iter_write+0x7c/0xd0 fs/read_write.c:902 ovl_write_iter+0xcdd/0x1d40 fs/overlayfs/file.c:380 call_write_iter include/linux/fs.h:1970 [inline] do_iter_readv_writev+0x735/0x8b0 fs/read_write.c:735 do_iter_write+0x19d/0x4b0 fs/read_write.c:861 vfs_writev+0x191/0x820 fs/read_write.c:934 do_writev+0x149/0x3c0 fs/read_write.c:977 __do_sys_writev fs/read_write.c:1050 [inline] __se_sys_writev fs/read_write.c:1047 [inline] __x64_sys_writev+0x79/0xc0 fs/read_write.c:1047 do_syscall_64+0x4b/0x80 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x62/0xc7 RIP: 0033:0x7f94741a1c08 Code: ff eb b6 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 f3 0f 1e fa 48 8d 05 15 eb 29 00 8b 00 85 c0 75 17 b8 14 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 58 c3 0f 1f 80 00 00 00 00 41 54 41 89 d4 55 RSP: 002b:00007ffdf2165ee8 EFLAGS: 00000246 ORIG_RAX: 0000000000000014 RAX: ffffffffffffffda RBX: 0000000000000079 RCX: 00007f94741a1c08 RDX: 0000000000000266 RSI: 0000000001b3f8a0 RDI: 0000000000000003 RBP: 0000000000000003 R08: 0000000001b3f87a R09: 0000000000000003 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000001b3f8a0 R13: 0000000001b2c7e0 R14: 0000000000000266 R15: 000000000000007f
The warning occurred in the following code of iomap_write_delalloc_release(). After analyzing vmcore, I found that the reason for the warning was that data_end was equal to start_byte.
WARN_ON_ONCE(data_end <= start_byte);
If some delay is added between seeking for data and seeking for hole in xfs_iomap_write_delalloc_release(), the problem can be reproduced quickly. The root cause of the problem is that clean data page was dropped between two seeking in the page cache. As a result, data_end equal to start_byte.
buffer write drop cache --------------------------- --------------------------- xfs_buffered_write_iomap_end xfs_iomap_file_buffered_write_punch_delalloc xfs_iomap_write_delalloc_release xfs_ilock(ip, XFS_MMAPLOCK_EXCL) start_byte = mapping_seek_hole_data(SEEK_DATA)
drop_pagecache_sb invalidate_mapping_pages invalidate_inode_page invalidate_complete_page remove_mapping <remove clean page>
data_end = mapping_seek_hole_data(SEEK_HOLE) xfs_iunlock(ip, XFS_MMAPLOCK_EXCL)
Although there is race between punch delalloc and drop cache, it does not affect the original punch logic for non-dirty data pages, so the warning can be eliminated directly.
Fixes: c515b6a4c619 ("iomap: buffered write failure should not truncate the page cache") Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/xfs_iomap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index ae96ac52c974..76285db4aaec 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c @@ -1269,7 +1269,7 @@ xfs_iomap_write_delalloc_release( error = data_end; goto out_unlock; } - WARN_ON_ONCE(data_end <= start_byte); + WARN_ON_ONCE(data_end < start_byte); WARN_ON_ONCE(data_end > scan_end_byte);
error = xfs_iomap_write_delalloc_scan(inode, &punch_start_byte,
From: Jiachen Zhang zhangjiachen.jaycee@bytedance.com
mainline inclusion from mainline-v6.7-rc4 commit e6af9c98cbf0164a619d95572136bfb54d482dd6 category: bugfix bugzilla: 188220, https://gitee.com/openeuler/kernel/issues/I76JSK CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
In the case of returning -ENOSPC, ensure logflagsp is initialized by 0. Otherwise the caller __xfs_bunmapi will set uninitialized illegal tmp_logflags value into xfs log, which might cause unpredictable error in the log recovery procedure.
Also, remove the flags variable and set the *logflagsp directly, so that the code should be more robust in the long run.
Fixes: 1b24b633aafe ("xfs: move some more code into xfs_bmap_del_extent_real") Signed-off-by: Jiachen Zhang zhangjiachen.jaycee@bytedance.com Reviewed-by: Christoph Hellwig hch@lst.de Reviewed-by: "Darrick J. Wong" djwong@kernel.org Signed-off-by: Chandan Babu R chandanbabu@kernel.org Conflicts: fs/xfs/libxfs/xfs_bmap.c [conflicts in xfs_bmap_del_extent_real()] Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/libxfs/xfs_bmap.c | 76 +++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 44 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index cecfa5280b51..15e9e335d167 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -4952,7 +4952,6 @@ xfs_bmap_del_extent_real( xfs_fileoff_t del_endoff; /* first offset past del */ int do_fx; /* free extent at end of routine */ int error; /* error return value */ - int flags = 0;/* inode logging flags */ struct xfs_bmbt_irec got; /* current extent entry */ xfs_fileoff_t got_endoff; /* first offset past got */ int i; /* temp state */ @@ -4965,6 +4964,8 @@ xfs_bmap_del_extent_real( int state = xfs_bmap_fork_to_state(whichfork); struct xfs_bmbt_irec old;
+ *logflagsp = 0; + mp = ip->i_mount; XFS_STATS_INC(mp, xs_del_exlist);
@@ -4977,7 +4978,6 @@ xfs_bmap_del_extent_real( ASSERT(got_endoff >= del_endoff); ASSERT(!isnullstartblock(got.br_startblock)); qfield = 0; - error = 0;
/* * If it's the case where the directory code is running with no block @@ -4993,7 +4993,7 @@ xfs_bmap_del_extent_real( del->br_startoff > got.br_startoff && del_endoff < got_endoff) return -ENOSPC;
- flags = XFS_ILOG_CORE; + *logflagsp = XFS_ILOG_CORE; if (whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip)) { xfs_filblks_t len; xfs_extlen_t mod; @@ -5011,7 +5011,7 @@ xfs_bmap_del_extent_real(
error = xfs_rtfree_extent(tp, bno, (xfs_extlen_t)len); if (error) - goto done; + return error; }
do_fx = 0; @@ -5027,11 +5027,9 @@ xfs_bmap_del_extent_real( if (cur) { error = xfs_bmbt_lookup_eq(cur, &got, &i); if (error) - goto done; - if (XFS_IS_CORRUPT(mp, i != 1)) { - error = -EFSCORRUPTED; - goto done; - } + return error; + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; }
if (got.br_startoff == del->br_startoff) @@ -5048,17 +5046,15 @@ xfs_bmap_del_extent_real( xfs_iext_prev(ifp, icur); ifp->if_nextents--;
- flags |= XFS_ILOG_CORE; + *logflagsp |= XFS_ILOG_CORE; if (!cur) { - flags |= xfs_ilog_fext(whichfork); + *logflagsp |= xfs_ilog_fext(whichfork); break; } if ((error = xfs_btree_delete(cur, &i))) - goto done; - if (XFS_IS_CORRUPT(mp, i != 1)) { - error = -EFSCORRUPTED; - goto done; - } + return error; + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; break; case BMAP_LEFT_FILLING: /* @@ -5069,12 +5065,12 @@ xfs_bmap_del_extent_real( got.br_blockcount -= del->br_blockcount; xfs_iext_update_extent(ip, state, icur, &got); if (!cur) { - flags |= xfs_ilog_fext(whichfork); + *logflagsp |= xfs_ilog_fext(whichfork); break; } error = xfs_bmbt_update(cur, &got); if (error) - goto done; + return error; break; case BMAP_RIGHT_FILLING: /* @@ -5083,12 +5079,12 @@ xfs_bmap_del_extent_real( got.br_blockcount -= del->br_blockcount; xfs_iext_update_extent(ip, state, icur, &got); if (!cur) { - flags |= xfs_ilog_fext(whichfork); + *logflagsp |= xfs_ilog_fext(whichfork); break; } error = xfs_bmbt_update(cur, &got); if (error) - goto done; + return error; break; case 0: /* @@ -5111,8 +5107,7 @@ xfs_bmap_del_extent_real( if (error) { ASSERT(S_ISDIR(VFS_I(ip)->i_mode) && whichfork == XFS_DATA_FORK); - error = -ENOSPC; - goto done; + return -ENOSPC; }
old = got; @@ -5125,18 +5120,18 @@ xfs_bmap_del_extent_real( new.br_state = got.br_state; new.br_startblock = del_endblock;
- flags |= XFS_ILOG_CORE; + *logflagsp |= XFS_ILOG_CORE; if (cur) { error = xfs_bmbt_update(cur, &got); if (error) - goto done; + return error; error = xfs_btree_increment(cur, 0, &i); if (error) - goto done; + return error; cur->bc_rec.b = new; error = xfs_btree_insert(cur, &i); if (error && error != -ENOSPC) - goto done; + return error; /* * If get no-space back from btree insert, it tried a * split, and we have a zero block reservation. Fix up @@ -5149,33 +5144,28 @@ xfs_bmap_del_extent_real( */ error = xfs_bmbt_lookup_eq(cur, &got, &i); if (error) - goto done; - if (XFS_IS_CORRUPT(mp, i != 1)) { - error = -EFSCORRUPTED; - goto done; - } + return error; + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; /* * Update the btree record back * to the original value. */ error = xfs_bmbt_update(cur, &old); if (error) - goto done; + return error; /* * Reset the extent record back * to the original value. */ xfs_iext_update_extent(ip, state, icur, &old); - flags = 0; - error = -ENOSPC; - goto done; - } - if (XFS_IS_CORRUPT(mp, i != 1)) { - error = -EFSCORRUPTED; - goto done; + *logflagsp = 0; + return -ENOSPC; } + if (XFS_IS_CORRUPT(mp, i != 1)) + return -EFSCORRUPTED; } else - flags |= xfs_ilog_fext(whichfork); + *logflagsp |= xfs_ilog_fext(whichfork);
ifp->if_nextents++; xfs_iext_next(ifp, icur); @@ -5199,7 +5189,7 @@ xfs_bmap_del_extent_real( ((bflags & XFS_BMAPI_NODISCARD) || del->br_state == XFS_EXT_UNWRITTEN)); if (error) - goto done; + return error; } }
@@ -5214,9 +5204,7 @@ xfs_bmap_del_extent_real( if (qfield && !(bflags & XFS_BMAPI_REMAP)) xfs_trans_mod_dquot_byino(tp, ip, qfield, (long)-nblks);
-done: - *logflagsp = flags; - return error; + return 0; }
/*
From: Zhang Tianci zhangtianci.1997@bytedance.com
mainline inclusion from mainline-v6.7-rc4 commit 5759aa4f956034b289b0ae2c99daddfc775442e1 category: bugfix bugzilla: 189393, https://gitee.com/openeuler/kernel/issues/I76JSK CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
xfs_da3_swap_lastblock() copy the last block content to the dead block, but do not update the metadata in it. We need update some metadata for some kinds of type block, such as dir3 leafn block records its blkno, we shall update it to the dead block blkno. Otherwise, before write the xfs_buf to disk, the verify_write() will fail in blk_hdr->blkno != xfs_buf->b_bn, then xfs will be shutdown.
We will get this warning:
XFS (dm-0): Metadata corruption detected at xfs_dir3_leaf_verify+0xa8/0xe0 [xfs], xfs_dir3_leafn block 0x178 XFS (dm-0): Unmount and run xfs_repair XFS (dm-0): First 128 bytes of corrupted metadata buffer: 00000000e80f1917: 00 80 00 0b 00 80 00 07 3d ff 00 00 00 00 00 00 ........=....... 000000009604c005: 00 00 00 00 00 00 01 a0 00 00 00 00 00 00 00 00 ................ 000000006b6fb2bf: e4 44 e3 97 b5 64 44 41 8b 84 60 0e 50 43 d9 bf .D...dDA..`.PC.. 00000000678978a2: 00 00 00 00 00 00 00 83 01 73 00 93 00 00 00 00 .........s...... 00000000b28b247c: 99 29 1d 38 00 00 00 00 99 29 1d 40 00 00 00 00 .).8.....).@.... 000000002b2a662c: 99 29 1d 48 00 00 00 00 99 49 11 00 00 00 00 00 .).H.....I...... 00000000ea2ffbb8: 99 49 11 08 00 00 45 25 99 49 11 10 00 00 48 fe .I....E%.I....H. 0000000069e86440: 99 49 11 18 00 00 4c 6b 99 49 11 20 00 00 4d 97 .I....Lk.I. ..M. XFS (dm-0): xfs_do_force_shutdown(0x8) called from line 1423 of file fs/xfs/xfs_buf.c. Return address = 00000000c0ff63c1 XFS (dm-0): Corruption of in-memory data detected. Shutting down filesystem XFS (dm-0): Please umount the filesystem and rectify the problem(s)
From the log above, we know xfs_buf->b_no is 0x178, but the block's hdr record
its blkno is 0x1a0.
Fixes: 24df33b45ecf ("xfs: add CRC checking to dir2 leaf blocks") Signed-off-by: Zhang Tianci zhangtianci.1997@bytedance.com Suggested-by: Dave Chinner david@fromorbit.com Reviewed-by: "Darrick J. Wong" djwong@kernel.org Signed-off-by: Chandan Babu R chandanbabu@kernel.org Signed-off-by: Long Li leo.lilong@huawei.com --- fs/xfs/libxfs/xfs_da_btree.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c index f1258e294ead..781a595ea756 100644 --- a/fs/xfs/libxfs/xfs_da_btree.c +++ b/fs/xfs/libxfs/xfs_da_btree.c @@ -2305,10 +2305,17 @@ xfs_da3_swap_lastblock( return error; /* * Copy the last block into the dead buffer and log it. + * On CRC-enabled file systems, also update the stamped in blkno. */ memcpy(dead_buf->b_addr, last_buf->b_addr, args->geo->blksize); + if (xfs_has_crc(mp)) { + struct xfs_da3_blkinfo *da3 = dead_buf->b_addr; + + da3->blkno = cpu_to_be64(xfs_buf_daddr(dead_buf)); + } xfs_trans_log_buf(tp, dead_buf, 0, args->geo->blksize - 1); dead_info = dead_buf->b_addr; + /* * Get values from the moved block. */
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/7681 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/S...
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/7681 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/S...