Loading...
Note: File does not exist in v3.5.6.
1/*
2 * Copyright (C) 2017 Oracle. All Rights Reserved.
3 *
4 * Author: Darrick J. Wong <darrick.wong@oracle.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it would be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
19 */
20#include "xfs.h"
21#include "xfs_fs.h"
22#include "xfs_shared.h"
23#include "xfs_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_mount.h"
26#include "xfs_defer.h"
27#include "xfs_btree.h"
28#include "xfs_bit.h"
29#include "xfs_log_format.h"
30#include "xfs_trans.h"
31#include "xfs_sb.h"
32#include "xfs_alloc.h"
33#include "xfs_rmap.h"
34#include "xfs_alloc.h"
35#include "scrub/xfs_scrub.h"
36#include "scrub/scrub.h"
37#include "scrub/common.h"
38#include "scrub/btree.h"
39#include "scrub/trace.h"
40
41/*
42 * Set us up to scrub free space btrees.
43 */
44int
45xfs_scrub_setup_ag_allocbt(
46 struct xfs_scrub_context *sc,
47 struct xfs_inode *ip)
48{
49 return xfs_scrub_setup_ag_btree(sc, ip, false);
50}
51
52/* Free space btree scrubber. */
53/*
54 * Ensure there's a corresponding cntbt/bnobt record matching this
55 * bnobt/cntbt record, respectively.
56 */
57STATIC void
58xfs_scrub_allocbt_xref_other(
59 struct xfs_scrub_context *sc,
60 xfs_agblock_t agbno,
61 xfs_extlen_t len)
62{
63 struct xfs_btree_cur **pcur;
64 xfs_agblock_t fbno;
65 xfs_extlen_t flen;
66 int has_otherrec;
67 int error;
68
69 if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
70 pcur = &sc->sa.cnt_cur;
71 else
72 pcur = &sc->sa.bno_cur;
73 if (!*pcur)
74 return;
75
76 error = xfs_alloc_lookup_le(*pcur, agbno, len, &has_otherrec);
77 if (!xfs_scrub_should_check_xref(sc, &error, pcur))
78 return;
79 if (!has_otherrec) {
80 xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
81 return;
82 }
83
84 error = xfs_alloc_get_rec(*pcur, &fbno, &flen, &has_otherrec);
85 if (!xfs_scrub_should_check_xref(sc, &error, pcur))
86 return;
87 if (!has_otherrec) {
88 xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
89 return;
90 }
91
92 if (fbno != agbno || flen != len)
93 xfs_scrub_btree_xref_set_corrupt(sc, *pcur, 0);
94}
95
96/* Cross-reference with the other btrees. */
97STATIC void
98xfs_scrub_allocbt_xref(
99 struct xfs_scrub_context *sc,
100 xfs_agblock_t agbno,
101 xfs_extlen_t len)
102{
103 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
104 return;
105
106 xfs_scrub_allocbt_xref_other(sc, agbno, len);
107 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, len);
108 xfs_scrub_xref_has_no_owner(sc, agbno, len);
109 xfs_scrub_xref_is_not_shared(sc, agbno, len);
110}
111
112/* Scrub a bnobt/cntbt record. */
113STATIC int
114xfs_scrub_allocbt_rec(
115 struct xfs_scrub_btree *bs,
116 union xfs_btree_rec *rec)
117{
118 struct xfs_mount *mp = bs->cur->bc_mp;
119 xfs_agnumber_t agno = bs->cur->bc_private.a.agno;
120 xfs_agblock_t bno;
121 xfs_extlen_t len;
122 int error = 0;
123
124 bno = be32_to_cpu(rec->alloc.ar_startblock);
125 len = be32_to_cpu(rec->alloc.ar_blockcount);
126
127 if (bno + len <= bno ||
128 !xfs_verify_agbno(mp, agno, bno) ||
129 !xfs_verify_agbno(mp, agno, bno + len - 1))
130 xfs_scrub_btree_set_corrupt(bs->sc, bs->cur, 0);
131
132 xfs_scrub_allocbt_xref(bs->sc, bno, len);
133
134 return error;
135}
136
137/* Scrub the freespace btrees for some AG. */
138STATIC int
139xfs_scrub_allocbt(
140 struct xfs_scrub_context *sc,
141 xfs_btnum_t which)
142{
143 struct xfs_owner_info oinfo;
144 struct xfs_btree_cur *cur;
145
146 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_AG);
147 cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur;
148 return xfs_scrub_btree(sc, cur, xfs_scrub_allocbt_rec, &oinfo, NULL);
149}
150
151int
152xfs_scrub_bnobt(
153 struct xfs_scrub_context *sc)
154{
155 return xfs_scrub_allocbt(sc, XFS_BTNUM_BNO);
156}
157
158int
159xfs_scrub_cntbt(
160 struct xfs_scrub_context *sc)
161{
162 return xfs_scrub_allocbt(sc, XFS_BTNUM_CNT);
163}
164
165/* xref check that the extent is not free */
166void
167xfs_scrub_xref_is_used_space(
168 struct xfs_scrub_context *sc,
169 xfs_agblock_t agbno,
170 xfs_extlen_t len)
171{
172 bool is_freesp;
173 int error;
174
175 if (!sc->sa.bno_cur)
176 return;
177
178 error = xfs_alloc_has_record(sc->sa.bno_cur, agbno, len, &is_freesp);
179 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.bno_cur))
180 return;
181 if (is_freesp)
182 xfs_scrub_btree_xref_set_corrupt(sc, sc->sa.bno_cur, 0);
183}