xfs_btree.c 26 KB

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