xref: /openbmc/linux/fs/xfs/scrub/bmap.c (revision 5334d983)
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 Oracle.  All Rights Reserved.
4  * Author: Darrick J. Wong <darrick.wong@oracle.com>
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_bit.h"
14 #include "xfs_log_format.h"
15 #include "xfs_trans.h"
16 #include "xfs_inode.h"
17 #include "xfs_alloc.h"
18 #include "xfs_bmap.h"
19 #include "xfs_bmap_btree.h"
20 #include "xfs_rmap.h"
21 #include "xfs_rmap_btree.h"
22 #include "scrub/scrub.h"
23 #include "scrub/common.h"
24 #include "scrub/btree.h"
25 
26 /* Set us up with an inode's bmap. */
27 int
28 xchk_setup_inode_bmap(
29 	struct xfs_scrub	*sc)
30 {
31 	int			error;
32 
33 	error = xchk_get_inode(sc);
34 	if (error)
35 		goto out;
36 
37 	sc->ilock_flags = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
38 	xfs_ilock(sc->ip, sc->ilock_flags);
39 
40 	/*
41 	 * We don't want any ephemeral data fork updates sitting around
42 	 * while we inspect block mappings, so wait for directio to finish
43 	 * and flush dirty data if we have delalloc reservations.
44 	 */
45 	if (S_ISREG(VFS_I(sc->ip)->i_mode) &&
46 	    sc->sm->sm_type == XFS_SCRUB_TYPE_BMBTD) {
47 		struct address_space	*mapping = VFS_I(sc->ip)->i_mapping;
48 
49 		inode_dio_wait(VFS_I(sc->ip));
50 
51 		/*
52 		 * Try to flush all incore state to disk before we examine the
53 		 * space mappings for the data fork.  Leave accumulated errors
54 		 * in the mapping for the writer threads to consume.
55 		 *
56 		 * On ENOSPC or EIO writeback errors, we continue into the
57 		 * extent mapping checks because write failures do not
58 		 * necessarily imply anything about the correctness of the file
59 		 * metadata.  The metadata and the file data could be on
60 		 * completely separate devices; a media failure might only
61 		 * affect a subset of the disk, etc.  We can handle delalloc
62 		 * extents in the scrubber, so leaving them in memory is fine.
63 		 */
64 		error = filemap_fdatawrite(mapping);
65 		if (!error)
66 			error = filemap_fdatawait_keep_errors(mapping);
67 		if (error && (error != -ENOSPC && error != -EIO))
68 			goto out;
69 	}
70 
71 	/* Got the inode, lock it and we're ready to go. */
72 	error = xchk_trans_alloc(sc, 0);
73 	if (error)
74 		goto out;
75 	sc->ilock_flags |= XFS_ILOCK_EXCL;
76 	xfs_ilock(sc->ip, XFS_ILOCK_EXCL);
77 
78 out:
79 	/* scrub teardown will unlock and release the inode */
80 	return error;
81 }
82 
83 /*
84  * Inode fork block mapping (BMBT) scrubber.
85  * More complex than the others because we have to scrub
86  * all the extents regardless of whether or not the fork
87  * is in btree format.
88  */
89 
90 struct xchk_bmap_info {
91 	struct xfs_scrub	*sc;
92 	xfs_fileoff_t		lastoff;
93 	bool			is_rt;
94 	bool			is_shared;
95 	bool			was_loaded;
96 	int			whichfork;
97 };
98 
99 /* Look for a corresponding rmap for this irec. */
100 static inline bool
101 xchk_bmap_get_rmap(
102 	struct xchk_bmap_info	*info,
103 	struct xfs_bmbt_irec	*irec,
104 	xfs_agblock_t		agbno,
105 	uint64_t		owner,
106 	struct xfs_rmap_irec	*rmap)
107 {
108 	xfs_fileoff_t		offset;
109 	unsigned int		rflags = 0;
110 	int			has_rmap;
111 	int			error;
112 
113 	if (info->whichfork == XFS_ATTR_FORK)
114 		rflags |= XFS_RMAP_ATTR_FORK;
115 	if (irec->br_state == XFS_EXT_UNWRITTEN)
116 		rflags |= XFS_RMAP_UNWRITTEN;
117 
118 	/*
119 	 * CoW staging extents are owned (on disk) by the refcountbt, so
120 	 * their rmaps do not have offsets.
121 	 */
122 	if (info->whichfork == XFS_COW_FORK)
123 		offset = 0;
124 	else
125 		offset = irec->br_startoff;
126 
127 	/*
128 	 * If the caller thinks this could be a shared bmbt extent (IOWs,
129 	 * any data fork extent of a reflink inode) then we have to use the
130 	 * range rmap lookup to make sure we get the correct owner/offset.
131 	 */
132 	if (info->is_shared) {
133 		error = xfs_rmap_lookup_le_range(info->sc->sa.rmap_cur, agbno,
134 				owner, offset, rflags, rmap, &has_rmap);
135 		if (!xchk_should_check_xref(info->sc, &error,
136 				&info->sc->sa.rmap_cur))
137 			return false;
138 		goto out;
139 	}
140 
141 	/*
142 	 * Otherwise, use the (faster) regular lookup.
143 	 */
144 	error = xfs_rmap_lookup_le(info->sc->sa.rmap_cur, agbno, 0, owner,
145 			offset, rflags, &has_rmap);
146 	if (!xchk_should_check_xref(info->sc, &error,
147 			&info->sc->sa.rmap_cur))
148 		return false;
149 	if (!has_rmap)
150 		goto out;
151 
152 	error = xfs_rmap_get_rec(info->sc->sa.rmap_cur, rmap, &has_rmap);
153 	if (!xchk_should_check_xref(info->sc, &error,
154 			&info->sc->sa.rmap_cur))
155 		return false;
156 
157 out:
158 	if (!has_rmap)
159 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
160 			irec->br_startoff);
161 	return has_rmap;
162 }
163 
164 /* Make sure that we have rmapbt records for this extent. */
165 STATIC void
166 xchk_bmap_xref_rmap(
167 	struct xchk_bmap_info	*info,
168 	struct xfs_bmbt_irec	*irec,
169 	xfs_agblock_t		agbno)
170 {
171 	struct xfs_rmap_irec	rmap;
172 	unsigned long long	rmap_end;
173 	uint64_t		owner;
174 
175 	if (!info->sc->sa.rmap_cur || xchk_skip_xref(info->sc->sm))
176 		return;
177 
178 	if (info->whichfork == XFS_COW_FORK)
179 		owner = XFS_RMAP_OWN_COW;
180 	else
181 		owner = info->sc->ip->i_ino;
182 
183 	/* Find the rmap record for this irec. */
184 	if (!xchk_bmap_get_rmap(info, irec, agbno, owner, &rmap))
185 		return;
186 
187 	/* Check the rmap. */
188 	rmap_end = (unsigned long long)rmap.rm_startblock + rmap.rm_blockcount;
189 	if (rmap.rm_startblock > agbno ||
190 	    agbno + irec->br_blockcount > rmap_end)
191 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
192 				irec->br_startoff);
193 
194 	/*
195 	 * Check the logical offsets if applicable.  CoW staging extents
196 	 * don't track logical offsets since the mappings only exist in
197 	 * memory.
198 	 */
199 	if (info->whichfork != XFS_COW_FORK) {
200 		rmap_end = (unsigned long long)rmap.rm_offset +
201 				rmap.rm_blockcount;
202 		if (rmap.rm_offset > irec->br_startoff ||
203 		    irec->br_startoff + irec->br_blockcount > rmap_end)
204 			xchk_fblock_xref_set_corrupt(info->sc,
205 					info->whichfork, irec->br_startoff);
206 	}
207 
208 	if (rmap.rm_owner != owner)
209 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
210 				irec->br_startoff);
211 
212 	/*
213 	 * Check for discrepancies between the unwritten flag in the irec and
214 	 * the rmap.  Note that the (in-memory) CoW fork distinguishes between
215 	 * unwritten and written extents, but we don't track that in the rmap
216 	 * records because the blocks are owned (on-disk) by the refcountbt,
217 	 * which doesn't track unwritten state.
218 	 */
219 	if (owner != XFS_RMAP_OWN_COW &&
220 	    !!(irec->br_state == XFS_EXT_UNWRITTEN) !=
221 	    !!(rmap.rm_flags & XFS_RMAP_UNWRITTEN))
222 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
223 				irec->br_startoff);
224 
225 	if (!!(info->whichfork == XFS_ATTR_FORK) !=
226 	    !!(rmap.rm_flags & XFS_RMAP_ATTR_FORK))
227 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
228 				irec->br_startoff);
229 	if (rmap.rm_flags & XFS_RMAP_BMBT_BLOCK)
230 		xchk_fblock_xref_set_corrupt(info->sc, info->whichfork,
231 				irec->br_startoff);
232 }
233 
234 /* Cross-reference a single rtdev extent record. */
235 STATIC void
236 xchk_bmap_rt_iextent_xref(
237 	struct xfs_inode	*ip,
238 	struct xchk_bmap_info	*info,
239 	struct xfs_bmbt_irec	*irec)
240 {
241 	xchk_xref_is_used_rt_space(info->sc, irec->br_startblock,
242 			irec->br_blockcount);
243 }
244 
245 /* Cross-reference a single datadev extent record. */
246 STATIC void
247 xchk_bmap_iextent_xref(
248 	struct xfs_inode	*ip,
249 	struct xchk_bmap_info	*info,
250 	struct xfs_bmbt_irec	*irec)
251 {
252 	struct xfs_mount	*mp = info->sc->mp;
253 	xfs_agnumber_t		agno;
254 	xfs_agblock_t		agbno;
255 	xfs_extlen_t		len;
256 	int			error;
257 
258 	agno = XFS_FSB_TO_AGNO(mp, irec->br_startblock);
259 	agbno = XFS_FSB_TO_AGBNO(mp, irec->br_startblock);
260 	len = irec->br_blockcount;
261 
262 	error = xchk_ag_init(info->sc, agno, &info->sc->sa);
263 	if (!xchk_fblock_process_error(info->sc, info->whichfork,
264 			irec->br_startoff, &error))
265 		return;
266 
267 	xchk_xref_is_used_space(info->sc, agbno, len);
268 	xchk_xref_is_not_inode_chunk(info->sc, agbno, len);
269 	xchk_bmap_xref_rmap(info, irec, agbno);
270 	switch (info->whichfork) {
271 	case XFS_DATA_FORK:
272 		if (xfs_is_reflink_inode(info->sc->ip))
273 			break;
274 		/* fall through */
275 	case XFS_ATTR_FORK:
276 		xchk_xref_is_not_shared(info->sc, agbno,
277 				irec->br_blockcount);
278 		break;
279 	case XFS_COW_FORK:
280 		xchk_xref_is_cow_staging(info->sc, agbno,
281 				irec->br_blockcount);
282 		break;
283 	}
284 
285 	xchk_ag_free(info->sc, &info->sc->sa);
286 }
287 
288 /*
289  * Directories and attr forks should never have blocks that can't be addressed
290  * by a xfs_dablk_t.
291  */
292 STATIC void
293 xchk_bmap_dirattr_extent(
294 	struct xfs_inode	*ip,
295 	struct xchk_bmap_info	*info,
296 	struct xfs_bmbt_irec	*irec)
297 {
298 	struct xfs_mount	*mp = ip->i_mount;
299 	xfs_fileoff_t		off;
300 
301 	if (!S_ISDIR(VFS_I(ip)->i_mode) && info->whichfork != XFS_ATTR_FORK)
302 		return;
303 
304 	if (!xfs_verify_dablk(mp, irec->br_startoff))
305 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
306 				irec->br_startoff);
307 
308 	off = irec->br_startoff + irec->br_blockcount - 1;
309 	if (!xfs_verify_dablk(mp, off))
310 		xchk_fblock_set_corrupt(info->sc, info->whichfork, off);
311 }
312 
313 /* Scrub a single extent record. */
314 STATIC int
315 xchk_bmap_iextent(
316 	struct xfs_inode	*ip,
317 	struct xchk_bmap_info	*info,
318 	struct xfs_bmbt_irec	*irec)
319 {
320 	struct xfs_mount	*mp = info->sc->mp;
321 	int			error = 0;
322 
323 	/*
324 	 * Check for out-of-order extents.  This record could have come
325 	 * from the incore list, for which there is no ordering check.
326 	 */
327 	if (irec->br_startoff < info->lastoff)
328 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
329 				irec->br_startoff);
330 
331 	if (!xfs_verify_fileext(mp, irec->br_startoff, irec->br_blockcount))
332 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
333 				irec->br_startoff);
334 
335 	xchk_bmap_dirattr_extent(ip, info, irec);
336 
337 	/* There should never be a "hole" extent in either extent list. */
338 	if (irec->br_startblock == HOLESTARTBLOCK)
339 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
340 				irec->br_startoff);
341 
342 	/*
343 	 * Check for delalloc extents.  We never iterate the ones in the
344 	 * in-core extent scan, and we should never see these in the bmbt.
345 	 */
346 	if (isnullstartblock(irec->br_startblock))
347 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
348 				irec->br_startoff);
349 
350 	/* Make sure the extent points to a valid place. */
351 	if (irec->br_blockcount > MAXEXTLEN)
352 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
353 				irec->br_startoff);
354 	if (info->is_rt &&
355 	    !xfs_verify_rtext(mp, irec->br_startblock, irec->br_blockcount))
356 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
357 				irec->br_startoff);
358 	if (!info->is_rt &&
359 	    !xfs_verify_fsbext(mp, irec->br_startblock, irec->br_blockcount))
360 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
361 				irec->br_startoff);
362 
363 	/* We don't allow unwritten extents on attr forks. */
364 	if (irec->br_state == XFS_EXT_UNWRITTEN &&
365 	    info->whichfork == XFS_ATTR_FORK)
366 		xchk_fblock_set_corrupt(info->sc, info->whichfork,
367 				irec->br_startoff);
368 
369 	if (info->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
370 		return 0;
371 
372 	if (info->is_rt)
373 		xchk_bmap_rt_iextent_xref(ip, info, irec);
374 	else
375 		xchk_bmap_iextent_xref(ip, info, irec);
376 
377 	info->lastoff = irec->br_startoff + irec->br_blockcount;
378 	return error;
379 }
380 
381 /* Scrub a bmbt record. */
382 STATIC int
383 xchk_bmapbt_rec(
384 	struct xchk_btree	*bs,
385 	union xfs_btree_rec	*rec)
386 {
387 	struct xfs_bmbt_irec	irec;
388 	struct xfs_bmbt_irec	iext_irec;
389 	struct xfs_iext_cursor	icur;
390 	struct xchk_bmap_info	*info = bs->private;
391 	struct xfs_inode	*ip = bs->cur->bc_ino.ip;
392 	struct xfs_buf		*bp = NULL;
393 	struct xfs_btree_block	*block;
394 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, info->whichfork);
395 	uint64_t		owner;
396 	int			i;
397 
398 	/*
399 	 * Check the owners of the btree blocks up to the level below
400 	 * the root since the verifiers don't do that.
401 	 */
402 	if (xfs_sb_version_hascrc(&bs->cur->bc_mp->m_sb) &&
403 	    bs->cur->bc_ptrs[0] == 1) {
404 		for (i = 0; i < bs->cur->bc_nlevels - 1; i++) {
405 			block = xfs_btree_get_block(bs->cur, i, &bp);
406 			owner = be64_to_cpu(block->bb_u.l.bb_owner);
407 			if (owner != ip->i_ino)
408 				xchk_fblock_set_corrupt(bs->sc,
409 						info->whichfork, 0);
410 		}
411 	}
412 
413 	/*
414 	 * Check that the incore extent tree contains an extent that matches
415 	 * this one exactly.  We validate those cached bmaps later, so we don't
416 	 * need to check them here.  If the incore extent tree was just loaded
417 	 * from disk by the scrubber, we assume that its contents match what's
418 	 * on disk (we still hold the ILOCK) and skip the equivalence check.
419 	 */
420 	if (!info->was_loaded)
421 		return 0;
422 
423 	xfs_bmbt_disk_get_all(&rec->bmbt, &irec);
424 	if (!xfs_iext_lookup_extent(ip, ifp, irec.br_startoff, &icur,
425 				&iext_irec) ||
426 	    irec.br_startoff != iext_irec.br_startoff ||
427 	    irec.br_startblock != iext_irec.br_startblock ||
428 	    irec.br_blockcount != iext_irec.br_blockcount ||
429 	    irec.br_state != iext_irec.br_state)
430 		xchk_fblock_set_corrupt(bs->sc, info->whichfork,
431 				irec.br_startoff);
432 	return 0;
433 }
434 
435 /* Scan the btree records. */
436 STATIC int
437 xchk_bmap_btree(
438 	struct xfs_scrub	*sc,
439 	int			whichfork,
440 	struct xchk_bmap_info	*info)
441 {
442 	struct xfs_owner_info	oinfo;
443 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
444 	struct xfs_mount	*mp = sc->mp;
445 	struct xfs_inode	*ip = sc->ip;
446 	struct xfs_btree_cur	*cur;
447 	int			error;
448 
449 	/* Load the incore bmap cache if it's not loaded. */
450 	info->was_loaded = !xfs_need_iread_extents(ifp);
451 
452 	error = xfs_iread_extents(sc->tp, ip, whichfork);
453 	if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
454 		goto out;
455 
456 	/* Check the btree structure. */
457 	cur = xfs_bmbt_init_cursor(mp, sc->tp, ip, whichfork);
458 	xfs_rmap_ino_bmbt_owner(&oinfo, ip->i_ino, whichfork);
459 	error = xchk_btree(sc, cur, xchk_bmapbt_rec, &oinfo, info);
460 	xfs_btree_del_cursor(cur, error);
461 out:
462 	return error;
463 }
464 
465 struct xchk_bmap_check_rmap_info {
466 	struct xfs_scrub	*sc;
467 	int			whichfork;
468 	struct xfs_iext_cursor	icur;
469 };
470 
471 /* Can we find bmaps that fit this rmap? */
472 STATIC int
473 xchk_bmap_check_rmap(
474 	struct xfs_btree_cur		*cur,
475 	struct xfs_rmap_irec		*rec,
476 	void				*priv)
477 {
478 	struct xfs_bmbt_irec		irec;
479 	struct xchk_bmap_check_rmap_info	*sbcri = priv;
480 	struct xfs_ifork		*ifp;
481 	struct xfs_scrub		*sc = sbcri->sc;
482 	bool				have_map;
483 
484 	/* Is this even the right fork? */
485 	if (rec->rm_owner != sc->ip->i_ino)
486 		return 0;
487 	if ((sbcri->whichfork == XFS_ATTR_FORK) ^
488 	    !!(rec->rm_flags & XFS_RMAP_ATTR_FORK))
489 		return 0;
490 	if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK)
491 		return 0;
492 
493 	/* Now look up the bmbt record. */
494 	ifp = XFS_IFORK_PTR(sc->ip, sbcri->whichfork);
495 	if (!ifp) {
496 		xchk_fblock_set_corrupt(sc, sbcri->whichfork,
497 				rec->rm_offset);
498 		goto out;
499 	}
500 	have_map = xfs_iext_lookup_extent(sc->ip, ifp, rec->rm_offset,
501 			&sbcri->icur, &irec);
502 	if (!have_map)
503 		xchk_fblock_set_corrupt(sc, sbcri->whichfork,
504 				rec->rm_offset);
505 	/*
506 	 * bmap extent record lengths are constrained to 2^21 blocks in length
507 	 * because of space constraints in the on-disk metadata structure.
508 	 * However, rmap extent record lengths are constrained only by AG
509 	 * length, so we have to loop through the bmbt to make sure that the
510 	 * entire rmap is covered by bmbt records.
511 	 */
512 	while (have_map) {
513 		if (irec.br_startoff != rec->rm_offset)
514 			xchk_fblock_set_corrupt(sc, sbcri->whichfork,
515 					rec->rm_offset);
516 		if (irec.br_startblock != XFS_AGB_TO_FSB(sc->mp,
517 				cur->bc_ag.agno, rec->rm_startblock))
518 			xchk_fblock_set_corrupt(sc, sbcri->whichfork,
519 					rec->rm_offset);
520 		if (irec.br_blockcount > rec->rm_blockcount)
521 			xchk_fblock_set_corrupt(sc, sbcri->whichfork,
522 					rec->rm_offset);
523 		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
524 			break;
525 		rec->rm_startblock += irec.br_blockcount;
526 		rec->rm_offset += irec.br_blockcount;
527 		rec->rm_blockcount -= irec.br_blockcount;
528 		if (rec->rm_blockcount == 0)
529 			break;
530 		have_map = xfs_iext_next_extent(ifp, &sbcri->icur, &irec);
531 		if (!have_map)
532 			xchk_fblock_set_corrupt(sc, sbcri->whichfork,
533 					rec->rm_offset);
534 	}
535 
536 out:
537 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
538 		return -ECANCELED;
539 	return 0;
540 }
541 
542 /* Make sure each rmap has a corresponding bmbt entry. */
543 STATIC int
544 xchk_bmap_check_ag_rmaps(
545 	struct xfs_scrub		*sc,
546 	int				whichfork,
547 	xfs_agnumber_t			agno)
548 {
549 	struct xchk_bmap_check_rmap_info	sbcri;
550 	struct xfs_btree_cur		*cur;
551 	struct xfs_buf			*agf;
552 	int				error;
553 
554 	error = xfs_alloc_read_agf(sc->mp, sc->tp, agno, 0, &agf);
555 	if (error)
556 		return error;
557 
558 	cur = xfs_rmapbt_init_cursor(sc->mp, sc->tp, agf, agno);
559 
560 	sbcri.sc = sc;
561 	sbcri.whichfork = whichfork;
562 	error = xfs_rmap_query_all(cur, xchk_bmap_check_rmap, &sbcri);
563 	if (error == -ECANCELED)
564 		error = 0;
565 
566 	xfs_btree_del_cursor(cur, error);
567 	xfs_trans_brelse(sc->tp, agf);
568 	return error;
569 }
570 
571 /* Make sure each rmap has a corresponding bmbt entry. */
572 STATIC int
573 xchk_bmap_check_rmaps(
574 	struct xfs_scrub	*sc,
575 	int			whichfork)
576 {
577 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(sc->ip, whichfork);
578 	xfs_agnumber_t		agno;
579 	bool			zero_size;
580 	int			error;
581 
582 	if (!xfs_sb_version_hasrmapbt(&sc->mp->m_sb) ||
583 	    whichfork == XFS_COW_FORK ||
584 	    (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
585 		return 0;
586 
587 	/* Don't support realtime rmap checks yet. */
588 	if (XFS_IS_REALTIME_INODE(sc->ip) && whichfork == XFS_DATA_FORK)
589 		return 0;
590 
591 	ASSERT(XFS_IFORK_PTR(sc->ip, whichfork) != NULL);
592 
593 	/*
594 	 * Only do this for complex maps that are in btree format, or for
595 	 * situations where we would seem to have a size but zero extents.
596 	 * The inode repair code can zap broken iforks, which means we have
597 	 * to flag this bmap as corrupt if there are rmaps that need to be
598 	 * reattached.
599 	 */
600 
601 	if (whichfork == XFS_DATA_FORK)
602 		zero_size = i_size_read(VFS_I(sc->ip)) == 0;
603 	else
604 		zero_size = false;
605 
606 	if (ifp->if_format != XFS_DINODE_FMT_BTREE &&
607 	    (zero_size || ifp->if_nextents > 0))
608 		return 0;
609 
610 	for (agno = 0; agno < sc->mp->m_sb.sb_agcount; agno++) {
611 		error = xchk_bmap_check_ag_rmaps(sc, whichfork, agno);
612 		if (error)
613 			return error;
614 		if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
615 			break;
616 	}
617 
618 	return 0;
619 }
620 
621 /*
622  * Scrub an inode fork's block mappings.
623  *
624  * First we scan every record in every btree block, if applicable.
625  * Then we unconditionally scan the incore extent cache.
626  */
627 STATIC int
628 xchk_bmap(
629 	struct xfs_scrub	*sc,
630 	int			whichfork)
631 {
632 	struct xfs_bmbt_irec	irec;
633 	struct xchk_bmap_info	info = { NULL };
634 	struct xfs_mount	*mp = sc->mp;
635 	struct xfs_inode	*ip = sc->ip;
636 	struct xfs_ifork	*ifp = XFS_IFORK_PTR(ip, whichfork);
637 	xfs_fileoff_t		endoff;
638 	struct xfs_iext_cursor	icur;
639 	int			error = 0;
640 
641 	/* Non-existent forks can be ignored. */
642 	if (!ifp)
643 		goto out;
644 
645 	info.is_rt = whichfork == XFS_DATA_FORK && XFS_IS_REALTIME_INODE(ip);
646 	info.whichfork = whichfork;
647 	info.is_shared = whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(ip);
648 	info.sc = sc;
649 
650 	switch (whichfork) {
651 	case XFS_COW_FORK:
652 		/* No CoW forks on non-reflink inodes/filesystems. */
653 		if (!xfs_is_reflink_inode(ip)) {
654 			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
655 			goto out;
656 		}
657 		break;
658 	case XFS_ATTR_FORK:
659 		if (!xfs_sb_version_hasattr(&mp->m_sb) &&
660 		    !xfs_sb_version_hasattr2(&mp->m_sb))
661 			xchk_ino_set_corrupt(sc, sc->ip->i_ino);
662 		break;
663 	default:
664 		ASSERT(whichfork == XFS_DATA_FORK);
665 		break;
666 	}
667 
668 	/* Check the fork values */
669 	switch (ifp->if_format) {
670 	case XFS_DINODE_FMT_UUID:
671 	case XFS_DINODE_FMT_DEV:
672 	case XFS_DINODE_FMT_LOCAL:
673 		/* No mappings to check. */
674 		goto out;
675 	case XFS_DINODE_FMT_EXTENTS:
676 		break;
677 	case XFS_DINODE_FMT_BTREE:
678 		if (whichfork == XFS_COW_FORK) {
679 			xchk_fblock_set_corrupt(sc, whichfork, 0);
680 			goto out;
681 		}
682 
683 		error = xchk_bmap_btree(sc, whichfork, &info);
684 		if (error)
685 			goto out;
686 		break;
687 	default:
688 		xchk_fblock_set_corrupt(sc, whichfork, 0);
689 		goto out;
690 	}
691 
692 	if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
693 		goto out;
694 
695 	/* Find the offset of the last extent in the mapping. */
696 	error = xfs_bmap_last_offset(ip, &endoff, whichfork);
697 	if (!xchk_fblock_process_error(sc, whichfork, 0, &error))
698 		goto out;
699 
700 	/* Scrub extent records. */
701 	info.lastoff = 0;
702 	ifp = XFS_IFORK_PTR(ip, whichfork);
703 	for_each_xfs_iext(ifp, &icur, &irec) {
704 		if (xchk_should_terminate(sc, &error) ||
705 		    (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
706 			goto out;
707 		if (isnullstartblock(irec.br_startblock))
708 			continue;
709 		if (irec.br_startoff >= endoff) {
710 			xchk_fblock_set_corrupt(sc, whichfork,
711 					irec.br_startoff);
712 			goto out;
713 		}
714 		error = xchk_bmap_iextent(ip, &info, &irec);
715 		if (error)
716 			goto out;
717 	}
718 
719 	error = xchk_bmap_check_rmaps(sc, whichfork);
720 	if (!xchk_fblock_xref_process_error(sc, whichfork, 0, &error))
721 		goto out;
722 out:
723 	return error;
724 }
725 
726 /* Scrub an inode's data fork. */
727 int
728 xchk_bmap_data(
729 	struct xfs_scrub	*sc)
730 {
731 	return xchk_bmap(sc, XFS_DATA_FORK);
732 }
733 
734 /* Scrub an inode's attr fork. */
735 int
736 xchk_bmap_attr(
737 	struct xfs_scrub	*sc)
738 {
739 	return xchk_bmap(sc, XFS_ATTR_FORK);
740 }
741 
742 /* Scrub an inode's CoW fork. */
743 int
744 xchk_bmap_cow(
745 	struct xfs_scrub	*sc)
746 {
747 	if (!xfs_is_reflink_inode(sc->ip))
748 		return -ENOENT;
749 
750 	return xchk_bmap(sc, XFS_COW_FORK);
751 }
752