* [PATCH v3 1/3] xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real
2023-11-30 4:05 [PATCH v3 0/3] Fixes for ENOSPC xfs_remove Jiachen Zhang
@ 2023-11-30 4:05 ` Jiachen Zhang
2023-11-30 19:01 ` Darrick J. Wong
2023-11-30 4:05 ` [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap Jiachen Zhang
2023-11-30 4:05 ` [PATCH v3 3/3] xfs: extract xfs_da_buf_copy() helper function Jiachen Zhang
2 siblings, 1 reply; 8+ messages in thread
From: Jiachen Zhang @ 2023-11-30 4:05 UTC (permalink / raw)
To: Chandan Babu R, Darrick J. Wong
Cc: Dave Chinner, Allison Henderson, Zhang Tianci, Brian Foster,
linux-xfs, linux-kernel, xieyongji, me, Jiachen Zhang,
Christoph Hellwig
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>
---
fs/xfs/libxfs/xfs_bmap.c | 73 +++++++++++++++++-----------------------
1 file changed, 31 insertions(+), 42 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index be62acffad6c..eacd7f43c952 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5010,7 +5010,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 */
@@ -5023,6 +5022,8 @@ xfs_bmap_del_extent_real(
uint32_t 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);
@@ -5035,7 +5036,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
@@ -5051,13 +5051,13 @@ 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)) {
if (!(bflags & XFS_BMAPI_REMAP)) {
error = xfs_rtfree_blocks(tp, del->br_startblock,
del->br_blockcount);
if (error)
- goto done;
+ return error;
}
do_fx = 0;
@@ -5072,11 +5072,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)
@@ -5093,17 +5091,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:
/*
@@ -5114,12 +5110,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:
/*
@@ -5128,12 +5124,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:
/*
@@ -5150,18 +5146,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
@@ -5174,33 +5170,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);
@@ -5224,7 +5215,7 @@ xfs_bmap_del_extent_real(
((bflags & XFS_BMAPI_NODISCARD) ||
del->br_state == XFS_EXT_UNWRITTEN));
if (error)
- goto done;
+ return error;
}
}
@@ -5239,9 +5230,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;
}
/*
--
2.20.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 1/3] xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real
2023-11-30 4:05 ` [PATCH v3 1/3] xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real Jiachen Zhang
@ 2023-11-30 19:01 ` Darrick J. Wong
0 siblings, 0 replies; 8+ messages in thread
From: Darrick J. Wong @ 2023-11-30 19:01 UTC (permalink / raw)
To: Jiachen Zhang
Cc: Chandan Babu R, Dave Chinner, Allison Henderson, Zhang Tianci,
Brian Foster, linux-xfs, linux-kernel, xieyongji, me,
Christoph Hellwig
On Thu, Nov 30, 2023 at 12:05:14PM +0800, Jiachen Zhang wrote:
> 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>
Looks good,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
--D
> ---
> fs/xfs/libxfs/xfs_bmap.c | 73 +++++++++++++++++-----------------------
> 1 file changed, 31 insertions(+), 42 deletions(-)
>
> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
> index be62acffad6c..eacd7f43c952 100644
> --- a/fs/xfs/libxfs/xfs_bmap.c
> +++ b/fs/xfs/libxfs/xfs_bmap.c
> @@ -5010,7 +5010,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 */
> @@ -5023,6 +5022,8 @@ xfs_bmap_del_extent_real(
> uint32_t 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);
>
> @@ -5035,7 +5036,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
> @@ -5051,13 +5051,13 @@ 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)) {
> if (!(bflags & XFS_BMAPI_REMAP)) {
> error = xfs_rtfree_blocks(tp, del->br_startblock,
> del->br_blockcount);
> if (error)
> - goto done;
> + return error;
> }
>
> do_fx = 0;
> @@ -5072,11 +5072,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)
> @@ -5093,17 +5091,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:
> /*
> @@ -5114,12 +5110,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:
> /*
> @@ -5128,12 +5124,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:
> /*
> @@ -5150,18 +5146,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
> @@ -5174,33 +5170,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);
> @@ -5224,7 +5215,7 @@ xfs_bmap_del_extent_real(
> ((bflags & XFS_BMAPI_NODISCARD) ||
> del->br_state == XFS_EXT_UNWRITTEN));
> if (error)
> - goto done;
> + return error;
> }
> }
>
> @@ -5239,9 +5230,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;
> }
>
> /*
> --
> 2.20.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap
2023-11-30 4:05 [PATCH v3 0/3] Fixes for ENOSPC xfs_remove Jiachen Zhang
2023-11-30 4:05 ` [PATCH v3 1/3] xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real Jiachen Zhang
@ 2023-11-30 4:05 ` Jiachen Zhang
2023-12-01 0:48 ` Darrick J. Wong
2023-12-04 7:18 ` Christoph Hellwig
2023-11-30 4:05 ` [PATCH v3 3/3] xfs: extract xfs_da_buf_copy() helper function Jiachen Zhang
2 siblings, 2 replies; 8+ messages in thread
From: Jiachen Zhang @ 2023-11-30 4:05 UTC (permalink / raw)
To: Chandan Babu R, Darrick J. Wong
Cc: Dave Chinner, Allison Henderson, Zhang Tianci, Brian Foster,
linux-xfs, linux-kernel, xieyongji, me, Dave Chinner
From: Zhang Tianci <zhangtianci.1997@bytedance.com>
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>
---
fs/xfs/libxfs/xfs_da_btree.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index e576560b46e9..f3f987a65bc1 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -2316,10 +2316,18 @@ xfs_da3_swap_lastblock(
return error;
/*
* Copy the last block into the dead buffer and log it.
+ * If xfs enable crc, the node/leaf block records its blkno, we
+ * must update it.
*/
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.
*/
--
2.20.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap
2023-11-30 4:05 ` [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap Jiachen Zhang
@ 2023-12-01 0:48 ` Darrick J. Wong
2023-12-04 7:18 ` Christoph Hellwig
1 sibling, 0 replies; 8+ messages in thread
From: Darrick J. Wong @ 2023-12-01 0:48 UTC (permalink / raw)
To: Jiachen Zhang
Cc: Chandan Babu R, Dave Chinner, Allison Henderson, Zhang Tianci,
Brian Foster, linux-xfs, linux-kernel, xieyongji, me,
Dave Chinner
On Thu, Nov 30, 2023 at 12:05:15PM +0800, Jiachen Zhang wrote:
> From: Zhang Tianci <zhangtianci.1997@bytedance.com>
>
> 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>
Looks fine to me,
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
--D
> ---
> fs/xfs/libxfs/xfs_da_btree.c | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
> index e576560b46e9..f3f987a65bc1 100644
> --- a/fs/xfs/libxfs/xfs_da_btree.c
> +++ b/fs/xfs/libxfs/xfs_da_btree.c
> @@ -2316,10 +2316,18 @@ xfs_da3_swap_lastblock(
> return error;
> /*
> * Copy the last block into the dead buffer and log it.
> + * If xfs enable crc, the node/leaf block records its blkno, we
> + * must update it.
> */
> 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.
> */
> --
> 2.20.1
>
>
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap
2023-11-30 4:05 ` [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap Jiachen Zhang
2023-12-01 0:48 ` Darrick J. Wong
@ 2023-12-04 7:18 ` Christoph Hellwig
1 sibling, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2023-12-04 7:18 UTC (permalink / raw)
To: Jiachen Zhang
Cc: Chandan Babu R, Darrick J. Wong, Dave Chinner, Allison Henderson,
Zhang Tianci, Brian Foster, linux-xfs, linux-kernel, xieyongji,
me, Dave Chinner
On Thu, Nov 30, 2023 at 12:05:15PM +0800, Jiachen Zhang wrote:
> return error;
> /*
> * Copy the last block into the dead buffer and log it.
> + * If xfs enable crc, the node/leaf block records its blkno, we
> + * must update it.
I'd rewrod this sentence as:
* On CRC-enabled file systems, also update the stamped in blkno.
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 3/3] xfs: extract xfs_da_buf_copy() helper function
2023-11-30 4:05 [PATCH v3 0/3] Fixes for ENOSPC xfs_remove Jiachen Zhang
2023-11-30 4:05 ` [PATCH v3 1/3] xfs: ensure logflagsp is initialized in xfs_bmap_del_extent_real Jiachen Zhang
2023-11-30 4:05 ` [PATCH v3 2/3] xfs: update dir3 leaf block metadata after swap Jiachen Zhang
@ 2023-11-30 4:05 ` Jiachen Zhang
2023-12-04 7:25 ` Christoph Hellwig
2 siblings, 1 reply; 8+ messages in thread
From: Jiachen Zhang @ 2023-11-30 4:05 UTC (permalink / raw)
To: Chandan Babu R, Darrick J. Wong
Cc: Dave Chinner, Allison Henderson, Zhang Tianci, Brian Foster,
linux-xfs, linux-kernel, xieyongji, me, Christoph Hellwig
From: Zhang Tianci <zhangtianci.1997@bytedance.com>
This patch does not modify logic.
xfs_da_buf_copy() will copy one block from src xfs_buf to
dst xfs_buf, and update the block metadata in dst directly.
Signed-off-by: Zhang Tianci <zhangtianci.1997@bytedance.com>
Suggested-by: Christoph Hellwig <hch@infradead.org>
---
fs/xfs/libxfs/xfs_attr_leaf.c | 12 ++----
fs/xfs/libxfs/xfs_da_btree.c | 76 ++++++++++++++---------------------
fs/xfs/libxfs/xfs_da_btree.h | 2 +
3 files changed, 37 insertions(+), 53 deletions(-)
diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c
index 2580ae47209a..628dcd2d971e 100644
--- a/fs/xfs/libxfs/xfs_attr_leaf.c
+++ b/fs/xfs/libxfs/xfs_attr_leaf.c
@@ -1244,14 +1244,10 @@ xfs_attr3_leaf_to_node(
if (error)
goto out;
- /* copy leaf to new buffer, update identifiers */
- xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF);
- bp2->b_ops = bp1->b_ops;
- memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize);
- if (xfs_has_crc(mp)) {
- struct xfs_da3_blkinfo *hdr3 = bp2->b_addr;
- hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp2));
- }
+ /*
+ * copy leaf to new buffer and log it.
+ */
+ xfs_da_buf_copy(bp2, bp1, args->geo->blksize);
xfs_trans_log_buf(args->trans, bp2, 0, args->geo->blksize - 1);
/*
diff --git a/fs/xfs/libxfs/xfs_da_btree.c b/fs/xfs/libxfs/xfs_da_btree.c
index f3f987a65bc1..d39d6ad0f97b 100644
--- a/fs/xfs/libxfs/xfs_da_btree.c
+++ b/fs/xfs/libxfs/xfs_da_btree.c
@@ -690,12 +690,6 @@ xfs_da3_root_split(
btree = icnodehdr.btree;
size = (int)((char *)&btree[icnodehdr.count] - (char *)oldroot);
level = icnodehdr.level;
-
- /*
- * we are about to copy oldroot to bp, so set up the type
- * of bp while we know exactly what it will be.
- */
- xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DA_NODE_BUF);
} else {
struct xfs_dir3_icleaf_hdr leafhdr;
@@ -707,31 +701,17 @@ xfs_da3_root_split(
size = (int)((char *)&leafhdr.ents[leafhdr.count] -
(char *)leaf);
level = 0;
-
- /*
- * we are about to copy oldroot to bp, so set up the type
- * of bp while we know exactly what it will be.
- */
- xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_LEAFN_BUF);
}
/*
- * we can copy most of the information in the node from one block to
- * another, but for CRC enabled headers we have to make sure that the
- * block specific identifiers are kept intact. We update the buffer
- * directly for this.
+ * Copy old root to new buffer and log it.
*/
- memcpy(node, oldroot, size);
- if (oldroot->hdr.info.magic == cpu_to_be16(XFS_DA3_NODE_MAGIC) ||
- oldroot->hdr.info.magic == cpu_to_be16(XFS_DIR3_LEAFN_MAGIC)) {
- struct xfs_da3_intnode *node3 = (struct xfs_da3_intnode *)node;
-
- node3->hdr.info.blkno = cpu_to_be64(xfs_buf_daddr(bp));
- }
+ xfs_da_buf_copy(bp, blk1->bp, size);
xfs_trans_log_buf(tp, bp, 0, size - 1);
- bp->b_ops = blk1->bp->b_ops;
- xfs_trans_buf_copy_type(bp, blk1->bp);
+ /*
+ * Update blk1 to point to new buffer.
+ */
blk1->bp = bp;
blk1->blkno = blkno;
@@ -1220,21 +1200,14 @@ xfs_da3_root_join(
xfs_da_blkinfo_onlychild_validate(bp->b_addr, oldroothdr.level);
/*
- * This could be copying a leaf back into the root block in the case of
- * there only being a single leaf block left in the tree. Hence we have
- * to update the b_ops pointer as well to match the buffer type change
- * that could occur. For dir3 blocks we also need to update the block
- * number in the buffer header.
+ * Copy child to root buffer and log it.
*/
- memcpy(root_blk->bp->b_addr, bp->b_addr, args->geo->blksize);
- root_blk->bp->b_ops = bp->b_ops;
- xfs_trans_buf_copy_type(root_blk->bp, bp);
- if (oldroothdr.magic == XFS_DA3_NODE_MAGIC) {
- struct xfs_da3_blkinfo *da3 = root_blk->bp->b_addr;
- da3->blkno = cpu_to_be64(xfs_buf_daddr(root_blk->bp));
- }
+ xfs_da_buf_copy(root_blk->bp, bp, args->geo->blksize);
xfs_trans_log_buf(args->trans, root_blk->bp, 0,
args->geo->blksize - 1);
+ /*
+ * Now we could drop the child buffer.
+ */
error = xfs_da_shrink_inode(args, child, bp);
return error;
}
@@ -2252,6 +2225,26 @@ xfs_da_grow_inode(
return error;
}
+/*
+ * Copy src directory/xattribute leaf/node buffer to the dst.
+ * If xfs enables crc(IOW, xfs' on-disk format is v5), we have to
+ * make sure that the block specific identifiers are kept intact.
+ */
+void
+xfs_da_buf_copy(
+ struct xfs_buf *dst,
+ struct xfs_buf *src,
+ size_t size)
+{
+ struct xfs_da3_blkinfo *da3 = dst->b_addr;
+
+ memcpy(dst->b_addr, src->b_addr, size);
+ dst->b_ops = src->b_ops;
+ xfs_trans_buf_copy_type(dst, src);
+ if (xfs_has_crc(dst->b_mount))
+ da3->blkno = cpu_to_be64(xfs_buf_daddr(dst));
+}
+
/*
* Ick. We need to always be able to remove a btree block, even
* if there's no space reservation because the filesystem is full.
@@ -2316,15 +2309,8 @@ xfs_da3_swap_lastblock(
return error;
/*
* Copy the last block into the dead buffer and log it.
- * If xfs enable crc, the node/leaf block records its blkno, we
- * must update it.
*/
- 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_da_buf_copy(dead_buf, last_buf, args->geo->blksize);
xfs_trans_log_buf(tp, dead_buf, 0, args->geo->blksize - 1);
dead_info = dead_buf->b_addr;
diff --git a/fs/xfs/libxfs/xfs_da_btree.h b/fs/xfs/libxfs/xfs_da_btree.h
index ffa3df5b2893..706baf36e175 100644
--- a/fs/xfs/libxfs/xfs_da_btree.h
+++ b/fs/xfs/libxfs/xfs_da_btree.h
@@ -219,6 +219,8 @@ int xfs_da_reada_buf(struct xfs_inode *dp, xfs_dablk_t bno,
const struct xfs_buf_ops *ops);
int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno,
struct xfs_buf *dead_buf);
+void xfs_da_buf_copy(struct xfs_buf *dst, struct xfs_buf *src,
+ size_t size);
uint xfs_da_hashname(const uint8_t *name_string, int name_length);
enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args,
--
2.20.1
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v3 3/3] xfs: extract xfs_da_buf_copy() helper function
2023-11-30 4:05 ` [PATCH v3 3/3] xfs: extract xfs_da_buf_copy() helper function Jiachen Zhang
@ 2023-12-04 7:25 ` Christoph Hellwig
0 siblings, 0 replies; 8+ messages in thread
From: Christoph Hellwig @ 2023-12-04 7:25 UTC (permalink / raw)
To: Jiachen Zhang
Cc: Chandan Babu R, Darrick J. Wong, Dave Chinner, Allison Henderson,
Zhang Tianci, Brian Foster, linux-xfs, linux-kernel, xieyongji,
me, Christoph Hellwig
> - /* copy leaf to new buffer, update identifiers */
> - xfs_trans_buf_set_type(args->trans, bp2, XFS_BLFT_ATTR_LEAF_BUF);
> - bp2->b_ops = bp1->b_ops;
> - memcpy(bp2->b_addr, bp1->b_addr, args->geo->blksize);
> - if (xfs_has_crc(mp)) {
> - struct xfs_da3_blkinfo *hdr3 = bp2->b_addr;
> - hdr3->blkno = cpu_to_be64(xfs_buf_daddr(bp2));
> - }
> + /*
> + * copy leaf to new buffer and log it.
> + */
Nit: The first word in a sentence should be capitalized.
Alternativalely just keep the old comment format that doesn't
pretence to be a sentence :)
> + /*
> + * Now we could drop the child buffer.
> + */
s/could/can/ ?
> +/*
> + * Copy src directory/xattribute leaf/node buffer to the dst.
> + * If xfs enables crc(IOW, xfs' on-disk format is v5), we have to
> + * make sure that the block specific identifiers are kept intact.
> + */
I'd reword this a bit:
* Copy src directory/attr leaf/node buffer to the dst.
* For v5 file systems make sure the right blkno is stamped in.
Also maybe move this function further up in the file? Even for
non-static functions it's kinda nice if they are implemented before
use to ease the reading flow.
Otherwise looks good:
Reviewed-by: Christoph Hellwig <hch@lst.de>
^ permalink raw reply [flat|nested] 8+ messages in thread