PageRenderTime 58ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/fs/xfs/xfs_ialloc_btree.c

https://bitbucket.org/evzijst/gittest
C | 2094 lines | 1348 code | 65 blank | 681 comment | 273 complexity | 6cfe42e8dbc7b9c5788f3b4064a96273 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. * Copyright (c) 2000-2001 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. #include "xfs.h"
  33. #include "xfs_macros.h"
  34. #include "xfs_types.h"
  35. #include "xfs_inum.h"
  36. #include "xfs_log.h"
  37. #include "xfs_trans.h"
  38. #include "xfs_sb.h"
  39. #include "xfs_ag.h"
  40. #include "xfs_dir.h"
  41. #include "xfs_dmapi.h"
  42. #include "xfs_mount.h"
  43. #include "xfs_alloc_btree.h"
  44. #include "xfs_bmap_btree.h"
  45. #include "xfs_ialloc_btree.h"
  46. #include "xfs_btree.h"
  47. #include "xfs_ialloc.h"
  48. #include "xfs_alloc.h"
  49. #include "xfs_error.h"
  50. /*
  51. * Inode allocation management for XFS.
  52. */
  53. /*
  54. * Prototypes for internal functions.
  55. */
  56. STATIC void xfs_inobt_log_block(xfs_trans_t *, xfs_buf_t *, int);
  57. STATIC void xfs_inobt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
  58. STATIC void xfs_inobt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
  59. STATIC void xfs_inobt_log_recs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
  60. STATIC int xfs_inobt_lshift(xfs_btree_cur_t *, int, int *);
  61. STATIC int xfs_inobt_newroot(xfs_btree_cur_t *, int *);
  62. STATIC int xfs_inobt_rshift(xfs_btree_cur_t *, int, int *);
  63. STATIC int xfs_inobt_split(xfs_btree_cur_t *, int, xfs_agblock_t *,
  64. xfs_inobt_key_t *, xfs_btree_cur_t **, int *);
  65. STATIC int xfs_inobt_updkey(xfs_btree_cur_t *, xfs_inobt_key_t *, int);
  66. /*
  67. * Internal functions.
  68. */
  69. /*
  70. * Single level of the xfs_inobt_delete record deletion routine.
  71. * Delete record pointed to by cur/level.
  72. * Remove the record from its block then rebalance the tree.
  73. * Return 0 for error, 1 for done, 2 to go on to the next level.
  74. */
  75. STATIC int /* error */
  76. xfs_inobt_delrec(
  77. xfs_btree_cur_t *cur, /* btree cursor */
  78. int level, /* level removing record from */
  79. int *stat) /* fail/done/go-on */
  80. {
  81. xfs_buf_t *agbp; /* buffer for a.g. inode header */
  82. xfs_mount_t *mp; /* mount structure */
  83. xfs_agi_t *agi; /* allocation group inode header */
  84. xfs_inobt_block_t *block; /* btree block record/key lives in */
  85. xfs_agblock_t bno; /* btree block number */
  86. xfs_buf_t *bp; /* buffer for block */
  87. int error; /* error return value */
  88. int i; /* loop index */
  89. xfs_inobt_key_t key; /* kp points here if block is level 0 */
  90. xfs_inobt_key_t *kp = NULL; /* pointer to btree keys */
  91. xfs_agblock_t lbno; /* left block's block number */
  92. xfs_buf_t *lbp; /* left block's buffer pointer */
  93. xfs_inobt_block_t *left; /* left btree block */
  94. xfs_inobt_key_t *lkp; /* left block key pointer */
  95. xfs_inobt_ptr_t *lpp; /* left block address pointer */
  96. int lrecs = 0; /* number of records in left block */
  97. xfs_inobt_rec_t *lrp; /* left block record pointer */
  98. xfs_inobt_ptr_t *pp = NULL; /* pointer to btree addresses */
  99. int ptr; /* index in btree block for this rec */
  100. xfs_agblock_t rbno; /* right block's block number */
  101. xfs_buf_t *rbp; /* right block's buffer pointer */
  102. xfs_inobt_block_t *right; /* right btree block */
  103. xfs_inobt_key_t *rkp; /* right block key pointer */
  104. xfs_inobt_rec_t *rp; /* pointer to btree records */
  105. xfs_inobt_ptr_t *rpp; /* right block address pointer */
  106. int rrecs = 0; /* number of records in right block */
  107. int numrecs;
  108. xfs_inobt_rec_t *rrp; /* right block record pointer */
  109. xfs_btree_cur_t *tcur; /* temporary btree cursor */
  110. mp = cur->bc_mp;
  111. /*
  112. * Get the index of the entry being deleted, check for nothing there.
  113. */
  114. ptr = cur->bc_ptrs[level];
  115. if (ptr == 0) {
  116. *stat = 0;
  117. return 0;
  118. }
  119. /*
  120. * Get the buffer & block containing the record or key/ptr.
  121. */
  122. bp = cur->bc_bufs[level];
  123. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  124. #ifdef DEBUG
  125. if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
  126. return error;
  127. #endif
  128. /*
  129. * Fail if we're off the end of the block.
  130. */
  131. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  132. if (ptr > numrecs) {
  133. *stat = 0;
  134. return 0;
  135. }
  136. /*
  137. * It's a nonleaf. Excise the key and ptr being deleted, by
  138. * sliding the entries past them down one.
  139. * Log the changed areas of the block.
  140. */
  141. if (level > 0) {
  142. kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
  143. pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
  144. #ifdef DEBUG
  145. for (i = ptr; i < numrecs; i++) {
  146. if ((error = xfs_btree_check_sptr(cur, INT_GET(pp[i], ARCH_CONVERT), level)))
  147. return error;
  148. }
  149. #endif
  150. if (ptr < numrecs) {
  151. memmove(&kp[ptr - 1], &kp[ptr],
  152. (numrecs - ptr) * sizeof(*kp));
  153. memmove(&pp[ptr - 1], &pp[ptr],
  154. (numrecs - ptr) * sizeof(*kp));
  155. xfs_inobt_log_keys(cur, bp, ptr, numrecs - 1);
  156. xfs_inobt_log_ptrs(cur, bp, ptr, numrecs - 1);
  157. }
  158. }
  159. /*
  160. * It's a leaf. Excise the record being deleted, by sliding the
  161. * entries past it down one. Log the changed areas of the block.
  162. */
  163. else {
  164. rp = XFS_INOBT_REC_ADDR(block, 1, cur);
  165. if (ptr < numrecs) {
  166. memmove(&rp[ptr - 1], &rp[ptr],
  167. (numrecs - ptr) * sizeof(*rp));
  168. xfs_inobt_log_recs(cur, bp, ptr, numrecs - 1);
  169. }
  170. /*
  171. * If it's the first record in the block, we'll need a key
  172. * structure to pass up to the next level (updkey).
  173. */
  174. if (ptr == 1) {
  175. key.ir_startino = rp->ir_startino;
  176. kp = &key;
  177. }
  178. }
  179. /*
  180. * Decrement and log the number of entries in the block.
  181. */
  182. numrecs--;
  183. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  184. xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
  185. /*
  186. * Is this the root level? If so, we're almost done.
  187. */
  188. if (level == cur->bc_nlevels - 1) {
  189. /*
  190. * If this is the root level,
  191. * and there's only one entry left,
  192. * and it's NOT the leaf level,
  193. * then we can get rid of this level.
  194. */
  195. if (numrecs == 1 && level > 0) {
  196. agbp = cur->bc_private.i.agbp;
  197. agi = XFS_BUF_TO_AGI(agbp);
  198. /*
  199. * pp is still set to the first pointer in the block.
  200. * Make it the new root of the btree.
  201. */
  202. bno = INT_GET(agi->agi_root, ARCH_CONVERT);
  203. agi->agi_root = *pp;
  204. INT_MOD(agi->agi_level, ARCH_CONVERT, -1);
  205. /*
  206. * Free the block.
  207. */
  208. if ((error = xfs_free_extent(cur->bc_tp,
  209. XFS_AGB_TO_FSB(mp, cur->bc_private.i.agno, bno), 1)))
  210. return error;
  211. xfs_trans_binval(cur->bc_tp, bp);
  212. xfs_ialloc_log_agi(cur->bc_tp, agbp,
  213. XFS_AGI_ROOT | XFS_AGI_LEVEL);
  214. /*
  215. * Update the cursor so there's one fewer level.
  216. */
  217. cur->bc_bufs[level] = NULL;
  218. cur->bc_nlevels--;
  219. } else if (level > 0 &&
  220. (error = xfs_inobt_decrement(cur, level, &i)))
  221. return error;
  222. *stat = 1;
  223. return 0;
  224. }
  225. /*
  226. * If we deleted the leftmost entry in the block, update the
  227. * key values above us in the tree.
  228. */
  229. if (ptr == 1 && (error = xfs_inobt_updkey(cur, kp, level + 1)))
  230. return error;
  231. /*
  232. * If the number of records remaining in the block is at least
  233. * the minimum, we're done.
  234. */
  235. if (numrecs >= XFS_INOBT_BLOCK_MINRECS(level, cur)) {
  236. if (level > 0 &&
  237. (error = xfs_inobt_decrement(cur, level, &i)))
  238. return error;
  239. *stat = 1;
  240. return 0;
  241. }
  242. /*
  243. * Otherwise, we have to move some records around to keep the
  244. * tree balanced. Look at the left and right sibling blocks to
  245. * see if we can re-balance by moving only one record.
  246. */
  247. rbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
  248. lbno = INT_GET(block->bb_leftsib, ARCH_CONVERT);
  249. bno = NULLAGBLOCK;
  250. ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
  251. /*
  252. * Duplicate the cursor so our btree manipulations here won't
  253. * disrupt the next level up.
  254. */
  255. if ((error = xfs_btree_dup_cursor(cur, &tcur)))
  256. return error;
  257. /*
  258. * If there's a right sibling, see if it's ok to shift an entry
  259. * out of it.
  260. */
  261. if (rbno != NULLAGBLOCK) {
  262. /*
  263. * Move the temp cursor to the last entry in the next block.
  264. * Actually any entry but the first would suffice.
  265. */
  266. i = xfs_btree_lastrec(tcur, level);
  267. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  268. if ((error = xfs_inobt_increment(tcur, level, &i)))
  269. goto error0;
  270. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  271. i = xfs_btree_lastrec(tcur, level);
  272. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  273. /*
  274. * Grab a pointer to the block.
  275. */
  276. rbp = tcur->bc_bufs[level];
  277. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  278. #ifdef DEBUG
  279. if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
  280. goto error0;
  281. #endif
  282. /*
  283. * Grab the current block number, for future use.
  284. */
  285. bno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
  286. /*
  287. * If right block is full enough so that removing one entry
  288. * won't make it too empty, and left-shifting an entry out
  289. * of right to us works, we're done.
  290. */
  291. if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >=
  292. XFS_INOBT_BLOCK_MINRECS(level, cur)) {
  293. if ((error = xfs_inobt_lshift(tcur, level, &i)))
  294. goto error0;
  295. if (i) {
  296. ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
  297. XFS_INOBT_BLOCK_MINRECS(level, cur));
  298. xfs_btree_del_cursor(tcur,
  299. XFS_BTREE_NOERROR);
  300. if (level > 0 &&
  301. (error = xfs_inobt_decrement(cur, level,
  302. &i)))
  303. return error;
  304. *stat = 1;
  305. return 0;
  306. }
  307. }
  308. /*
  309. * Otherwise, grab the number of records in right for
  310. * future reference, and fix up the temp cursor to point
  311. * to our block again (last record).
  312. */
  313. rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
  314. if (lbno != NULLAGBLOCK) {
  315. xfs_btree_firstrec(tcur, level);
  316. if ((error = xfs_inobt_decrement(tcur, level, &i)))
  317. goto error0;
  318. }
  319. }
  320. /*
  321. * If there's a left sibling, see if it's ok to shift an entry
  322. * out of it.
  323. */
  324. if (lbno != NULLAGBLOCK) {
  325. /*
  326. * Move the temp cursor to the first entry in the
  327. * previous block.
  328. */
  329. xfs_btree_firstrec(tcur, level);
  330. if ((error = xfs_inobt_decrement(tcur, level, &i)))
  331. goto error0;
  332. xfs_btree_firstrec(tcur, level);
  333. /*
  334. * Grab a pointer to the block.
  335. */
  336. lbp = tcur->bc_bufs[level];
  337. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  338. #ifdef DEBUG
  339. if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
  340. goto error0;
  341. #endif
  342. /*
  343. * Grab the current block number, for future use.
  344. */
  345. bno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
  346. /*
  347. * If left block is full enough so that removing one entry
  348. * won't make it too empty, and right-shifting an entry out
  349. * of left to us works, we're done.
  350. */
  351. if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >=
  352. XFS_INOBT_BLOCK_MINRECS(level, cur)) {
  353. if ((error = xfs_inobt_rshift(tcur, level, &i)))
  354. goto error0;
  355. if (i) {
  356. ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
  357. XFS_INOBT_BLOCK_MINRECS(level, cur));
  358. xfs_btree_del_cursor(tcur,
  359. XFS_BTREE_NOERROR);
  360. if (level == 0)
  361. cur->bc_ptrs[0]++;
  362. *stat = 1;
  363. return 0;
  364. }
  365. }
  366. /*
  367. * Otherwise, grab the number of records in right for
  368. * future reference.
  369. */
  370. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  371. }
  372. /*
  373. * Delete the temp cursor, we're done with it.
  374. */
  375. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  376. /*
  377. * If here, we need to do a join to keep the tree balanced.
  378. */
  379. ASSERT(bno != NULLAGBLOCK);
  380. /*
  381. * See if we can join with the left neighbor block.
  382. */
  383. if (lbno != NULLAGBLOCK &&
  384. lrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
  385. /*
  386. * Set "right" to be the starting block,
  387. * "left" to be the left neighbor.
  388. */
  389. rbno = bno;
  390. right = block;
  391. rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
  392. rbp = bp;
  393. if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
  394. cur->bc_private.i.agno, lbno, 0, &lbp,
  395. XFS_INO_BTREE_REF)))
  396. return error;
  397. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  398. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  399. if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
  400. return error;
  401. }
  402. /*
  403. * If that won't work, see if we can join with the right neighbor block.
  404. */
  405. else if (rbno != NULLAGBLOCK &&
  406. rrecs + numrecs <= XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
  407. /*
  408. * Set "left" to be the starting block,
  409. * "right" to be the right neighbor.
  410. */
  411. lbno = bno;
  412. left = block;
  413. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  414. lbp = bp;
  415. if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
  416. cur->bc_private.i.agno, rbno, 0, &rbp,
  417. XFS_INO_BTREE_REF)))
  418. return error;
  419. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  420. rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
  421. if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
  422. return error;
  423. }
  424. /*
  425. * Otherwise, we can't fix the imbalance.
  426. * Just return. This is probably a logic error, but it's not fatal.
  427. */
  428. else {
  429. if (level > 0 && (error = xfs_inobt_decrement(cur, level, &i)))
  430. return error;
  431. *stat = 1;
  432. return 0;
  433. }
  434. /*
  435. * We're now going to join "left" and "right" by moving all the stuff
  436. * in "right" to "left" and deleting "right".
  437. */
  438. if (level > 0) {
  439. /*
  440. * It's a non-leaf. Move keys and pointers.
  441. */
  442. lkp = XFS_INOBT_KEY_ADDR(left, lrecs + 1, cur);
  443. lpp = XFS_INOBT_PTR_ADDR(left, lrecs + 1, cur);
  444. rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
  445. rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
  446. #ifdef DEBUG
  447. for (i = 0; i < rrecs; i++) {
  448. if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
  449. return error;
  450. }
  451. #endif
  452. memcpy(lkp, rkp, rrecs * sizeof(*lkp));
  453. memcpy(lpp, rpp, rrecs * sizeof(*lpp));
  454. xfs_inobt_log_keys(cur, lbp, lrecs + 1, lrecs + rrecs);
  455. xfs_inobt_log_ptrs(cur, lbp, lrecs + 1, lrecs + rrecs);
  456. } else {
  457. /*
  458. * It's a leaf. Move records.
  459. */
  460. lrp = XFS_INOBT_REC_ADDR(left, lrecs + 1, cur);
  461. rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
  462. memcpy(lrp, rrp, rrecs * sizeof(*lrp));
  463. xfs_inobt_log_recs(cur, lbp, lrecs + 1, lrecs + rrecs);
  464. }
  465. /*
  466. * If we joined with the left neighbor, set the buffer in the
  467. * cursor to the left block, and fix up the index.
  468. */
  469. if (bp != lbp) {
  470. xfs_btree_setbuf(cur, level, lbp);
  471. cur->bc_ptrs[level] += lrecs;
  472. }
  473. /*
  474. * If we joined with the right neighbor and there's a level above
  475. * us, increment the cursor at that level.
  476. */
  477. else if (level + 1 < cur->bc_nlevels &&
  478. (error = xfs_alloc_increment(cur, level + 1, &i)))
  479. return error;
  480. /*
  481. * Fix up the number of records in the surviving block.
  482. */
  483. lrecs += rrecs;
  484. INT_SET(left->bb_numrecs, ARCH_CONVERT, lrecs);
  485. /*
  486. * Fix up the right block pointer in the surviving block, and log it.
  487. */
  488. left->bb_rightsib = right->bb_rightsib;
  489. xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
  490. /*
  491. * If there is a right sibling now, make it point to the
  492. * remaining block.
  493. */
  494. if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
  495. xfs_inobt_block_t *rrblock;
  496. xfs_buf_t *rrbp;
  497. if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
  498. cur->bc_private.i.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0,
  499. &rrbp, XFS_INO_BTREE_REF)))
  500. return error;
  501. rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
  502. if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
  503. return error;
  504. INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno);
  505. xfs_inobt_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
  506. }
  507. /*
  508. * Free the deleting block.
  509. */
  510. if ((error = xfs_free_extent(cur->bc_tp, XFS_AGB_TO_FSB(mp,
  511. cur->bc_private.i.agno, rbno), 1)))
  512. return error;
  513. xfs_trans_binval(cur->bc_tp, rbp);
  514. /*
  515. * Readjust the ptr at this level if it's not a leaf, since it's
  516. * still pointing at the deletion point, which makes the cursor
  517. * inconsistent. If this makes the ptr 0, the caller fixes it up.
  518. * We can't use decrement because it would change the next level up.
  519. */
  520. if (level > 0)
  521. cur->bc_ptrs[level]--;
  522. /*
  523. * Return value means the next level up has something to do.
  524. */
  525. *stat = 2;
  526. return 0;
  527. error0:
  528. xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
  529. return error;
  530. }
  531. /*
  532. * Insert one record/level. Return information to the caller
  533. * allowing the next level up to proceed if necessary.
  534. */
  535. STATIC int /* error */
  536. xfs_inobt_insrec(
  537. xfs_btree_cur_t *cur, /* btree cursor */
  538. int level, /* level to insert record at */
  539. xfs_agblock_t *bnop, /* i/o: block number inserted */
  540. xfs_inobt_rec_t *recp, /* i/o: record data inserted */
  541. xfs_btree_cur_t **curp, /* output: new cursor replacing cur */
  542. int *stat) /* success/failure */
  543. {
  544. xfs_inobt_block_t *block; /* btree block record/key lives in */
  545. xfs_buf_t *bp; /* buffer for block */
  546. int error; /* error return value */
  547. int i; /* loop index */
  548. xfs_inobt_key_t key; /* key value being inserted */
  549. xfs_inobt_key_t *kp=NULL; /* pointer to btree keys */
  550. xfs_agblock_t nbno; /* block number of allocated block */
  551. xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */
  552. xfs_inobt_key_t nkey; /* new key value, from split */
  553. xfs_inobt_rec_t nrec; /* new record value, for caller */
  554. int numrecs;
  555. int optr; /* old ptr value */
  556. xfs_inobt_ptr_t *pp; /* pointer to btree addresses */
  557. int ptr; /* index in btree block for this rec */
  558. xfs_inobt_rec_t *rp=NULL; /* pointer to btree records */
  559. /*
  560. * If we made it to the root level, allocate a new root block
  561. * and we're done.
  562. */
  563. if (level >= cur->bc_nlevels) {
  564. error = xfs_inobt_newroot(cur, &i);
  565. *bnop = NULLAGBLOCK;
  566. *stat = i;
  567. return error;
  568. }
  569. /*
  570. * Make a key out of the record data to be inserted, and save it.
  571. */
  572. key.ir_startino = recp->ir_startino; /* INT_: direct copy */
  573. optr = ptr = cur->bc_ptrs[level];
  574. /*
  575. * If we're off the left edge, return failure.
  576. */
  577. if (ptr == 0) {
  578. *stat = 0;
  579. return 0;
  580. }
  581. /*
  582. * Get pointers to the btree buffer and block.
  583. */
  584. bp = cur->bc_bufs[level];
  585. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  586. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  587. #ifdef DEBUG
  588. if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
  589. return error;
  590. /*
  591. * Check that the new entry is being inserted in the right place.
  592. */
  593. if (ptr <= numrecs) {
  594. if (level == 0) {
  595. rp = XFS_INOBT_REC_ADDR(block, ptr, cur);
  596. xfs_btree_check_rec(cur->bc_btnum, recp, rp);
  597. } else {
  598. kp = XFS_INOBT_KEY_ADDR(block, ptr, cur);
  599. xfs_btree_check_key(cur->bc_btnum, &key, kp);
  600. }
  601. }
  602. #endif
  603. nbno = NULLAGBLOCK;
  604. ncur = (xfs_btree_cur_t *)0;
  605. /*
  606. * If the block is full, we can't insert the new entry until we
  607. * make the block un-full.
  608. */
  609. if (numrecs == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
  610. /*
  611. * First, try shifting an entry to the right neighbor.
  612. */
  613. if ((error = xfs_inobt_rshift(cur, level, &i)))
  614. return error;
  615. if (i) {
  616. /* nothing */
  617. }
  618. /*
  619. * Next, try shifting an entry to the left neighbor.
  620. */
  621. else {
  622. if ((error = xfs_inobt_lshift(cur, level, &i)))
  623. return error;
  624. if (i) {
  625. optr = ptr = cur->bc_ptrs[level];
  626. } else {
  627. /*
  628. * Next, try splitting the current block
  629. * in half. If this works we have to
  630. * re-set our variables because
  631. * we could be in a different block now.
  632. */
  633. if ((error = xfs_inobt_split(cur, level, &nbno,
  634. &nkey, &ncur, &i)))
  635. return error;
  636. if (i) {
  637. bp = cur->bc_bufs[level];
  638. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  639. #ifdef DEBUG
  640. if ((error = xfs_btree_check_sblock(cur,
  641. block, level, bp)))
  642. return error;
  643. #endif
  644. ptr = cur->bc_ptrs[level];
  645. nrec.ir_startino = nkey.ir_startino; /* INT_: direct copy */
  646. } else {
  647. /*
  648. * Otherwise the insert fails.
  649. */
  650. *stat = 0;
  651. return 0;
  652. }
  653. }
  654. }
  655. }
  656. /*
  657. * At this point we know there's room for our new entry in the block
  658. * we're pointing at.
  659. */
  660. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  661. if (level > 0) {
  662. /*
  663. * It's a non-leaf entry. Make a hole for the new data
  664. * in the key and ptr regions of the block.
  665. */
  666. kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
  667. pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
  668. #ifdef DEBUG
  669. for (i = numrecs; i >= ptr; i--) {
  670. if ((error = xfs_btree_check_sptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT), level)))
  671. return error;
  672. }
  673. #endif
  674. memmove(&kp[ptr], &kp[ptr - 1],
  675. (numrecs - ptr + 1) * sizeof(*kp));
  676. memmove(&pp[ptr], &pp[ptr - 1],
  677. (numrecs - ptr + 1) * sizeof(*pp));
  678. /*
  679. * Now stuff the new data in, bump numrecs and log the new data.
  680. */
  681. #ifdef DEBUG
  682. if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
  683. return error;
  684. #endif
  685. kp[ptr - 1] = key; /* INT_: struct copy */
  686. INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
  687. numrecs++;
  688. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  689. xfs_inobt_log_keys(cur, bp, ptr, numrecs);
  690. xfs_inobt_log_ptrs(cur, bp, ptr, numrecs);
  691. } else {
  692. /*
  693. * It's a leaf entry. Make a hole for the new record.
  694. */
  695. rp = XFS_INOBT_REC_ADDR(block, 1, cur);
  696. memmove(&rp[ptr], &rp[ptr - 1],
  697. (numrecs - ptr + 1) * sizeof(*rp));
  698. /*
  699. * Now stuff the new record in, bump numrecs
  700. * and log the new data.
  701. */
  702. rp[ptr - 1] = *recp; /* INT_: struct copy */
  703. numrecs++;
  704. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  705. xfs_inobt_log_recs(cur, bp, ptr, numrecs);
  706. }
  707. /*
  708. * Log the new number of records in the btree header.
  709. */
  710. xfs_inobt_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
  711. #ifdef DEBUG
  712. /*
  713. * Check that the key/record is in the right place, now.
  714. */
  715. if (ptr < numrecs) {
  716. if (level == 0)
  717. xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
  718. rp + ptr);
  719. else
  720. xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
  721. kp + ptr);
  722. }
  723. #endif
  724. /*
  725. * If we inserted at the start of a block, update the parents' keys.
  726. */
  727. if (optr == 1 && (error = xfs_inobt_updkey(cur, &key, level + 1)))
  728. return error;
  729. /*
  730. * Return the new block number, if any.
  731. * If there is one, give back a record value and a cursor too.
  732. */
  733. *bnop = nbno;
  734. if (nbno != NULLAGBLOCK) {
  735. *recp = nrec; /* INT_: struct copy */
  736. *curp = ncur;
  737. }
  738. *stat = 1;
  739. return 0;
  740. }
  741. /*
  742. * Log header fields from a btree block.
  743. */
  744. STATIC void
  745. xfs_inobt_log_block(
  746. xfs_trans_t *tp, /* transaction pointer */
  747. xfs_buf_t *bp, /* buffer containing btree block */
  748. int fields) /* mask of fields: XFS_BB_... */
  749. {
  750. int first; /* first byte offset logged */
  751. int last; /* last byte offset logged */
  752. static const short offsets[] = { /* table of offsets */
  753. offsetof(xfs_inobt_block_t, bb_magic),
  754. offsetof(xfs_inobt_block_t, bb_level),
  755. offsetof(xfs_inobt_block_t, bb_numrecs),
  756. offsetof(xfs_inobt_block_t, bb_leftsib),
  757. offsetof(xfs_inobt_block_t, bb_rightsib),
  758. sizeof(xfs_inobt_block_t)
  759. };
  760. xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
  761. xfs_trans_log_buf(tp, bp, first, last);
  762. }
  763. /*
  764. * Log keys from a btree block (nonleaf).
  765. */
  766. STATIC void
  767. xfs_inobt_log_keys(
  768. xfs_btree_cur_t *cur, /* btree cursor */
  769. xfs_buf_t *bp, /* buffer containing btree block */
  770. int kfirst, /* index of first key to log */
  771. int klast) /* index of last key to log */
  772. {
  773. xfs_inobt_block_t *block; /* btree block to log from */
  774. int first; /* first byte offset logged */
  775. xfs_inobt_key_t *kp; /* key pointer in btree block */
  776. int last; /* last byte offset logged */
  777. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  778. kp = XFS_INOBT_KEY_ADDR(block, 1, cur);
  779. first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
  780. last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
  781. xfs_trans_log_buf(cur->bc_tp, bp, first, last);
  782. }
  783. /*
  784. * Log block pointer fields from a btree block (nonleaf).
  785. */
  786. STATIC void
  787. xfs_inobt_log_ptrs(
  788. xfs_btree_cur_t *cur, /* btree cursor */
  789. xfs_buf_t *bp, /* buffer containing btree block */
  790. int pfirst, /* index of first pointer to log */
  791. int plast) /* index of last pointer to log */
  792. {
  793. xfs_inobt_block_t *block; /* btree block to log from */
  794. int first; /* first byte offset logged */
  795. int last; /* last byte offset logged */
  796. xfs_inobt_ptr_t *pp; /* block-pointer pointer in btree blk */
  797. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  798. pp = XFS_INOBT_PTR_ADDR(block, 1, cur);
  799. first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
  800. last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
  801. xfs_trans_log_buf(cur->bc_tp, bp, first, last);
  802. }
  803. /*
  804. * Log records from a btree block (leaf).
  805. */
  806. STATIC void
  807. xfs_inobt_log_recs(
  808. xfs_btree_cur_t *cur, /* btree cursor */
  809. xfs_buf_t *bp, /* buffer containing btree block */
  810. int rfirst, /* index of first record to log */
  811. int rlast) /* index of last record to log */
  812. {
  813. xfs_inobt_block_t *block; /* btree block to log from */
  814. int first; /* first byte offset logged */
  815. int last; /* last byte offset logged */
  816. xfs_inobt_rec_t *rp; /* record pointer for btree block */
  817. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  818. rp = XFS_INOBT_REC_ADDR(block, 1, cur);
  819. first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
  820. last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
  821. xfs_trans_log_buf(cur->bc_tp, bp, first, last);
  822. }
  823. /*
  824. * Lookup the record. The cursor is made to point to it, based on dir.
  825. * Return 0 if can't find any such record, 1 for success.
  826. */
  827. STATIC int /* error */
  828. xfs_inobt_lookup(
  829. xfs_btree_cur_t *cur, /* btree cursor */
  830. xfs_lookup_t dir, /* <=, ==, or >= */
  831. int *stat) /* success/failure */
  832. {
  833. xfs_agblock_t agbno; /* a.g. relative btree block number */
  834. xfs_agnumber_t agno; /* allocation group number */
  835. xfs_inobt_block_t *block=NULL; /* current btree block */
  836. __int64_t diff; /* difference for the current key */
  837. int error; /* error return value */
  838. int keyno=0; /* current key number */
  839. int level; /* level in the btree */
  840. xfs_mount_t *mp; /* file system mount point */
  841. /*
  842. * Get the allocation group header, and the root block number.
  843. */
  844. mp = cur->bc_mp;
  845. {
  846. xfs_agi_t *agi; /* a.g. inode header */
  847. agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
  848. agno = INT_GET(agi->agi_seqno, ARCH_CONVERT);
  849. agbno = INT_GET(agi->agi_root, ARCH_CONVERT);
  850. }
  851. /*
  852. * Iterate over each level in the btree, starting at the root.
  853. * For each level above the leaves, find the key we need, based
  854. * on the lookup record, then follow the corresponding block
  855. * pointer down to the next level.
  856. */
  857. for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
  858. xfs_buf_t *bp; /* buffer pointer for btree block */
  859. xfs_daddr_t d; /* disk address of btree block */
  860. /*
  861. * Get the disk address we're looking for.
  862. */
  863. d = XFS_AGB_TO_DADDR(mp, agno, agbno);
  864. /*
  865. * If the old buffer at this level is for a different block,
  866. * throw it away, otherwise just use it.
  867. */
  868. bp = cur->bc_bufs[level];
  869. if (bp && XFS_BUF_ADDR(bp) != d)
  870. bp = (xfs_buf_t *)0;
  871. if (!bp) {
  872. /*
  873. * Need to get a new buffer. Read it, then
  874. * set it in the cursor, releasing the old one.
  875. */
  876. if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
  877. agno, agbno, 0, &bp, XFS_INO_BTREE_REF)))
  878. return error;
  879. xfs_btree_setbuf(cur, level, bp);
  880. /*
  881. * Point to the btree block, now that we have the buffer
  882. */
  883. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  884. if ((error = xfs_btree_check_sblock(cur, block, level,
  885. bp)))
  886. return error;
  887. } else
  888. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  889. /*
  890. * If we already had a key match at a higher level, we know
  891. * we need to use the first entry in this block.
  892. */
  893. if (diff == 0)
  894. keyno = 1;
  895. /*
  896. * Otherwise we need to search this block. Do a binary search.
  897. */
  898. else {
  899. int high; /* high entry number */
  900. xfs_inobt_key_t *kkbase=NULL;/* base of keys in block */
  901. xfs_inobt_rec_t *krbase=NULL;/* base of records in block */
  902. int low; /* low entry number */
  903. /*
  904. * Get a pointer to keys or records.
  905. */
  906. if (level > 0)
  907. kkbase = XFS_INOBT_KEY_ADDR(block, 1, cur);
  908. else
  909. krbase = XFS_INOBT_REC_ADDR(block, 1, cur);
  910. /*
  911. * Set low and high entry numbers, 1-based.
  912. */
  913. low = 1;
  914. if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) {
  915. /*
  916. * If the block is empty, the tree must
  917. * be an empty leaf.
  918. */
  919. ASSERT(level == 0 && cur->bc_nlevels == 1);
  920. cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
  921. *stat = 0;
  922. return 0;
  923. }
  924. /*
  925. * Binary search the block.
  926. */
  927. while (low <= high) {
  928. xfs_agino_t startino; /* key value */
  929. /*
  930. * keyno is average of low and high.
  931. */
  932. keyno = (low + high) >> 1;
  933. /*
  934. * Get startino.
  935. */
  936. if (level > 0) {
  937. xfs_inobt_key_t *kkp;
  938. kkp = kkbase + keyno - 1;
  939. startino = INT_GET(kkp->ir_startino, ARCH_CONVERT);
  940. } else {
  941. xfs_inobt_rec_t *krp;
  942. krp = krbase + keyno - 1;
  943. startino = INT_GET(krp->ir_startino, ARCH_CONVERT);
  944. }
  945. /*
  946. * Compute difference to get next direction.
  947. */
  948. diff = (__int64_t)
  949. startino - cur->bc_rec.i.ir_startino;
  950. /*
  951. * Less than, move right.
  952. */
  953. if (diff < 0)
  954. low = keyno + 1;
  955. /*
  956. * Greater than, move left.
  957. */
  958. else if (diff > 0)
  959. high = keyno - 1;
  960. /*
  961. * Equal, we're done.
  962. */
  963. else
  964. break;
  965. }
  966. }
  967. /*
  968. * If there are more levels, set up for the next level
  969. * by getting the block number and filling in the cursor.
  970. */
  971. if (level > 0) {
  972. /*
  973. * If we moved left, need the previous key number,
  974. * unless there isn't one.
  975. */
  976. if (diff > 0 && --keyno < 1)
  977. keyno = 1;
  978. agbno = INT_GET(*XFS_INOBT_PTR_ADDR(block, keyno, cur), ARCH_CONVERT);
  979. #ifdef DEBUG
  980. if ((error = xfs_btree_check_sptr(cur, agbno, level)))
  981. return error;
  982. #endif
  983. cur->bc_ptrs[level] = keyno;
  984. }
  985. }
  986. /*
  987. * Done with the search.
  988. * See if we need to adjust the results.
  989. */
  990. if (dir != XFS_LOOKUP_LE && diff < 0) {
  991. keyno++;
  992. /*
  993. * If ge search and we went off the end of the block, but it's
  994. * not the last block, we're in the wrong block.
  995. */
  996. if (dir == XFS_LOOKUP_GE &&
  997. keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) &&
  998. INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
  999. int i;
  1000. cur->bc_ptrs[0] = keyno;
  1001. if ((error = xfs_inobt_increment(cur, 0, &i)))
  1002. return error;
  1003. ASSERT(i == 1);
  1004. *stat = 1;
  1005. return 0;
  1006. }
  1007. }
  1008. else if (dir == XFS_LOOKUP_LE && diff > 0)
  1009. keyno--;
  1010. cur->bc_ptrs[0] = keyno;
  1011. /*
  1012. * Return if we succeeded or not.
  1013. */
  1014. if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT))
  1015. *stat = 0;
  1016. else
  1017. *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
  1018. return 0;
  1019. }
  1020. /*
  1021. * Move 1 record left from cur/level if possible.
  1022. * Update cur to reflect the new path.
  1023. */
  1024. STATIC int /* error */
  1025. xfs_inobt_lshift(
  1026. xfs_btree_cur_t *cur, /* btree cursor */
  1027. int level, /* level to shift record on */
  1028. int *stat) /* success/failure */
  1029. {
  1030. int error; /* error return value */
  1031. #ifdef DEBUG
  1032. int i; /* loop index */
  1033. #endif
  1034. xfs_inobt_key_t key; /* key value for leaf level upward */
  1035. xfs_buf_t *lbp; /* buffer for left neighbor block */
  1036. xfs_inobt_block_t *left; /* left neighbor btree block */
  1037. xfs_inobt_key_t *lkp=NULL; /* key pointer for left block */
  1038. xfs_inobt_ptr_t *lpp; /* address pointer for left block */
  1039. xfs_inobt_rec_t *lrp=NULL; /* record pointer for left block */
  1040. int nrec; /* new number of left block entries */
  1041. xfs_buf_t *rbp; /* buffer for right (current) block */
  1042. xfs_inobt_block_t *right; /* right (current) btree block */
  1043. xfs_inobt_key_t *rkp=NULL; /* key pointer for right block */
  1044. xfs_inobt_ptr_t *rpp=NULL; /* address pointer for right block */
  1045. xfs_inobt_rec_t *rrp=NULL; /* record pointer for right block */
  1046. /*
  1047. * Set up variables for this block as "right".
  1048. */
  1049. rbp = cur->bc_bufs[level];
  1050. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  1051. #ifdef DEBUG
  1052. if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
  1053. return error;
  1054. #endif
  1055. /*
  1056. * If we've got no left sibling then we can't shift an entry left.
  1057. */
  1058. if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {
  1059. *stat = 0;
  1060. return 0;
  1061. }
  1062. /*
  1063. * If the cursor entry is the one that would be moved, don't
  1064. * do it... it's too complicated.
  1065. */
  1066. if (cur->bc_ptrs[level] <= 1) {
  1067. *stat = 0;
  1068. return 0;
  1069. }
  1070. /*
  1071. * Set up the left neighbor as "left".
  1072. */
  1073. if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
  1074. cur->bc_private.i.agno, INT_GET(right->bb_leftsib, ARCH_CONVERT), 0, &lbp,
  1075. XFS_INO_BTREE_REF)))
  1076. return error;
  1077. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  1078. if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
  1079. return error;
  1080. /*
  1081. * If it's full, it can't take another entry.
  1082. */
  1083. if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
  1084. *stat = 0;
  1085. return 0;
  1086. }
  1087. nrec = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1;
  1088. /*
  1089. * If non-leaf, copy a key and a ptr to the left block.
  1090. */
  1091. if (level > 0) {
  1092. lkp = XFS_INOBT_KEY_ADDR(left, nrec, cur);
  1093. rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
  1094. *lkp = *rkp;
  1095. xfs_inobt_log_keys(cur, lbp, nrec, nrec);
  1096. lpp = XFS_INOBT_PTR_ADDR(left, nrec, cur);
  1097. rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
  1098. #ifdef DEBUG
  1099. if ((error = xfs_btree_check_sptr(cur, INT_GET(*rpp, ARCH_CONVERT), level)))
  1100. return error;
  1101. #endif
  1102. *lpp = *rpp; /* INT_: no-change copy */
  1103. xfs_inobt_log_ptrs(cur, lbp, nrec, nrec);
  1104. }
  1105. /*
  1106. * If leaf, copy a record to the left block.
  1107. */
  1108. else {
  1109. lrp = XFS_INOBT_REC_ADDR(left, nrec, cur);
  1110. rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
  1111. *lrp = *rrp;
  1112. xfs_inobt_log_recs(cur, lbp, nrec, nrec);
  1113. }
  1114. /*
  1115. * Bump and log left's numrecs, decrement and log right's numrecs.
  1116. */
  1117. INT_MOD(left->bb_numrecs, ARCH_CONVERT, +1);
  1118. xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
  1119. #ifdef DEBUG
  1120. if (level > 0)
  1121. xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
  1122. else
  1123. xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp);
  1124. #endif
  1125. INT_MOD(right->bb_numrecs, ARCH_CONVERT, -1);
  1126. xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
  1127. /*
  1128. * Slide the contents of right down one entry.
  1129. */
  1130. if (level > 0) {
  1131. #ifdef DEBUG
  1132. for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
  1133. if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
  1134. level)))
  1135. return error;
  1136. }
  1137. #endif
  1138. memmove(rkp, rkp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
  1139. memmove(rpp, rpp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
  1140. xfs_inobt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1141. xfs_inobt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1142. } else {
  1143. memmove(rrp, rrp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
  1144. xfs_inobt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1145. key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
  1146. rkp = &key;
  1147. }
  1148. /*
  1149. * Update the parent key values of right.
  1150. */
  1151. if ((error = xfs_inobt_updkey(cur, rkp, level + 1)))
  1152. return error;
  1153. /*
  1154. * Slide the cursor value left one.
  1155. */
  1156. cur->bc_ptrs[level]--;
  1157. *stat = 1;
  1158. return 0;
  1159. }
  1160. /*
  1161. * Allocate a new root block, fill it in.
  1162. */
  1163. STATIC int /* error */
  1164. xfs_inobt_newroot(
  1165. xfs_btree_cur_t *cur, /* btree cursor */
  1166. int *stat) /* success/failure */
  1167. {
  1168. xfs_agi_t *agi; /* a.g. inode header */
  1169. xfs_alloc_arg_t args; /* allocation argument structure */
  1170. xfs_inobt_block_t *block; /* one half of the old root block */
  1171. xfs_buf_t *bp; /* buffer containing block */
  1172. int error; /* error return value */
  1173. xfs_inobt_key_t *kp; /* btree key pointer */
  1174. xfs_agblock_t lbno; /* left block number */
  1175. xfs_buf_t *lbp; /* left buffer pointer */
  1176. xfs_inobt_block_t *left; /* left btree block */
  1177. xfs_buf_t *nbp; /* new (root) buffer */
  1178. xfs_inobt_block_t *new; /* new (root) btree block */
  1179. int nptr; /* new value for key index, 1 or 2 */
  1180. xfs_inobt_ptr_t *pp; /* btree address pointer */
  1181. xfs_agblock_t rbno; /* right block number */
  1182. xfs_buf_t *rbp; /* right buffer pointer */
  1183. xfs_inobt_block_t *right; /* right btree block */
  1184. xfs_inobt_rec_t *rp; /* btree record pointer */
  1185. ASSERT(cur->bc_nlevels < XFS_IN_MAXLEVELS(cur->bc_mp));
  1186. /*
  1187. * Get a block & a buffer.
  1188. */
  1189. agi = XFS_BUF_TO_AGI(cur->bc_private.i.agbp);
  1190. args.tp = cur->bc_tp;
  1191. args.mp = cur->bc_mp;
  1192. args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno,
  1193. INT_GET(agi->agi_root, ARCH_CONVERT));
  1194. args.mod = args.minleft = args.alignment = args.total = args.wasdel =
  1195. args.isfl = args.userdata = args.minalignslop = 0;
  1196. args.minlen = args.maxlen = args.prod = 1;
  1197. args.type = XFS_ALLOCTYPE_NEAR_BNO;
  1198. if ((error = xfs_alloc_vextent(&args)))
  1199. return error;
  1200. /*
  1201. * None available, we fail.
  1202. */
  1203. if (args.fsbno == NULLFSBLOCK) {
  1204. *stat = 0;
  1205. return 0;
  1206. }
  1207. ASSERT(args.len == 1);
  1208. nbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0);
  1209. new = XFS_BUF_TO_INOBT_BLOCK(nbp);
  1210. /*
  1211. * Set the root data in the a.g. inode structure.
  1212. */
  1213. INT_SET(agi->agi_root, ARCH_CONVERT, args.agbno);
  1214. INT_MOD(agi->agi_level, ARCH_CONVERT, 1);
  1215. xfs_ialloc_log_agi(args.tp, cur->bc_private.i.agbp,
  1216. XFS_AGI_ROOT | XFS_AGI_LEVEL);
  1217. /*
  1218. * At the previous root level there are now two blocks: the old
  1219. * root, and the new block generated when it was split.
  1220. * We don't know which one the cursor is pointing at, so we
  1221. * set up variables "left" and "right" for each case.
  1222. */
  1223. bp = cur->bc_bufs[cur->bc_nlevels - 1];
  1224. block = XFS_BUF_TO_INOBT_BLOCK(bp);
  1225. #ifdef DEBUG
  1226. if ((error = xfs_btree_check_sblock(cur, block, cur->bc_nlevels - 1, bp)))
  1227. return error;
  1228. #endif
  1229. if (INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
  1230. /*
  1231. * Our block is left, pick up the right block.
  1232. */
  1233. lbp = bp;
  1234. lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp));
  1235. left = block;
  1236. rbno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
  1237. if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
  1238. rbno, 0, &rbp, XFS_INO_BTREE_REF)))
  1239. return error;
  1240. bp = rbp;
  1241. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  1242. if ((error = xfs_btree_check_sblock(cur, right,
  1243. cur->bc_nlevels - 1, rbp)))
  1244. return error;
  1245. nptr = 1;
  1246. } else {
  1247. /*
  1248. * Our block is right, pick up the left block.
  1249. */
  1250. rbp = bp;
  1251. rbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(rbp));
  1252. right = block;
  1253. lbno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
  1254. if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
  1255. lbno, 0, &lbp, XFS_INO_BTREE_REF)))
  1256. return error;
  1257. bp = lbp;
  1258. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  1259. if ((error = xfs_btree_check_sblock(cur, left,
  1260. cur->bc_nlevels - 1, lbp)))
  1261. return error;
  1262. nptr = 2;
  1263. }
  1264. /*
  1265. * Fill in the new block's btree header and log it.
  1266. */
  1267. INT_SET(new->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
  1268. INT_SET(new->bb_level, ARCH_CONVERT, (__uint16_t)cur->bc_nlevels);
  1269. INT_SET(new->bb_numrecs, ARCH_CONVERT, 2);
  1270. INT_SET(new->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
  1271. INT_SET(new->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
  1272. xfs_inobt_log_block(args.tp, nbp, XFS_BB_ALL_BITS);
  1273. ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK);
  1274. /*
  1275. * Fill in the key data in the new root.
  1276. */
  1277. kp = XFS_INOBT_KEY_ADDR(new, 1, cur);
  1278. if (INT_GET(left->bb_level, ARCH_CONVERT) > 0) {
  1279. kp[0] = *XFS_INOBT_KEY_ADDR(left, 1, cur); /* INT_: struct copy */
  1280. kp[1] = *XFS_INOBT_KEY_ADDR(right, 1, cur); /* INT_: struct copy */
  1281. } else {
  1282. rp = XFS_INOBT_REC_ADDR(left, 1, cur);
  1283. INT_COPY(kp[0].ir_startino, rp->ir_startino, ARCH_CONVERT);
  1284. rp = XFS_INOBT_REC_ADDR(right, 1, cur);
  1285. INT_COPY(kp[1].ir_startino, rp->ir_startino, ARCH_CONVERT);
  1286. }
  1287. xfs_inobt_log_keys(cur, nbp, 1, 2);
  1288. /*
  1289. * Fill in the pointer data in the new root.
  1290. */
  1291. pp = XFS_INOBT_PTR_ADDR(new, 1, cur);
  1292. INT_SET(pp[0], ARCH_CONVERT, lbno);
  1293. INT_SET(pp[1], ARCH_CONVERT, rbno);
  1294. xfs_inobt_log_ptrs(cur, nbp, 1, 2);
  1295. /*
  1296. * Fix up the cursor.
  1297. */
  1298. xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
  1299. cur->bc_ptrs[cur->bc_nlevels] = nptr;
  1300. cur->bc_nlevels++;
  1301. *stat = 1;
  1302. return 0;
  1303. }
  1304. /*
  1305. * Move 1 record right from cur/level if possible.
  1306. * Update cur to reflect the new path.
  1307. */
  1308. STATIC int /* error */
  1309. xfs_inobt_rshift(
  1310. xfs_btree_cur_t *cur, /* btree cursor */
  1311. int level, /* level to shift record on */
  1312. int *stat) /* success/failure */
  1313. {
  1314. int error; /* error return value */
  1315. int i; /* loop index */
  1316. xfs_inobt_key_t key; /* key value for leaf level upward */
  1317. xfs_buf_t *lbp; /* buffer for left (current) block */
  1318. xfs_inobt_block_t *left; /* left (current) btree block */
  1319. xfs_inobt_key_t *lkp; /* key pointer for left block */
  1320. xfs_inobt_ptr_t *lpp; /* address pointer for left block */
  1321. xfs_inobt_rec_t *lrp; /* record pointer for left block */
  1322. xfs_buf_t *rbp; /* buffer for right neighbor block */
  1323. xfs_inobt_block_t *right; /* right neighbor btree block */
  1324. xfs_inobt_key_t *rkp; /* key pointer for right block */
  1325. xfs_inobt_ptr_t *rpp; /* address pointer for right block */
  1326. xfs_inobt_rec_t *rrp=NULL; /* record pointer for right block */
  1327. xfs_btree_cur_t *tcur; /* temporary cursor */
  1328. /*
  1329. * Set up variables for this block as "left".
  1330. */
  1331. lbp = cur->bc_bufs[level];
  1332. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  1333. #ifdef DEBUG
  1334. if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
  1335. return error;
  1336. #endif
  1337. /*
  1338. * If we've got no right sibling then we can't shift an entry right.
  1339. */
  1340. if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {
  1341. *stat = 0;
  1342. return 0;
  1343. }
  1344. /*
  1345. * If the cursor entry is the one that would be moved, don't
  1346. * do it... it's too complicated.
  1347. */
  1348. if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) {
  1349. *stat = 0;
  1350. return 0;
  1351. }
  1352. /*
  1353. * Set up the right neighbor as "right".
  1354. */
  1355. if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
  1356. cur->bc_private.i.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, &rbp,
  1357. XFS_INO_BTREE_REF)))
  1358. return error;
  1359. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  1360. if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
  1361. return error;
  1362. /*
  1363. * If it's full, it can't take another entry.
  1364. */
  1365. if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_INOBT_BLOCK_MAXRECS(level, cur)) {
  1366. *stat = 0;
  1367. return 0;
  1368. }
  1369. /*
  1370. * Make a hole at the start of the right neighbor block, then
  1371. * copy the last left block entry to the hole.
  1372. */
  1373. if (level > 0) {
  1374. lkp = XFS_INOBT_KEY_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1375. lpp = XFS_INOBT_PTR_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1376. rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
  1377. rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
  1378. #ifdef DEBUG
  1379. for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) {
  1380. if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
  1381. return error;
  1382. }
  1383. #endif
  1384. memmove(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
  1385. memmove(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
  1386. #ifdef DEBUG
  1387. if ((error = xfs_btree_check_sptr(cur, INT_GET(*lpp, ARCH_CONVERT), level)))
  1388. return error;
  1389. #endif
  1390. *rkp = *lkp; /* INT_: no change copy */
  1391. *rpp = *lpp; /* INT_: no change copy */
  1392. xfs_inobt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1393. xfs_inobt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1394. } else {
  1395. lrp = XFS_INOBT_REC_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1396. rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
  1397. memmove(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
  1398. *rrp = *lrp;
  1399. xfs_inobt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1400. key.ir_startino = rrp->ir_startino; /* INT_: direct copy */
  1401. rkp = &key;
  1402. }
  1403. /*
  1404. * Decrement and log left's numrecs, bump and log right's numrecs.
  1405. */
  1406. INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1);
  1407. xfs_inobt_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
  1408. INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
  1409. #ifdef DEBUG
  1410. if (level > 0)
  1411. xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
  1412. else
  1413. xfs_btree_check_rec(cur->bc_btnum, rrp, rrp + 1);
  1414. #endif
  1415. xfs_inobt_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
  1416. /*
  1417. * Using a temporary cursor, update the parent key values of the
  1418. * block on the right.
  1419. */
  1420. if ((error = xfs_btree_dup_cursor(cur, &tcur)))
  1421. return error;
  1422. xfs_btree_lastrec(tcur, level);
  1423. if ((error = xfs_inobt_increment(tcur, level, &i)) ||
  1424. (error = xfs_inobt_updkey(tcur, rkp, level + 1))) {
  1425. xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
  1426. return error;
  1427. }
  1428. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  1429. *stat = 1;
  1430. return 0;
  1431. }
  1432. /*
  1433. * Split cur/level block in half.
  1434. * Return new block number and its first record (to be inserted into parent).
  1435. */
  1436. STATIC int /* error */
  1437. xfs_inobt_split(
  1438. xfs_btree_cur_t *cur, /* btree cursor */
  1439. int level, /* level to split */
  1440. xfs_agblock_t *bnop, /* output: block number allocated */
  1441. xfs_inobt_key_t *keyp, /* output: first key of new block */
  1442. xfs_btree_cur_t **curp, /* output: new cursor */
  1443. int *stat) /* success/failure */
  1444. {
  1445. xfs_alloc_arg_t args; /* allocation argument structure */
  1446. int error; /* error return value */
  1447. int i; /* loop index/record number */
  1448. xfs_agblock_t lbno; /* left (current) block number */
  1449. xfs_buf_t *lbp; /* buffer for left block */
  1450. xfs_inobt_block_t *left; /* left (current) btree block */
  1451. xfs_inobt_key_t *lkp; /* left btree key pointer */
  1452. xfs_inobt_ptr_t *lpp; /* left btree address pointer */
  1453. xfs_inobt_rec_t *lrp; /* left btree record pointer */
  1454. xfs_buf_t *rbp; /* buffer for right block */
  1455. xfs_inobt_block_t *right; /* right (new) btree block */
  1456. xfs_inobt_key_t *rkp; /* right btree key pointer */
  1457. xfs_inobt_ptr_t *rpp; /* right btree address pointer */
  1458. xfs_inobt_rec_t *rrp; /* right btree record pointer */
  1459. /*
  1460. * Set up left block (current one).
  1461. */
  1462. lbp = cur->bc_bufs[level];
  1463. args.tp = cur->bc_tp;
  1464. args.mp = cur->bc_mp;
  1465. lbno = XFS_DADDR_TO_AGBNO(args.mp, XFS_BUF_ADDR(lbp));
  1466. /*
  1467. * Allocate the new block.
  1468. * If we can't do it, we're toast. Give up.
  1469. */
  1470. args.fsbno = XFS_AGB_TO_FSB(args.mp, cur->bc_private.i.agno, lbno);
  1471. args.mod = args.minleft = args.alignment = args.total = args.wasdel =
  1472. args.isfl = args.userdata = args.minalignslop = 0;
  1473. args.minlen = args.maxlen = args.prod = 1;
  1474. args.type = XFS_ALLOCTYPE_NEAR_BNO;
  1475. if ((error = xfs_alloc_vextent(&args)))
  1476. return error;
  1477. if (args.fsbno == NULLFSBLOCK) {
  1478. *stat = 0;
  1479. return 0;
  1480. }
  1481. ASSERT(args.len == 1);
  1482. rbp = xfs_btree_get_bufs(args.mp, args.tp, args.agno, args.agbno, 0);
  1483. /*
  1484. * Set up the new block as "right".
  1485. */
  1486. right = XFS_BUF_TO_INOBT_BLOCK(rbp);
  1487. /*
  1488. * "Left" is the current (according to the cursor) block.
  1489. */
  1490. left = XFS_BUF_TO_INOBT_BLOCK(lbp);
  1491. #ifdef DEBUG
  1492. if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
  1493. return error;
  1494. #endif
  1495. /*
  1496. * Fill in the btree header for the new block.
  1497. */
  1498. INT_SET(right->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
  1499. right->bb_level = left->bb_level; /* INT_: direct copy */
  1500. INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2));
  1501. /*
  1502. * Make sure that if there's an odd number of entries now, that
  1503. * each new block will have the same number of entries.
  1504. */
  1505. if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) &&
  1506. cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1)
  1507. INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
  1508. i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1;
  1509. /*
  1510. * For non-leaf blocks, copy keys and addresses over to the new block.
  1511. */
  1512. if (level > 0) {
  1513. lkp = XFS_INOBT_KEY_ADDR(left, i, cur);
  1514. lpp = XFS_INOBT_PTR_ADDR(left, i, cur);
  1515. rkp = XFS_INOBT_KEY_ADDR(right, 1, cur);
  1516. rpp = XFS_INOBT_PTR_ADDR(right, 1, cur);
  1517. #ifdef DEBUG
  1518. for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
  1519. if ((error = xfs_btree_check_sptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level)))
  1520. return error;
  1521. }
  1522. #endif
  1523. memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
  1524. memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
  1525. xfs_inobt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1526. xfs_inobt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1527. *keyp = *rkp;
  1528. }
  1529. /*
  1530. * For leaf blocks, copy records over to the new block.
  1531. */
  1532. else {
  1533. lrp = XFS_INOBT_REC_ADDR(left, i, cur);
  1534. rrp = XFS_INOBT_REC_ADDR(right, 1, cur);
  1535. memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
  1536. xfs_inobt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1537. keyp->ir_startino = rrp->ir_startino; /* INT_: direct copy */
  1538. }
  1539. /*
  1540. * Find the left block number by looking in the buffer.
  1541. * Adjust numrecs, sibling pointers.
  1542. */
  1543. INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT)));
  1544. right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */
  1545. INT_SET(left->bb_rightsib, ARCH_CONVERT, args.agbno);
  1546. INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno);
  1547. xfs_inobt_log_block(args.tp, rbp, XFS_BB_ALL_BITS);
  1548. xfs_inobt_log_block(args.tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
  1549. /*
  1550. * If there's a block to the new block's right, make that block
  1551. * point back to right instead of to left.
  1552. */
  1553. if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
  1554. xfs_inobt_block_t *rrblock; /* rr btree block */
  1555. xfs_buf_t *rrbp; /* buffer for rrblock */
  1556. if ((error = xfs_btree_read_bufs(args.mp, args.tp, args.agno,
  1557. INT_GET(right->bb_rightsib, ARCH_CONVERT), 0, &rrbp,
  1558. XFS_INO_BTREE_REF)))
  1559. return error;
  1560. rrblock = XFS_BUF_TO_INOBT_BLOCK(rrbp);
  1561. if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
  1562. return error;
  1563. INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, args.agbno);
  1564. xfs_inobt_log_block(args.tp, rrbp, XFS_BB_LEFTSIB);
  1565. }
  1566. /*
  1567. * If the cursor is really in theā€¦

Large files files are truncated, but you can click here to view the full file