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