btree.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703
  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_alloc.h"
  20. #include "scrub/scrub.h"
  21. #include "scrub/common.h"
  22. #include "scrub/btree.h"
  23. #include "scrub/trace.h"
  24. /* btree scrubbing */
  25. /*
  26. * Check for btree operation errors. See the section about handling
  27. * operational errors in common.c.
  28. */
  29. static bool
  30. __xchk_btree_process_error(
  31. struct xfs_scrub *sc,
  32. struct xfs_btree_cur *cur,
  33. int level,
  34. int *error,
  35. __u32 errflag,
  36. void *ret_ip)
  37. {
  38. if (*error == 0)
  39. return true;
  40. switch (*error) {
  41. case -EDEADLOCK:
  42. /* Used to restart an op with deadlock avoidance. */
  43. trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
  44. break;
  45. case -EFSBADCRC:
  46. case -EFSCORRUPTED:
  47. /* Note the badness but don't abort. */
  48. sc->sm->sm_flags |= errflag;
  49. *error = 0;
  50. /* fall through */
  51. default:
  52. if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
  53. trace_xchk_ifork_btree_op_error(sc, cur, level,
  54. *error, ret_ip);
  55. else
  56. trace_xchk_btree_op_error(sc, cur, level,
  57. *error, ret_ip);
  58. break;
  59. }
  60. return false;
  61. }
  62. bool
  63. xchk_btree_process_error(
  64. struct xfs_scrub *sc,
  65. struct xfs_btree_cur *cur,
  66. int level,
  67. int *error)
  68. {
  69. return __xchk_btree_process_error(sc, cur, level, error,
  70. XFS_SCRUB_OFLAG_CORRUPT, __return_address);
  71. }
  72. bool
  73. xchk_btree_xref_process_error(
  74. struct xfs_scrub *sc,
  75. struct xfs_btree_cur *cur,
  76. int level,
  77. int *error)
  78. {
  79. return __xchk_btree_process_error(sc, cur, level, error,
  80. XFS_SCRUB_OFLAG_XFAIL, __return_address);
  81. }
  82. /* Record btree block corruption. */
  83. static void
  84. __xchk_btree_set_corrupt(
  85. struct xfs_scrub *sc,
  86. struct xfs_btree_cur *cur,
  87. int level,
  88. __u32 errflag,
  89. void *ret_ip)
  90. {
  91. sc->sm->sm_flags |= errflag;
  92. if (cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
  93. trace_xchk_ifork_btree_error(sc, cur, level,
  94. ret_ip);
  95. else
  96. trace_xchk_btree_error(sc, cur, level,
  97. ret_ip);
  98. }
  99. void
  100. xchk_btree_set_corrupt(
  101. struct xfs_scrub *sc,
  102. struct xfs_btree_cur *cur,
  103. int level)
  104. {
  105. __xchk_btree_set_corrupt(sc, cur, level, XFS_SCRUB_OFLAG_CORRUPT,
  106. __return_address);
  107. }
  108. void
  109. xchk_btree_xref_set_corrupt(
  110. struct xfs_scrub *sc,
  111. struct xfs_btree_cur *cur,
  112. int level)
  113. {
  114. __xchk_btree_set_corrupt(sc, cur, level, XFS_SCRUB_OFLAG_XCORRUPT,
  115. __return_address);
  116. }
  117. /*
  118. * Make sure this record is in order and doesn't stray outside of the parent
  119. * keys.
  120. */
  121. STATIC void
  122. xchk_btree_rec(
  123. struct xchk_btree *bs)
  124. {
  125. struct xfs_btree_cur *cur = bs->cur;
  126. union xfs_btree_rec *rec;
  127. union xfs_btree_key key;
  128. union xfs_btree_key hkey;
  129. union xfs_btree_key *keyp;
  130. struct xfs_btree_block *block;
  131. struct xfs_btree_block *keyblock;
  132. struct xfs_buf *bp;
  133. block = xfs_btree_get_block(cur, 0, &bp);
  134. rec = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
  135. trace_xchk_btree_rec(bs->sc, cur, 0);
  136. /* If this isn't the first record, are they in order? */
  137. if (!bs->firstrec && !cur->bc_ops->recs_inorder(cur, &bs->lastrec, rec))
  138. xchk_btree_set_corrupt(bs->sc, cur, 0);
  139. bs->firstrec = false;
  140. memcpy(&bs->lastrec, rec, cur->bc_ops->rec_len);
  141. if (cur->bc_nlevels == 1)
  142. return;
  143. /* Is this at least as large as the parent low key? */
  144. cur->bc_ops->init_key_from_rec(&key, rec);
  145. keyblock = xfs_btree_get_block(cur, 1, &bp);
  146. keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[1], keyblock);
  147. if (cur->bc_ops->diff_two_keys(cur, &key, keyp) < 0)
  148. xchk_btree_set_corrupt(bs->sc, cur, 1);
  149. if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
  150. return;
  151. /* Is this no larger than the parent high key? */
  152. cur->bc_ops->init_high_key_from_rec(&hkey, rec);
  153. keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[1], keyblock);
  154. if (cur->bc_ops->diff_two_keys(cur, keyp, &hkey) < 0)
  155. xchk_btree_set_corrupt(bs->sc, cur, 1);
  156. }
  157. /*
  158. * Make sure this key is in order and doesn't stray outside of the parent
  159. * keys.
  160. */
  161. STATIC void
  162. xchk_btree_key(
  163. struct xchk_btree *bs,
  164. int level)
  165. {
  166. struct xfs_btree_cur *cur = bs->cur;
  167. union xfs_btree_key *key;
  168. union xfs_btree_key *keyp;
  169. struct xfs_btree_block *block;
  170. struct xfs_btree_block *keyblock;
  171. struct xfs_buf *bp;
  172. block = xfs_btree_get_block(cur, level, &bp);
  173. key = xfs_btree_key_addr(cur, cur->bc_ptrs[level], block);
  174. trace_xchk_btree_key(bs->sc, cur, level);
  175. /* If this isn't the first key, are they in order? */
  176. if (!bs->firstkey[level] &&
  177. !cur->bc_ops->keys_inorder(cur, &bs->lastkey[level], key))
  178. xchk_btree_set_corrupt(bs->sc, cur, level);
  179. bs->firstkey[level] = false;
  180. memcpy(&bs->lastkey[level], key, cur->bc_ops->key_len);
  181. if (level + 1 >= cur->bc_nlevels)
  182. return;
  183. /* Is this at least as large as the parent low key? */
  184. keyblock = xfs_btree_get_block(cur, level + 1, &bp);
  185. keyp = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
  186. if (cur->bc_ops->diff_two_keys(cur, key, keyp) < 0)
  187. xchk_btree_set_corrupt(bs->sc, cur, level);
  188. if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
  189. return;
  190. /* Is this no larger than the parent high key? */
  191. key = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level], block);
  192. keyp = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1], keyblock);
  193. if (cur->bc_ops->diff_two_keys(cur, keyp, key) < 0)
  194. xchk_btree_set_corrupt(bs->sc, cur, level);
  195. }
  196. /*
  197. * Check a btree pointer. Returns true if it's ok to use this pointer.
  198. * Callers do not need to set the corrupt flag.
  199. */
  200. static bool
  201. xchk_btree_ptr_ok(
  202. struct xchk_btree *bs,
  203. int level,
  204. union xfs_btree_ptr *ptr)
  205. {
  206. bool res;
  207. /* A btree rooted in an inode has no block pointer to the root. */
  208. if ((bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
  209. level == bs->cur->bc_nlevels)
  210. return true;
  211. /* Otherwise, check the pointers. */
  212. if (bs->cur->bc_flags & XFS_BTREE_LONG_PTRS)
  213. res = xfs_btree_check_lptr(bs->cur, be64_to_cpu(ptr->l), level);
  214. else
  215. res = xfs_btree_check_sptr(bs->cur, be32_to_cpu(ptr->s), level);
  216. if (!res)
  217. xchk_btree_set_corrupt(bs->sc, bs->cur, level);
  218. return res;
  219. }
  220. /* Check that a btree block's sibling matches what we expect it. */
  221. STATIC int
  222. xchk_btree_block_check_sibling(
  223. struct xchk_btree *bs,
  224. int level,
  225. int direction,
  226. union xfs_btree_ptr *sibling)
  227. {
  228. struct xfs_btree_cur *cur = bs->cur;
  229. struct xfs_btree_block *pblock;
  230. struct xfs_buf *pbp;
  231. struct xfs_btree_cur *ncur = NULL;
  232. union xfs_btree_ptr *pp;
  233. int success;
  234. int error;
  235. error = xfs_btree_dup_cursor(cur, &ncur);
  236. if (!xchk_btree_process_error(bs->sc, cur, level + 1, &error) ||
  237. !ncur)
  238. return error;
  239. /*
  240. * If the pointer is null, we shouldn't be able to move the upper
  241. * level pointer anywhere.
  242. */
  243. if (xfs_btree_ptr_is_null(cur, sibling)) {
  244. if (direction > 0)
  245. error = xfs_btree_increment(ncur, level + 1, &success);
  246. else
  247. error = xfs_btree_decrement(ncur, level + 1, &success);
  248. if (error == 0 && success)
  249. xchk_btree_set_corrupt(bs->sc, cur, level);
  250. error = 0;
  251. goto out;
  252. }
  253. /* Increment upper level pointer. */
  254. if (direction > 0)
  255. error = xfs_btree_increment(ncur, level + 1, &success);
  256. else
  257. error = xfs_btree_decrement(ncur, level + 1, &success);
  258. if (!xchk_btree_process_error(bs->sc, cur, level + 1, &error))
  259. goto out;
  260. if (!success) {
  261. xchk_btree_set_corrupt(bs->sc, cur, level + 1);
  262. goto out;
  263. }
  264. /* Compare upper level pointer to sibling pointer. */
  265. pblock = xfs_btree_get_block(ncur, level + 1, &pbp);
  266. pp = xfs_btree_ptr_addr(ncur, ncur->bc_ptrs[level + 1], pblock);
  267. if (!xchk_btree_ptr_ok(bs, level + 1, pp))
  268. goto out;
  269. if (pbp)
  270. xchk_buffer_recheck(bs->sc, pbp);
  271. if (xfs_btree_diff_two_ptrs(cur, pp, sibling))
  272. xchk_btree_set_corrupt(bs->sc, cur, level);
  273. out:
  274. xfs_btree_del_cursor(ncur, XFS_BTREE_ERROR);
  275. return error;
  276. }
  277. /* Check the siblings of a btree block. */
  278. STATIC int
  279. xchk_btree_block_check_siblings(
  280. struct xchk_btree *bs,
  281. struct xfs_btree_block *block)
  282. {
  283. struct xfs_btree_cur *cur = bs->cur;
  284. union xfs_btree_ptr leftsib;
  285. union xfs_btree_ptr rightsib;
  286. int level;
  287. int error = 0;
  288. xfs_btree_get_sibling(cur, block, &leftsib, XFS_BB_LEFTSIB);
  289. xfs_btree_get_sibling(cur, block, &rightsib, XFS_BB_RIGHTSIB);
  290. level = xfs_btree_get_level(block);
  291. /* Root block should never have siblings. */
  292. if (level == cur->bc_nlevels - 1) {
  293. if (!xfs_btree_ptr_is_null(cur, &leftsib) ||
  294. !xfs_btree_ptr_is_null(cur, &rightsib))
  295. xchk_btree_set_corrupt(bs->sc, cur, level);
  296. goto out;
  297. }
  298. /*
  299. * Does the left & right sibling pointers match the adjacent
  300. * parent level pointers?
  301. * (These function absorbs error codes for us.)
  302. */
  303. error = xchk_btree_block_check_sibling(bs, level, -1, &leftsib);
  304. if (error)
  305. return error;
  306. error = xchk_btree_block_check_sibling(bs, level, 1, &rightsib);
  307. if (error)
  308. return error;
  309. out:
  310. return error;
  311. }
  312. struct check_owner {
  313. struct list_head list;
  314. xfs_daddr_t daddr;
  315. int level;
  316. };
  317. /*
  318. * Make sure this btree block isn't in the free list and that there's
  319. * an rmap record for it.
  320. */
  321. STATIC int
  322. xchk_btree_check_block_owner(
  323. struct xchk_btree *bs,
  324. int level,
  325. xfs_daddr_t daddr)
  326. {
  327. xfs_agnumber_t agno;
  328. xfs_agblock_t agbno;
  329. xfs_btnum_t btnum;
  330. bool init_sa;
  331. int error = 0;
  332. if (!bs->cur)
  333. return 0;
  334. btnum = bs->cur->bc_btnum;
  335. agno = xfs_daddr_to_agno(bs->cur->bc_mp, daddr);
  336. agbno = xfs_daddr_to_agbno(bs->cur->bc_mp, daddr);
  337. init_sa = bs->cur->bc_flags & XFS_BTREE_LONG_PTRS;
  338. if (init_sa) {
  339. error = xchk_ag_init(bs->sc, agno, &bs->sc->sa);
  340. if (!xchk_btree_xref_process_error(bs->sc, bs->cur,
  341. level, &error))
  342. return error;
  343. }
  344. xchk_xref_is_used_space(bs->sc, agbno, 1);
  345. /*
  346. * The bnobt scrubber aliases bs->cur to bs->sc->sa.bno_cur, so we
  347. * have to nullify it (to shut down further block owner checks) if
  348. * self-xref encounters problems.
  349. */
  350. if (!bs->sc->sa.bno_cur && btnum == XFS_BTNUM_BNO)
  351. bs->cur = NULL;
  352. xchk_xref_is_owned_by(bs->sc, agbno, 1, bs->oinfo);
  353. if (!bs->sc->sa.rmap_cur && btnum == XFS_BTNUM_RMAP)
  354. bs->cur = NULL;
  355. if (init_sa)
  356. xchk_ag_free(bs->sc, &bs->sc->sa);
  357. return error;
  358. }
  359. /* Check the owner of a btree block. */
  360. STATIC int
  361. xchk_btree_check_owner(
  362. struct xchk_btree *bs,
  363. int level,
  364. struct xfs_buf *bp)
  365. {
  366. struct xfs_btree_cur *cur = bs->cur;
  367. struct check_owner *co;
  368. if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) && bp == NULL)
  369. return 0;
  370. /*
  371. * We want to cross-reference each btree block with the bnobt
  372. * and the rmapbt. We cannot cross-reference the bnobt or
  373. * rmapbt while scanning the bnobt or rmapbt, respectively,
  374. * because we cannot alter the cursor and we'd prefer not to
  375. * duplicate cursors. Therefore, save the buffer daddr for
  376. * later scanning.
  377. */
  378. if (cur->bc_btnum == XFS_BTNUM_BNO || cur->bc_btnum == XFS_BTNUM_RMAP) {
  379. co = kmem_alloc(sizeof(struct check_owner),
  380. KM_MAYFAIL);
  381. if (!co)
  382. return -ENOMEM;
  383. co->level = level;
  384. co->daddr = XFS_BUF_ADDR(bp);
  385. list_add_tail(&co->list, &bs->to_check);
  386. return 0;
  387. }
  388. return xchk_btree_check_block_owner(bs, level, XFS_BUF_ADDR(bp));
  389. }
  390. /*
  391. * Check that this btree block has at least minrecs records or is one of the
  392. * special blocks that don't require that.
  393. */
  394. STATIC void
  395. xchk_btree_check_minrecs(
  396. struct xchk_btree *bs,
  397. int level,
  398. struct xfs_btree_block *block)
  399. {
  400. unsigned int numrecs;
  401. int ok_level;
  402. numrecs = be16_to_cpu(block->bb_numrecs);
  403. /* More records than minrecs means the block is ok. */
  404. if (numrecs >= bs->cur->bc_ops->get_minrecs(bs->cur, level))
  405. return;
  406. /*
  407. * Certain btree blocks /can/ have fewer than minrecs records. Any
  408. * level greater than or equal to the level of the highest dedicated
  409. * btree block are allowed to violate this constraint.
  410. *
  411. * For a btree rooted in a block, the btree root can have fewer than
  412. * minrecs records. If the btree is rooted in an inode and does not
  413. * store records in the root, the direct children of the root and the
  414. * root itself can have fewer than minrecs records.
  415. */
  416. ok_level = bs->cur->bc_nlevels - 1;
  417. if (bs->cur->bc_flags & XFS_BTREE_ROOT_IN_INODE)
  418. ok_level--;
  419. if (level >= ok_level)
  420. return;
  421. xchk_btree_set_corrupt(bs->sc, bs->cur, level);
  422. }
  423. /*
  424. * Grab and scrub a btree block given a btree pointer. Returns block
  425. * and buffer pointers (if applicable) if they're ok to use.
  426. */
  427. STATIC int
  428. xchk_btree_get_block(
  429. struct xchk_btree *bs,
  430. int level,
  431. union xfs_btree_ptr *pp,
  432. struct xfs_btree_block **pblock,
  433. struct xfs_buf **pbp)
  434. {
  435. xfs_failaddr_t failed_at;
  436. int error;
  437. *pblock = NULL;
  438. *pbp = NULL;
  439. error = xfs_btree_lookup_get_block(bs->cur, level, pp, pblock);
  440. if (!xchk_btree_process_error(bs->sc, bs->cur, level, &error) ||
  441. !*pblock)
  442. return error;
  443. xfs_btree_get_block(bs->cur, level, pbp);
  444. if (bs->cur->bc_flags & XFS_BTREE_LONG_PTRS)
  445. failed_at = __xfs_btree_check_lblock(bs->cur, *pblock,
  446. level, *pbp);
  447. else
  448. failed_at = __xfs_btree_check_sblock(bs->cur, *pblock,
  449. level, *pbp);
  450. if (failed_at) {
  451. xchk_btree_set_corrupt(bs->sc, bs->cur, level);
  452. return 0;
  453. }
  454. if (*pbp)
  455. xchk_buffer_recheck(bs->sc, *pbp);
  456. xchk_btree_check_minrecs(bs, level, *pblock);
  457. /*
  458. * Check the block's owner; this function absorbs error codes
  459. * for us.
  460. */
  461. error = xchk_btree_check_owner(bs, level, *pbp);
  462. if (error)
  463. return error;
  464. /*
  465. * Check the block's siblings; this function absorbs error codes
  466. * for us.
  467. */
  468. return xchk_btree_block_check_siblings(bs, *pblock);
  469. }
  470. /*
  471. * Check that the low and high keys of this block match the keys stored
  472. * in the parent block.
  473. */
  474. STATIC void
  475. xchk_btree_block_keys(
  476. struct xchk_btree *bs,
  477. int level,
  478. struct xfs_btree_block *block)
  479. {
  480. union xfs_btree_key block_keys;
  481. struct xfs_btree_cur *cur = bs->cur;
  482. union xfs_btree_key *high_bk;
  483. union xfs_btree_key *parent_keys;
  484. union xfs_btree_key *high_pk;
  485. struct xfs_btree_block *parent_block;
  486. struct xfs_buf *bp;
  487. if (level >= cur->bc_nlevels - 1)
  488. return;
  489. /* Calculate the keys for this block. */
  490. xfs_btree_get_keys(cur, block, &block_keys);
  491. /* Obtain the parent's copy of the keys for this block. */
  492. parent_block = xfs_btree_get_block(cur, level + 1, &bp);
  493. parent_keys = xfs_btree_key_addr(cur, cur->bc_ptrs[level + 1],
  494. parent_block);
  495. if (cur->bc_ops->diff_two_keys(cur, &block_keys, parent_keys) != 0)
  496. xchk_btree_set_corrupt(bs->sc, cur, 1);
  497. if (!(cur->bc_flags & XFS_BTREE_OVERLAPPING))
  498. return;
  499. /* Get high keys */
  500. high_bk = xfs_btree_high_key_from_key(cur, &block_keys);
  501. high_pk = xfs_btree_high_key_addr(cur, cur->bc_ptrs[level + 1],
  502. parent_block);
  503. if (cur->bc_ops->diff_two_keys(cur, high_bk, high_pk) != 0)
  504. xchk_btree_set_corrupt(bs->sc, cur, 1);
  505. }
  506. /*
  507. * Visit all nodes and leaves of a btree. Check that all pointers and
  508. * records are in order, that the keys reflect the records, and use a callback
  509. * so that the caller can verify individual records.
  510. */
  511. int
  512. xchk_btree(
  513. struct xfs_scrub *sc,
  514. struct xfs_btree_cur *cur,
  515. xchk_btree_rec_fn scrub_fn,
  516. struct xfs_owner_info *oinfo,
  517. void *private)
  518. {
  519. struct xchk_btree bs = { NULL };
  520. union xfs_btree_ptr ptr;
  521. union xfs_btree_ptr *pp;
  522. union xfs_btree_rec *recp;
  523. struct xfs_btree_block *block;
  524. int level;
  525. struct xfs_buf *bp;
  526. struct check_owner *co;
  527. struct check_owner *n;
  528. int i;
  529. int error = 0;
  530. /* Initialize scrub state */
  531. bs.cur = cur;
  532. bs.scrub_rec = scrub_fn;
  533. bs.oinfo = oinfo;
  534. bs.firstrec = true;
  535. bs.private = private;
  536. bs.sc = sc;
  537. for (i = 0; i < XFS_BTREE_MAXLEVELS; i++)
  538. bs.firstkey[i] = true;
  539. INIT_LIST_HEAD(&bs.to_check);
  540. /* Don't try to check a tree with a height we can't handle. */
  541. if (cur->bc_nlevels > XFS_BTREE_MAXLEVELS) {
  542. xchk_btree_set_corrupt(sc, cur, 0);
  543. goto out;
  544. }
  545. /*
  546. * Load the root of the btree. The helper function absorbs
  547. * error codes for us.
  548. */
  549. level = cur->bc_nlevels - 1;
  550. cur->bc_ops->init_ptr_from_cur(cur, &ptr);
  551. if (!xchk_btree_ptr_ok(&bs, cur->bc_nlevels, &ptr))
  552. goto out;
  553. error = xchk_btree_get_block(&bs, level, &ptr, &block, &bp);
  554. if (error || !block)
  555. goto out;
  556. cur->bc_ptrs[level] = 1;
  557. while (level < cur->bc_nlevels) {
  558. block = xfs_btree_get_block(cur, level, &bp);
  559. if (level == 0) {
  560. /* End of leaf, pop back towards the root. */
  561. if (cur->bc_ptrs[level] >
  562. be16_to_cpu(block->bb_numrecs)) {
  563. xchk_btree_block_keys(&bs, level, block);
  564. if (level < cur->bc_nlevels - 1)
  565. cur->bc_ptrs[level + 1]++;
  566. level++;
  567. continue;
  568. }
  569. /* Records in order for scrub? */
  570. xchk_btree_rec(&bs);
  571. /* Call out to the record checker. */
  572. recp = xfs_btree_rec_addr(cur, cur->bc_ptrs[0], block);
  573. error = bs.scrub_rec(&bs, recp);
  574. if (error)
  575. break;
  576. if (xchk_should_terminate(sc, &error) ||
  577. (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT))
  578. break;
  579. cur->bc_ptrs[level]++;
  580. continue;
  581. }
  582. /* End of node, pop back towards the root. */
  583. if (cur->bc_ptrs[level] > be16_to_cpu(block->bb_numrecs)) {
  584. xchk_btree_block_keys(&bs, level, block);
  585. if (level < cur->bc_nlevels - 1)
  586. cur->bc_ptrs[level + 1]++;
  587. level++;
  588. continue;
  589. }
  590. /* Keys in order for scrub? */
  591. xchk_btree_key(&bs, level);
  592. /* Drill another level deeper. */
  593. pp = xfs_btree_ptr_addr(cur, cur->bc_ptrs[level], block);
  594. if (!xchk_btree_ptr_ok(&bs, level, pp)) {
  595. cur->bc_ptrs[level]++;
  596. continue;
  597. }
  598. level--;
  599. error = xchk_btree_get_block(&bs, level, pp, &block, &bp);
  600. if (error || !block)
  601. goto out;
  602. cur->bc_ptrs[level] = 1;
  603. }
  604. out:
  605. /* Process deferred owner checks on btree blocks. */
  606. list_for_each_entry_safe(co, n, &bs.to_check, list) {
  607. if (!error && bs.cur)
  608. error = xchk_btree_check_block_owner(&bs,
  609. co->level, co->daddr);
  610. list_del(&co->list);
  611. kmem_free(co);
  612. }
  613. return error;
  614. }