xfs_btree.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. /*
  2. * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * This program is distributed in the hope that it would be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write the Free Software Foundation,
  16. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include "xfs.h"
  19. #include "xfs_fs.h"
  20. #include "xfs_types.h"
  21. #include "xfs_bit.h"
  22. #include "xfs_log.h"
  23. #include "xfs_inum.h"
  24. #include "xfs_trans.h"
  25. #include "xfs_sb.h"
  26. #include "xfs_ag.h"
  27. #include "xfs_dir2.h"
  28. #include "xfs_dmapi.h"
  29. #include "xfs_mount.h"
  30. #include "xfs_bmap_btree.h"
  31. #include "xfs_alloc_btree.h"
  32. #include "xfs_ialloc_btree.h"
  33. #include "xfs_dir2_sf.h"
  34. #include "xfs_attr_sf.h"
  35. #include "xfs_dinode.h"
  36. #include "xfs_inode.h"
  37. #include "xfs_btree.h"
  38. #include "xfs_ialloc.h"
  39. #include "xfs_error.h"
  40. /*
  41. * Cursor allocation zone.
  42. */
  43. kmem_zone_t *xfs_btree_cur_zone;
  44. /*
  45. * Btree magic numbers.
  46. */
  47. const __uint32_t xfs_magics[XFS_BTNUM_MAX] = {
  48. XFS_ABTB_MAGIC, XFS_ABTC_MAGIC, XFS_BMAP_MAGIC, XFS_IBT_MAGIC
  49. };
  50. /*
  51. * Checking routine: return maxrecs for the block.
  52. */
  53. STATIC int /* number of records fitting in block */
  54. xfs_btree_maxrecs(
  55. xfs_btree_cur_t *cur, /* btree cursor */
  56. xfs_btree_block_t *block) /* generic btree block pointer */
  57. {
  58. switch (cur->bc_btnum) {
  59. case XFS_BTNUM_BNO:
  60. case XFS_BTNUM_CNT:
  61. return (int)XFS_ALLOC_BLOCK_MAXRECS(
  62. be16_to_cpu(block->bb_level), cur);
  63. case XFS_BTNUM_BMAP:
  64. return (int)XFS_BMAP_BLOCK_IMAXRECS(
  65. be16_to_cpu(block->bb_level), cur);
  66. case XFS_BTNUM_INO:
  67. return (int)XFS_INOBT_BLOCK_MAXRECS(
  68. be16_to_cpu(block->bb_level), cur);
  69. default:
  70. ASSERT(0);
  71. return 0;
  72. }
  73. }
  74. /*
  75. * External routines.
  76. */
  77. #ifdef DEBUG
  78. /*
  79. * Debug routine: check that keys are in the right order.
  80. */
  81. void
  82. xfs_btree_check_key(
  83. xfs_btnum_t btnum, /* btree identifier */
  84. void *ak1, /* pointer to left (lower) key */
  85. void *ak2) /* pointer to right (higher) key */
  86. {
  87. switch (btnum) {
  88. case XFS_BTNUM_BNO: {
  89. xfs_alloc_key_t *k1;
  90. xfs_alloc_key_t *k2;
  91. k1 = ak1;
  92. k2 = ak2;
  93. ASSERT(be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock));
  94. break;
  95. }
  96. case XFS_BTNUM_CNT: {
  97. xfs_alloc_key_t *k1;
  98. xfs_alloc_key_t *k2;
  99. k1 = ak1;
  100. k2 = ak2;
  101. ASSERT(be32_to_cpu(k1->ar_blockcount) < be32_to_cpu(k2->ar_blockcount) ||
  102. (k1->ar_blockcount == k2->ar_blockcount &&
  103. be32_to_cpu(k1->ar_startblock) < be32_to_cpu(k2->ar_startblock)));
  104. break;
  105. }
  106. case XFS_BTNUM_BMAP: {
  107. xfs_bmbt_key_t *k1;
  108. xfs_bmbt_key_t *k2;
  109. k1 = ak1;
  110. k2 = ak2;
  111. ASSERT(be64_to_cpu(k1->br_startoff) < be64_to_cpu(k2->br_startoff));
  112. break;
  113. }
  114. case XFS_BTNUM_INO: {
  115. xfs_inobt_key_t *k1;
  116. xfs_inobt_key_t *k2;
  117. k1 = ak1;
  118. k2 = ak2;
  119. ASSERT(be32_to_cpu(k1->ir_startino) < be32_to_cpu(k2->ir_startino));
  120. break;
  121. }
  122. default:
  123. ASSERT(0);
  124. }
  125. }
  126. /*
  127. * Debug routine: check that records are in the right order.
  128. */
  129. void
  130. xfs_btree_check_rec(
  131. xfs_btnum_t btnum, /* btree identifier */
  132. void *ar1, /* pointer to left (lower) record */
  133. void *ar2) /* pointer to right (higher) record */
  134. {
  135. switch (btnum) {
  136. case XFS_BTNUM_BNO: {
  137. xfs_alloc_rec_t *r1;
  138. xfs_alloc_rec_t *r2;
  139. r1 = ar1;
  140. r2 = ar2;
  141. ASSERT(be32_to_cpu(r1->ar_startblock) +
  142. be32_to_cpu(r1->ar_blockcount) <=
  143. be32_to_cpu(r2->ar_startblock));
  144. break;
  145. }
  146. case XFS_BTNUM_CNT: {
  147. xfs_alloc_rec_t *r1;
  148. xfs_alloc_rec_t *r2;
  149. r1 = ar1;
  150. r2 = ar2;
  151. ASSERT(be32_to_cpu(r1->ar_blockcount) < be32_to_cpu(r2->ar_blockcount) ||
  152. (r1->ar_blockcount == r2->ar_blockcount &&
  153. be32_to_cpu(r1->ar_startblock) < be32_to_cpu(r2->ar_startblock)));
  154. break;
  155. }
  156. case XFS_BTNUM_BMAP: {
  157. xfs_bmbt_rec_t *r1;
  158. xfs_bmbt_rec_t *r2;
  159. r1 = ar1;
  160. r2 = ar2;
  161. ASSERT(xfs_bmbt_disk_get_startoff(r1) +
  162. xfs_bmbt_disk_get_blockcount(r1) <=
  163. xfs_bmbt_disk_get_startoff(r2));
  164. break;
  165. }
  166. case XFS_BTNUM_INO: {
  167. xfs_inobt_rec_t *r1;
  168. xfs_inobt_rec_t *r2;
  169. r1 = ar1;
  170. r2 = ar2;
  171. ASSERT(be32_to_cpu(r1->ir_startino) + XFS_INODES_PER_CHUNK <=
  172. be32_to_cpu(r2->ir_startino));
  173. break;
  174. }
  175. default:
  176. ASSERT(0);
  177. }
  178. }
  179. #endif /* DEBUG */
  180. int /* error (0 or EFSCORRUPTED) */
  181. xfs_btree_check_lblock(
  182. struct xfs_btree_cur *cur, /* btree cursor */
  183. struct xfs_btree_lblock *block, /* btree long form block pointer */
  184. int level, /* level of the btree block */
  185. struct xfs_buf *bp) /* buffer for block, if any */
  186. {
  187. int lblock_ok; /* block passes checks */
  188. struct xfs_mount *mp; /* file system mount point */
  189. mp = cur->bc_mp;
  190. lblock_ok =
  191. be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
  192. be16_to_cpu(block->bb_level) == level &&
  193. be16_to_cpu(block->bb_numrecs) <=
  194. xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
  195. block->bb_leftsib &&
  196. (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO ||
  197. XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_leftsib))) &&
  198. block->bb_rightsib &&
  199. (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO ||
  200. XFS_FSB_SANITY_CHECK(mp, be64_to_cpu(block->bb_rightsib)));
  201. if (unlikely(XFS_TEST_ERROR(!lblock_ok, mp,
  202. XFS_ERRTAG_BTREE_CHECK_LBLOCK,
  203. XFS_RANDOM_BTREE_CHECK_LBLOCK))) {
  204. if (bp)
  205. xfs_buftrace("LBTREE ERROR", bp);
  206. XFS_ERROR_REPORT("xfs_btree_check_lblock", XFS_ERRLEVEL_LOW,
  207. mp);
  208. return XFS_ERROR(EFSCORRUPTED);
  209. }
  210. return 0;
  211. }
  212. int /* error (0 or EFSCORRUPTED) */
  213. xfs_btree_check_sblock(
  214. struct xfs_btree_cur *cur, /* btree cursor */
  215. struct xfs_btree_sblock *block, /* btree short form block pointer */
  216. int level, /* level of the btree block */
  217. struct xfs_buf *bp) /* buffer containing block */
  218. {
  219. struct xfs_buf *agbp; /* buffer for ag. freespace struct */
  220. struct xfs_agf *agf; /* ag. freespace structure */
  221. xfs_agblock_t agflen; /* native ag. freespace length */
  222. int sblock_ok; /* block passes checks */
  223. agbp = cur->bc_private.a.agbp;
  224. agf = XFS_BUF_TO_AGF(agbp);
  225. agflen = be32_to_cpu(agf->agf_length);
  226. sblock_ok =
  227. be32_to_cpu(block->bb_magic) == xfs_magics[cur->bc_btnum] &&
  228. be16_to_cpu(block->bb_level) == level &&
  229. be16_to_cpu(block->bb_numrecs) <=
  230. xfs_btree_maxrecs(cur, (xfs_btree_block_t *)block) &&
  231. (be32_to_cpu(block->bb_leftsib) == NULLAGBLOCK ||
  232. be32_to_cpu(block->bb_leftsib) < agflen) &&
  233. block->bb_leftsib &&
  234. (be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK ||
  235. be32_to_cpu(block->bb_rightsib) < agflen) &&
  236. block->bb_rightsib;
  237. if (unlikely(XFS_TEST_ERROR(!sblock_ok, cur->bc_mp,
  238. XFS_ERRTAG_BTREE_CHECK_SBLOCK,
  239. XFS_RANDOM_BTREE_CHECK_SBLOCK))) {
  240. if (bp)
  241. xfs_buftrace("SBTREE ERROR", bp);
  242. XFS_ERROR_REPORT("xfs_btree_check_sblock", XFS_ERRLEVEL_LOW,
  243. cur->bc_mp);
  244. return XFS_ERROR(EFSCORRUPTED);
  245. }
  246. return 0;
  247. }
  248. /*
  249. * Debug routine: check that block header is ok.
  250. */
  251. int
  252. xfs_btree_check_block(
  253. struct xfs_btree_cur *cur, /* btree cursor */
  254. struct xfs_btree_block *block, /* generic btree block pointer */
  255. int level, /* level of the btree block */
  256. struct xfs_buf *bp) /* buffer containing block, if any */
  257. {
  258. if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
  259. return xfs_btree_check_lblock(cur,
  260. (struct xfs_btree_lblock *)block, level, bp);
  261. } else {
  262. return xfs_btree_check_sblock(cur,
  263. (struct xfs_btree_sblock *)block, level, bp);
  264. }
  265. }
  266. /*
  267. * Check that (long) pointer is ok.
  268. */
  269. int /* error (0 or EFSCORRUPTED) */
  270. xfs_btree_check_lptr(
  271. struct xfs_btree_cur *cur, /* btree cursor */
  272. xfs_dfsbno_t bno, /* btree block disk address */
  273. int level) /* btree block level */
  274. {
  275. XFS_WANT_CORRUPTED_RETURN(
  276. level > 0 &&
  277. bno != NULLDFSBNO &&
  278. XFS_FSB_SANITY_CHECK(cur->bc_mp, bno));
  279. return 0;
  280. }
  281. /*
  282. * Check that (short) pointer is ok.
  283. */
  284. int /* error (0 or EFSCORRUPTED) */
  285. xfs_btree_check_sptr(
  286. struct xfs_btree_cur *cur, /* btree cursor */
  287. xfs_agblock_t bno, /* btree block disk address */
  288. int level) /* btree block level */
  289. {
  290. xfs_agblock_t agblocks = cur->bc_mp->m_sb.sb_agblocks;
  291. XFS_WANT_CORRUPTED_RETURN(
  292. level > 0 &&
  293. bno != NULLAGBLOCK &&
  294. bno != 0 &&
  295. bno < agblocks);
  296. return 0;
  297. }
  298. /*
  299. * Check that block ptr is ok.
  300. */
  301. int /* error (0 or EFSCORRUPTED) */
  302. xfs_btree_check_ptr(
  303. struct xfs_btree_cur *cur, /* btree cursor */
  304. union xfs_btree_ptr *ptr, /* btree block disk address */
  305. int index, /* offset from ptr to check */
  306. int level) /* btree block level */
  307. {
  308. if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
  309. return xfs_btree_check_lptr(cur,
  310. be64_to_cpu((&ptr->l)[index]), level);
  311. } else {
  312. return xfs_btree_check_sptr(cur,
  313. be32_to_cpu((&ptr->s)[index]), level);
  314. }
  315. }
  316. /*
  317. * Delete the btree cursor.
  318. */
  319. void
  320. xfs_btree_del_cursor(
  321. xfs_btree_cur_t *cur, /* btree cursor */
  322. int error) /* del because of error */
  323. {
  324. int i; /* btree level */
  325. /*
  326. * Clear the buffer pointers, and release the buffers.
  327. * If we're doing this in the face of an error, we
  328. * need to make sure to inspect all of the entries
  329. * in the bc_bufs array for buffers to be unlocked.
  330. * This is because some of the btree code works from
  331. * level n down to 0, and if we get an error along
  332. * the way we won't have initialized all the entries
  333. * down to 0.
  334. */
  335. for (i = 0; i < cur->bc_nlevels; i++) {
  336. if (cur->bc_bufs[i])
  337. xfs_btree_setbuf(cur, i, NULL);
  338. else if (!error)
  339. break;
  340. }
  341. /*
  342. * Can't free a bmap cursor without having dealt with the
  343. * allocated indirect blocks' accounting.
  344. */
  345. ASSERT(cur->bc_btnum != XFS_BTNUM_BMAP ||
  346. cur->bc_private.b.allocated == 0);
  347. /*
  348. * Free the cursor.
  349. */
  350. kmem_zone_free(xfs_btree_cur_zone, cur);
  351. }
  352. /*
  353. * Duplicate the btree cursor.
  354. * Allocate a new one, copy the record, re-get the buffers.
  355. */
  356. int /* error */
  357. xfs_btree_dup_cursor(
  358. xfs_btree_cur_t *cur, /* input cursor */
  359. xfs_btree_cur_t **ncur) /* output cursor */
  360. {
  361. xfs_buf_t *bp; /* btree block's buffer pointer */
  362. int error; /* error return value */
  363. int i; /* level number of btree block */
  364. xfs_mount_t *mp; /* mount structure for filesystem */
  365. xfs_btree_cur_t *new; /* new cursor value */
  366. xfs_trans_t *tp; /* transaction pointer, can be NULL */
  367. tp = cur->bc_tp;
  368. mp = cur->bc_mp;
  369. /*
  370. * Allocate a new cursor like the old one.
  371. */
  372. new = cur->bc_ops->dup_cursor(cur);
  373. /*
  374. * Copy the record currently in the cursor.
  375. */
  376. new->bc_rec = cur->bc_rec;
  377. /*
  378. * For each level current, re-get the buffer and copy the ptr value.
  379. */
  380. for (i = 0; i < new->bc_nlevels; i++) {
  381. new->bc_ptrs[i] = cur->bc_ptrs[i];
  382. new->bc_ra[i] = cur->bc_ra[i];
  383. if ((bp = cur->bc_bufs[i])) {
  384. if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
  385. XFS_BUF_ADDR(bp), mp->m_bsize, 0, &bp))) {
  386. xfs_btree_del_cursor(new, error);
  387. *ncur = NULL;
  388. return error;
  389. }
  390. new->bc_bufs[i] = bp;
  391. ASSERT(bp);
  392. ASSERT(!XFS_BUF_GETERROR(bp));
  393. } else
  394. new->bc_bufs[i] = NULL;
  395. }
  396. *ncur = new;
  397. return 0;
  398. }
  399. /*
  400. * Get a the root block which is stored in the inode.
  401. *
  402. * For now this btree implementation assumes the btree root is always
  403. * stored in the if_broot field of an inode fork.
  404. */
  405. STATIC struct xfs_btree_block *
  406. xfs_btree_get_iroot(
  407. struct xfs_btree_cur *cur)
  408. {
  409. struct xfs_ifork *ifp;
  410. ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork);
  411. return (struct xfs_btree_block *)ifp->if_broot;
  412. }
  413. /*
  414. * Retrieve the block pointer from the cursor at the given level.
  415. * This may be an inode btree root or from a buffer.
  416. */
  417. STATIC struct xfs_btree_block * /* generic btree block pointer */
  418. xfs_btree_get_block(
  419. struct xfs_btree_cur *cur, /* btree cursor */
  420. int level, /* level in btree */
  421. struct xfs_buf **bpp) /* buffer containing the block */
  422. {
  423. if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
  424. (level == cur->bc_nlevels - 1)) {
  425. *bpp = NULL;
  426. return xfs_btree_get_iroot(cur);
  427. }
  428. *bpp = cur->bc_bufs[level];
  429. return XFS_BUF_TO_BLOCK(*bpp);
  430. }
  431. /*
  432. * Get a buffer for the block, return it with no data read.
  433. * Long-form addressing.
  434. */
  435. xfs_buf_t * /* buffer for fsbno */
  436. xfs_btree_get_bufl(
  437. xfs_mount_t *mp, /* file system mount point */
  438. xfs_trans_t *tp, /* transaction pointer */
  439. xfs_fsblock_t fsbno, /* file system block number */
  440. uint lock) /* lock flags for get_buf */
  441. {
  442. xfs_buf_t *bp; /* buffer pointer (return value) */
  443. xfs_daddr_t d; /* real disk block address */
  444. ASSERT(fsbno != NULLFSBLOCK);
  445. d = XFS_FSB_TO_DADDR(mp, fsbno);
  446. bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
  447. ASSERT(bp);
  448. ASSERT(!XFS_BUF_GETERROR(bp));
  449. return bp;
  450. }
  451. /*
  452. * Get a buffer for the block, return it with no data read.
  453. * Short-form addressing.
  454. */
  455. xfs_buf_t * /* buffer for agno/agbno */
  456. xfs_btree_get_bufs(
  457. xfs_mount_t *mp, /* file system mount point */
  458. xfs_trans_t *tp, /* transaction pointer */
  459. xfs_agnumber_t agno, /* allocation group number */
  460. xfs_agblock_t agbno, /* allocation group block number */
  461. uint lock) /* lock flags for get_buf */
  462. {
  463. xfs_buf_t *bp; /* buffer pointer (return value) */
  464. xfs_daddr_t d; /* real disk block address */
  465. ASSERT(agno != NULLAGNUMBER);
  466. ASSERT(agbno != NULLAGBLOCK);
  467. d = XFS_AGB_TO_DADDR(mp, agno, agbno);
  468. bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock);
  469. ASSERT(bp);
  470. ASSERT(!XFS_BUF_GETERROR(bp));
  471. return bp;
  472. }
  473. /*
  474. * Check for the cursor referring to the last block at the given level.
  475. */
  476. int /* 1=is last block, 0=not last block */
  477. xfs_btree_islastblock(
  478. xfs_btree_cur_t *cur, /* btree cursor */
  479. int level) /* level to check */
  480. {
  481. xfs_btree_block_t *block; /* generic btree block pointer */
  482. xfs_buf_t *bp; /* buffer containing block */
  483. block = xfs_btree_get_block(cur, level, &bp);
  484. xfs_btree_check_block(cur, block, level, bp);
  485. if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
  486. return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO;
  487. else
  488. return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;
  489. }
  490. /*
  491. * Change the cursor to point to the first record at the given level.
  492. * Other levels are unaffected.
  493. */
  494. int /* success=1, failure=0 */
  495. xfs_btree_firstrec(
  496. xfs_btree_cur_t *cur, /* btree cursor */
  497. int level) /* level to change */
  498. {
  499. xfs_btree_block_t *block; /* generic btree block pointer */
  500. xfs_buf_t *bp; /* buffer containing block */
  501. /*
  502. * Get the block pointer for this level.
  503. */
  504. block = xfs_btree_get_block(cur, level, &bp);
  505. xfs_btree_check_block(cur, block, level, bp);
  506. /*
  507. * It's empty, there is no such record.
  508. */
  509. if (!block->bb_numrecs)
  510. return 0;
  511. /*
  512. * Set the ptr value to 1, that's the first record/key.
  513. */
  514. cur->bc_ptrs[level] = 1;
  515. return 1;
  516. }
  517. /*
  518. * Change the cursor to point to the last record in the current block
  519. * at the given level. Other levels are unaffected.
  520. */
  521. int /* success=1, failure=0 */
  522. xfs_btree_lastrec(
  523. xfs_btree_cur_t *cur, /* btree cursor */
  524. int level) /* level to change */
  525. {
  526. xfs_btree_block_t *block; /* generic btree block pointer */
  527. xfs_buf_t *bp; /* buffer containing block */
  528. /*
  529. * Get the block pointer for this level.
  530. */
  531. block = xfs_btree_get_block(cur, level, &bp);
  532. xfs_btree_check_block(cur, block, level, bp);
  533. /*
  534. * It's empty, there is no such record.
  535. */
  536. if (!block->bb_numrecs)
  537. return 0;
  538. /*
  539. * Set the ptr value to numrecs, that's the last record/key.
  540. */
  541. cur->bc_ptrs[level] = be16_to_cpu(block->bb_numrecs);
  542. return 1;
  543. }
  544. /*
  545. * Compute first and last byte offsets for the fields given.
  546. * Interprets the offsets table, which contains struct field offsets.
  547. */
  548. void
  549. xfs_btree_offsets(
  550. __int64_t fields, /* bitmask of fields */
  551. const short *offsets, /* table of field offsets */
  552. int nbits, /* number of bits to inspect */
  553. int *first, /* output: first byte offset */
  554. int *last) /* output: last byte offset */
  555. {
  556. int i; /* current bit number */
  557. __int64_t imask; /* mask for current bit number */
  558. ASSERT(fields != 0);
  559. /*
  560. * Find the lowest bit, so the first byte offset.
  561. */
  562. for (i = 0, imask = 1LL; ; i++, imask <<= 1) {
  563. if (imask & fields) {
  564. *first = offsets[i];
  565. break;
  566. }
  567. }
  568. /*
  569. * Find the highest bit, so the last byte offset.
  570. */
  571. for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) {
  572. if (imask & fields) {
  573. *last = offsets[i + 1] - 1;
  574. break;
  575. }
  576. }
  577. }
  578. /*
  579. * Get a buffer for the block, return it read in.
  580. * Long-form addressing.
  581. */
  582. int /* error */
  583. xfs_btree_read_bufl(
  584. xfs_mount_t *mp, /* file system mount point */
  585. xfs_trans_t *tp, /* transaction pointer */
  586. xfs_fsblock_t fsbno, /* file system block number */
  587. uint lock, /* lock flags for read_buf */
  588. xfs_buf_t **bpp, /* buffer for fsbno */
  589. int refval) /* ref count value for buffer */
  590. {
  591. xfs_buf_t *bp; /* return value */
  592. xfs_daddr_t d; /* real disk block address */
  593. int error;
  594. ASSERT(fsbno != NULLFSBLOCK);
  595. d = XFS_FSB_TO_DADDR(mp, fsbno);
  596. if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
  597. mp->m_bsize, lock, &bp))) {
  598. return error;
  599. }
  600. ASSERT(!bp || !XFS_BUF_GETERROR(bp));
  601. if (bp != NULL) {
  602. XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
  603. }
  604. *bpp = bp;
  605. return 0;
  606. }
  607. /*
  608. * Get a buffer for the block, return it read in.
  609. * Short-form addressing.
  610. */
  611. int /* error */
  612. xfs_btree_read_bufs(
  613. xfs_mount_t *mp, /* file system mount point */
  614. xfs_trans_t *tp, /* transaction pointer */
  615. xfs_agnumber_t agno, /* allocation group number */
  616. xfs_agblock_t agbno, /* allocation group block number */
  617. uint lock, /* lock flags for read_buf */
  618. xfs_buf_t **bpp, /* buffer for agno/agbno */
  619. int refval) /* ref count value for buffer */
  620. {
  621. xfs_buf_t *bp; /* return value */
  622. xfs_daddr_t d; /* real disk block address */
  623. int error;
  624. ASSERT(agno != NULLAGNUMBER);
  625. ASSERT(agbno != NULLAGBLOCK);
  626. d = XFS_AGB_TO_DADDR(mp, agno, agbno);
  627. if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d,
  628. mp->m_bsize, lock, &bp))) {
  629. return error;
  630. }
  631. ASSERT(!bp || !XFS_BUF_GETERROR(bp));
  632. if (bp != NULL) {
  633. switch (refval) {
  634. case XFS_ALLOC_BTREE_REF:
  635. XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval);
  636. break;
  637. case XFS_INO_BTREE_REF:
  638. XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval);
  639. break;
  640. }
  641. }
  642. *bpp = bp;
  643. return 0;
  644. }
  645. /*
  646. * Read-ahead the block, don't wait for it, don't return a buffer.
  647. * Long-form addressing.
  648. */
  649. /* ARGSUSED */
  650. void
  651. xfs_btree_reada_bufl(
  652. xfs_mount_t *mp, /* file system mount point */
  653. xfs_fsblock_t fsbno, /* file system block number */
  654. xfs_extlen_t count) /* count of filesystem blocks */
  655. {
  656. xfs_daddr_t d;
  657. ASSERT(fsbno != NULLFSBLOCK);
  658. d = XFS_FSB_TO_DADDR(mp, fsbno);
  659. xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
  660. }
  661. /*
  662. * Read-ahead the block, don't wait for it, don't return a buffer.
  663. * Short-form addressing.
  664. */
  665. /* ARGSUSED */
  666. void
  667. xfs_btree_reada_bufs(
  668. xfs_mount_t *mp, /* file system mount point */
  669. xfs_agnumber_t agno, /* allocation group number */
  670. xfs_agblock_t agbno, /* allocation group block number */
  671. xfs_extlen_t count) /* count of filesystem blocks */
  672. {
  673. xfs_daddr_t d;
  674. ASSERT(agno != NULLAGNUMBER);
  675. ASSERT(agbno != NULLAGBLOCK);
  676. d = XFS_AGB_TO_DADDR(mp, agno, agbno);
  677. xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);
  678. }
  679. STATIC int
  680. xfs_btree_readahead_lblock(
  681. struct xfs_btree_cur *cur,
  682. int lr,
  683. struct xfs_btree_block *block)
  684. {
  685. int rval = 0;
  686. xfs_fsblock_t left = be64_to_cpu(block->bb_u.l.bb_leftsib);
  687. xfs_fsblock_t right = be64_to_cpu(block->bb_u.l.bb_rightsib);
  688. if ((lr & XFS_BTCUR_LEFTRA) && left != NULLDFSBNO) {
  689. xfs_btree_reada_bufl(cur->bc_mp, left, 1);
  690. rval++;
  691. }
  692. if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLDFSBNO) {
  693. xfs_btree_reada_bufl(cur->bc_mp, right, 1);
  694. rval++;
  695. }
  696. return rval;
  697. }
  698. STATIC int
  699. xfs_btree_readahead_sblock(
  700. struct xfs_btree_cur *cur,
  701. int lr,
  702. struct xfs_btree_block *block)
  703. {
  704. int rval = 0;
  705. xfs_agblock_t left = be32_to_cpu(block->bb_u.s.bb_leftsib);
  706. xfs_agblock_t right = be32_to_cpu(block->bb_u.s.bb_rightsib);
  707. if ((lr & XFS_BTCUR_LEFTRA) && left != NULLAGBLOCK) {
  708. xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
  709. left, 1);
  710. rval++;
  711. }
  712. if ((lr & XFS_BTCUR_RIGHTRA) && right != NULLAGBLOCK) {
  713. xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno,
  714. right, 1);
  715. rval++;
  716. }
  717. return rval;
  718. }
  719. /*
  720. * Read-ahead btree blocks, at the given level.
  721. * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
  722. */
  723. int
  724. xfs_btree_readahead(
  725. struct xfs_btree_cur *cur, /* btree cursor */
  726. int lev, /* level in btree */
  727. int lr) /* left/right bits */
  728. {
  729. struct xfs_btree_block *block;
  730. /*
  731. * No readahead needed if we are at the root level and the
  732. * btree root is stored in the inode.
  733. */
  734. if ((cur->bc_flags & XFS_BTREE_ROOT_IN_INODE) &&
  735. (lev == cur->bc_nlevels - 1))
  736. return 0;
  737. if ((cur->bc_ra[lev] | lr) == cur->bc_ra[lev])
  738. return 0;
  739. cur->bc_ra[lev] |= lr;
  740. block = XFS_BUF_TO_BLOCK(cur->bc_bufs[lev]);
  741. if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
  742. return xfs_btree_readahead_lblock(cur, lr, block);
  743. return xfs_btree_readahead_sblock(cur, lr, block);
  744. }
  745. /*
  746. * Set the buffer for level "lev" in the cursor to bp, releasing
  747. * any previous buffer.
  748. */
  749. void
  750. xfs_btree_setbuf(
  751. xfs_btree_cur_t *cur, /* btree cursor */
  752. int lev, /* level in btree */
  753. xfs_buf_t *bp) /* new buffer to set */
  754. {
  755. xfs_btree_block_t *b; /* btree block */
  756. xfs_buf_t *obp; /* old buffer pointer */
  757. obp = cur->bc_bufs[lev];
  758. if (obp)
  759. xfs_trans_brelse(cur->bc_tp, obp);
  760. cur->bc_bufs[lev] = bp;
  761. cur->bc_ra[lev] = 0;
  762. if (!bp)
  763. return;
  764. b = XFS_BUF_TO_BLOCK(bp);
  765. if (cur->bc_flags & XFS_BTREE_LONG_PTRS) {
  766. if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO)
  767. cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
  768. if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO)
  769. cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
  770. } else {
  771. if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK)
  772. cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA;
  773. if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK)
  774. cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA;
  775. }
  776. }