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