1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2020-2023 Oracle. All Rights Reserved.
4 * Author: Darrick J. Wong <djwong@kernel.org>
5 */
6#include "xfs.h"
7#include "xfs_fs.h"
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"
16#include "xfs_bit.h"
17#include "xfs_bmap.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"
25
26/* Set up to repair the realtime bitmap file metadata. */
27int
28xrep_setup_rtbitmap(
29 struct xfs_scrub *sc,
30 struct xchk_rtbitmap *rtb)
31{
32 struct xfs_mount *mp = sc->mp;
33 unsigned long long blocks = 0;
34
35 /*
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.
39 */
40 blocks = xfs_bmbt_calc_size(mp, mp->m_sb.sb_rbmblocks);
41 if (blocks > UINT_MAX)
42 return -EOPNOTSUPP;
43
44 rtb->resblks += blocks;
45 return 0;
46}
47
48/*
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
51 * to the transaction.
52 */
53STATIC int
54xrep_rtbitmap_data_mappings(
55 struct xfs_scrub *sc,
56 xfs_filblks_t len)
57{
58 struct xfs_bmbt_irec map;
59 xfs_fileoff_t off = 0;
60 int error;
61
62 ASSERT(sc->ip != NULL);
63
64 while (off < len) {
65 int nmaps = 1;
66
67 /*
68 * If we have a real extent mapping this block then we're
69 * in ok shape.
70 */
71 error = xfs_bmapi_read(sc->ip, off, len - off, &map, &nmaps,
72 XFS_DATA_FORK);
73 if (error)
74 return error;
75 if (nmaps == 0) {
76 ASSERT(nmaps != 0);
77 return -EFSCORRUPTED;
78 }
79
80 /*
81 * Written extents are ok. Holes are not filled because we
82 * do not know the freespace information.
83 */
84 if (xfs_bmap_is_written_extent(&map) ||
85 map.br_startblock == HOLESTARTBLOCK) {
86 off = map.br_startoff + map.br_blockcount;
87 continue;
88 }
89
90 /*
91 * If we find a delalloc reservation then something is very
92 * very wrong. Bail out.
93 */
94 if (map.br_startblock == DELAYSTARTBLOCK)
95 return -EFSCORRUPTED;
96
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;
101 }
102
103 /* Make sure this block has a real zeroed extent mapped. */
104 nmaps = 1;
105 error = xfs_bmapi_write(sc->tp, sc->ip, map.br_startoff,
106 map.br_blockcount,
107 XFS_BMAPI_CONVERT | XFS_BMAPI_ZERO,
108 0, &map, &nmaps);
109 if (error)
110 return error;
111 if (nmaps != 1)
112 return -EFSCORRUPTED;
113
114 /* Commit new extent and all deferred work. */
115 error = xrep_defer_finish(sc);
116 if (error)
117 return error;
118
119 off = map.br_startoff + map.br_blockcount;
120 }
121
122 return 0;
123}
124
125/* Fix broken rt volume geometry. */
126STATIC int
127xrep_rtbitmap_geometry(
128 struct xfs_scrub *sc,
129 struct xchk_rtbitmap *rtb)
130{
131 struct xfs_mount *mp = sc->mp;
132 struct xfs_trans *tp = sc->tp;
133
134 /* Superblock fields */
135 if (mp->m_sb.sb_rextents != rtb->rextents)
136 xfs_trans_mod_sb(sc->tp, XFS_TRANS_SB_REXTENTS,
137 rtb->rextents - mp->m_sb.sb_rextents);
138
139 if (mp->m_sb.sb_rbmblocks != rtb->rbmblocks)
140 xfs_trans_mod_sb(tp, XFS_TRANS_SB_RBMBLOCKS,
141 rtb->rbmblocks - mp->m_sb.sb_rbmblocks);
142
143 if (mp->m_sb.sb_rextslog != rtb->rextslog)
144 xfs_trans_mod_sb(tp, XFS_TRANS_SB_REXTSLOG,
145 rtb->rextslog - mp->m_sb.sb_rextslog);
146
147 /* Fix broken isize */
148 sc->ip->i_disk_size = roundup_64(sc->ip->i_disk_size,
149 mp->m_sb.sb_blocksize);
150
151 if (sc->ip->i_disk_size < XFS_FSB_TO_B(mp, rtb->rbmblocks))
152 sc->ip->i_disk_size = XFS_FSB_TO_B(mp, rtb->rbmblocks);
153
154 xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
155 return xrep_roll_trans(sc);
156}
157
158/* Repair the realtime bitmap file metadata. */
159int
160xrep_rtbitmap(
161 struct xfs_scrub *sc)
162{
163 struct xchk_rtbitmap *rtb = sc->buf;
164 struct xfs_mount *mp = sc->mp;
165 unsigned long long blocks = 0;
166 int error;
167
168 /* Impossibly large rtbitmap means we can't touch the filesystem. */
169 if (rtb->rbmblocks > U32_MAX)
170 return 0;
171
172 /*
173 * If the size of the rt bitmap file is larger than what we reserved,
174 * figure out if we need to adjust the block reservation in the
175 * transaction.
176 */
177 blocks = xfs_bmbt_calc_size(mp, rtb->rbmblocks);
178 if (blocks > UINT_MAX)
179 return -EOPNOTSUPP;
180 if (blocks > rtb->resblks) {
181 error = xfs_trans_reserve_more(sc->tp, blocks, 0);
182 if (error)
183 return error;
184
185 rtb->resblks += blocks;
186 }
187
188 /* Fix inode core and forks. */
189 error = xrep_metadata_inode_forks(sc);
190 if (error)
191 return error;
192
193 xfs_trans_ijoin(sc->tp, sc->ip, 0);
194
195 /* Ensure no unwritten extents. */
196 error = xrep_rtbitmap_data_mappings(sc, rtb->rbmblocks);
197 if (error)
198 return error;
199
200 /* Fix inconsistent bitmap geometry */
201 return xrep_rtbitmap_geometry(sc, rtb);
202}
203

source code of linux/fs/xfs/scrub/rtbitmap_repair.c