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