blob: 709d4916fe0479ddda16b65d39c8e8295d87f521 [file] [log] [blame]
Darrick J. Wongdcb660f2017-10-17 21:37:36 -07001/*
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_inode.h"
33#include "xfs_alloc.h"
34#include "xfs_alloc_btree.h"
35#include "xfs_bmap.h"
36#include "xfs_bmap_btree.h"
37#include "xfs_ialloc.h"
38#include "xfs_ialloc_btree.h"
39#include "xfs_refcount.h"
40#include "xfs_refcount_btree.h"
41#include "xfs_rmap.h"
42#include "xfs_rmap_btree.h"
43#include "scrub/xfs_scrub.h"
44#include "scrub/scrub.h"
45#include "scrub/common.h"
46#include "scrub/trace.h"
47
48/* Common code for the metadata scrubbers. */
49
Darrick J. Wong4700d222017-10-17 21:37:36 -070050/*
51 * Handling operational errors.
52 *
53 * The *_process_error() family of functions are used to process error return
54 * codes from functions called as part of a scrub operation.
55 *
56 * If there's no error, we return true to tell the caller that it's ok
57 * to move on to the next check in its list.
58 *
59 * For non-verifier errors (e.g. ENOMEM) we return false to tell the
60 * caller that something bad happened, and we preserve *error so that
61 * the caller can return the *error up the stack to userspace.
62 *
63 * Verifier errors (EFSBADCRC/EFSCORRUPTED) are recorded by setting
64 * OFLAG_CORRUPT in sm_flags and the *error is cleared. In other words,
65 * we track verifier errors (and failed scrub checks) via OFLAG_CORRUPT,
66 * not via return codes. We return false to tell the caller that
67 * something bad happened. Since the error has been cleared, the caller
68 * will (presumably) return that zero and scrubbing will move on to
69 * whatever's next.
70 *
71 * ftrace can be used to record the precise metadata location and the
72 * approximate code location of the failed operation.
73 */
74
75/* Check for operational errors. */
76bool
77xfs_scrub_process_error(
78 struct xfs_scrub_context *sc,
79 xfs_agnumber_t agno,
80 xfs_agblock_t bno,
81 int *error)
82{
83 switch (*error) {
84 case 0:
85 return true;
86 case -EDEADLOCK:
87 /* Used to restart an op with deadlock avoidance. */
88 trace_xfs_scrub_deadlock_retry(sc->ip, sc->sm, *error);
89 break;
90 case -EFSBADCRC:
91 case -EFSCORRUPTED:
92 /* Note the badness but don't abort. */
93 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
94 *error = 0;
95 /* fall through */
96 default:
97 trace_xfs_scrub_op_error(sc, agno, bno, *error,
98 __return_address);
99 break;
100 }
101 return false;
102}
103
104/* Check for operational errors for a file offset. */
105bool
106xfs_scrub_fblock_process_error(
107 struct xfs_scrub_context *sc,
108 int whichfork,
109 xfs_fileoff_t offset,
110 int *error)
111{
112 switch (*error) {
113 case 0:
114 return true;
115 case -EDEADLOCK:
116 /* Used to restart an op with deadlock avoidance. */
117 trace_xfs_scrub_deadlock_retry(sc->ip, sc->sm, *error);
118 break;
119 case -EFSBADCRC:
120 case -EFSCORRUPTED:
121 /* Note the badness but don't abort. */
122 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
123 *error = 0;
124 /* fall through */
125 default:
126 trace_xfs_scrub_file_op_error(sc, whichfork, offset, *error,
127 __return_address);
128 break;
129 }
130 return false;
131}
132
133/*
134 * Handling scrub corruption/optimization/warning checks.
135 *
136 * The *_set_{corrupt,preen,warning}() family of functions are used to
137 * record the presence of metadata that is incorrect (corrupt), could be
138 * optimized somehow (preen), or should be flagged for administrative
139 * review but is not incorrect (warn).
140 *
141 * ftrace can be used to record the precise metadata location and
142 * approximate code location of the failed check.
143 */
144
145/* Record a block which could be optimized. */
146void
147xfs_scrub_block_set_preen(
148 struct xfs_scrub_context *sc,
149 struct xfs_buf *bp)
150{
151 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_PREEN;
152 trace_xfs_scrub_block_preen(sc, bp->b_bn, __return_address);
153}
154
155/*
156 * Record an inode which could be optimized. The trace data will
157 * include the block given by bp if bp is given; otherwise it will use
158 * the block location of the inode record itself.
159 */
160void
161xfs_scrub_ino_set_preen(
162 struct xfs_scrub_context *sc,
163 struct xfs_buf *bp)
164{
165 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_PREEN;
166 trace_xfs_scrub_ino_preen(sc, sc->ip->i_ino, bp ? bp->b_bn : 0,
167 __return_address);
168}
169
170/* Record a corrupt block. */
171void
172xfs_scrub_block_set_corrupt(
173 struct xfs_scrub_context *sc,
174 struct xfs_buf *bp)
175{
176 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
177 trace_xfs_scrub_block_error(sc, bp->b_bn, __return_address);
178}
179
180/*
181 * Record a corrupt inode. The trace data will include the block given
182 * by bp if bp is given; otherwise it will use the block location of the
183 * inode record itself.
184 */
185void
186xfs_scrub_ino_set_corrupt(
187 struct xfs_scrub_context *sc,
188 xfs_ino_t ino,
189 struct xfs_buf *bp)
190{
191 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
192 trace_xfs_scrub_ino_error(sc, ino, bp ? bp->b_bn : 0, __return_address);
193}
194
195/* Record corruption in a block indexed by a file fork. */
196void
197xfs_scrub_fblock_set_corrupt(
198 struct xfs_scrub_context *sc,
199 int whichfork,
200 xfs_fileoff_t offset)
201{
202 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_CORRUPT;
203 trace_xfs_scrub_fblock_error(sc, whichfork, offset, __return_address);
204}
205
206/*
207 * Warn about inodes that need administrative review but is not
208 * incorrect.
209 */
210void
211xfs_scrub_ino_set_warning(
212 struct xfs_scrub_context *sc,
213 struct xfs_buf *bp)
214{
215 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
216 trace_xfs_scrub_ino_warning(sc, sc->ip->i_ino, bp ? bp->b_bn : 0,
217 __return_address);
218}
219
220/* Warn about a block indexed by a file fork that needs review. */
221void
222xfs_scrub_fblock_set_warning(
223 struct xfs_scrub_context *sc,
224 int whichfork,
225 xfs_fileoff_t offset)
226{
227 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_WARNING;
228 trace_xfs_scrub_fblock_warning(sc, whichfork, offset, __return_address);
229}
230
231/* Signal an incomplete scrub. */
232void
233xfs_scrub_set_incomplete(
234 struct xfs_scrub_context *sc)
235{
236 sc->sm->sm_flags |= XFS_SCRUB_OFLAG_INCOMPLETE;
237 trace_xfs_scrub_incomplete(sc, __return_address);
238}
239
Darrick J. Wongdcb660f2017-10-17 21:37:36 -0700240/* Per-scrubber setup functions */
241
242/* Set us up with a transaction and an empty context. */
243int
244xfs_scrub_setup_fs(
245 struct xfs_scrub_context *sc,
246 struct xfs_inode *ip)
247{
248 return xfs_scrub_trans_alloc(sc->sm, sc->mp, &sc->tp);
249}