]> Git Repo - J-linux.git/blob - fs/xfs/scrub/rtbitmap_repair.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / fs / xfs / scrub / rtbitmap_repair.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2020-2023 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <[email protected]>
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. */
27 int
28 xrep_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  */
53 STATIC int
54 xrep_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
112                 /* Commit new extent and all deferred work. */
113                 error = xrep_defer_finish(sc);
114                 if (error)
115                         return error;
116
117                 off = map.br_startoff + map.br_blockcount;
118         }
119
120         return 0;
121 }
122
123 /* Fix broken rt volume geometry. */
124 STATIC int
125 xrep_rtbitmap_geometry(
126         struct xfs_scrub        *sc,
127         struct xchk_rtbitmap    *rtb)
128 {
129         struct xfs_mount        *mp = sc->mp;
130         struct xfs_trans        *tp = sc->tp;
131
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);
136
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);
140
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);
144
145         /* Fix broken isize */
146         sc->ip->i_disk_size = roundup_64(sc->ip->i_disk_size,
147                                          mp->m_sb.sb_blocksize);
148
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);
151
152         xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
153         return xrep_roll_trans(sc);
154 }
155
156 /* Repair the realtime bitmap file metadata. */
157 int
158 xrep_rtbitmap(
159         struct xfs_scrub        *sc)
160 {
161         struct xchk_rtbitmap    *rtb = sc->buf;
162         struct xfs_mount        *mp = sc->mp;
163         unsigned long long      blocks = 0;
164         int                     error;
165
166         /* Impossibly large rtbitmap means we can't touch the filesystem. */
167         if (rtb->rbmblocks > U32_MAX)
168                 return 0;
169
170         /*
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
173          * transaction.
174          */
175         blocks = xfs_bmbt_calc_size(mp, rtb->rbmblocks);
176         if (blocks > UINT_MAX)
177                 return -EOPNOTSUPP;
178         if (blocks > rtb->resblks) {
179                 error = xfs_trans_reserve_more(sc->tp, blocks, 0);
180                 if (error)
181                         return error;
182
183                 rtb->resblks += blocks;
184         }
185
186         /* Fix inode core and forks. */
187         error = xrep_metadata_inode_forks(sc);
188         if (error)
189                 return error;
190
191         xfs_trans_ijoin(sc->tp, sc->ip, 0);
192
193         /* Ensure no unwritten extents. */
194         error = xrep_rtbitmap_data_mappings(sc, rtb->rbmblocks);
195         if (error)
196                 return error;
197
198         /* Fix inconsistent bitmap geometry */
199         return xrep_rtbitmap_geometry(sc, rtb);
200 }
This page took 0.035309 seconds and 4 git commands to generate.