PageRenderTime 63ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/fs/xfs/xfs_bmap_btree.c

https://bitbucket.org/evzijst/gittest
C | 2807 lines | 2454 code | 115 blank | 238 comment | 389 complexity | 08587f72db288bd87645ba7773483b56 MD5 | raw file
Possible License(s): CC-BY-SA-3.0, GPL-2.0, LGPL-2.0
  1. /*
  2. * Copyright (c) 2000-2003 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_dir2.h"
  42. #include "xfs_dmapi.h"
  43. #include "xfs_mount.h"
  44. #include "xfs_alloc_btree.h"
  45. #include "xfs_bmap_btree.h"
  46. #include "xfs_ialloc_btree.h"
  47. #include "xfs_btree.h"
  48. #include "xfs_ialloc.h"
  49. #include "xfs_itable.h"
  50. #include "xfs_attr_sf.h"
  51. #include "xfs_dir_sf.h"
  52. #include "xfs_dir2_sf.h"
  53. #include "xfs_dinode.h"
  54. #include "xfs_inode_item.h"
  55. #include "xfs_inode.h"
  56. #include "xfs_alloc.h"
  57. #include "xfs_bit.h"
  58. #include "xfs_bmap.h"
  59. #include "xfs_error.h"
  60. #include "xfs_quota.h"
  61. #if defined(XFS_BMBT_TRACE)
  62. ktrace_t *xfs_bmbt_trace_buf;
  63. #endif
  64. /*
  65. * Prototypes for internal btree functions.
  66. */
  67. STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *);
  68. STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int);
  69. STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int);
  70. STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *);
  71. STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *);
  72. STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *,
  73. xfs_bmbt_key_t *, xfs_btree_cur_t **, int *);
  74. STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int);
  75. #if defined(XFS_BMBT_TRACE)
  76. static char ARGS[] = "args";
  77. static char ENTRY[] = "entry";
  78. static char ERROR[] = "error";
  79. #undef EXIT
  80. static char EXIT[] = "exit";
  81. /*
  82. * Add a trace buffer entry for the arguments given to the routine,
  83. * generic form.
  84. */
  85. STATIC void
  86. xfs_bmbt_trace_enter(
  87. char *func,
  88. xfs_btree_cur_t *cur,
  89. char *s,
  90. int type,
  91. int line,
  92. __psunsigned_t a0,
  93. __psunsigned_t a1,
  94. __psunsigned_t a2,
  95. __psunsigned_t a3,
  96. __psunsigned_t a4,
  97. __psunsigned_t a5,
  98. __psunsigned_t a6,
  99. __psunsigned_t a7,
  100. __psunsigned_t a8,
  101. __psunsigned_t a9,
  102. __psunsigned_t a10)
  103. {
  104. xfs_inode_t *ip;
  105. int whichfork;
  106. ip = cur->bc_private.b.ip;
  107. whichfork = cur->bc_private.b.whichfork;
  108. ktrace_enter(xfs_bmbt_trace_buf,
  109. (void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
  110. (void *)func, (void *)s, (void *)ip, (void *)cur,
  111. (void *)a0, (void *)a1, (void *)a2, (void *)a3,
  112. (void *)a4, (void *)a5, (void *)a6, (void *)a7,
  113. (void *)a8, (void *)a9, (void *)a10);
  114. ASSERT(ip->i_btrace);
  115. ktrace_enter(ip->i_btrace,
  116. (void *)((__psint_t)type | (whichfork << 8) | (line << 16)),
  117. (void *)func, (void *)s, (void *)ip, (void *)cur,
  118. (void *)a0, (void *)a1, (void *)a2, (void *)a3,
  119. (void *)a4, (void *)a5, (void *)a6, (void *)a7,
  120. (void *)a8, (void *)a9, (void *)a10);
  121. }
  122. /*
  123. * Add a trace buffer entry for arguments, for a buffer & 1 integer arg.
  124. */
  125. STATIC void
  126. xfs_bmbt_trace_argbi(
  127. char *func,
  128. xfs_btree_cur_t *cur,
  129. xfs_buf_t *b,
  130. int i,
  131. int line)
  132. {
  133. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line,
  134. (__psunsigned_t)b, i, 0, 0,
  135. 0, 0, 0, 0,
  136. 0, 0, 0);
  137. }
  138. /*
  139. * Add a trace buffer entry for arguments, for a buffer & 2 integer args.
  140. */
  141. STATIC void
  142. xfs_bmbt_trace_argbii(
  143. char *func,
  144. xfs_btree_cur_t *cur,
  145. xfs_buf_t *b,
  146. int i0,
  147. int i1,
  148. int line)
  149. {
  150. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line,
  151. (__psunsigned_t)b, i0, i1, 0,
  152. 0, 0, 0, 0,
  153. 0, 0, 0);
  154. }
  155. /*
  156. * Add a trace buffer entry for arguments, for 3 block-length args
  157. * and an integer arg.
  158. */
  159. STATIC void
  160. xfs_bmbt_trace_argfffi(
  161. char *func,
  162. xfs_btree_cur_t *cur,
  163. xfs_dfiloff_t o,
  164. xfs_dfsbno_t b,
  165. xfs_dfilblks_t i,
  166. int j,
  167. int line)
  168. {
  169. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line,
  170. o >> 32, (int)o, b >> 32, (int)b,
  171. i >> 32, (int)i, (int)j, 0,
  172. 0, 0, 0);
  173. }
  174. /*
  175. * Add a trace buffer entry for arguments, for one integer arg.
  176. */
  177. STATIC void
  178. xfs_bmbt_trace_argi(
  179. char *func,
  180. xfs_btree_cur_t *cur,
  181. int i,
  182. int line)
  183. {
  184. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line,
  185. i, 0, 0, 0,
  186. 0, 0, 0, 0,
  187. 0, 0, 0);
  188. }
  189. /*
  190. * Add a trace buffer entry for arguments, for int, fsblock, key.
  191. */
  192. STATIC void
  193. xfs_bmbt_trace_argifk(
  194. char *func,
  195. xfs_btree_cur_t *cur,
  196. int i,
  197. xfs_fsblock_t f,
  198. xfs_bmbt_key_t *k,
  199. int line)
  200. {
  201. xfs_dfsbno_t d;
  202. xfs_dfiloff_t o;
  203. d = (xfs_dfsbno_t)f;
  204. o = INT_GET(k->br_startoff, ARCH_CONVERT);
  205. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
  206. i, d >> 32, (int)d, o >> 32,
  207. (int)o, 0, 0, 0,
  208. 0, 0, 0);
  209. }
  210. /*
  211. * Add a trace buffer entry for arguments, for int, fsblock, rec.
  212. */
  213. STATIC void
  214. xfs_bmbt_trace_argifr(
  215. char *func,
  216. xfs_btree_cur_t *cur,
  217. int i,
  218. xfs_fsblock_t f,
  219. xfs_bmbt_rec_t *r,
  220. int line)
  221. {
  222. xfs_dfsbno_t b;
  223. xfs_dfilblks_t c;
  224. xfs_dfsbno_t d;
  225. xfs_dfiloff_t o;
  226. xfs_bmbt_irec_t s;
  227. d = (xfs_dfsbno_t)f;
  228. xfs_bmbt_disk_get_all(r, &s);
  229. o = (xfs_dfiloff_t)s.br_startoff;
  230. b = (xfs_dfsbno_t)s.br_startblock;
  231. c = s.br_blockcount;
  232. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line,
  233. i, d >> 32, (int)d, o >> 32,
  234. (int)o, b >> 32, (int)b, c >> 32,
  235. (int)c, 0, 0);
  236. }
  237. /*
  238. * Add a trace buffer entry for arguments, for int, key.
  239. */
  240. STATIC void
  241. xfs_bmbt_trace_argik(
  242. char *func,
  243. xfs_btree_cur_t *cur,
  244. int i,
  245. xfs_bmbt_key_t *k,
  246. int line)
  247. {
  248. xfs_dfiloff_t o;
  249. o = INT_GET(k->br_startoff, ARCH_CONVERT);
  250. xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line,
  251. i, o >> 32, (int)o, 0,
  252. 0, 0, 0, 0,
  253. 0, 0, 0);
  254. }
  255. /*
  256. * Add a trace buffer entry for the cursor/operation.
  257. */
  258. STATIC void
  259. xfs_bmbt_trace_cursor(
  260. char *func,
  261. xfs_btree_cur_t *cur,
  262. char *s,
  263. int line)
  264. {
  265. xfs_bmbt_rec_t r;
  266. xfs_bmbt_set_all(&r, &cur->bc_rec.b);
  267. xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line,
  268. (cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) |
  269. cur->bc_private.b.allocated,
  270. INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT),
  271. (unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1],
  272. (unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3],
  273. (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1],
  274. (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]);
  275. }
  276. #define XFS_BMBT_TRACE_ARGBI(c,b,i) \
  277. xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__)
  278. #define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \
  279. xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__)
  280. #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \
  281. xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__)
  282. #define XFS_BMBT_TRACE_ARGI(c,i) \
  283. xfs_bmbt_trace_argi(fname, c, i, __LINE__)
  284. #define XFS_BMBT_TRACE_ARGIFK(c,i,f,k) \
  285. xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__)
  286. #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \
  287. xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__)
  288. #define XFS_BMBT_TRACE_ARGIK(c,i,k) \
  289. xfs_bmbt_trace_argik(fname, c, i, k, __LINE__)
  290. #define XFS_BMBT_TRACE_CURSOR(c,s) \
  291. xfs_bmbt_trace_cursor(fname, c, s, __LINE__)
  292. #else
  293. #define XFS_BMBT_TRACE_ARGBI(c,b,i)
  294. #define XFS_BMBT_TRACE_ARGBII(c,b,i,j)
  295. #define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j)
  296. #define XFS_BMBT_TRACE_ARGI(c,i)
  297. #define XFS_BMBT_TRACE_ARGIFK(c,i,f,k)
  298. #define XFS_BMBT_TRACE_ARGIFR(c,i,f,r)
  299. #define XFS_BMBT_TRACE_ARGIK(c,i,k)
  300. #define XFS_BMBT_TRACE_CURSOR(c,s)
  301. #endif /* XFS_BMBT_TRACE */
  302. /*
  303. * Internal functions.
  304. */
  305. /*
  306. * Delete record pointed to by cur/level.
  307. */
  308. STATIC int /* error */
  309. xfs_bmbt_delrec(
  310. xfs_btree_cur_t *cur,
  311. int level,
  312. int *stat) /* success/failure */
  313. {
  314. xfs_bmbt_block_t *block; /* bmap btree block */
  315. xfs_fsblock_t bno; /* fs-relative block number */
  316. xfs_buf_t *bp; /* buffer for block */
  317. int error; /* error return value */
  318. #ifdef XFS_BMBT_TRACE
  319. static char fname[] = "xfs_bmbt_delrec";
  320. #endif
  321. int i; /* loop counter */
  322. int j; /* temp state */
  323. xfs_bmbt_key_t key; /* bmap btree key */
  324. xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */
  325. xfs_fsblock_t lbno; /* left sibling block number */
  326. xfs_buf_t *lbp; /* left buffer pointer */
  327. xfs_bmbt_block_t *left; /* left btree block */
  328. xfs_bmbt_key_t *lkp; /* left btree key */
  329. xfs_bmbt_ptr_t *lpp; /* left address pointer */
  330. int lrecs=0; /* left record count */
  331. xfs_bmbt_rec_t *lrp; /* left record pointer */
  332. xfs_mount_t *mp; /* file system mount point */
  333. xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */
  334. int ptr; /* key/record index */
  335. xfs_fsblock_t rbno; /* right sibling block number */
  336. xfs_buf_t *rbp; /* right buffer pointer */
  337. xfs_bmbt_block_t *right; /* right btree block */
  338. xfs_bmbt_key_t *rkp; /* right btree key */
  339. xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */
  340. xfs_bmbt_ptr_t *rpp; /* right address pointer */
  341. xfs_bmbt_block_t *rrblock; /* right-right btree block */
  342. xfs_buf_t *rrbp; /* right-right buffer pointer */
  343. int rrecs=0; /* right record count */
  344. xfs_bmbt_rec_t *rrp; /* right record pointer */
  345. xfs_btree_cur_t *tcur; /* temporary btree cursor */
  346. int numrecs; /* temporary numrec count */
  347. int numlrecs, numrrecs;
  348. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  349. XFS_BMBT_TRACE_ARGI(cur, level);
  350. ptr = cur->bc_ptrs[level];
  351. tcur = (xfs_btree_cur_t *)0;
  352. if (ptr == 0) {
  353. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  354. *stat = 0;
  355. return 0;
  356. }
  357. block = xfs_bmbt_get_block(cur, level, &bp);
  358. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  359. #ifdef DEBUG
  360. if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
  361. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  362. goto error0;
  363. }
  364. #endif
  365. if (ptr > numrecs) {
  366. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  367. *stat = 0;
  368. return 0;
  369. }
  370. XFS_STATS_INC(xs_bmbt_delrec);
  371. if (level > 0) {
  372. kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
  373. pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
  374. #ifdef DEBUG
  375. for (i = ptr; i < numrecs; i++) {
  376. if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
  377. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  378. goto error0;
  379. }
  380. }
  381. #endif
  382. if (ptr < numrecs) {
  383. memmove(&kp[ptr - 1], &kp[ptr],
  384. (numrecs - ptr) * sizeof(*kp));
  385. memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */
  386. (numrecs - ptr) * sizeof(*pp));
  387. xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1);
  388. xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1);
  389. }
  390. } else {
  391. rp = XFS_BMAP_REC_IADDR(block, 1, cur);
  392. if (ptr < numrecs) {
  393. memmove(&rp[ptr - 1], &rp[ptr],
  394. (numrecs - ptr) * sizeof(*rp));
  395. xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1);
  396. }
  397. if (ptr == 1) {
  398. INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp));
  399. kp = &key;
  400. }
  401. }
  402. numrecs--;
  403. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  404. xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
  405. /*
  406. * We're at the root level.
  407. * First, shrink the root block in-memory.
  408. * Try to get rid of the next level down.
  409. * If we can't then there's nothing left to do.
  410. */
  411. if (level == cur->bc_nlevels - 1) {
  412. xfs_iroot_realloc(cur->bc_private.b.ip, -1,
  413. cur->bc_private.b.whichfork);
  414. if ((error = xfs_bmbt_killroot(cur))) {
  415. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  416. goto error0;
  417. }
  418. if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
  419. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  420. goto error0;
  421. }
  422. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  423. *stat = 1;
  424. return 0;
  425. }
  426. if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) {
  427. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  428. goto error0;
  429. }
  430. if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
  431. if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) {
  432. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  433. goto error0;
  434. }
  435. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  436. *stat = 1;
  437. return 0;
  438. }
  439. rbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
  440. lbno = INT_GET(block->bb_leftsib, ARCH_CONVERT);
  441. /*
  442. * One child of root, need to get a chance to copy its contents
  443. * into the root and delete it. Can't go up to next level,
  444. * there's nothing to delete there.
  445. */
  446. if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK &&
  447. level == cur->bc_nlevels - 2) {
  448. if ((error = xfs_bmbt_killroot(cur))) {
  449. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  450. goto error0;
  451. }
  452. if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
  453. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  454. goto error0;
  455. }
  456. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  457. *stat = 1;
  458. return 0;
  459. }
  460. ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK);
  461. if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
  462. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  463. goto error0;
  464. }
  465. bno = NULLFSBLOCK;
  466. if (rbno != NULLFSBLOCK) {
  467. i = xfs_btree_lastrec(tcur, level);
  468. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  469. if ((error = xfs_bmbt_increment(tcur, level, &i))) {
  470. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  471. goto error0;
  472. }
  473. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  474. i = xfs_btree_lastrec(tcur, level);
  475. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  476. rbp = tcur->bc_bufs[level];
  477. right = XFS_BUF_TO_BMBT_BLOCK(rbp);
  478. #ifdef DEBUG
  479. if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
  480. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  481. goto error0;
  482. }
  483. #endif
  484. bno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
  485. if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >=
  486. XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
  487. if ((error = xfs_bmbt_lshift(tcur, level, &i))) {
  488. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  489. goto error0;
  490. }
  491. if (i) {
  492. ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
  493. XFS_BMAP_BLOCK_IMINRECS(level, tcur));
  494. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  495. tcur = NULL;
  496. if (level > 0) {
  497. if ((error = xfs_bmbt_decrement(cur,
  498. level, &i))) {
  499. XFS_BMBT_TRACE_CURSOR(cur,
  500. ERROR);
  501. goto error0;
  502. }
  503. }
  504. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  505. *stat = 1;
  506. return 0;
  507. }
  508. }
  509. rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
  510. if (lbno != NULLFSBLOCK) {
  511. i = xfs_btree_firstrec(tcur, level);
  512. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  513. if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
  514. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  515. goto error0;
  516. }
  517. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  518. }
  519. }
  520. if (lbno != NULLFSBLOCK) {
  521. i = xfs_btree_firstrec(tcur, level);
  522. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  523. /*
  524. * decrement to last in block
  525. */
  526. if ((error = xfs_bmbt_decrement(tcur, level, &i))) {
  527. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  528. goto error0;
  529. }
  530. i = xfs_btree_firstrec(tcur, level);
  531. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  532. lbp = tcur->bc_bufs[level];
  533. left = XFS_BUF_TO_BMBT_BLOCK(lbp);
  534. #ifdef DEBUG
  535. if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
  536. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  537. goto error0;
  538. }
  539. #endif
  540. bno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
  541. if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >=
  542. XFS_BMAP_BLOCK_IMINRECS(level, cur)) {
  543. if ((error = xfs_bmbt_rshift(tcur, level, &i))) {
  544. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  545. goto error0;
  546. }
  547. if (i) {
  548. ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
  549. XFS_BMAP_BLOCK_IMINRECS(level, tcur));
  550. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  551. tcur = NULL;
  552. if (level == 0)
  553. cur->bc_ptrs[0]++;
  554. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  555. *stat = 1;
  556. return 0;
  557. }
  558. }
  559. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  560. }
  561. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  562. tcur = NULL;
  563. mp = cur->bc_mp;
  564. ASSERT(bno != NULLFSBLOCK);
  565. if (lbno != NULLFSBLOCK &&
  566. lrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
  567. rbno = bno;
  568. right = block;
  569. rbp = bp;
  570. if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp,
  571. XFS_BMAP_BTREE_REF))) {
  572. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  573. goto error0;
  574. }
  575. left = XFS_BUF_TO_BMBT_BLOCK(lbp);
  576. if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
  577. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  578. goto error0;
  579. }
  580. } else if (rbno != NULLFSBLOCK &&
  581. rrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <=
  582. XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
  583. lbno = bno;
  584. left = block;
  585. lbp = bp;
  586. if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp,
  587. XFS_BMAP_BTREE_REF))) {
  588. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  589. goto error0;
  590. }
  591. right = XFS_BUF_TO_BMBT_BLOCK(rbp);
  592. if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
  593. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  594. goto error0;
  595. }
  596. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  597. } else {
  598. if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) {
  599. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  600. goto error0;
  601. }
  602. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  603. *stat = 1;
  604. return 0;
  605. }
  606. numlrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
  607. numrrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
  608. if (level > 0) {
  609. lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur);
  610. lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur);
  611. rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
  612. rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
  613. #ifdef DEBUG
  614. for (i = 0; i < numrrecs; i++) {
  615. if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
  616. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  617. goto error0;
  618. }
  619. }
  620. #endif
  621. memcpy(lkp, rkp, numrrecs * sizeof(*lkp));
  622. memcpy(lpp, rpp, numrrecs * sizeof(*lpp));
  623. xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
  624. xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
  625. } else {
  626. lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur);
  627. rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
  628. memcpy(lrp, rrp, numrrecs * sizeof(*lrp));
  629. xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs);
  630. }
  631. INT_MOD(left->bb_numrecs, ARCH_CONVERT, numrrecs);
  632. left->bb_rightsib = right->bb_rightsib; /* INT_: direct copy */
  633. xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS);
  634. if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) {
  635. if ((error = xfs_btree_read_bufl(mp, cur->bc_tp,
  636. INT_GET(left->bb_rightsib, ARCH_CONVERT),
  637. 0, &rrbp, XFS_BMAP_BTREE_REF))) {
  638. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  639. goto error0;
  640. }
  641. rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
  642. if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
  643. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  644. goto error0;
  645. }
  646. INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno);
  647. xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
  648. }
  649. xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1,
  650. cur->bc_private.b.flist, mp);
  651. cur->bc_private.b.ip->i_d.di_nblocks--;
  652. xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
  653. XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip,
  654. XFS_TRANS_DQ_BCOUNT, -1L);
  655. xfs_trans_binval(cur->bc_tp, rbp);
  656. if (bp != lbp) {
  657. cur->bc_bufs[level] = lbp;
  658. cur->bc_ptrs[level] += lrecs;
  659. cur->bc_ra[level] = 0;
  660. } else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) {
  661. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  662. goto error0;
  663. }
  664. if (level > 0)
  665. cur->bc_ptrs[level]--;
  666. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  667. *stat = 2;
  668. return 0;
  669. error0:
  670. if (tcur)
  671. xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
  672. return error;
  673. }
  674. #ifdef DEBUG
  675. /*
  676. * Get the data from the pointed-to record.
  677. */
  678. int
  679. xfs_bmbt_get_rec(
  680. xfs_btree_cur_t *cur,
  681. xfs_fileoff_t *off,
  682. xfs_fsblock_t *bno,
  683. xfs_filblks_t *len,
  684. xfs_exntst_t *state,
  685. int *stat)
  686. {
  687. xfs_bmbt_block_t *block;
  688. xfs_buf_t *bp;
  689. #ifdef DEBUG
  690. int error;
  691. #endif
  692. int ptr;
  693. xfs_bmbt_rec_t *rp;
  694. block = xfs_bmbt_get_block(cur, 0, &bp);
  695. ptr = cur->bc_ptrs[0];
  696. #ifdef DEBUG
  697. if ((error = xfs_btree_check_lblock(cur, block, 0, bp)))
  698. return error;
  699. #endif
  700. if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) {
  701. *stat = 0;
  702. return 0;
  703. }
  704. rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
  705. *off = xfs_bmbt_disk_get_startoff(rp);
  706. *bno = xfs_bmbt_disk_get_startblock(rp);
  707. *len = xfs_bmbt_disk_get_blockcount(rp);
  708. *state = xfs_bmbt_disk_get_state(rp);
  709. *stat = 1;
  710. return 0;
  711. }
  712. #endif
  713. /*
  714. * Insert one record/level. Return information to the caller
  715. * allowing the next level up to proceed if necessary.
  716. */
  717. STATIC int /* error */
  718. xfs_bmbt_insrec(
  719. xfs_btree_cur_t *cur,
  720. int level,
  721. xfs_fsblock_t *bnop,
  722. xfs_bmbt_rec_t *recp,
  723. xfs_btree_cur_t **curp,
  724. int *stat) /* no-go/done/continue */
  725. {
  726. xfs_bmbt_block_t *block; /* bmap btree block */
  727. xfs_buf_t *bp; /* buffer for block */
  728. int error; /* error return value */
  729. #ifdef XFS_BMBT_TRACE
  730. static char fname[] = "xfs_bmbt_insrec";
  731. #endif
  732. int i; /* loop index */
  733. xfs_bmbt_key_t key; /* bmap btree key */
  734. xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */
  735. int logflags; /* inode logging flags */
  736. xfs_fsblock_t nbno; /* new block number */
  737. struct xfs_btree_cur *ncur; /* new btree cursor */
  738. xfs_bmbt_key_t nkey; /* new btree key value */
  739. xfs_bmbt_rec_t nrec; /* new record count */
  740. int optr; /* old key/record index */
  741. xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */
  742. int ptr; /* key/record index */
  743. xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */
  744. int numrecs;
  745. ASSERT(level < cur->bc_nlevels);
  746. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  747. XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp);
  748. ncur = (xfs_btree_cur_t *)0;
  749. INT_SET(key.br_startoff, ARCH_CONVERT,
  750. xfs_bmbt_disk_get_startoff(recp));
  751. optr = ptr = cur->bc_ptrs[level];
  752. if (ptr == 0) {
  753. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  754. *stat = 0;
  755. return 0;
  756. }
  757. XFS_STATS_INC(xs_bmbt_insrec);
  758. block = xfs_bmbt_get_block(cur, level, &bp);
  759. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  760. #ifdef DEBUG
  761. if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
  762. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  763. return error;
  764. }
  765. if (ptr <= numrecs) {
  766. if (level == 0) {
  767. rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
  768. xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp);
  769. } else {
  770. kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
  771. xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp);
  772. }
  773. }
  774. #endif
  775. nbno = NULLFSBLOCK;
  776. if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
  777. if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
  778. /*
  779. * A root block, that can be made bigger.
  780. */
  781. xfs_iroot_realloc(cur->bc_private.b.ip, 1,
  782. cur->bc_private.b.whichfork);
  783. block = xfs_bmbt_get_block(cur, level, &bp);
  784. } else if (level == cur->bc_nlevels - 1) {
  785. if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) ||
  786. *stat == 0) {
  787. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  788. return error;
  789. }
  790. xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip,
  791. logflags);
  792. block = xfs_bmbt_get_block(cur, level, &bp);
  793. } else {
  794. if ((error = xfs_bmbt_rshift(cur, level, &i))) {
  795. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  796. return error;
  797. }
  798. if (i) {
  799. /* nothing */
  800. } else {
  801. if ((error = xfs_bmbt_lshift(cur, level, &i))) {
  802. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  803. return error;
  804. }
  805. if (i) {
  806. optr = ptr = cur->bc_ptrs[level];
  807. } else {
  808. if ((error = xfs_bmbt_split(cur, level,
  809. &nbno, &nkey, &ncur,
  810. &i))) {
  811. XFS_BMBT_TRACE_CURSOR(cur,
  812. ERROR);
  813. return error;
  814. }
  815. if (i) {
  816. block = xfs_bmbt_get_block(
  817. cur, level, &bp);
  818. #ifdef DEBUG
  819. if ((error =
  820. xfs_btree_check_lblock(cur,
  821. block, level, bp))) {
  822. XFS_BMBT_TRACE_CURSOR(
  823. cur, ERROR);
  824. return error;
  825. }
  826. #endif
  827. ptr = cur->bc_ptrs[level];
  828. xfs_bmbt_disk_set_allf(&nrec,
  829. nkey.br_startoff, 0, 0,
  830. XFS_EXT_NORM);
  831. } else {
  832. XFS_BMBT_TRACE_CURSOR(cur,
  833. EXIT);
  834. *stat = 0;
  835. return 0;
  836. }
  837. }
  838. }
  839. }
  840. }
  841. numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  842. if (level > 0) {
  843. kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
  844. pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
  845. #ifdef DEBUG
  846. for (i = numrecs; i >= ptr; i--) {
  847. if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT),
  848. level))) {
  849. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  850. return error;
  851. }
  852. }
  853. #endif
  854. memmove(&kp[ptr], &kp[ptr - 1],
  855. (numrecs - ptr + 1) * sizeof(*kp));
  856. memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */
  857. (numrecs - ptr + 1) * sizeof(*pp));
  858. #ifdef DEBUG
  859. if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop,
  860. level))) {
  861. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  862. return error;
  863. }
  864. #endif
  865. kp[ptr - 1] = key;
  866. INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
  867. numrecs++;
  868. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  869. xfs_bmbt_log_keys(cur, bp, ptr, numrecs);
  870. xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs);
  871. } else {
  872. rp = XFS_BMAP_REC_IADDR(block, 1, cur);
  873. memmove(&rp[ptr], &rp[ptr - 1],
  874. (numrecs - ptr + 1) * sizeof(*rp));
  875. rp[ptr - 1] = *recp;
  876. numrecs++;
  877. INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs);
  878. xfs_bmbt_log_recs(cur, bp, ptr, numrecs);
  879. }
  880. xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS);
  881. #ifdef DEBUG
  882. if (ptr < numrecs) {
  883. if (level == 0)
  884. xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1,
  885. rp + ptr);
  886. else
  887. xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1,
  888. kp + ptr);
  889. }
  890. #endif
  891. if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) {
  892. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  893. return error;
  894. }
  895. *bnop = nbno;
  896. if (nbno != NULLFSBLOCK) {
  897. *recp = nrec;
  898. *curp = ncur;
  899. }
  900. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  901. *stat = 1;
  902. return 0;
  903. }
  904. STATIC int
  905. xfs_bmbt_killroot(
  906. xfs_btree_cur_t *cur)
  907. {
  908. xfs_bmbt_block_t *block;
  909. xfs_bmbt_block_t *cblock;
  910. xfs_buf_t *cbp;
  911. xfs_bmbt_key_t *ckp;
  912. xfs_bmbt_ptr_t *cpp;
  913. #ifdef DEBUG
  914. int error;
  915. #endif
  916. #ifdef XFS_BMBT_TRACE
  917. static char fname[] = "xfs_bmbt_killroot";
  918. #endif
  919. int i;
  920. xfs_bmbt_key_t *kp;
  921. xfs_inode_t *ip;
  922. xfs_ifork_t *ifp;
  923. int level;
  924. xfs_bmbt_ptr_t *pp;
  925. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  926. level = cur->bc_nlevels - 1;
  927. ASSERT(level >= 1);
  928. /*
  929. * Don't deal with the root block needs to be a leaf case.
  930. * We're just going to turn the thing back into extents anyway.
  931. */
  932. if (level == 1) {
  933. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  934. return 0;
  935. }
  936. block = xfs_bmbt_get_block(cur, level, &cbp);
  937. /*
  938. * Give up if the root has multiple children.
  939. */
  940. if (INT_GET(block->bb_numrecs, ARCH_CONVERT) != 1) {
  941. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  942. return 0;
  943. }
  944. /*
  945. * Only do this if the next level will fit.
  946. * Then the data must be copied up to the inode,
  947. * instead of freeing the root you free the next level.
  948. */
  949. cbp = cur->bc_bufs[level - 1];
  950. cblock = XFS_BUF_TO_BMBT_BLOCK(cbp);
  951. if (INT_GET(cblock->bb_numrecs, ARCH_CONVERT) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) {
  952. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  953. return 0;
  954. }
  955. ASSERT(INT_GET(cblock->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO);
  956. ASSERT(INT_GET(cblock->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO);
  957. ip = cur->bc_private.b.ip;
  958. ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork);
  959. ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) ==
  960. XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes));
  961. i = (int)(INT_GET(cblock->bb_numrecs, ARCH_CONVERT) - XFS_BMAP_BLOCK_IMAXRECS(level, cur));
  962. if (i) {
  963. xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork);
  964. block = ifp->if_broot;
  965. }
  966. INT_MOD(block->bb_numrecs, ARCH_CONVERT, i);
  967. ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) == INT_GET(cblock->bb_numrecs, ARCH_CONVERT));
  968. kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
  969. ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
  970. memcpy(kp, ckp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*kp));
  971. pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
  972. cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
  973. #ifdef DEBUG
  974. for (i = 0; i < INT_GET(cblock->bb_numrecs, ARCH_CONVERT); i++) {
  975. if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) {
  976. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  977. return error;
  978. }
  979. }
  980. #endif
  981. memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp));
  982. xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1,
  983. cur->bc_private.b.flist, cur->bc_mp);
  984. ip->i_d.di_nblocks--;
  985. XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip,
  986. XFS_TRANS_DQ_BCOUNT, -1L);
  987. xfs_trans_binval(cur->bc_tp, cbp);
  988. cur->bc_bufs[level - 1] = NULL;
  989. INT_MOD(block->bb_level, ARCH_CONVERT, -1);
  990. xfs_trans_log_inode(cur->bc_tp, ip,
  991. XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
  992. cur->bc_nlevels--;
  993. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  994. return 0;
  995. }
  996. /*
  997. * Log key values from the btree block.
  998. */
  999. STATIC void
  1000. xfs_bmbt_log_keys(
  1001. xfs_btree_cur_t *cur,
  1002. xfs_buf_t *bp,
  1003. int kfirst,
  1004. int klast)
  1005. {
  1006. #ifdef XFS_BMBT_TRACE
  1007. static char fname[] = "xfs_bmbt_log_keys";
  1008. #endif
  1009. xfs_trans_t *tp;
  1010. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1011. XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast);
  1012. tp = cur->bc_tp;
  1013. if (bp) {
  1014. xfs_bmbt_block_t *block;
  1015. int first;
  1016. xfs_bmbt_key_t *kp;
  1017. int last;
  1018. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  1019. kp = XFS_BMAP_KEY_DADDR(block, 1, cur);
  1020. first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
  1021. last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
  1022. xfs_trans_log_buf(tp, bp, first, last);
  1023. } else {
  1024. xfs_inode_t *ip;
  1025. ip = cur->bc_private.b.ip;
  1026. xfs_trans_log_inode(tp, ip,
  1027. XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
  1028. }
  1029. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1030. }
  1031. /*
  1032. * Log pointer values from the btree block.
  1033. */
  1034. STATIC void
  1035. xfs_bmbt_log_ptrs(
  1036. xfs_btree_cur_t *cur,
  1037. xfs_buf_t *bp,
  1038. int pfirst,
  1039. int plast)
  1040. {
  1041. #ifdef XFS_BMBT_TRACE
  1042. static char fname[] = "xfs_bmbt_log_ptrs";
  1043. #endif
  1044. xfs_trans_t *tp;
  1045. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1046. XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast);
  1047. tp = cur->bc_tp;
  1048. if (bp) {
  1049. xfs_bmbt_block_t *block;
  1050. int first;
  1051. int last;
  1052. xfs_bmbt_ptr_t *pp;
  1053. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  1054. pp = XFS_BMAP_PTR_DADDR(block, 1, cur);
  1055. first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
  1056. last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
  1057. xfs_trans_log_buf(tp, bp, first, last);
  1058. } else {
  1059. xfs_inode_t *ip;
  1060. ip = cur->bc_private.b.ip;
  1061. xfs_trans_log_inode(tp, ip,
  1062. XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
  1063. }
  1064. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1065. }
  1066. /*
  1067. * Lookup the record. The cursor is made to point to it, based on dir.
  1068. */
  1069. STATIC int /* error */
  1070. xfs_bmbt_lookup(
  1071. xfs_btree_cur_t *cur,
  1072. xfs_lookup_t dir,
  1073. int *stat) /* success/failure */
  1074. {
  1075. xfs_bmbt_block_t *block=NULL;
  1076. xfs_buf_t *bp;
  1077. xfs_daddr_t d;
  1078. xfs_sfiloff_t diff;
  1079. int error; /* error return value */
  1080. #ifdef XFS_BMBT_TRACE
  1081. static char fname[] = "xfs_bmbt_lookup";
  1082. #endif
  1083. xfs_fsblock_t fsbno=0;
  1084. int high;
  1085. int i;
  1086. int keyno=0;
  1087. xfs_bmbt_key_t *kkbase=NULL;
  1088. xfs_bmbt_key_t *kkp;
  1089. xfs_bmbt_rec_t *krbase=NULL;
  1090. xfs_bmbt_rec_t *krp;
  1091. int level;
  1092. int low;
  1093. xfs_mount_t *mp;
  1094. xfs_bmbt_ptr_t *pp;
  1095. xfs_bmbt_irec_t *rp;
  1096. xfs_fileoff_t startoff;
  1097. xfs_trans_t *tp;
  1098. XFS_STATS_INC(xs_bmbt_lookup);
  1099. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1100. XFS_BMBT_TRACE_ARGI(cur, (int)dir);
  1101. tp = cur->bc_tp;
  1102. mp = cur->bc_mp;
  1103. rp = &cur->bc_rec.b;
  1104. for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
  1105. if (level < cur->bc_nlevels - 1) {
  1106. d = XFS_FSB_TO_DADDR(mp, fsbno);
  1107. bp = cur->bc_bufs[level];
  1108. if (bp && XFS_BUF_ADDR(bp) != d)
  1109. bp = (xfs_buf_t *)0;
  1110. if (!bp) {
  1111. if ((error = xfs_btree_read_bufl(mp, tp, fsbno,
  1112. 0, &bp, XFS_BMAP_BTREE_REF))) {
  1113. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1114. return error;
  1115. }
  1116. xfs_btree_setbuf(cur, level, bp);
  1117. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  1118. if ((error = xfs_btree_check_lblock(cur, block,
  1119. level, bp))) {
  1120. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1121. return error;
  1122. }
  1123. } else
  1124. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  1125. } else
  1126. block = xfs_bmbt_get_block(cur, level, &bp);
  1127. if (diff == 0)
  1128. keyno = 1;
  1129. else {
  1130. if (level > 0)
  1131. kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur);
  1132. else
  1133. krbase = XFS_BMAP_REC_IADDR(block, 1, cur);
  1134. low = 1;
  1135. if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) {
  1136. ASSERT(level == 0);
  1137. cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
  1138. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1139. *stat = 0;
  1140. return 0;
  1141. }
  1142. while (low <= high) {
  1143. XFS_STATS_INC(xs_bmbt_compare);
  1144. keyno = (low + high) >> 1;
  1145. if (level > 0) {
  1146. kkp = kkbase + keyno - 1;
  1147. startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT);
  1148. } else {
  1149. krp = krbase + keyno - 1;
  1150. startoff = xfs_bmbt_disk_get_startoff(krp);
  1151. }
  1152. diff = (xfs_sfiloff_t)
  1153. (startoff - rp->br_startoff);
  1154. if (diff < 0)
  1155. low = keyno + 1;
  1156. else if (diff > 0)
  1157. high = keyno - 1;
  1158. else
  1159. break;
  1160. }
  1161. }
  1162. if (level > 0) {
  1163. if (diff > 0 && --keyno < 1)
  1164. keyno = 1;
  1165. pp = XFS_BMAP_PTR_IADDR(block, keyno, cur);
  1166. #ifdef DEBUG
  1167. if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
  1168. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1169. return error;
  1170. }
  1171. #endif
  1172. fsbno = INT_GET(*pp, ARCH_CONVERT);
  1173. cur->bc_ptrs[level] = keyno;
  1174. }
  1175. }
  1176. if (dir != XFS_LOOKUP_LE && diff < 0) {
  1177. keyno++;
  1178. /*
  1179. * If ge search and we went off the end of the block, but it's
  1180. * not the last block, we're in the wrong block.
  1181. */
  1182. if (dir == XFS_LOOKUP_GE && keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) &&
  1183. INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) {
  1184. cur->bc_ptrs[0] = keyno;
  1185. if ((error = xfs_bmbt_increment(cur, 0, &i))) {
  1186. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1187. return error;
  1188. }
  1189. XFS_WANT_CORRUPTED_RETURN(i == 1);
  1190. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1191. *stat = 1;
  1192. return 0;
  1193. }
  1194. }
  1195. else if (dir == XFS_LOOKUP_LE && diff > 0)
  1196. keyno--;
  1197. cur->bc_ptrs[0] = keyno;
  1198. if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
  1199. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1200. *stat = 0;
  1201. } else {
  1202. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1203. *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
  1204. }
  1205. return 0;
  1206. }
  1207. /*
  1208. * Move 1 record left from cur/level if possible.
  1209. * Update cur to reflect the new path.
  1210. */
  1211. STATIC int /* error */
  1212. xfs_bmbt_lshift(
  1213. xfs_btree_cur_t *cur,
  1214. int level,
  1215. int *stat) /* success/failure */
  1216. {
  1217. int error; /* error return value */
  1218. #ifdef XFS_BMBT_TRACE
  1219. static char fname[] = "xfs_bmbt_lshift";
  1220. #endif
  1221. #ifdef DEBUG
  1222. int i; /* loop counter */
  1223. #endif
  1224. xfs_bmbt_key_t key; /* bmap btree key */
  1225. xfs_buf_t *lbp; /* left buffer pointer */
  1226. xfs_bmbt_block_t *left; /* left btree block */
  1227. xfs_bmbt_key_t *lkp=NULL; /* left btree key */
  1228. xfs_bmbt_ptr_t *lpp; /* left address pointer */
  1229. int lrecs; /* left record count */
  1230. xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */
  1231. xfs_mount_t *mp; /* file system mount point */
  1232. xfs_buf_t *rbp; /* right buffer pointer */
  1233. xfs_bmbt_block_t *right; /* right btree block */
  1234. xfs_bmbt_key_t *rkp=NULL; /* right btree key */
  1235. xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */
  1236. xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */
  1237. int rrecs; /* right record count */
  1238. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1239. XFS_BMBT_TRACE_ARGI(cur, level);
  1240. if (level == cur->bc_nlevels - 1) {
  1241. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1242. *stat = 0;
  1243. return 0;
  1244. }
  1245. rbp = cur->bc_bufs[level];
  1246. right = XFS_BUF_TO_BMBT_BLOCK(rbp);
  1247. #ifdef DEBUG
  1248. if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
  1249. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1250. return error;
  1251. }
  1252. #endif
  1253. if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO) {
  1254. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1255. *stat = 0;
  1256. return 0;
  1257. }
  1258. if (cur->bc_ptrs[level] <= 1) {
  1259. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1260. *stat = 0;
  1261. return 0;
  1262. }
  1263. mp = cur->bc_mp;
  1264. if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, INT_GET(right->bb_leftsib, ARCH_CONVERT), 0,
  1265. &lbp, XFS_BMAP_BTREE_REF))) {
  1266. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1267. return error;
  1268. }
  1269. left = XFS_BUF_TO_BMBT_BLOCK(lbp);
  1270. if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
  1271. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1272. return error;
  1273. }
  1274. if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
  1275. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1276. *stat = 0;
  1277. return 0;
  1278. }
  1279. lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1;
  1280. if (level > 0) {
  1281. lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur);
  1282. rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
  1283. *lkp = *rkp;
  1284. xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs);
  1285. lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur);
  1286. rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
  1287. #ifdef DEBUG
  1288. if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) {
  1289. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1290. return error;
  1291. }
  1292. #endif
  1293. *lpp = *rpp; /* INT_: direct copy */
  1294. xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs);
  1295. } else {
  1296. lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur);
  1297. rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
  1298. *lrp = *rrp;
  1299. xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs);
  1300. }
  1301. INT_SET(left->bb_numrecs, ARCH_CONVERT, lrecs);
  1302. xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
  1303. #ifdef DEBUG
  1304. if (level > 0)
  1305. xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp);
  1306. else
  1307. xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp);
  1308. #endif
  1309. rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1;
  1310. INT_SET(right->bb_numrecs, ARCH_CONVERT, rrecs);
  1311. xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
  1312. if (level > 0) {
  1313. #ifdef DEBUG
  1314. for (i = 0; i < rrecs; i++) {
  1315. if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
  1316. level))) {
  1317. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1318. return error;
  1319. }
  1320. }
  1321. #endif
  1322. memmove(rkp, rkp + 1, rrecs * sizeof(*rkp));
  1323. memmove(rpp, rpp + 1, rrecs * sizeof(*rpp));
  1324. xfs_bmbt_log_keys(cur, rbp, 1, rrecs);
  1325. xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs);
  1326. } else {
  1327. memmove(rrp, rrp + 1, rrecs * sizeof(*rrp));
  1328. xfs_bmbt_log_recs(cur, rbp, 1, rrecs);
  1329. INT_SET(key.br_startoff, ARCH_CONVERT,
  1330. xfs_bmbt_disk_get_startoff(rrp));
  1331. rkp = &key;
  1332. }
  1333. if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) {
  1334. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1335. return error;
  1336. }
  1337. cur->bc_ptrs[level]--;
  1338. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1339. *stat = 1;
  1340. return 0;
  1341. }
  1342. /*
  1343. * Move 1 record right from cur/level if possible.
  1344. * Update cur to reflect the new path.
  1345. */
  1346. STATIC int /* error */
  1347. xfs_bmbt_rshift(
  1348. xfs_btree_cur_t *cur,
  1349. int level,
  1350. int *stat) /* success/failure */
  1351. {
  1352. int error; /* error return value */
  1353. #ifdef XFS_BMBT_TRACE
  1354. static char fname[] = "xfs_bmbt_rshift";
  1355. #endif
  1356. int i; /* loop counter */
  1357. xfs_bmbt_key_t key; /* bmap btree key */
  1358. xfs_buf_t *lbp; /* left buffer pointer */
  1359. xfs_bmbt_block_t *left; /* left btree block */
  1360. xfs_bmbt_key_t *lkp; /* left btree key */
  1361. xfs_bmbt_ptr_t *lpp; /* left address pointer */
  1362. xfs_bmbt_rec_t *lrp; /* left record pointer */
  1363. xfs_mount_t *mp; /* file system mount point */
  1364. xfs_buf_t *rbp; /* right buffer pointer */
  1365. xfs_bmbt_block_t *right; /* right btree block */
  1366. xfs_bmbt_key_t *rkp; /* right btree key */
  1367. xfs_bmbt_ptr_t *rpp; /* right address pointer */
  1368. xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */
  1369. struct xfs_btree_cur *tcur; /* temporary btree cursor */
  1370. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1371. XFS_BMBT_TRACE_ARGI(cur, level);
  1372. if (level == cur->bc_nlevels - 1) {
  1373. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1374. *stat = 0;
  1375. return 0;
  1376. }
  1377. lbp = cur->bc_bufs[level];
  1378. left = XFS_BUF_TO_BMBT_BLOCK(lbp);
  1379. #ifdef DEBUG
  1380. if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) {
  1381. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1382. return error;
  1383. }
  1384. #endif
  1385. if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO) {
  1386. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1387. *stat = 0;
  1388. return 0;
  1389. }
  1390. if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) {
  1391. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1392. *stat = 0;
  1393. return 0;
  1394. }
  1395. mp = cur->bc_mp;
  1396. if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0,
  1397. &rbp, XFS_BMAP_BTREE_REF))) {
  1398. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1399. return error;
  1400. }
  1401. right = XFS_BUF_TO_BMBT_BLOCK(rbp);
  1402. if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) {
  1403. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1404. return error;
  1405. }
  1406. if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) {
  1407. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1408. *stat = 0;
  1409. return 0;
  1410. }
  1411. if (level > 0) {
  1412. lkp = XFS_BMAP_KEY_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1413. lpp = XFS_BMAP_PTR_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1414. rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
  1415. rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
  1416. #ifdef DEBUG
  1417. for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) {
  1418. if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) {
  1419. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1420. return error;
  1421. }
  1422. }
  1423. #endif
  1424. memmove(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
  1425. memmove(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
  1426. #ifdef DEBUG
  1427. if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) {
  1428. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1429. return error;
  1430. }
  1431. #endif
  1432. *rkp = *lkp;
  1433. *rpp = *lpp; /* INT_: direct copy */
  1434. xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1435. xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1436. } else {
  1437. lrp = XFS_BMAP_REC_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
  1438. rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
  1439. memmove(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
  1440. *rrp = *lrp;
  1441. xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
  1442. INT_SET(key.br_startoff, ARCH_CONVERT,
  1443. xfs_bmbt_disk_get_startoff(rrp));
  1444. rkp = &key;
  1445. }
  1446. INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1);
  1447. xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS);
  1448. INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
  1449. #ifdef DEBUG
  1450. if (level > 0)
  1451. xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1);
  1452. else
  1453. xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1);
  1454. #endif
  1455. xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS);
  1456. if ((error = xfs_btree_dup_cursor(cur, &tcur))) {
  1457. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1458. return error;
  1459. }
  1460. i = xfs_btree_lastrec(tcur, level);
  1461. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  1462. if ((error = xfs_bmbt_increment(tcur, level, &i))) {
  1463. XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
  1464. goto error1;
  1465. }
  1466. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  1467. if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) {
  1468. XFS_BMBT_TRACE_CURSOR(tcur, ERROR);
  1469. goto error1;
  1470. }
  1471. xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
  1472. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1473. *stat = 1;
  1474. return 0;
  1475. error0:
  1476. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1477. error1:
  1478. xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
  1479. return error;
  1480. }
  1481. /*
  1482. * Determine the extent state.
  1483. */
  1484. /* ARGSUSED */
  1485. STATIC xfs_exntst_t
  1486. xfs_extent_state(
  1487. xfs_filblks_t blks,
  1488. int extent_flag)
  1489. {
  1490. if (extent_flag) {
  1491. ASSERT(blks != 0); /* saved for DMIG */
  1492. return XFS_EXT_UNWRITTEN;
  1493. }
  1494. return XFS_EXT_NORM;
  1495. }
  1496. /*
  1497. * Split cur/level block in half.
  1498. * Return new block number and its first record (to be inserted into parent).
  1499. */
  1500. STATIC int /* error */
  1501. xfs_bmbt_split(
  1502. xfs_btree_cur_t *cur,
  1503. int level,
  1504. xfs_fsblock_t *bnop,
  1505. xfs_bmbt_key_t *keyp,
  1506. xfs_btree_cur_t **curp,
  1507. int *stat) /* success/failure */
  1508. {
  1509. xfs_alloc_arg_t args; /* block allocation args */
  1510. int error; /* error return value */
  1511. #ifdef XFS_BMBT_TRACE
  1512. static char fname[] = "xfs_bmbt_split";
  1513. #endif
  1514. int i; /* loop counter */
  1515. xfs_fsblock_t lbno; /* left sibling block number */
  1516. xfs_buf_t *lbp; /* left buffer pointer */
  1517. xfs_bmbt_block_t *left; /* left btree block */
  1518. xfs_bmbt_key_t *lkp; /* left btree key */
  1519. xfs_bmbt_ptr_t *lpp; /* left address pointer */
  1520. xfs_bmbt_rec_t *lrp; /* left record pointer */
  1521. xfs_buf_t *rbp; /* right buffer pointer */
  1522. xfs_bmbt_block_t *right; /* right btree block */
  1523. xfs_bmbt_key_t *rkp; /* right btree key */
  1524. xfs_bmbt_ptr_t *rpp; /* right address pointer */
  1525. xfs_bmbt_block_t *rrblock; /* right-right btree block */
  1526. xfs_buf_t *rrbp; /* right-right buffer pointer */
  1527. xfs_bmbt_rec_t *rrp; /* right record pointer */
  1528. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1529. XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp);
  1530. args.tp = cur->bc_tp;
  1531. args.mp = cur->bc_mp;
  1532. lbp = cur->bc_bufs[level];
  1533. lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp));
  1534. left = XFS_BUF_TO_BMBT_BLOCK(lbp);
  1535. args.fsbno = cur->bc_private.b.firstblock;
  1536. if (args.fsbno == NULLFSBLOCK) {
  1537. args.fsbno = lbno;
  1538. args.type = XFS_ALLOCTYPE_START_BNO;
  1539. } else if (cur->bc_private.b.flist->xbf_low)
  1540. args.type = XFS_ALLOCTYPE_FIRST_AG;
  1541. else
  1542. args.type = XFS_ALLOCTYPE_NEAR_BNO;
  1543. args.mod = args.minleft = args.alignment = args.total = args.isfl =
  1544. args.userdata = args.minalignslop = 0;
  1545. args.minlen = args.maxlen = args.prod = 1;
  1546. args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
  1547. if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) {
  1548. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1549. return XFS_ERROR(ENOSPC);
  1550. }
  1551. if ((error = xfs_alloc_vextent(&args))) {
  1552. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1553. return error;
  1554. }
  1555. if (args.fsbno == NULLFSBLOCK) {
  1556. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1557. *stat = 0;
  1558. return 0;
  1559. }
  1560. ASSERT(args.len == 1);
  1561. cur->bc_private.b.firstblock = args.fsbno;
  1562. cur->bc_private.b.allocated++;
  1563. cur->bc_private.b.ip->i_d.di_nblocks++;
  1564. xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE);
  1565. XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
  1566. XFS_TRANS_DQ_BCOUNT, 1L);
  1567. rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0);
  1568. right = XFS_BUF_TO_BMBT_BLOCK(rbp);
  1569. #ifdef DEBUG
  1570. if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) {
  1571. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1572. return error;
  1573. }
  1574. #endif
  1575. INT_SET(right->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
  1576. right->bb_level = left->bb_level; /* INT_: direct copy */
  1577. INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2));
  1578. if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) &&
  1579. cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1)
  1580. INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
  1581. i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1;
  1582. if (level > 0) {
  1583. lkp = XFS_BMAP_KEY_IADDR(left, i, cur);
  1584. lpp = XFS_BMAP_PTR_IADDR(left, i, cur);
  1585. rkp = XFS_BMAP_KEY_IADDR(right, 1, cur);
  1586. rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);
  1587. #ifdef DEBUG
  1588. for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
  1589. if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) {
  1590. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1591. return error;
  1592. }
  1593. }
  1594. #endif
  1595. memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
  1596. memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
  1597. xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1598. xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1599. keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT);
  1600. } else {
  1601. lrp = XFS_BMAP_REC_IADDR(left, i, cur);
  1602. rrp = XFS_BMAP_REC_IADDR(right, 1, cur);
  1603. memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
  1604. xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
  1605. keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp);
  1606. }
  1607. INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT)));
  1608. right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */
  1609. INT_SET(left->bb_rightsib, ARCH_CONVERT, args.fsbno);
  1610. INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno);
  1611. xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS);
  1612. xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
  1613. if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) {
  1614. if ((error = xfs_btree_read_bufl(args.mp, args.tp,
  1615. INT_GET(right->bb_rightsib, ARCH_CONVERT), 0, &rrbp,
  1616. XFS_BMAP_BTREE_REF))) {
  1617. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1618. return error;
  1619. }
  1620. rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp);
  1621. if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) {
  1622. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1623. return error;
  1624. }
  1625. INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, args.fsbno);
  1626. xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB);
  1627. }
  1628. if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) {
  1629. xfs_btree_setbuf(cur, level, rbp);
  1630. cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT);
  1631. }
  1632. if (level + 1 < cur->bc_nlevels) {
  1633. if ((error = xfs_btree_dup_cursor(cur, curp))) {
  1634. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1635. return error;
  1636. }
  1637. (*curp)->bc_ptrs[level + 1]++;
  1638. }
  1639. *bnop = args.fsbno;
  1640. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1641. *stat = 1;
  1642. return 0;
  1643. }
  1644. /*
  1645. * Update keys for the record.
  1646. */
  1647. STATIC int
  1648. xfs_bmbt_updkey(
  1649. xfs_btree_cur_t *cur,
  1650. xfs_bmbt_key_t *keyp, /* on-disk format */
  1651. int level)
  1652. {
  1653. xfs_bmbt_block_t *block;
  1654. xfs_buf_t *bp;
  1655. #ifdef DEBUG
  1656. int error;
  1657. #endif
  1658. #ifdef XFS_BMBT_TRACE
  1659. static char fname[] = "xfs_bmbt_updkey";
  1660. #endif
  1661. xfs_bmbt_key_t *kp;
  1662. int ptr;
  1663. ASSERT(level >= 1);
  1664. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1665. XFS_BMBT_TRACE_ARGIK(cur, level, keyp);
  1666. for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
  1667. block = xfs_bmbt_get_block(cur, level, &bp);
  1668. #ifdef DEBUG
  1669. if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
  1670. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1671. return error;
  1672. }
  1673. #endif
  1674. ptr = cur->bc_ptrs[level];
  1675. kp = XFS_BMAP_KEY_IADDR(block, ptr, cur);
  1676. *kp = *keyp;
  1677. xfs_bmbt_log_keys(cur, bp, ptr, ptr);
  1678. }
  1679. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1680. return 0;
  1681. }
  1682. /*
  1683. * Convert on-disk form of btree root to in-memory form.
  1684. */
  1685. void
  1686. xfs_bmdr_to_bmbt(
  1687. xfs_bmdr_block_t *dblock,
  1688. int dblocklen,
  1689. xfs_bmbt_block_t *rblock,
  1690. int rblocklen)
  1691. {
  1692. int dmxr;
  1693. xfs_bmbt_key_t *fkp;
  1694. xfs_bmbt_ptr_t *fpp;
  1695. xfs_bmbt_key_t *tkp;
  1696. xfs_bmbt_ptr_t *tpp;
  1697. INT_SET(rblock->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC);
  1698. rblock->bb_level = dblock->bb_level; /* both in on-disk format */
  1699. ASSERT(INT_GET(rblock->bb_level, ARCH_CONVERT) > 0);
  1700. rblock->bb_numrecs = dblock->bb_numrecs;/* both in on-disk format */
  1701. INT_SET(rblock->bb_leftsib, ARCH_CONVERT, NULLDFSBNO);
  1702. INT_SET(rblock->bb_rightsib, ARCH_CONVERT, NULLDFSBNO);
  1703. dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
  1704. fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
  1705. tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
  1706. fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
  1707. tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
  1708. dmxr = INT_GET(dblock->bb_numrecs, ARCH_CONVERT);
  1709. memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
  1710. memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
  1711. }
  1712. /*
  1713. * Decrement cursor by one record at the level.
  1714. * For nonzero levels the leaf-ward information is untouched.
  1715. */
  1716. int /* error */
  1717. xfs_bmbt_decrement(
  1718. xfs_btree_cur_t *cur,
  1719. int level,
  1720. int *stat) /* success/failure */
  1721. {
  1722. xfs_bmbt_block_t *block;
  1723. xfs_buf_t *bp;
  1724. int error; /* error return value */
  1725. #ifdef XFS_BMBT_TRACE
  1726. static char fname[] = "xfs_bmbt_decrement";
  1727. #endif
  1728. xfs_fsblock_t fsbno;
  1729. int lev;
  1730. xfs_mount_t *mp;
  1731. xfs_trans_t *tp;
  1732. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1733. XFS_BMBT_TRACE_ARGI(cur, level);
  1734. ASSERT(level < cur->bc_nlevels);
  1735. if (level < cur->bc_nlevels - 1)
  1736. xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
  1737. if (--cur->bc_ptrs[level] > 0) {
  1738. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1739. *stat = 1;
  1740. return 0;
  1741. }
  1742. block = xfs_bmbt_get_block(cur, level, &bp);
  1743. #ifdef DEBUG
  1744. if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
  1745. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1746. return error;
  1747. }
  1748. #endif
  1749. if (INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO) {
  1750. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1751. *stat = 0;
  1752. return 0;
  1753. }
  1754. for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
  1755. if (--cur->bc_ptrs[lev] > 0)
  1756. break;
  1757. if (lev < cur->bc_nlevels - 1)
  1758. xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
  1759. }
  1760. if (lev == cur->bc_nlevels) {
  1761. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1762. *stat = 0;
  1763. return 0;
  1764. }
  1765. tp = cur->bc_tp;
  1766. mp = cur->bc_mp;
  1767. for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
  1768. fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
  1769. if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
  1770. XFS_BMAP_BTREE_REF))) {
  1771. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1772. return error;
  1773. }
  1774. lev--;
  1775. xfs_btree_setbuf(cur, lev, bp);
  1776. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  1777. if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
  1778. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1779. return error;
  1780. }
  1781. cur->bc_ptrs[lev] = INT_GET(block->bb_numrecs, ARCH_CONVERT);
  1782. }
  1783. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1784. *stat = 1;
  1785. return 0;
  1786. }
  1787. /*
  1788. * Delete the record pointed to by cur.
  1789. */
  1790. int /* error */
  1791. xfs_bmbt_delete(
  1792. xfs_btree_cur_t *cur,
  1793. int *stat) /* success/failure */
  1794. {
  1795. int error; /* error return value */
  1796. #ifdef XFS_BMBT_TRACE
  1797. static char fname[] = "xfs_bmbt_delete";
  1798. #endif
  1799. int i;
  1800. int level;
  1801. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  1802. for (level = 0, i = 2; i == 2; level++) {
  1803. if ((error = xfs_bmbt_delrec(cur, level, &i))) {
  1804. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1805. return error;
  1806. }
  1807. }
  1808. if (i == 0) {
  1809. for (level = 1; level < cur->bc_nlevels; level++) {
  1810. if (cur->bc_ptrs[level] == 0) {
  1811. if ((error = xfs_bmbt_decrement(cur, level,
  1812. &i))) {
  1813. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  1814. return error;
  1815. }
  1816. break;
  1817. }
  1818. }
  1819. }
  1820. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  1821. *stat = i;
  1822. return 0;
  1823. }
  1824. /*
  1825. * Convert a compressed bmap extent record to an uncompressed form.
  1826. * This code must be in sync with the routines xfs_bmbt_get_startoff,
  1827. * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state.
  1828. */
  1829. STATIC __inline__ void
  1830. __xfs_bmbt_get_all(
  1831. __uint64_t l0,
  1832. __uint64_t l1,
  1833. xfs_bmbt_irec_t *s)
  1834. {
  1835. int ext_flag;
  1836. xfs_exntst_t st;
  1837. ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN));
  1838. s->br_startoff = ((xfs_fileoff_t)l0 &
  1839. XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
  1840. #if XFS_BIG_BLKNOS
  1841. s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) |
  1842. (((xfs_fsblock_t)l1) >> 21);
  1843. #else
  1844. #ifdef DEBUG
  1845. {
  1846. xfs_dfsbno_t b;
  1847. b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) |
  1848. (((xfs_dfsbno_t)l1) >> 21);
  1849. ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
  1850. s->br_startblock = (xfs_fsblock_t)b;
  1851. }
  1852. #else /* !DEBUG */
  1853. s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);
  1854. #endif /* DEBUG */
  1855. #endif /* XFS_BIG_BLKNOS */
  1856. s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21));
  1857. /* This is xfs_extent_state() in-line */
  1858. if (ext_flag) {
  1859. ASSERT(s->br_blockcount != 0); /* saved for DMIG */
  1860. st = XFS_EXT_UNWRITTEN;
  1861. } else
  1862. st = XFS_EXT_NORM;
  1863. s->br_state = st;
  1864. }
  1865. void
  1866. xfs_bmbt_get_all(
  1867. xfs_bmbt_rec_t *r,
  1868. xfs_bmbt_irec_t *s)
  1869. {
  1870. __xfs_bmbt_get_all(r->l0, r->l1, s);
  1871. }
  1872. /*
  1873. * Get the block pointer for the given level of the cursor.
  1874. * Fill in the buffer pointer, if applicable.
  1875. */
  1876. xfs_bmbt_block_t *
  1877. xfs_bmbt_get_block(
  1878. xfs_btree_cur_t *cur,
  1879. int level,
  1880. xfs_buf_t **bpp)
  1881. {
  1882. xfs_ifork_t *ifp;
  1883. xfs_bmbt_block_t *rval;
  1884. if (level < cur->bc_nlevels - 1) {
  1885. *bpp = cur->bc_bufs[level];
  1886. rval = XFS_BUF_TO_BMBT_BLOCK(*bpp);
  1887. } else {
  1888. *bpp = NULL;
  1889. ifp = XFS_IFORK_PTR(cur->bc_private.b.ip,
  1890. cur->bc_private.b.whichfork);
  1891. rval = ifp->if_broot;
  1892. }
  1893. return rval;
  1894. }
  1895. /*
  1896. * Extract the blockcount field from an in memory bmap extent record.
  1897. */
  1898. xfs_filblks_t
  1899. xfs_bmbt_get_blockcount(
  1900. xfs_bmbt_rec_t *r)
  1901. {
  1902. return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));
  1903. }
  1904. /*
  1905. * Extract the startblock field from an in memory bmap extent record.
  1906. */
  1907. xfs_fsblock_t
  1908. xfs_bmbt_get_startblock(
  1909. xfs_bmbt_rec_t *r)
  1910. {
  1911. #if XFS_BIG_BLKNOS
  1912. return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) |
  1913. (((xfs_fsblock_t)r->l1) >> 21);
  1914. #else
  1915. #ifdef DEBUG
  1916. xfs_dfsbno_t b;
  1917. b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) |
  1918. (((xfs_dfsbno_t)r->l1) >> 21);
  1919. ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
  1920. return (xfs_fsblock_t)b;
  1921. #else /* !DEBUG */
  1922. return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);
  1923. #endif /* DEBUG */
  1924. #endif /* XFS_BIG_BLKNOS */
  1925. }
  1926. /*
  1927. * Extract the startoff field from an in memory bmap extent record.
  1928. */
  1929. xfs_fileoff_t
  1930. xfs_bmbt_get_startoff(
  1931. xfs_bmbt_rec_t *r)
  1932. {
  1933. return ((xfs_fileoff_t)r->l0 &
  1934. XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
  1935. }
  1936. xfs_exntst_t
  1937. xfs_bmbt_get_state(
  1938. xfs_bmbt_rec_t *r)
  1939. {
  1940. int ext_flag;
  1941. ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN));
  1942. return xfs_extent_state(xfs_bmbt_get_blockcount(r),
  1943. ext_flag);
  1944. }
  1945. #if __BYTE_ORDER != __BIG_ENDIAN
  1946. /* Endian flipping versions of the bmbt extraction functions */
  1947. void
  1948. xfs_bmbt_disk_get_all(
  1949. xfs_bmbt_rec_t *r,
  1950. xfs_bmbt_irec_t *s)
  1951. {
  1952. __uint64_t l0, l1;
  1953. l0 = INT_GET(r->l0, ARCH_CONVERT);
  1954. l1 = INT_GET(r->l1, ARCH_CONVERT);
  1955. __xfs_bmbt_get_all(l0, l1, s);
  1956. }
  1957. /*
  1958. * Extract the blockcount field from an on disk bmap extent record.
  1959. */
  1960. xfs_filblks_t
  1961. xfs_bmbt_disk_get_blockcount(
  1962. xfs_bmbt_rec_t *r)
  1963. {
  1964. return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21));
  1965. }
  1966. /*
  1967. * Extract the startblock field from an on disk bmap extent record.
  1968. */
  1969. xfs_fsblock_t
  1970. xfs_bmbt_disk_get_startblock(
  1971. xfs_bmbt_rec_t *r)
  1972. {
  1973. #if XFS_BIG_BLKNOS
  1974. return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
  1975. (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
  1976. #else
  1977. #ifdef DEBUG
  1978. xfs_dfsbno_t b;
  1979. b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) |
  1980. (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
  1981. ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b));
  1982. return (xfs_fsblock_t)b;
  1983. #else /* !DEBUG */
  1984. return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21);
  1985. #endif /* DEBUG */
  1986. #endif /* XFS_BIG_BLKNOS */
  1987. }
  1988. /*
  1989. * Extract the startoff field from a disk format bmap extent record.
  1990. */
  1991. xfs_fileoff_t
  1992. xfs_bmbt_disk_get_startoff(
  1993. xfs_bmbt_rec_t *r)
  1994. {
  1995. return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) &
  1996. XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;
  1997. }
  1998. xfs_exntst_t
  1999. xfs_bmbt_disk_get_state(
  2000. xfs_bmbt_rec_t *r)
  2001. {
  2002. int ext_flag;
  2003. ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN));
  2004. return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r),
  2005. ext_flag);
  2006. }
  2007. #endif
  2008. /*
  2009. * Increment cursor by one record at the level.
  2010. * For nonzero levels the leaf-ward information is untouched.
  2011. */
  2012. int /* error */
  2013. xfs_bmbt_increment(
  2014. xfs_btree_cur_t *cur,
  2015. int level,
  2016. int *stat) /* success/failure */
  2017. {
  2018. xfs_bmbt_block_t *block;
  2019. xfs_buf_t *bp;
  2020. int error; /* error return value */
  2021. #ifdef XFS_BMBT_TRACE
  2022. static char fname[] = "xfs_bmbt_increment";
  2023. #endif
  2024. xfs_fsblock_t fsbno;
  2025. int lev;
  2026. xfs_mount_t *mp;
  2027. xfs_trans_t *tp;
  2028. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2029. XFS_BMBT_TRACE_ARGI(cur, level);
  2030. ASSERT(level < cur->bc_nlevels);
  2031. if (level < cur->bc_nlevels - 1)
  2032. xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
  2033. block = xfs_bmbt_get_block(cur, level, &bp);
  2034. #ifdef DEBUG
  2035. if ((error = xfs_btree_check_lblock(cur, block, level, bp))) {
  2036. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2037. return error;
  2038. }
  2039. #endif
  2040. if (++cur->bc_ptrs[level] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
  2041. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2042. *stat = 1;
  2043. return 0;
  2044. }
  2045. if (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO) {
  2046. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2047. *stat = 0;
  2048. return 0;
  2049. }
  2050. for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
  2051. block = xfs_bmbt_get_block(cur, lev, &bp);
  2052. #ifdef DEBUG
  2053. if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
  2054. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2055. return error;
  2056. }
  2057. #endif
  2058. if (++cur->bc_ptrs[lev] <= INT_GET(block->bb_numrecs, ARCH_CONVERT))
  2059. break;
  2060. if (lev < cur->bc_nlevels - 1)
  2061. xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
  2062. }
  2063. if (lev == cur->bc_nlevels) {
  2064. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2065. *stat = 0;
  2066. return 0;
  2067. }
  2068. tp = cur->bc_tp;
  2069. mp = cur->bc_mp;
  2070. for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) {
  2071. fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
  2072. if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp,
  2073. XFS_BMAP_BTREE_REF))) {
  2074. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2075. return error;
  2076. }
  2077. lev--;
  2078. xfs_btree_setbuf(cur, lev, bp);
  2079. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  2080. if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) {
  2081. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2082. return error;
  2083. }
  2084. cur->bc_ptrs[lev] = 1;
  2085. }
  2086. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2087. *stat = 1;
  2088. return 0;
  2089. }
  2090. /*
  2091. * Insert the current record at the point referenced by cur.
  2092. */
  2093. int /* error */
  2094. xfs_bmbt_insert(
  2095. xfs_btree_cur_t *cur,
  2096. int *stat) /* success/failure */
  2097. {
  2098. int error; /* error return value */
  2099. #ifdef XFS_BMBT_TRACE
  2100. static char fname[] = "xfs_bmbt_insert";
  2101. #endif
  2102. int i;
  2103. int level;
  2104. xfs_fsblock_t nbno;
  2105. xfs_btree_cur_t *ncur;
  2106. xfs_bmbt_rec_t nrec;
  2107. xfs_btree_cur_t *pcur;
  2108. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2109. level = 0;
  2110. nbno = NULLFSBLOCK;
  2111. xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b);
  2112. ncur = (xfs_btree_cur_t *)0;
  2113. pcur = cur;
  2114. do {
  2115. if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur,
  2116. &i))) {
  2117. if (pcur != cur)
  2118. xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
  2119. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2120. return error;
  2121. }
  2122. XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
  2123. if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) {
  2124. cur->bc_nlevels = pcur->bc_nlevels;
  2125. cur->bc_private.b.allocated +=
  2126. pcur->bc_private.b.allocated;
  2127. pcur->bc_private.b.allocated = 0;
  2128. ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) ||
  2129. (cur->bc_private.b.ip->i_d.di_flags &
  2130. XFS_DIFLAG_REALTIME));
  2131. cur->bc_private.b.firstblock =
  2132. pcur->bc_private.b.firstblock;
  2133. ASSERT(cur->bc_private.b.flist ==
  2134. pcur->bc_private.b.flist);
  2135. xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
  2136. }
  2137. if (ncur) {
  2138. pcur = ncur;
  2139. ncur = (xfs_btree_cur_t *)0;
  2140. }
  2141. } while (nbno != NULLFSBLOCK);
  2142. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2143. *stat = i;
  2144. return 0;
  2145. error0:
  2146. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2147. return error;
  2148. }
  2149. /*
  2150. * Log fields from the btree block header.
  2151. */
  2152. void
  2153. xfs_bmbt_log_block(
  2154. xfs_btree_cur_t *cur,
  2155. xfs_buf_t *bp,
  2156. int fields)
  2157. {
  2158. int first;
  2159. #ifdef XFS_BMBT_TRACE
  2160. static char fname[] = "xfs_bmbt_log_block";
  2161. #endif
  2162. int last;
  2163. xfs_trans_t *tp;
  2164. static const short offsets[] = {
  2165. offsetof(xfs_bmbt_block_t, bb_magic),
  2166. offsetof(xfs_bmbt_block_t, bb_level),
  2167. offsetof(xfs_bmbt_block_t, bb_numrecs),
  2168. offsetof(xfs_bmbt_block_t, bb_leftsib),
  2169. offsetof(xfs_bmbt_block_t, bb_rightsib),
  2170. sizeof(xfs_bmbt_block_t)
  2171. };
  2172. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2173. XFS_BMBT_TRACE_ARGBI(cur, bp, fields);
  2174. tp = cur->bc_tp;
  2175. if (bp) {
  2176. xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first,
  2177. &last);
  2178. xfs_trans_log_buf(tp, bp, first, last);
  2179. } else
  2180. xfs_trans_log_inode(tp, cur->bc_private.b.ip,
  2181. XFS_ILOG_FBROOT(cur->bc_private.b.whichfork));
  2182. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2183. }
  2184. /*
  2185. * Log record values from the btree block.
  2186. */
  2187. void
  2188. xfs_bmbt_log_recs(
  2189. xfs_btree_cur_t *cur,
  2190. xfs_buf_t *bp,
  2191. int rfirst,
  2192. int rlast)
  2193. {
  2194. xfs_bmbt_block_t *block;
  2195. int first;
  2196. #ifdef XFS_BMBT_TRACE
  2197. static char fname[] = "xfs_bmbt_log_recs";
  2198. #endif
  2199. int last;
  2200. xfs_bmbt_rec_t *rp;
  2201. xfs_trans_t *tp;
  2202. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2203. XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast);
  2204. ASSERT(bp);
  2205. tp = cur->bc_tp;
  2206. block = XFS_BUF_TO_BMBT_BLOCK(bp);
  2207. rp = XFS_BMAP_REC_DADDR(block, 1, cur);
  2208. first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
  2209. last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
  2210. xfs_trans_log_buf(tp, bp, first, last);
  2211. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2212. }
  2213. int /* error */
  2214. xfs_bmbt_lookup_eq(
  2215. xfs_btree_cur_t *cur,
  2216. xfs_fileoff_t off,
  2217. xfs_fsblock_t bno,
  2218. xfs_filblks_t len,
  2219. int *stat) /* success/failure */
  2220. {
  2221. cur->bc_rec.b.br_startoff = off;
  2222. cur->bc_rec.b.br_startblock = bno;
  2223. cur->bc_rec.b.br_blockcount = len;
  2224. return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);
  2225. }
  2226. int /* error */
  2227. xfs_bmbt_lookup_ge(
  2228. xfs_btree_cur_t *cur,
  2229. xfs_fileoff_t off,
  2230. xfs_fsblock_t bno,
  2231. xfs_filblks_t len,
  2232. int *stat) /* success/failure */
  2233. {
  2234. cur->bc_rec.b.br_startoff = off;
  2235. cur->bc_rec.b.br_startblock = bno;
  2236. cur->bc_rec.b.br_blockcount = len;
  2237. return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);
  2238. }
  2239. int /* error */
  2240. xfs_bmbt_lookup_le(
  2241. xfs_btree_cur_t *cur,
  2242. xfs_fileoff_t off,
  2243. xfs_fsblock_t bno,
  2244. xfs_filblks_t len,
  2245. int *stat) /* success/failure */
  2246. {
  2247. cur->bc_rec.b.br_startoff = off;
  2248. cur->bc_rec.b.br_startblock = bno;
  2249. cur->bc_rec.b.br_blockcount = len;
  2250. return xfs_bmbt_lookup(cur, XFS_LOOKUP_LE, stat);
  2251. }
  2252. /*
  2253. * Give the bmap btree a new root block. Copy the old broot contents
  2254. * down into a real block and make the broot point to it.
  2255. */
  2256. int /* error */
  2257. xfs_bmbt_newroot(
  2258. xfs_btree_cur_t *cur, /* btree cursor */
  2259. int *logflags, /* logging flags for inode */
  2260. int *stat) /* return status - 0 fail */
  2261. {
  2262. xfs_alloc_arg_t args; /* allocation arguments */
  2263. xfs_bmbt_block_t *block; /* bmap btree block */
  2264. xfs_buf_t *bp; /* buffer for block */
  2265. xfs_bmbt_block_t *cblock; /* child btree block */
  2266. xfs_bmbt_key_t *ckp; /* child key pointer */
  2267. xfs_bmbt_ptr_t *cpp; /* child ptr pointer */
  2268. int error; /* error return code */
  2269. #ifdef XFS_BMBT_TRACE
  2270. static char fname[] = "xfs_bmbt_newroot";
  2271. #endif
  2272. #ifdef DEBUG
  2273. int i; /* loop counter */
  2274. #endif
  2275. xfs_bmbt_key_t *kp; /* pointer to bmap btree key */
  2276. int level; /* btree level */
  2277. xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */
  2278. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2279. level = cur->bc_nlevels - 1;
  2280. block = xfs_bmbt_get_block(cur, level, &bp);
  2281. /*
  2282. * Copy the root into a real block.
  2283. */
  2284. args.mp = cur->bc_mp;
  2285. pp = XFS_BMAP_PTR_IADDR(block, 1, cur);
  2286. args.tp = cur->bc_tp;
  2287. args.fsbno = cur->bc_private.b.firstblock;
  2288. args.mod = args.minleft = args.alignment = args.total = args.isfl =
  2289. args.userdata = args.minalignslop = 0;
  2290. args.minlen = args.maxlen = args.prod = 1;
  2291. args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL;
  2292. if (args.fsbno == NULLFSBLOCK) {
  2293. #ifdef DEBUG
  2294. if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) {
  2295. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2296. return error;
  2297. }
  2298. #endif
  2299. args.fsbno = INT_GET(*pp, ARCH_CONVERT);
  2300. args.type = XFS_ALLOCTYPE_START_BNO;
  2301. } else if (args.wasdel)
  2302. args.type = XFS_ALLOCTYPE_FIRST_AG;
  2303. else
  2304. args.type = XFS_ALLOCTYPE_NEAR_BNO;
  2305. if ((error = xfs_alloc_vextent(&args))) {
  2306. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2307. return error;
  2308. }
  2309. if (args.fsbno == NULLFSBLOCK) {
  2310. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2311. *stat = 0;
  2312. return 0;
  2313. }
  2314. ASSERT(args.len == 1);
  2315. cur->bc_private.b.firstblock = args.fsbno;
  2316. cur->bc_private.b.allocated++;
  2317. cur->bc_private.b.ip->i_d.di_nblocks++;
  2318. XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip,
  2319. XFS_TRANS_DQ_BCOUNT, 1L);
  2320. bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0);
  2321. cblock = XFS_BUF_TO_BMBT_BLOCK(bp);
  2322. *cblock = *block;
  2323. INT_MOD(block->bb_level, ARCH_CONVERT, +1);
  2324. INT_SET(block->bb_numrecs, ARCH_CONVERT, 1);
  2325. cur->bc_nlevels++;
  2326. cur->bc_ptrs[level + 1] = 1;
  2327. kp = XFS_BMAP_KEY_IADDR(block, 1, cur);
  2328. ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur);
  2329. memcpy(ckp, kp, INT_GET(cblock->bb_numrecs, ARCH_CONVERT) * sizeof(*kp));
  2330. cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);
  2331. #ifdef DEBUG
  2332. for (i = 0; i < INT_GET(cblock->bb_numrecs, ARCH_CONVERT); i++) {
  2333. if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) {
  2334. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2335. return error;
  2336. }
  2337. }
  2338. #endif
  2339. memcpy(cpp, pp, INT_GET(cblock->bb_numrecs, ARCH_CONVERT) * sizeof(*pp));
  2340. #ifdef DEBUG
  2341. if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno,
  2342. level))) {
  2343. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2344. return error;
  2345. }
  2346. #endif
  2347. INT_SET(*pp, ARCH_CONVERT, args.fsbno);
  2348. xfs_iroot_realloc(cur->bc_private.b.ip, 1 - INT_GET(cblock->bb_numrecs, ARCH_CONVERT),
  2349. cur->bc_private.b.whichfork);
  2350. xfs_btree_setbuf(cur, level, bp);
  2351. /*
  2352. * Do all this logging at the end so that
  2353. * the root is at the right level.
  2354. */
  2355. xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS);
  2356. xfs_bmbt_log_keys(cur, bp, 1, INT_GET(cblock->bb_numrecs, ARCH_CONVERT));
  2357. xfs_bmbt_log_ptrs(cur, bp, 1, INT_GET(cblock->bb_numrecs, ARCH_CONVERT));
  2358. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2359. *logflags |=
  2360. XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork);
  2361. *stat = 1;
  2362. return 0;
  2363. }
  2364. /*
  2365. * Set all the fields in a bmap extent record from the uncompressed form.
  2366. */
  2367. void
  2368. xfs_bmbt_set_all(
  2369. xfs_bmbt_rec_t *r,
  2370. xfs_bmbt_irec_t *s)
  2371. {
  2372. int extent_flag;
  2373. ASSERT((s->br_state == XFS_EXT_NORM) ||
  2374. (s->br_state == XFS_EXT_UNWRITTEN));
  2375. extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
  2376. ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
  2377. ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
  2378. #if XFS_BIG_BLKNOS
  2379. ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
  2380. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2381. ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
  2382. ((xfs_bmbt_rec_base_t)s->br_startblock >> 43);
  2383. r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2384. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2385. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2386. #else /* !XFS_BIG_BLKNOS */
  2387. if (ISNULLSTARTBLOCK(s->br_startblock)) {
  2388. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2389. ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
  2390. (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
  2391. r->l1 = XFS_MASK64HI(11) |
  2392. ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2393. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2394. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2395. } else {
  2396. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2397. ((xfs_bmbt_rec_base_t)s->br_startoff << 9);
  2398. r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2399. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2400. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2401. }
  2402. #endif /* XFS_BIG_BLKNOS */
  2403. }
  2404. /*
  2405. * Set all the fields in a bmap extent record from the arguments.
  2406. */
  2407. void
  2408. xfs_bmbt_set_allf(
  2409. xfs_bmbt_rec_t *r,
  2410. xfs_fileoff_t o,
  2411. xfs_fsblock_t b,
  2412. xfs_filblks_t c,
  2413. xfs_exntst_t v)
  2414. {
  2415. int extent_flag;
  2416. ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
  2417. extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
  2418. ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
  2419. ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
  2420. #if XFS_BIG_BLKNOS
  2421. ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
  2422. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2423. ((xfs_bmbt_rec_base_t)o << 9) |
  2424. ((xfs_bmbt_rec_base_t)b >> 43);
  2425. r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
  2426. ((xfs_bmbt_rec_base_t)c &
  2427. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2428. #else /* !XFS_BIG_BLKNOS */
  2429. if (ISNULLSTARTBLOCK(b)) {
  2430. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2431. ((xfs_bmbt_rec_base_t)o << 9) |
  2432. (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
  2433. r->l1 = XFS_MASK64HI(11) |
  2434. ((xfs_bmbt_rec_base_t)b << 21) |
  2435. ((xfs_bmbt_rec_base_t)c &
  2436. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2437. } else {
  2438. r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2439. ((xfs_bmbt_rec_base_t)o << 9);
  2440. r->l1 = ((xfs_bmbt_rec_base_t)b << 21) |
  2441. ((xfs_bmbt_rec_base_t)c &
  2442. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2443. }
  2444. #endif /* XFS_BIG_BLKNOS */
  2445. }
  2446. #if __BYTE_ORDER != __BIG_ENDIAN
  2447. /*
  2448. * Set all the fields in a bmap extent record from the uncompressed form.
  2449. */
  2450. void
  2451. xfs_bmbt_disk_set_all(
  2452. xfs_bmbt_rec_t *r,
  2453. xfs_bmbt_irec_t *s)
  2454. {
  2455. int extent_flag;
  2456. ASSERT((s->br_state == XFS_EXT_NORM) ||
  2457. (s->br_state == XFS_EXT_UNWRITTEN));
  2458. extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1;
  2459. ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0);
  2460. ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0);
  2461. #if XFS_BIG_BLKNOS
  2462. ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0);
  2463. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2464. ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
  2465. ((xfs_bmbt_rec_base_t)s->br_startblock >> 43));
  2466. INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2467. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2468. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2469. #else /* !XFS_BIG_BLKNOS */
  2470. if (ISNULLSTARTBLOCK(s->br_startblock)) {
  2471. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2472. ((xfs_bmbt_rec_base_t)s->br_startoff << 9) |
  2473. (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
  2474. INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
  2475. ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2476. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2477. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2478. } else {
  2479. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2480. ((xfs_bmbt_rec_base_t)s->br_startoff << 9));
  2481. INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) |
  2482. ((xfs_bmbt_rec_base_t)s->br_blockcount &
  2483. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2484. }
  2485. #endif /* XFS_BIG_BLKNOS */
  2486. }
  2487. /*
  2488. * Set all the fields in a disk format bmap extent record from the arguments.
  2489. */
  2490. void
  2491. xfs_bmbt_disk_set_allf(
  2492. xfs_bmbt_rec_t *r,
  2493. xfs_fileoff_t o,
  2494. xfs_fsblock_t b,
  2495. xfs_filblks_t c,
  2496. xfs_exntst_t v)
  2497. {
  2498. int extent_flag;
  2499. ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN));
  2500. extent_flag = (v == XFS_EXT_NORM) ? 0 : 1;
  2501. ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0);
  2502. ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);
  2503. #if XFS_BIG_BLKNOS
  2504. ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0);
  2505. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2506. ((xfs_bmbt_rec_base_t)o << 9) |
  2507. ((xfs_bmbt_rec_base_t)b >> 43));
  2508. INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
  2509. ((xfs_bmbt_rec_base_t)c &
  2510. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2511. #else /* !XFS_BIG_BLKNOS */
  2512. if (ISNULLSTARTBLOCK(b)) {
  2513. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2514. ((xfs_bmbt_rec_base_t)o << 9) |
  2515. (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
  2516. INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) |
  2517. ((xfs_bmbt_rec_base_t)b << 21) |
  2518. ((xfs_bmbt_rec_base_t)c &
  2519. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2520. } else {
  2521. INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) |
  2522. ((xfs_bmbt_rec_base_t)o << 9));
  2523. INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) |
  2524. ((xfs_bmbt_rec_base_t)c &
  2525. (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));
  2526. }
  2527. #endif /* XFS_BIG_BLKNOS */
  2528. }
  2529. #endif
  2530. /*
  2531. * Set the blockcount field in a bmap extent record.
  2532. */
  2533. void
  2534. xfs_bmbt_set_blockcount(
  2535. xfs_bmbt_rec_t *r,
  2536. xfs_filblks_t v)
  2537. {
  2538. ASSERT((v & XFS_MASK64HI(43)) == 0);
  2539. r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) |
  2540. (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21));
  2541. }
  2542. /*
  2543. * Set the startblock field in a bmap extent record.
  2544. */
  2545. void
  2546. xfs_bmbt_set_startblock(
  2547. xfs_bmbt_rec_t *r,
  2548. xfs_fsblock_t v)
  2549. {
  2550. #if XFS_BIG_BLKNOS
  2551. ASSERT((v & XFS_MASK64HI(12)) == 0);
  2552. r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) |
  2553. (xfs_bmbt_rec_base_t)(v >> 43);
  2554. r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) |
  2555. (xfs_bmbt_rec_base_t)(v << 21);
  2556. #else /* !XFS_BIG_BLKNOS */
  2557. if (ISNULLSTARTBLOCK(v)) {
  2558. r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
  2559. r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) |
  2560. ((xfs_bmbt_rec_base_t)v << 21) |
  2561. (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2562. } else {
  2563. r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9);
  2564. r->l1 = ((xfs_bmbt_rec_base_t)v << 21) |
  2565. (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));
  2566. }
  2567. #endif /* XFS_BIG_BLKNOS */
  2568. }
  2569. /*
  2570. * Set the startoff field in a bmap extent record.
  2571. */
  2572. void
  2573. xfs_bmbt_set_startoff(
  2574. xfs_bmbt_rec_t *r,
  2575. xfs_fileoff_t v)
  2576. {
  2577. ASSERT((v & XFS_MASK64HI(9)) == 0);
  2578. r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) |
  2579. ((xfs_bmbt_rec_base_t)v << 9) |
  2580. (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9));
  2581. }
  2582. /*
  2583. * Set the extent state field in a bmap extent record.
  2584. */
  2585. void
  2586. xfs_bmbt_set_state(
  2587. xfs_bmbt_rec_t *r,
  2588. xfs_exntst_t v)
  2589. {
  2590. ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN);
  2591. if (v == XFS_EXT_NORM)
  2592. r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN);
  2593. else
  2594. r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN);
  2595. }
  2596. /*
  2597. * Convert in-memory form of btree root to on-disk form.
  2598. */
  2599. void
  2600. xfs_bmbt_to_bmdr(
  2601. xfs_bmbt_block_t *rblock,
  2602. int rblocklen,
  2603. xfs_bmdr_block_t *dblock,
  2604. int dblocklen)
  2605. {
  2606. int dmxr;
  2607. xfs_bmbt_key_t *fkp;
  2608. xfs_bmbt_ptr_t *fpp;
  2609. xfs_bmbt_key_t *tkp;
  2610. xfs_bmbt_ptr_t *tpp;
  2611. ASSERT(INT_GET(rblock->bb_magic, ARCH_CONVERT) == XFS_BMAP_MAGIC);
  2612. ASSERT(INT_GET(rblock->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO);
  2613. ASSERT(INT_GET(rblock->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO);
  2614. ASSERT(INT_GET(rblock->bb_level, ARCH_CONVERT) > 0);
  2615. dblock->bb_level = rblock->bb_level; /* both in on-disk format */
  2616. dblock->bb_numrecs = rblock->bb_numrecs;/* both in on-disk format */
  2617. dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0);
  2618. fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen);
  2619. tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
  2620. fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen);
  2621. tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr);
  2622. dmxr = INT_GET(dblock->bb_numrecs, ARCH_CONVERT);
  2623. memcpy(tkp, fkp, sizeof(*fkp) * dmxr);
  2624. memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */
  2625. }
  2626. /*
  2627. * Update the record to the passed values.
  2628. */
  2629. int
  2630. xfs_bmbt_update(
  2631. xfs_btree_cur_t *cur,
  2632. xfs_fileoff_t off,
  2633. xfs_fsblock_t bno,
  2634. xfs_filblks_t len,
  2635. xfs_exntst_t state)
  2636. {
  2637. xfs_bmbt_block_t *block;
  2638. xfs_buf_t *bp;
  2639. int error;
  2640. #ifdef XFS_BMBT_TRACE
  2641. static char fname[] = "xfs_bmbt_update";
  2642. #endif
  2643. xfs_bmbt_key_t key;
  2644. int ptr;
  2645. xfs_bmbt_rec_t *rp;
  2646. XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
  2647. XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
  2648. (xfs_dfilblks_t)len, (int)state);
  2649. block = xfs_bmbt_get_block(cur, 0, &bp);
  2650. #ifdef DEBUG
  2651. if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
  2652. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2653. return error;
  2654. }
  2655. #endif
  2656. ptr = cur->bc_ptrs[0];
  2657. rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
  2658. xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
  2659. xfs_bmbt_log_recs(cur, bp, ptr, ptr);
  2660. if (ptr > 1) {
  2661. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2662. return 0;
  2663. }
  2664. INT_SET(key.br_startoff, ARCH_CONVERT, off);
  2665. if ((error = xfs_bmbt_updkey(cur, &key, 1))) {
  2666. XFS_BMBT_TRACE_CURSOR(cur, ERROR);
  2667. return error;
  2668. }
  2669. XFS_BMBT_TRACE_CURSOR(cur, EXIT);
  2670. return 0;
  2671. }
  2672. /*
  2673. * Check an extent list, which has just been read, for
  2674. * any bit in the extent flag field. ASSERT on debug
  2675. * kernels, as this condition should not occur.
  2676. * Return an error condition (1) if any flags found,
  2677. * otherwise return 0.
  2678. */
  2679. int
  2680. xfs_check_nostate_extents(
  2681. xfs_bmbt_rec_t *ep,
  2682. xfs_extnum_t num)
  2683. {
  2684. for (; num > 0; num--, ep++) {
  2685. if ((ep->l0 >>
  2686. (64 - BMBT_EXNTFLAG_BITLEN)) != 0) {
  2687. ASSERT(0);
  2688. return 1;
  2689. }
  2690. }
  2691. return 0;
  2692. }