1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2020-2023 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_btree.h"
13 #include "xfs_log_format.h"
14 #include "xfs_trans.h"
15 #include "xfs_inode.h"
18 #include "xfs_bmap_btree.h"
19 #include "scrub/scrub.h"
20 #include "scrub/common.h"
21 #include "scrub/trace.h"
22 #include "scrub/repair.h"
23 #include "scrub/xfile.h"
24 #include "scrub/rtbitmap.h"
26 /* Set up to repair the realtime bitmap file metadata. */
30 struct xchk_rtbitmap
*rtb
)
32 struct xfs_mount
*mp
= sc
->mp
;
33 unsigned long long blocks
= 0;
36 * Reserve enough blocks to write out a completely new bmbt for a
37 * maximally fragmented bitmap file. We do not hold the rtbitmap
38 * ILOCK yet, so this is entirely speculative.
40 blocks
= xfs_bmbt_calc_size(mp
, mp
->m_sb
.sb_rbmblocks
);
41 if (blocks
> UINT_MAX
)
44 rtb
->resblks
+= blocks
;
49 * Make sure that the given range of the data fork of the realtime file is
50 * mapped to written blocks. The caller must ensure that the inode is joined
54 xrep_rtbitmap_data_mappings(
58 struct xfs_bmbt_irec map
;
59 xfs_fileoff_t off
= 0;
62 ASSERT(sc
->ip
!= NULL
);
68 * If we have a real extent mapping this block then we're
71 error
= xfs_bmapi_read(sc
->ip
, off
, len
- off
, &map
, &nmaps
,
81 * Written extents are ok. Holes are not filled because we
82 * do not know the freespace information.
84 if (xfs_bmap_is_written_extent(&map
) ||
85 map
.br_startblock
== HOLESTARTBLOCK
) {
86 off
= map
.br_startoff
+ map
.br_blockcount
;
91 * If we find a delalloc reservation then something is very
92 * very wrong. Bail out.
94 if (map
.br_startblock
== DELAYSTARTBLOCK
)
97 /* Make sure we're really converting an unwritten extent. */
98 if (map
.br_state
!= XFS_EXT_UNWRITTEN
) {
99 ASSERT(map
.br_state
== XFS_EXT_UNWRITTEN
);
100 return -EFSCORRUPTED
;
103 /* Make sure this block has a real zeroed extent mapped. */
105 error
= xfs_bmapi_write(sc
->tp
, sc
->ip
, map
.br_startoff
,
107 XFS_BMAPI_CONVERT
| XFS_BMAPI_ZERO
,
112 /* Commit new extent and all deferred work. */
113 error
= xrep_defer_finish(sc
);
117 off
= map
.br_startoff
+ map
.br_blockcount
;
123 /* Fix broken rt volume geometry. */
125 xrep_rtbitmap_geometry(
126 struct xfs_scrub
*sc
,
127 struct xchk_rtbitmap
*rtb
)
129 struct xfs_mount
*mp
= sc
->mp
;
130 struct xfs_trans
*tp
= sc
->tp
;
132 /* Superblock fields */
133 if (mp
->m_sb
.sb_rextents
!= rtb
->rextents
)
134 xfs_trans_mod_sb(sc
->tp
, XFS_TRANS_SB_REXTENTS
,
135 rtb
->rextents
- mp
->m_sb
.sb_rextents
);
137 if (mp
->m_sb
.sb_rbmblocks
!= rtb
->rbmblocks
)
138 xfs_trans_mod_sb(tp
, XFS_TRANS_SB_RBMBLOCKS
,
139 rtb
->rbmblocks
- mp
->m_sb
.sb_rbmblocks
);
141 if (mp
->m_sb
.sb_rextslog
!= rtb
->rextslog
)
142 xfs_trans_mod_sb(tp
, XFS_TRANS_SB_REXTSLOG
,
143 rtb
->rextslog
- mp
->m_sb
.sb_rextslog
);
145 /* Fix broken isize */
146 sc
->ip
->i_disk_size
= roundup_64(sc
->ip
->i_disk_size
,
147 mp
->m_sb
.sb_blocksize
);
149 if (sc
->ip
->i_disk_size
< XFS_FSB_TO_B(mp
, rtb
->rbmblocks
))
150 sc
->ip
->i_disk_size
= XFS_FSB_TO_B(mp
, rtb
->rbmblocks
);
152 xfs_trans_log_inode(sc
->tp
, sc
->ip
, XFS_ILOG_CORE
);
153 return xrep_roll_trans(sc
);
156 /* Repair the realtime bitmap file metadata. */
159 struct xfs_scrub
*sc
)
161 struct xchk_rtbitmap
*rtb
= sc
->buf
;
162 struct xfs_mount
*mp
= sc
->mp
;
163 unsigned long long blocks
= 0;
166 /* Impossibly large rtbitmap means we can't touch the filesystem. */
167 if (rtb
->rbmblocks
> U32_MAX
)
171 * If the size of the rt bitmap file is larger than what we reserved,
172 * figure out if we need to adjust the block reservation in the
175 blocks
= xfs_bmbt_calc_size(mp
, rtb
->rbmblocks
);
176 if (blocks
> UINT_MAX
)
178 if (blocks
> rtb
->resblks
) {
179 error
= xfs_trans_reserve_more(sc
->tp
, blocks
, 0);
183 rtb
->resblks
+= blocks
;
186 /* Fix inode core and forks. */
187 error
= xrep_metadata_inode_forks(sc
);
191 xfs_trans_ijoin(sc
->tp
, sc
->ip
, 0);
193 /* Ensure no unwritten extents. */
194 error
= xrep_rtbitmap_data_mappings(sc
, rtb
->rbmblocks
);
198 /* Fix inconsistent bitmap geometry */
199 return xrep_rtbitmap_geometry(sc
, rtb
);