]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - libxfs/xfs_alloc_btree.c
Merge whitespace changes over
[thirdparty/xfsprogs-dev.git] / libxfs / xfs_alloc_btree.c
CommitLineData
2bd0ea18 1/*
0d3e0b37 2 * Copyright (c) 2000-2001 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/*
34 * Free space allocation for XFS.
35 */
36
37#include <xfs.h>
38
39/*
40 * Single level of the xfs_alloc_delete record deletion routine.
41 * Delete record pointed to by cur/level.
42 * Remove the record from its block then rebalance the tree.
43 * Return 0 for error, 1 for done, 2 to go on to the next level.
44 */
45STATIC int /* error */
46xfs_alloc_delrec(
47 xfs_btree_cur_t *cur, /* btree cursor */
48 int level, /* level removing record from */
49 int *stat) /* fail/done/go-on */
50{
51 xfs_agf_t *agf; /* allocation group freelist header */
dfc130f3 52 xfs_alloc_block_t *block; /* btree block record/key lives in */
2bd0ea18
NS
53 xfs_agblock_t bno; /* btree block number */
54 xfs_buf_t *bp; /* buffer for block */
55 int error; /* error return value */
56 int i; /* loop index */
57 xfs_alloc_key_t key; /* kp points here if block is level 0 */
58 xfs_agblock_t lbno; /* left block's block number */
59 xfs_buf_t *lbp; /* left block's buffer pointer */
60 xfs_alloc_block_t *left; /* left btree block */
0e266570
NS
61 xfs_alloc_key_t *lkp=NULL; /* left block key pointer */
62 xfs_alloc_ptr_t *lpp=NULL; /* left block address pointer */
63 int lrecs=0; /* number of records in left block */
2bd0ea18
NS
64 xfs_alloc_rec_t *lrp; /* left block record pointer */
65 xfs_mount_t *mp; /* mount structure */
66 int ptr; /* index in btree block for this rec */
67 xfs_agblock_t rbno; /* right block's block number */
68 xfs_buf_t *rbp; /* right block's buffer pointer */
dfc130f3 69 xfs_alloc_block_t *right; /* right btree block */
2bd0ea18
NS
70 xfs_alloc_key_t *rkp; /* right block key pointer */
71 xfs_alloc_ptr_t *rpp; /* right block address pointer */
0e266570 72 int rrecs=0; /* number of records in right block */
2bd0ea18
NS
73 xfs_alloc_rec_t *rrp; /* right block record pointer */
74 xfs_btree_cur_t *tcur; /* temporary btree cursor */
75
76 /*
77 * Get the index of the entry being deleted, check for nothing there.
78 */
79 ptr = cur->bc_ptrs[level];
80 if (ptr == 0) {
81 *stat = 0;
82 return 0;
83 }
84 /*
85 * Get the buffer & block containing the record or key/ptr.
86 */
87 bp = cur->bc_bufs[level];
88 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
89#ifdef DEBUG
0e266570 90 if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
2bd0ea18
NS
91 return error;
92#endif
93 /*
94 * Fail if we're off the end of the block.
95 */
96 if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
97 *stat = 0;
98 return 0;
99 }
7a3bffe4 100 XFS_STATS_INC(xfsstats.xs_abt_delrec);
2bd0ea18
NS
101 /*
102 * It's a nonleaf. Excise the key and ptr being deleted, by
103 * sliding the entries past them down one.
104 * Log the changed areas of the block.
105 */
106 if (level > 0) {
107 lkp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
108 lpp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
109#ifdef DEBUG
110 for (i = ptr; i < INT_GET(block->bb_numrecs, ARCH_CONVERT); i++) {
0e266570 111 if ((error = xfs_btree_check_sptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level)))
2bd0ea18
NS
112 return error;
113 }
114#endif
115 if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
32181a02 116 memmove(&lkp[ptr - 1], &lkp[ptr],
2bd0ea18 117 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lkp)); /* INT_: mem copy */
32181a02 118 memmove(&lpp[ptr - 1], &lpp[ptr],
2bd0ea18
NS
119 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lpp)); /* INT_: mem copy */
120 xfs_alloc_log_ptrs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
121 xfs_alloc_log_keys(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
122 }
123 }
124 /*
dfc130f3 125 * It's a leaf. Excise the record being deleted, by sliding the
2bd0ea18
NS
126 * entries past it down one. Log the changed areas of the block.
127 */
128 else {
129 lrp = XFS_ALLOC_REC_ADDR(block, 1, cur);
130 if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
32181a02 131 memmove(&lrp[ptr - 1], &lrp[ptr],
2bd0ea18
NS
132 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr) * sizeof(*lrp));
133 xfs_alloc_log_recs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT) - 1);
134 }
135 /*
136 * If it's the first record in the block, we'll need a key
137 * structure to pass up to the next level (updkey).
138 */
139 if (ptr == 1) {
140 key.ar_startblock = lrp->ar_startblock; /* INT_: direct copy */
141 key.ar_blockcount = lrp->ar_blockcount; /* INT_: direct copy */
142 lkp = &key;
143 }
144 }
145 /*
146 * Decrement and log the number of entries in the block.
147 */
148 INT_MOD(block->bb_numrecs, ARCH_CONVERT, -1);
149 xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
150 /*
151 * See if the longest free extent in the allocation group was
152 * changed by this operation. True if it's the by-size btree, and
153 * this is the leaf level, and there is no right sibling block,
154 * and this was the last record.
155 */
156 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
157 mp = cur->bc_mp;
158
159 if (level == 0 &&
160 cur->bc_btnum == XFS_BTNUM_CNT &&
161 INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
162 ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
163 ASSERT(ptr == INT_GET(block->bb_numrecs, ARCH_CONVERT) + 1);
164 /*
165 * There are still records in the block. Grab the size
166 * from the last one.
167 */
168 if (INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
169 rrp = XFS_ALLOC_REC_ADDR(block, INT_GET(block->bb_numrecs, ARCH_CONVERT), cur);
170 INT_COPY(agf->agf_longest, rrp->ar_blockcount, ARCH_CONVERT);
171 }
172 /*
173 * No free extents left.
174 */
175 else
176 INT_ZERO(agf->agf_longest, ARCH_CONVERT);
177 mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_longest =
178 INT_GET(agf->agf_longest, ARCH_CONVERT);
179 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
180 XFS_AGF_LONGEST);
181 }
182 /*
183 * Is this the root level? If so, we're almost done.
184 */
185 if (level == cur->bc_nlevels - 1) {
186 /*
187 * If this is the root level,
188 * and there's only one entry left,
189 * and it's NOT the leaf level,
190 * then we can get rid of this level.
191 */
192 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) == 1 && level > 0) {
193 /*
194 * lpp is still set to the first pointer in the block.
195 * Make it the new root of the btree.
196 */
197 bno = INT_GET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT);
198 INT_COPY(agf->agf_roots[cur->bc_btnum], *lpp, ARCH_CONVERT);
199 INT_MOD(agf->agf_levels[cur->bc_btnum], ARCH_CONVERT, -1);
200 mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_levels[cur->bc_btnum]--;
201 /*
202 * Put this buffer/block on the ag's freelist.
203 */
0e266570
NS
204 if ((error = xfs_alloc_put_freelist(cur->bc_tp,
205 cur->bc_private.a.agbp, NULL, bno)))
2bd0ea18 206 return error;
f9e56f43
NS
207 /*
208 * Since blocks move to the free list without the
209 * coordination used in xfs_bmap_finish, we can't allow
210 * block to be available for reallocation and
211 * non-transaction writing (user data) until we know
212 * that the transaction that moved it to the free list
213 * is permanently on disk. We track the blocks by
214 * declaring these blocks as "busy"; the busy list is
215 * maintained on a per-ag basis and each transaction
216 * records which entries should be removed when the
217 * iclog commits to disk. If a busy block is
218 * allocated, the iclog is pushed up to the LSN
219 * that freed the block.
220 */
221 xfs_alloc_mark_busy(cur->bc_tp,
222 INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
223
2bd0ea18
NS
224 xfs_trans_agbtree_delta(cur->bc_tp, -1);
225 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
226 XFS_AGF_ROOTS | XFS_AGF_LEVELS);
227 /*
228 * Update the cursor so there's one fewer level.
229 */
230 xfs_btree_setbuf(cur, level, 0);
231 cur->bc_nlevels--;
232 } else if (level > 0 &&
233 (error = xfs_alloc_decrement(cur, level, &i)))
234 return error;
235 *stat = 1;
236 return 0;
237 }
238 /*
239 * If we deleted the leftmost entry in the block, update the
240 * key values above us in the tree.
241 */
242 if (ptr == 1 && (error = xfs_alloc_updkey(cur, lkp, level + 1)))
243 return error;
244 /*
245 * If the number of records remaining in the block is at least
246 * the minimum, we're done.
247 */
248 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) >= XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
249 if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
250 return error;
251 *stat = 1;
252 return 0;
253 }
254 /*
255 * Otherwise, we have to move some records around to keep the
256 * tree balanced. Look at the left and right sibling blocks to
257 * see if we can re-balance by moving only one record.
258 */
259 rbno = INT_GET(block->bb_rightsib, ARCH_CONVERT);
260 lbno = INT_GET(block->bb_leftsib, ARCH_CONVERT);
261 bno = NULLAGBLOCK;
262 ASSERT(rbno != NULLAGBLOCK || lbno != NULLAGBLOCK);
263 /*
264 * Duplicate the cursor so our btree manipulations here won't
265 * disrupt the next level up.
266 */
0e266570 267 if ((error = xfs_btree_dup_cursor(cur, &tcur)))
2bd0ea18
NS
268 return error;
269 /*
270 * If there's a right sibling, see if it's ok to shift an entry
271 * out of it.
272 */
273 if (rbno != NULLAGBLOCK) {
274 /*
275 * Move the temp cursor to the last entry in the next block.
276 * Actually any entry but the first would suffice.
277 */
278 i = xfs_btree_lastrec(tcur, level);
279 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
0e266570 280 if ((error = xfs_alloc_increment(tcur, level, &i)))
2bd0ea18
NS
281 goto error0;
282 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
283 i = xfs_btree_lastrec(tcur, level);
284 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
285 /*
286 * Grab a pointer to the block.
287 */
288 rbp = tcur->bc_bufs[level];
289 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
290#ifdef DEBUG
0e266570 291 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
2bd0ea18
NS
292 goto error0;
293#endif
294 /*
295 * Grab the current block number, for future use.
296 */
297 bno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
298 /*
299 * If right block is full enough so that removing one entry
300 * won't make it too empty, and left-shifting an entry out
301 * of right to us works, we're done.
302 */
303 if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >=
304 XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
0e266570 305 if ((error = xfs_alloc_lshift(tcur, level, &i)))
2bd0ea18
NS
306 goto error0;
307 if (i) {
308 ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
309 XFS_ALLOC_BLOCK_MINRECS(level, cur));
310 xfs_btree_del_cursor(tcur,
311 XFS_BTREE_NOERROR);
312 if (level > 0 &&
313 (error = xfs_alloc_decrement(cur, level,
314 &i)))
315 return error;
316 *stat = 1;
317 return 0;
318 }
319 }
320 /*
321 * Otherwise, grab the number of records in right for
5000d01d 322 * future reference, and fix up the temp cursor to point
2bd0ea18
NS
323 * to our block again (last record).
324 */
325 rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT);
326 if (lbno != NULLAGBLOCK) {
327 i = xfs_btree_firstrec(tcur, level);
328 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
0e266570 329 if ((error = xfs_alloc_decrement(tcur, level, &i)))
2bd0ea18
NS
330 goto error0;
331 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
332 }
333 }
334 /*
335 * If there's a left sibling, see if it's ok to shift an entry
336 * out of it.
337 */
338 if (lbno != NULLAGBLOCK) {
339 /*
340 * Move the temp cursor to the first entry in the
341 * previous block.
342 */
343 i = xfs_btree_firstrec(tcur, level);
344 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
0e266570 345 if ((error = xfs_alloc_decrement(tcur, level, &i)))
2bd0ea18
NS
346 goto error0;
347 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
348 xfs_btree_firstrec(tcur, level);
349 /*
350 * Grab a pointer to the block.
351 */
352 lbp = tcur->bc_bufs[level];
353 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
354#ifdef DEBUG
0e266570 355 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
2bd0ea18
NS
356 goto error0;
357#endif
358 /*
359 * Grab the current block number, for future use.
360 */
361 bno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
362 /*
363 * If left block is full enough so that removing one entry
364 * won't make it too empty, and right-shifting an entry out
365 * of left to us works, we're done.
366 */
367 if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >=
368 XFS_ALLOC_BLOCK_MINRECS(level, cur)) {
0e266570 369 if ((error = xfs_alloc_rshift(tcur, level, &i)))
2bd0ea18
NS
370 goto error0;
371 if (i) {
372 ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >=
373 XFS_ALLOC_BLOCK_MINRECS(level, cur));
374 xfs_btree_del_cursor(tcur,
375 XFS_BTREE_NOERROR);
376 if (level == 0)
377 cur->bc_ptrs[0]++;
378 *stat = 1;
379 return 0;
380 }
381 }
382 /*
383 * Otherwise, grab the number of records in right for
384 * future reference.
385 */
386 lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT);
387 }
388 /*
389 * Delete the temp cursor, we're done with it.
390 */
391 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
392 /*
393 * If here, we need to do a join to keep the tree balanced.
394 */
395 ASSERT(bno != NULLAGBLOCK);
396 /*
397 * See if we can join with the left neighbor block.
398 */
399 if (lbno != NULLAGBLOCK &&
400 lrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
401 /*
402 * Set "right" to be the starting block,
403 * "left" to be the left neighbor.
404 */
405 rbno = bno;
406 right = block;
407 rbp = bp;
0e266570 408 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
2bd0ea18 409 cur->bc_private.a.agno, lbno, 0, &lbp,
0e266570 410 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
411 return error;
412 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
0e266570 413 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
2bd0ea18
NS
414 return error;
415 }
416 /*
417 * If that won't work, see if we can join with the right neighbor block.
418 */
419 else if (rbno != NULLAGBLOCK &&
420 rrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <=
421 XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
422 /*
423 * Set "left" to be the starting block,
424 * "right" to be the right neighbor.
425 */
426 lbno = bno;
427 left = block;
428 lbp = bp;
0e266570 429 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
2bd0ea18 430 cur->bc_private.a.agno, rbno, 0, &rbp,
0e266570 431 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
432 return error;
433 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
0e266570 434 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
2bd0ea18
NS
435 return error;
436 }
437 /*
438 * Otherwise, we can't fix the imbalance.
dfc130f3 439 * Just return. This is probably a logic error, but it's not fatal.
2bd0ea18
NS
440 */
441 else {
442 if (level > 0 && (error = xfs_alloc_decrement(cur, level, &i)))
443 return error;
444 *stat = 1;
445 return 0;
446 }
447 /*
448 * We're now going to join "left" and "right" by moving all the stuff
449 * in "right" to "left" and deleting "right".
450 */
451 if (level > 0) {
452 /*
453 * It's a non-leaf. Move keys and pointers.
454 */
455 lkp = XFS_ALLOC_KEY_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
456 lpp = XFS_ALLOC_PTR_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
457 rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
458 rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
459#ifdef DEBUG
460 for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
0e266570 461 if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
2bd0ea18
NS
462 return error;
463 }
464#endif
32181a02
NS
465 memcpy(lkp, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lkp)); /* INT_: structure copy */
466 memcpy(lpp, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lpp)); /* INT_: structure copy */
2bd0ea18
NS
467 xfs_alloc_log_keys(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
468 INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
469 xfs_alloc_log_ptrs(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
470 INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
471 } else {
472 /*
dfc130f3 473 * It's a leaf. Move records.
2bd0ea18
NS
474 */
475 lrp = XFS_ALLOC_REC_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1, cur);
476 rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
32181a02 477 memcpy(lrp, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*lrp));
2bd0ea18
NS
478 xfs_alloc_log_recs(cur, lbp, INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1,
479 INT_GET(left->bb_numrecs, ARCH_CONVERT) + INT_GET(right->bb_numrecs, ARCH_CONVERT));
480 }
481 /*
482 * If we joined with the left neighbor, set the buffer in the
483 * cursor to the left block, and fix up the index.
484 */
485 if (bp != lbp) {
486 xfs_btree_setbuf(cur, level, lbp);
487 cur->bc_ptrs[level] += INT_GET(left->bb_numrecs, ARCH_CONVERT);
488 }
489 /*
490 * If we joined with the right neighbor and there's a level above
491 * us, increment the cursor at that level.
492 */
493 else if (level + 1 < cur->bc_nlevels &&
494 (error = xfs_alloc_increment(cur, level + 1, &i)))
495 return error;
496 /*
497 * Fix up the number of records in the surviving block.
498 */
499 INT_MOD(left->bb_numrecs, ARCH_CONVERT, INT_GET(right->bb_numrecs, ARCH_CONVERT));
500 /*
501 * Fix up the right block pointer in the surviving block, and log it.
502 */
503 left->bb_rightsib = right->bb_rightsib; /* INT_: direct copy */
504 xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
505 /*
5000d01d 506 * If there is a right sibling now, make it point to the
2bd0ea18
NS
507 * remaining block.
508 */
509 if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
510 xfs_alloc_block_t *rrblock;
7a3bffe4 511 xfs_buf_t *rrbp;
2bd0ea18 512
0e266570 513 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
2bd0ea18 514 cur->bc_private.a.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0,
0e266570 515 &rrbp, XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
516 return error;
517 rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
0e266570 518 if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
2bd0ea18
NS
519 return error;
520 INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno);
521 xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
522 }
523 /*
524 * Free the deleting block by putting it on the freelist.
525 */
0e266570
NS
526 if ((error = xfs_alloc_put_freelist(cur->bc_tp, cur->bc_private.a.agbp,
527 NULL, rbno)))
2bd0ea18 528 return error;
f9e56f43
NS
529 /*
530 * Since blocks move to the free list without the coordination
531 * used in xfs_bmap_finish, we can't allow block to be available
532 * for reallocation and non-transaction writing (user data)
533 * until we know that the transaction that moved it to the free
534 * list is permanently on disk. We track the blocks by declaring
535 * these blocks as "busy"; the busy list is maintained on a
536 * per-ag basis and each transaction records which entries
537 * should be removed when the iclog commits to disk. If a
538 * busy block is allocated, the iclog is pushed up to the
539 * LSN that freed the block.
540 */
541 xfs_alloc_mark_busy(cur->bc_tp,
542 INT_GET(agf->agf_seqno, ARCH_CONVERT), bno, 1);
543
2bd0ea18
NS
544 xfs_trans_agbtree_delta(cur->bc_tp, -1);
545 /*
546 * Adjust the current level's cursor so that we're left referring
547 * to the right node, after we're done.
548 * If this leaves the ptr value 0 our caller will fix it up.
549 */
550 if (level > 0)
551 cur->bc_ptrs[level]--;
5000d01d 552 /*
2bd0ea18
NS
553 * Return value means the next level up has something to do.
554 */
555 *stat = 2;
556 return 0;
557
558error0:
559 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
560 return error;
561}
562
563/*
564 * Insert one record/level. Return information to the caller
565 * allowing the next level up to proceed if necessary.
566 */
567STATIC int /* error */
568xfs_alloc_insrec(
569 xfs_btree_cur_t *cur, /* btree cursor */
570 int level, /* level to insert record at */
571 xfs_agblock_t *bnop, /* i/o: block number inserted */
572 xfs_alloc_rec_t *recp, /* i/o: record data inserted */
dfc130f3 573 xfs_btree_cur_t **curp, /* output: new cursor replacing cur */
2bd0ea18
NS
574 int *stat) /* output: success/failure */
575{
576 xfs_agf_t *agf; /* allocation group freelist header */
dfc130f3 577 xfs_alloc_block_t *block; /* btree block record/key lives in */
2bd0ea18
NS
578 xfs_buf_t *bp; /* buffer for block */
579 int error; /* error return value */
580 int i; /* loop index */
581 xfs_alloc_key_t key; /* key value being inserted */
582 xfs_alloc_key_t *kp; /* pointer to btree keys */
583 xfs_agblock_t nbno; /* block number of allocated block */
584 xfs_btree_cur_t *ncur; /* new cursor to be used at next lvl */
585 xfs_alloc_key_t nkey; /* new key value, from split */
586 xfs_alloc_rec_t nrec; /* new record value, for caller */
587 int optr; /* old ptr value */
588 xfs_alloc_ptr_t *pp; /* pointer to btree addresses */
589 int ptr; /* index in btree block for this rec */
590 xfs_alloc_rec_t *rp; /* pointer to btree records */
591
592 ASSERT(INT_GET(recp->ar_blockcount, ARCH_CONVERT) > 0);
593 /*
594 * If we made it to the root level, allocate a new root block
595 * and we're done.
596 */
597 if (level >= cur->bc_nlevels) {
7a3bffe4 598 XFS_STATS_INC(xfsstats.xs_abt_insrec);
0e266570 599 if ((error = xfs_alloc_newroot(cur, &i)))
2bd0ea18
NS
600 return error;
601 *bnop = NULLAGBLOCK;
602 *stat = i;
603 return 0;
604 }
605 /*
606 * Make a key out of the record data to be inserted, and save it.
607 */
608 key.ar_startblock = recp->ar_startblock; /* INT_: direct copy */
609 key.ar_blockcount = recp->ar_blockcount; /* INT_: direct copy */
610 optr = ptr = cur->bc_ptrs[level];
611 /*
612 * If we're off the left edge, return failure.
613 */
614 if (ptr == 0) {
615 *stat = 0;
616 return 0;
617 }
7a3bffe4 618 XFS_STATS_INC(xfsstats.xs_abt_insrec);
2bd0ea18
NS
619 /*
620 * Get pointers to the btree buffer and block.
621 */
622 bp = cur->bc_bufs[level];
623 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
624#ifdef DEBUG
0e266570 625 if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
2bd0ea18 626 return error;
5000d01d 627 /*
2bd0ea18
NS
628 * Check that the new entry is being inserted in the right place.
629 */
630 if (ptr <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
631 if (level == 0) {
632 rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
633 xfs_btree_check_rec(cur->bc_btnum, recp, rp);
634 } else {
635 kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
636 xfs_btree_check_key(cur->bc_btnum, &key, kp);
637 }
638 }
639#endif
640 nbno = NULLAGBLOCK;
641 ncur = (xfs_btree_cur_t *)0;
642 /*
643 * If the block is full, we can't insert the new entry until we
644 * make the block un-full.
645 */
646 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
647 /*
648 * First, try shifting an entry to the right neighbor.
649 */
0e266570 650 if ((error = xfs_alloc_rshift(cur, level, &i)))
2bd0ea18
NS
651 return error;
652 if (i) {
653 /* nothing */
654 }
655 /*
656 * Next, try shifting an entry to the left neighbor.
657 */
658 else {
0e266570 659 if ((error = xfs_alloc_lshift(cur, level, &i)))
2bd0ea18
NS
660 return error;
661 if (i)
662 optr = ptr = cur->bc_ptrs[level];
663 else {
664 /*
665 * Next, try splitting the current block in
666 * half. If this works we have to re-set our
667 * variables because we could be in a
668 * different block now.
669 */
0e266570
NS
670 if ((error = xfs_alloc_split(cur, level, &nbno,
671 &nkey, &ncur, &i)))
2bd0ea18
NS
672 return error;
673 if (i) {
674 bp = cur->bc_bufs[level];
675 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
676#ifdef DEBUG
0e266570 677 if ((error =
2bd0ea18 678 xfs_btree_check_sblock(cur,
0e266570 679 block, level, bp)))
2bd0ea18
NS
680 return error;
681#endif
682 ptr = cur->bc_ptrs[level];
683 nrec.ar_startblock = nkey.ar_startblock; /* INT_: direct copy */
684 nrec.ar_blockcount = nkey.ar_blockcount; /* INT_: direct copy */
685 }
686 /*
687 * Otherwise the insert fails.
688 */
689 else {
690 *stat = 0;
691 return 0;
692 }
693 }
694 }
695 }
696 /*
697 * At this point we know there's room for our new entry in the block
698 * we're pointing at.
699 */
700 if (level > 0) {
701 /*
702 * It's a non-leaf entry. Make a hole for the new data
703 * in the key and ptr regions of the block.
704 */
705 kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
706 pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
707#ifdef DEBUG
708 for (i = INT_GET(block->bb_numrecs, ARCH_CONVERT); i >= ptr; i--) {
0e266570 709 if ((error = xfs_btree_check_sptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT), level)))
2bd0ea18
NS
710 return error;
711 }
712#endif
32181a02 713 memmove(&kp[ptr], &kp[ptr - 1],
2bd0ea18 714 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*kp)); /* INT_: copy */
32181a02 715 memmove(&pp[ptr], &pp[ptr - 1],
2bd0ea18
NS
716 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*pp)); /* INT_: copy */
717#ifdef DEBUG
0e266570 718 if ((error = xfs_btree_check_sptr(cur, *bnop, level)))
2bd0ea18
NS
719 return error;
720#endif
721 /*
722 * Now stuff the new data in, bump numrecs and log the new data.
723 */
724 kp[ptr - 1] = key;
725 INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop);
726 INT_MOD(block->bb_numrecs, ARCH_CONVERT, +1);
727 xfs_alloc_log_keys(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
728 xfs_alloc_log_ptrs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
729#ifdef DEBUG
730 if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT))
731 xfs_btree_check_key(cur->bc_btnum, kp + ptr - 1,
732 kp + ptr);
733#endif
734 } else {
735 /*
736 * It's a leaf entry. Make a hole for the new record.
737 */
738 rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
32181a02 739 memmove(&rp[ptr], &rp[ptr - 1],
2bd0ea18
NS
740 (INT_GET(block->bb_numrecs, ARCH_CONVERT) - ptr + 1) * sizeof(*rp));
741 /*
742 * Now stuff the new record in, bump numrecs
743 * and log the new data.
744 */
745 rp[ptr - 1] = *recp; /* INT_: struct copy */
746 INT_MOD(block->bb_numrecs, ARCH_CONVERT, +1);
747 xfs_alloc_log_recs(cur, bp, ptr, INT_GET(block->bb_numrecs, ARCH_CONVERT));
748#ifdef DEBUG
749 if (ptr < INT_GET(block->bb_numrecs, ARCH_CONVERT))
750 xfs_btree_check_rec(cur->bc_btnum, rp + ptr - 1,
751 rp + ptr);
752#endif
753 }
754 /*
755 * Log the new number of records in the btree header.
756 */
757 xfs_alloc_log_block(cur->bc_tp, bp, XFS_BB_NUMRECS);
758 /*
759 * If we inserted at the start of a block, update the parents' keys.
760 */
761 if (optr == 1 && (error = xfs_alloc_updkey(cur, &key, level + 1)))
762 return error;
763 /*
764 * Look to see if the longest extent in the allocation group
765 * needs to be updated.
766 */
767
768 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
769 if (level == 0 &&
770 cur->bc_btnum == XFS_BTNUM_CNT &&
771 INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
772 INT_GET(recp->ar_blockcount, ARCH_CONVERT) > INT_GET(agf->agf_longest, ARCH_CONVERT)) {
773 /*
774 * If this is a leaf in the by-size btree and there
775 * is no right sibling block and this block is bigger
776 * than the previous longest block, update it.
777 */
778 INT_COPY(agf->agf_longest, recp->ar_blockcount, ARCH_CONVERT);
779 cur->bc_mp->m_perag[INT_GET(agf->agf_seqno, ARCH_CONVERT)].pagf_longest
780 = INT_GET(recp->ar_blockcount, ARCH_CONVERT);
781 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
782 XFS_AGF_LONGEST);
783 }
784 /*
785 * Return the new block number, if any.
786 * If there is one, give back a record value and a cursor too.
787 */
788 *bnop = nbno;
789 if (nbno != NULLAGBLOCK) {
790 *recp = nrec; /* INT_: struct copy */
791 *curp = ncur; /* INT_: struct copy */
792 }
793 *stat = 1;
794 return 0;
795}
796
797/*
798 * Log header fields from a btree block.
799 */
800STATIC void
801xfs_alloc_log_block(
802 xfs_trans_t *tp, /* transaction pointer */
803 xfs_buf_t *bp, /* buffer containing btree block */
dfc130f3 804 int fields) /* mask of fields: XFS_BB_... */
2bd0ea18
NS
805{
806 int first; /* first byte offset logged */
807 int last; /* last byte offset logged */
808 static const short offsets[] = { /* table of offsets */
809 offsetof(xfs_alloc_block_t, bb_magic),
810 offsetof(xfs_alloc_block_t, bb_level),
811 offsetof(xfs_alloc_block_t, bb_numrecs),
812 offsetof(xfs_alloc_block_t, bb_leftsib),
813 offsetof(xfs_alloc_block_t, bb_rightsib),
814 sizeof(xfs_alloc_block_t)
815 };
816
817 xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last);
818 xfs_trans_log_buf(tp, bp, first, last);
819}
820
821/*
822 * Log keys from a btree block (nonleaf).
823 */
824STATIC void
825xfs_alloc_log_keys(
826 xfs_btree_cur_t *cur, /* btree cursor */
dfc130f3
RC
827 xfs_buf_t *bp, /* buffer containing btree block */
828 int kfirst, /* index of first key to log */
2bd0ea18
NS
829 int klast) /* index of last key to log */
830{
dfc130f3 831 xfs_alloc_block_t *block; /* btree block to log from */
2bd0ea18
NS
832 int first; /* first byte offset logged */
833 xfs_alloc_key_t *kp; /* key pointer in btree block */
834 int last; /* last byte offset logged */
835
836 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
837 kp = XFS_ALLOC_KEY_ADDR(block, 1, cur);
838 first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block);
839 last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block);
840 xfs_trans_log_buf(cur->bc_tp, bp, first, last);
841}
842
843/*
844 * Log block pointer fields from a btree block (nonleaf).
845 */
846STATIC void
847xfs_alloc_log_ptrs(
848 xfs_btree_cur_t *cur, /* btree cursor */
dfc130f3
RC
849 xfs_buf_t *bp, /* buffer containing btree block */
850 int pfirst, /* index of first pointer to log */
2bd0ea18
NS
851 int plast) /* index of last pointer to log */
852{
dfc130f3 853 xfs_alloc_block_t *block; /* btree block to log from */
2bd0ea18
NS
854 int first; /* first byte offset logged */
855 int last; /* last byte offset logged */
856 xfs_alloc_ptr_t *pp; /* block-pointer pointer in btree blk */
857
858 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
859 pp = XFS_ALLOC_PTR_ADDR(block, 1, cur);
860 first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block);
861 last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block);
862 xfs_trans_log_buf(cur->bc_tp, bp, first, last);
863}
864
865/*
866 * Log records from a btree block (leaf).
867 */
868STATIC void
869xfs_alloc_log_recs(
870 xfs_btree_cur_t *cur, /* btree cursor */
871 xfs_buf_t *bp, /* buffer containing btree block */
dfc130f3 872 int rfirst, /* index of first record to log */
2bd0ea18
NS
873 int rlast) /* index of last record to log */
874{
dfc130f3 875 xfs_alloc_block_t *block; /* btree block to log from */
2bd0ea18
NS
876 int first; /* first byte offset logged */
877 int last; /* last byte offset logged */
878 xfs_alloc_rec_t *rp; /* record pointer for btree block */
879
880
881 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
882 rp = XFS_ALLOC_REC_ADDR(block, 1, cur);
883#ifdef DEBUG
884 {
885 xfs_agf_t *agf;
dfc130f3 886 xfs_alloc_rec_t *p;
2bd0ea18
NS
887
888 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
889 for (p = &rp[rfirst - 1]; p <= &rp[rlast - 1]; p++)
890 ASSERT(INT_GET(p->ar_startblock, ARCH_CONVERT) + INT_GET(p->ar_blockcount, ARCH_CONVERT) <=
891 INT_GET(agf->agf_length, ARCH_CONVERT));
892 }
893#endif
894 first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block);
895 last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block);
896 xfs_trans_log_buf(cur->bc_tp, bp, first, last);
897}
898
899/*
900 * Lookup the record. The cursor is made to point to it, based on dir.
901 * Return 0 if can't find any such record, 1 for success.
902 */
903STATIC int /* error */
904xfs_alloc_lookup(
905 xfs_btree_cur_t *cur, /* btree cursor */
906 xfs_lookup_t dir, /* <=, ==, or >= */
907 int *stat) /* success/failure */
908{
909 xfs_agblock_t agbno; /* a.g. relative btree block number */
910 xfs_agnumber_t agno; /* allocation group number */
0e266570 911 xfs_alloc_block_t *block=NULL; /* current btree block */
2bd0ea18
NS
912 int diff; /* difference for the current key */
913 int error; /* error return value */
0e266570 914 int keyno=0; /* current key number */
2bd0ea18
NS
915 int level; /* level in the btree */
916 xfs_mount_t *mp; /* file system mount point */
917
7a3bffe4 918 XFS_STATS_INC(xfsstats.xs_abt_lookup);
2bd0ea18
NS
919 /*
920 * Get the allocation group header, and the root block number.
921 */
922 mp = cur->bc_mp;
923
924 {
925 xfs_agf_t *agf; /* a.g. freespace header */
926
927 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
928 agno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
929 agbno = INT_GET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT);
930 }
931 /*
932 * Iterate over each level in the btree, starting at the root.
933 * For each level above the leaves, find the key we need, based
934 * on the lookup record, then follow the corresponding block
935 * pointer down to the next level.
936 */
937 for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) {
7a3bffe4
NS
938 xfs_buf_t *bp; /* buffer pointer for btree block */
939 xfs_daddr_t d; /* disk address of btree block */
2bd0ea18
NS
940
941 /*
942 * Get the disk address we're looking for.
943 */
944 d = XFS_AGB_TO_DADDR(mp, agno, agbno);
945 /*
946 * If the old buffer at this level is for a different block,
947 * throw it away, otherwise just use it.
948 */
949 bp = cur->bc_bufs[level];
950 if (bp && XFS_BUF_ADDR(bp) != d)
951 bp = (xfs_buf_t *)0;
952 if (!bp) {
953 /*
5000d01d 954 * Need to get a new buffer. Read it, then
2bd0ea18
NS
955 * set it in the cursor, releasing the old one.
956 */
0e266570
NS
957 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp, agno,
958 agbno, 0, &bp, XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
959 return error;
960 xfs_btree_setbuf(cur, level, bp);
961 /*
962 * Point to the btree block, now that we have the buffer
963 */
964 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
0e266570
NS
965 if ((error = xfs_btree_check_sblock(cur, block, level,
966 bp)))
2bd0ea18
NS
967 return error;
968 } else
969 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
970 /*
971 * If we already had a key match at a higher level, we know
972 * we need to use the first entry in this block.
973 */
974 if (diff == 0)
975 keyno = 1;
976 /*
977 * Otherwise we need to search this block. Do a binary search.
978 */
979 else {
980 int high; /* high entry number */
dfc130f3
RC
981 xfs_alloc_key_t *kkbase=NULL;/* base of keys in block */
982 xfs_alloc_rec_t *krbase=NULL;/* base of records in block */
2bd0ea18
NS
983 int low; /* low entry number */
984
985 /*
986 * Get a pointer to keys or records.
987 */
988 if (level > 0)
989 kkbase = XFS_ALLOC_KEY_ADDR(block, 1, cur);
990 else
991 krbase = XFS_ALLOC_REC_ADDR(block, 1, cur);
992 /*
993 * Set low and high entry numbers, 1-based.
994 */
995 low = 1;
996 if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) {
997 /*
998 * If the block is empty, the tree must
999 * be an empty leaf.
1000 */
1001 ASSERT(level == 0 && cur->bc_nlevels == 1);
1002 cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE;
1003 *stat = 0;
1004 return 0;
1005 }
1006 /*
1007 * Binary search the block.
1008 */
1009 while (low <= high) {
1010 xfs_extlen_t blockcount; /* key value */
1011 xfs_agblock_t startblock; /* key value */
1012
7a3bffe4 1013 XFS_STATS_INC(xfsstats.xs_abt_compare);
2bd0ea18
NS
1014 /*
1015 * keyno is average of low and high.
1016 */
1017 keyno = (low + high) >> 1;
1018 /*
1019 * Get startblock & blockcount.
1020 */
1021 if (level > 0) {
dfc130f3 1022 xfs_alloc_key_t *kkp;
2bd0ea18
NS
1023
1024 kkp = kkbase + keyno - 1;
1025 startblock = INT_GET(kkp->ar_startblock, ARCH_CONVERT);
1026 blockcount = INT_GET(kkp->ar_blockcount, ARCH_CONVERT);
1027 } else {
dfc130f3 1028 xfs_alloc_rec_t *krp;
2bd0ea18
NS
1029
1030 krp = krbase + keyno - 1;
1031 startblock = INT_GET(krp->ar_startblock, ARCH_CONVERT);
1032 blockcount = INT_GET(krp->ar_blockcount, ARCH_CONVERT);
1033 }
1034 /*
1035 * Compute difference to get next direction.
1036 */
1037 if (cur->bc_btnum == XFS_BTNUM_BNO)
1038 diff = (int)startblock -
1039 (int)cur->bc_rec.a.ar_startblock;
1040 else if (!(diff = (int)blockcount -
1041 (int)cur->bc_rec.a.ar_blockcount))
1042 diff = (int)startblock -
1043 (int)cur->bc_rec.a.ar_startblock;
1044 /*
1045 * Less than, move right.
1046 */
1047 if (diff < 0)
1048 low = keyno + 1;
1049 /*
1050 * Greater than, move left.
1051 */
1052 else if (diff > 0)
1053 high = keyno - 1;
1054 /*
1055 * Equal, we're done.
1056 */
1057 else
1058 break;
1059 }
1060 }
1061 /*
1062 * If there are more levels, set up for the next level
1063 * by getting the block number and filling in the cursor.
1064 */
1065 if (level > 0) {
1066 /*
1067 * If we moved left, need the previous key number,
1068 * unless there isn't one.
1069 */
1070 if (diff > 0 && --keyno < 1)
1071 keyno = 1;
1072 agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, keyno, cur), ARCH_CONVERT);
1073#ifdef DEBUG
0e266570 1074 if ((error = xfs_btree_check_sptr(cur, agbno, level)))
2bd0ea18
NS
1075 return error;
1076#endif
1077 cur->bc_ptrs[level] = keyno;
1078 }
1079 }
1080 /*
1081 * Done with the search.
1082 * See if we need to adjust the results.
1083 */
1084 if (dir != XFS_LOOKUP_LE && diff < 0) {
1085 keyno++;
1086 /*
1087 * If ge search and we went off the end of the block, but it's
1088 * not the last block, we're in the wrong block.
1089 */
1090 if (dir == XFS_LOOKUP_GE &&
1091 keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) &&
1092 INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
1093 int i;
1094
1095 cur->bc_ptrs[0] = keyno;
0e266570 1096 if ((error = xfs_alloc_increment(cur, 0, &i)))
2bd0ea18
NS
1097 return error;
1098 XFS_WANT_CORRUPTED_RETURN(i == 1);
1099 *stat = 1;
1100 return 0;
1101 }
1102 }
1103 else if (dir == XFS_LOOKUP_LE && diff > 0)
1104 keyno--;
1105 cur->bc_ptrs[0] = keyno;
1106 /*
1107 * Return if we succeeded or not.
1108 */
1109 if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT))
1110 *stat = 0;
1111 else
1112 *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0));
1113 return 0;
1114}
1115
1116/*
1117 * Move 1 record left from cur/level if possible.
1118 * Update cur to reflect the new path.
1119 */
1120STATIC int /* error */
1121xfs_alloc_lshift(
1122 xfs_btree_cur_t *cur, /* btree cursor */
1123 int level, /* level to shift record on */
1124 int *stat) /* success/failure */
1125{
1126 int error; /* error return value */
1127#ifdef DEBUG
1128 int i; /* loop index */
1129#endif
1130 xfs_alloc_key_t key; /* key value for leaf level upward */
7a3bffe4 1131 xfs_buf_t *lbp; /* buffer for left neighbor block */
2bd0ea18
NS
1132 xfs_alloc_block_t *left; /* left neighbor btree block */
1133 int nrec; /* new number of left block entries */
7a3bffe4 1134 xfs_buf_t *rbp; /* buffer for right (current) block */
dfc130f3 1135 xfs_alloc_block_t *right; /* right (current) btree block */
0e266570
NS
1136 xfs_alloc_key_t *rkp=NULL; /* key pointer for right block */
1137 xfs_alloc_ptr_t *rpp=NULL; /* address pointer for right block */
1138 xfs_alloc_rec_t *rrp=NULL; /* record pointer for right block */
2bd0ea18
NS
1139
1140 /*
1141 * Set up variables for this block as "right".
1142 */
1143 rbp = cur->bc_bufs[level];
1144 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
1145#ifdef DEBUG
0e266570 1146 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
2bd0ea18
NS
1147 return error;
1148#endif
1149 /*
1150 * If we've got no left sibling then we can't shift an entry left.
1151 */
1152 if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {
1153 *stat = 0;
1154 return 0;
1155 }
1156 /*
5000d01d 1157 * If the cursor entry is the one that would be moved, don't
2bd0ea18
NS
1158 * do it... it's too complicated.
1159 */
1160 if (cur->bc_ptrs[level] <= 1) {
1161 *stat = 0;
1162 return 0;
1163 }
1164 /*
1165 * Set up the left neighbor as "left".
1166 */
0e266570 1167 if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
2bd0ea18 1168 cur->bc_private.a.agno, INT_GET(right->bb_leftsib, ARCH_CONVERT), 0, &lbp,
0e266570 1169 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1170 return error;
1171 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
0e266570 1172 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
2bd0ea18
NS
1173 return error;
1174 /*
1175 * If it's full, it can't take another entry.
1176 */
1177 if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
1178 *stat = 0;
1179 return 0;
1180 }
1181 nrec = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1;
1182 /*
1183 * If non-leaf, copy a key and a ptr to the left block.
1184 */
1185 if (level > 0) {
dfc130f3
RC
1186 xfs_alloc_key_t *lkp; /* key pointer for left block */
1187 xfs_alloc_ptr_t *lpp; /* address pointer for left block */
2bd0ea18
NS
1188
1189 lkp = XFS_ALLOC_KEY_ADDR(left, nrec, cur);
1190 rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
1191 *lkp = *rkp;
1192 xfs_alloc_log_keys(cur, lbp, nrec, nrec);
1193 lpp = XFS_ALLOC_PTR_ADDR(left, nrec, cur);
1194 rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
1195#ifdef DEBUG
0e266570 1196 if ((error = xfs_btree_check_sptr(cur, INT_GET(*rpp, ARCH_CONVERT), level)))
2bd0ea18
NS
1197 return error;
1198#endif
1199 *lpp = *rpp; /* INT_: copy */
1200 xfs_alloc_log_ptrs(cur, lbp, nrec, nrec);
1201 xfs_btree_check_key(cur->bc_btnum, lkp - 1, lkp);
1202 }
1203 /*
1204 * If leaf, copy a record to the left block.
1205 */
1206 else {
dfc130f3 1207 xfs_alloc_rec_t *lrp; /* record pointer for left block */
2bd0ea18
NS
1208
1209 lrp = XFS_ALLOC_REC_ADDR(left, nrec, cur);
1210 rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
1211 *lrp = *rrp;
1212 xfs_alloc_log_recs(cur, lbp, nrec, nrec);
1213 xfs_btree_check_rec(cur->bc_btnum, lrp - 1, lrp);
1214 }
1215 /*
1216 * Bump and log left's numrecs, decrement and log right's numrecs.
1217 */
1218 INT_MOD(left->bb_numrecs, ARCH_CONVERT, +1);
1219 xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
1220 INT_MOD(right->bb_numrecs, ARCH_CONVERT, -1);
1221 xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
1222 /*
1223 * Slide the contents of right down one entry.
1224 */
1225 if (level > 0) {
1226#ifdef DEBUG
1227 for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
0e266570
NS
1228 if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT),
1229 level)))
2bd0ea18
NS
1230 return error;
1231 }
1232#endif
32181a02
NS
1233 memmove(rkp, rkp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
1234 memmove(rpp, rpp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
2bd0ea18
NS
1235 xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1236 xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1237 } else {
32181a02 1238 memmove(rrp, rrp + 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
2bd0ea18
NS
1239 xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1240 key.ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
1241 key.ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
1242 rkp = &key;
1243 }
1244 /*
1245 * Update the parent key values of right.
1246 */
0e266570 1247 if ((error = xfs_alloc_updkey(cur, rkp, level + 1)))
2bd0ea18
NS
1248 return error;
1249 /*
1250 * Slide the cursor value left one.
1251 */
1252 cur->bc_ptrs[level]--;
1253 *stat = 1;
1254 return 0;
1255}
1256
1257/*
1258 * Allocate a new root block, fill it in.
1259 */
1260STATIC int /* error */
1261xfs_alloc_newroot(
1262 xfs_btree_cur_t *cur, /* btree cursor */
1263 int *stat) /* success/failure */
1264{
1265 int error; /* error return value */
1266 xfs_agblock_t lbno; /* left block number */
7a3bffe4 1267 xfs_buf_t *lbp; /* left btree buffer */
2bd0ea18
NS
1268 xfs_alloc_block_t *left; /* left btree block */
1269 xfs_mount_t *mp; /* mount structure */
1270 xfs_agblock_t nbno; /* new block number */
7a3bffe4 1271 xfs_buf_t *nbp; /* new (root) buffer */
2bd0ea18
NS
1272 xfs_alloc_block_t *new; /* new (root) btree block */
1273 int nptr; /* new value for key index, 1 or 2 */
1274 xfs_agblock_t rbno; /* right block number */
7a3bffe4 1275 xfs_buf_t *rbp; /* right btree buffer */
dfc130f3 1276 xfs_alloc_block_t *right; /* right btree block */
2bd0ea18
NS
1277
1278 mp = cur->bc_mp;
1279
1280 ASSERT(cur->bc_nlevels < XFS_AG_MAXLEVELS(mp));
1281 /*
1282 * Get a buffer from the freelist blocks, for the new root.
1283 */
0e266570
NS
1284 if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
1285 &nbno)))
2bd0ea18
NS
1286 return error;
1287 /*
1288 * None available, we fail.
1289 */
1290 if (nbno == NULLAGBLOCK) {
1291 *stat = 0;
1292 return 0;
1293 }
1294 xfs_trans_agbtree_delta(cur->bc_tp, 1);
1295 nbp = xfs_btree_get_bufs(mp, cur->bc_tp, cur->bc_private.a.agno, nbno,
1296 0);
1297 new = XFS_BUF_TO_ALLOC_BLOCK(nbp);
1298 /*
1299 * Set the root data in the a.g. freespace structure.
1300 */
1301 {
1302 xfs_agf_t *agf; /* a.g. freespace header */
1303 xfs_agnumber_t seqno;
1304
1305 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
1306 INT_SET(agf->agf_roots[cur->bc_btnum], ARCH_CONVERT, nbno);
1307 INT_MOD(agf->agf_levels[cur->bc_btnum], ARCH_CONVERT, 1);
1308 seqno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
1309 mp->m_perag[seqno].pagf_levels[cur->bc_btnum]++;
1310 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
1311 XFS_AGF_ROOTS | XFS_AGF_LEVELS);
1312 }
1313 /*
1314 * At the previous root level there are now two blocks: the old
1315 * root, and the new block generated when it was split.
1316 * We don't know which one the cursor is pointing at, so we
1317 * set up variables "left" and "right" for each case.
1318 */
1319 lbp = cur->bc_bufs[cur->bc_nlevels - 1];
1320 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
1321#ifdef DEBUG
0e266570 1322 if ((error = xfs_btree_check_sblock(cur, left, cur->bc_nlevels - 1, lbp)))
2bd0ea18
NS
1323 return error;
1324#endif
1325 if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
1326 /*
1327 * Our block is left, pick up the right block.
1328 */
1329 lbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(lbp));
1330 rbno = INT_GET(left->bb_rightsib, ARCH_CONVERT);
0e266570 1331 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
2bd0ea18 1332 cur->bc_private.a.agno, rbno, 0, &rbp,
0e266570 1333 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1334 return error;
1335 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
0e266570
NS
1336 if ((error = xfs_btree_check_sblock(cur, right,
1337 cur->bc_nlevels - 1, rbp)))
2bd0ea18
NS
1338 return error;
1339 nptr = 1;
1340 } else {
1341 /*
1342 * Our block is right, pick up the left block.
1343 */
1344 rbp = lbp;
1345 right = left;
1346 rbno = XFS_DADDR_TO_AGBNO(mp, XFS_BUF_ADDR(rbp));
1347 lbno = INT_GET(right->bb_leftsib, ARCH_CONVERT);
0e266570 1348 if ((error = xfs_btree_read_bufs(mp, cur->bc_tp,
2bd0ea18 1349 cur->bc_private.a.agno, lbno, 0, &lbp,
0e266570 1350 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1351 return error;
1352 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
0e266570
NS
1353 if ((error = xfs_btree_check_sblock(cur, left,
1354 cur->bc_nlevels - 1, lbp)))
2bd0ea18
NS
1355 return error;
1356 nptr = 2;
1357 }
1358 /*
1359 * Fill in the new block's btree header and log it.
1360 */
1361 INT_SET(new->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
1362 INT_SET(new->bb_level, ARCH_CONVERT, (__uint16_t)cur->bc_nlevels);
1363 INT_SET(new->bb_numrecs, ARCH_CONVERT, 2);
1364 INT_SET(new->bb_leftsib, ARCH_CONVERT, NULLAGBLOCK);
5000d01d 1365 INT_SET(new->bb_rightsib, ARCH_CONVERT, NULLAGBLOCK);
2bd0ea18
NS
1366 xfs_alloc_log_block(cur->bc_tp, nbp, XFS_BB_ALL_BITS);
1367 ASSERT(lbno != NULLAGBLOCK && rbno != NULLAGBLOCK);
1368 /*
1369 * Fill in the key data in the new root.
1370 */
1371 {
1372 xfs_alloc_key_t *kp; /* btree key pointer */
1373
1374 kp = XFS_ALLOC_KEY_ADDR(new, 1, cur);
1375 if (INT_GET(left->bb_level, ARCH_CONVERT) > 0) {
1376 kp[0] = *XFS_ALLOC_KEY_ADDR(left, 1, cur); /* INT_: structure copy */
1377 kp[1] = *XFS_ALLOC_KEY_ADDR(right, 1, cur);/* INT_: structure copy */
1378 } else {
dfc130f3 1379 xfs_alloc_rec_t *rp; /* btree record pointer */
2bd0ea18
NS
1380
1381 rp = XFS_ALLOC_REC_ADDR(left, 1, cur);
1382 kp[0].ar_startblock = rp->ar_startblock; /* INT_: direct copy */
1383 kp[0].ar_blockcount = rp->ar_blockcount; /* INT_: direct copy */
1384 rp = XFS_ALLOC_REC_ADDR(right, 1, cur);
1385 kp[1].ar_startblock = rp->ar_startblock; /* INT_: direct copy */
1386 kp[1].ar_blockcount = rp->ar_blockcount; /* INT_: direct copy */
1387 }
1388 }
1389 xfs_alloc_log_keys(cur, nbp, 1, 2);
1390 /*
1391 * Fill in the pointer data in the new root.
1392 */
1393 {
1394 xfs_alloc_ptr_t *pp; /* btree address pointer */
1395
1396 pp = XFS_ALLOC_PTR_ADDR(new, 1, cur);
1397 INT_SET(pp[0], ARCH_CONVERT, lbno);
1398 INT_SET(pp[1], ARCH_CONVERT, rbno);
1399 }
1400 xfs_alloc_log_ptrs(cur, nbp, 1, 2);
1401 /*
1402 * Fix up the cursor.
1403 */
1404 xfs_btree_setbuf(cur, cur->bc_nlevels, nbp);
1405 cur->bc_ptrs[cur->bc_nlevels] = nptr;
1406 cur->bc_nlevels++;
1407 *stat = 1;
1408 return 0;
1409}
1410
1411/*
1412 * Move 1 record right from cur/level if possible.
1413 * Update cur to reflect the new path.
1414 */
1415STATIC int /* error */
1416xfs_alloc_rshift(
1417 xfs_btree_cur_t *cur, /* btree cursor */
1418 int level, /* level to shift record on */
1419 int *stat) /* success/failure */
1420{
1421 int error; /* error return value */
1422 int i; /* loop index */
1423 xfs_alloc_key_t key; /* key value for leaf level upward */
7a3bffe4 1424 xfs_buf_t *lbp; /* buffer for left (current) block */
2bd0ea18 1425 xfs_alloc_block_t *left; /* left (current) btree block */
7a3bffe4 1426 xfs_buf_t *rbp; /* buffer for right neighbor block */
dfc130f3 1427 xfs_alloc_block_t *right; /* right neighbor btree block */
2bd0ea18
NS
1428 xfs_alloc_key_t *rkp; /* key pointer for right block */
1429 xfs_btree_cur_t *tcur; /* temporary cursor */
1430
1431 /*
1432 * Set up variables for this block as "left".
1433 */
1434 lbp = cur->bc_bufs[level];
1435 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
1436#ifdef DEBUG
0e266570 1437 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
2bd0ea18
NS
1438 return error;
1439#endif
1440 /*
1441 * If we've got no right sibling then we can't shift an entry right.
1442 */
1443 if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {
1444 *stat = 0;
1445 return 0;
1446 }
1447 /*
1448 * If the cursor entry is the one that would be moved, don't
1449 * do it... it's too complicated.
1450 */
1451 if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) {
1452 *stat = 0;
1453 return 0;
1454 }
1455 /*
1456 * Set up the right neighbor as "right".
1457 */
0e266570 1458 if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
2bd0ea18 1459 cur->bc_private.a.agno, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, &rbp,
0e266570 1460 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1461 return error;
1462 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
0e266570 1463 if ((error = xfs_btree_check_sblock(cur, right, level, rbp)))
2bd0ea18
NS
1464 return error;
1465 /*
1466 * If it's full, it can't take another entry.
1467 */
1468 if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_ALLOC_BLOCK_MAXRECS(level, cur)) {
1469 *stat = 0;
1470 return 0;
1471 }
1472 /*
1473 * Make a hole at the start of the right neighbor block, then
1474 * copy the last left block entry to the hole.
1475 */
1476 if (level > 0) {
dfc130f3
RC
1477 xfs_alloc_key_t *lkp; /* key pointer for left block */
1478 xfs_alloc_ptr_t *lpp; /* address pointer for left block */
1479 xfs_alloc_ptr_t *rpp; /* address pointer for right block */
2bd0ea18
NS
1480
1481 lkp = XFS_ALLOC_KEY_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
1482 lpp = XFS_ALLOC_PTR_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
1483 rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
1484 rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
1485#ifdef DEBUG
1486 for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) {
0e266570 1487 if ((error = xfs_btree_check_sptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level)))
2bd0ea18
NS
1488 return error;
1489 }
1490#endif
32181a02
NS
1491 memmove(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp));
1492 memmove(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp));
2bd0ea18 1493#ifdef DEBUG
0e266570 1494 if ((error = xfs_btree_check_sptr(cur, INT_GET(*lpp, ARCH_CONVERT), level)))
2bd0ea18
NS
1495 return error;
1496#endif
1497 *rkp = *lkp; /* INT_: copy */
1498 *rpp = *lpp; /* INT_: copy */
1499 xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
1500 xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
1501 xfs_btree_check_key(cur->bc_btnum, rkp, rkp + 1);
1502 } else {
dfc130f3
RC
1503 xfs_alloc_rec_t *lrp; /* record pointer for left block */
1504 xfs_alloc_rec_t *rrp; /* record pointer for right block */
2bd0ea18
NS
1505
1506 lrp = XFS_ALLOC_REC_ADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur);
1507 rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
32181a02 1508 memmove(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
2bd0ea18
NS
1509 *rrp = *lrp;
1510 xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1);
1511 key.ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
1512 key.ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
1513 rkp = &key;
1514 xfs_btree_check_rec(cur->bc_btnum, rrp, rrp + 1);
1515 }
1516 /*
1517 * Decrement and log left's numrecs, bump and log right's numrecs.
1518 */
1519 INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1);
1520 xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS);
1521 INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
1522 xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_NUMRECS);
1523 /*
1524 * Using a temporary cursor, update the parent key values of the
1525 * block on the right.
1526 */
0e266570 1527 if ((error = xfs_btree_dup_cursor(cur, &tcur)))
2bd0ea18
NS
1528 return error;
1529 i = xfs_btree_lastrec(tcur, level);
1530 XFS_WANT_CORRUPTED_GOTO(i == 1, error0);
1531 if ((error = xfs_alloc_increment(tcur, level, &i)) ||
1532 (error = xfs_alloc_updkey(tcur, rkp, level + 1)))
1533 goto error0;
1534 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR);
1535 *stat = 1;
1536 return 0;
1537error0:
1538 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR);
1539 return error;
1540}
1541
1542/*
1543 * Split cur/level block in half.
1544 * Return new block number and its first record (to be inserted into parent).
1545 */
1546STATIC int /* error */
1547xfs_alloc_split(
1548 xfs_btree_cur_t *cur, /* btree cursor */
1549 int level, /* level to split */
1550 xfs_agblock_t *bnop, /* output: block number allocated */
1551 xfs_alloc_key_t *keyp, /* output: first key of new block */
dfc130f3 1552 xfs_btree_cur_t **curp, /* output: new cursor */
2bd0ea18
NS
1553 int *stat) /* success/failure */
1554{
1555 int error; /* error return value */
1556 int i; /* loop index/record number */
1557 xfs_agblock_t lbno; /* left (current) block number */
7a3bffe4 1558 xfs_buf_t *lbp; /* buffer for left block */
2bd0ea18
NS
1559 xfs_alloc_block_t *left; /* left (current) btree block */
1560 xfs_agblock_t rbno; /* right (new) block number */
7a3bffe4 1561 xfs_buf_t *rbp; /* buffer for right block */
dfc130f3 1562 xfs_alloc_block_t *right; /* right (new) btree block */
2bd0ea18
NS
1563
1564 /*
1565 * Allocate the new block from the freelist.
1566 * If we can't do it, we're toast. Give up.
1567 */
0e266570
NS
1568 if ((error = xfs_alloc_get_freelist(cur->bc_tp, cur->bc_private.a.agbp,
1569 &rbno)))
2bd0ea18
NS
1570 return error;
1571 if (rbno == NULLAGBLOCK) {
1572 *stat = 0;
1573 return 0;
1574 }
1575 xfs_trans_agbtree_delta(cur->bc_tp, 1);
1576 rbp = xfs_btree_get_bufs(cur->bc_mp, cur->bc_tp, cur->bc_private.a.agno,
1577 rbno, 0);
1578 /*
1579 * Set up the new block as "right".
1580 */
1581 right = XFS_BUF_TO_ALLOC_BLOCK(rbp);
1582 /*
1583 * "Left" is the current (according to the cursor) block.
1584 */
1585 lbp = cur->bc_bufs[level];
1586 left = XFS_BUF_TO_ALLOC_BLOCK(lbp);
1587#ifdef DEBUG
0e266570 1588 if ((error = xfs_btree_check_sblock(cur, left, level, lbp)))
2bd0ea18
NS
1589 return error;
1590#endif
1591 /*
1592 * Fill in the btree header for the new block.
1593 */
1594 INT_SET(right->bb_magic, ARCH_CONVERT, xfs_magics[cur->bc_btnum]);
1595 right->bb_level = left->bb_level; /* INT_: direct copy */
1596 INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2));
1597 /*
1598 * Make sure that if there's an odd number of entries now, that
1599 * each new block will have the same number of entries.
1600 */
1601 if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) &&
1602 cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1)
1603 INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1);
1604 i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1;
1605 /*
1606 * For non-leaf blocks, copy keys and addresses over to the new block.
1607 */
1608 if (level > 0) {
dfc130f3
RC
1609 xfs_alloc_key_t *lkp; /* left btree key pointer */
1610 xfs_alloc_ptr_t *lpp; /* left btree address pointer */
1611 xfs_alloc_key_t *rkp; /* right btree key pointer */
1612 xfs_alloc_ptr_t *rpp; /* right btree address pointer */
2bd0ea18
NS
1613
1614 lkp = XFS_ALLOC_KEY_ADDR(left, i, cur);
1615 lpp = XFS_ALLOC_PTR_ADDR(left, i, cur);
1616 rkp = XFS_ALLOC_KEY_ADDR(right, 1, cur);
1617 rpp = XFS_ALLOC_PTR_ADDR(right, 1, cur);
1618#ifdef DEBUG
1619 for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) {
0e266570 1620 if ((error = xfs_btree_check_sptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level)))
2bd0ea18
NS
1621 return error;
1622 }
1623#endif
32181a02
NS
1624 memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); /* INT_: copy */
1625 memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); /* INT_: copy */
2bd0ea18
NS
1626 xfs_alloc_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1627 xfs_alloc_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1628 *keyp = *rkp;
1629 }
1630 /*
1631 * For leaf blocks, copy records over to the new block.
1632 */
1633 else {
dfc130f3
RC
1634 xfs_alloc_rec_t *lrp; /* left btree record pointer */
1635 xfs_alloc_rec_t *rrp; /* right btree record pointer */
2bd0ea18
NS
1636
1637 lrp = XFS_ALLOC_REC_ADDR(left, i, cur);
1638 rrp = XFS_ALLOC_REC_ADDR(right, 1, cur);
32181a02 1639 memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp));
2bd0ea18
NS
1640 xfs_alloc_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT));
1641 keyp->ar_startblock = rrp->ar_startblock; /* INT_: direct copy */
1642 keyp->ar_blockcount = rrp->ar_blockcount; /* INT_: direct copy */
1643 }
1644 /*
1645 * Find the left block number by looking in the buffer.
1646 * Adjust numrecs, sibling pointers.
1647 */
1648 lbno = XFS_DADDR_TO_AGBNO(cur->bc_mp, XFS_BUF_ADDR(lbp));
1649 INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT)));
1650 right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */
1651 INT_SET(left->bb_rightsib, ARCH_CONVERT, rbno);
1652 INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno);
1653 xfs_alloc_log_block(cur->bc_tp, rbp, XFS_BB_ALL_BITS);
1654 xfs_alloc_log_block(cur->bc_tp, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB);
1655 /*
1656 * If there's a block to the new block's right, make that block
1657 * point back to right instead of to left.
1658 */
1659 if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLAGBLOCK) {
1660 xfs_alloc_block_t *rrblock; /* rr btree block */
7a3bffe4 1661 xfs_buf_t *rrbp; /* buffer for rrblock */
2bd0ea18 1662
0e266570 1663 if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
2bd0ea18 1664 cur->bc_private.a.agno, INT_GET(right->bb_rightsib, ARCH_CONVERT), 0,
0e266570 1665 &rrbp, XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1666 return error;
1667 rrblock = XFS_BUF_TO_ALLOC_BLOCK(rrbp);
0e266570 1668 if ((error = xfs_btree_check_sblock(cur, rrblock, level, rrbp)))
2bd0ea18
NS
1669 return error;
1670 INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, rbno);
1671 xfs_alloc_log_block(cur->bc_tp, rrbp, XFS_BB_LEFTSIB);
1672 }
1673 /*
1674 * If the cursor is really in the right block, move it there.
1675 * If it's just pointing past the last entry in left, then we'll
1676 * insert there, so don't change anything in that case.
1677 */
1678 if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) {
1679 xfs_btree_setbuf(cur, level, rbp);
1680 cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT);
1681 }
1682 /*
1683 * If there are more levels, we'll need another cursor which refers to
1684 * the right block, no matter where this cursor was.
1685 */
1686 if (level + 1 < cur->bc_nlevels) {
0e266570 1687 if ((error = xfs_btree_dup_cursor(cur, curp)))
2bd0ea18
NS
1688 return error;
1689 (*curp)->bc_ptrs[level + 1]++;
1690 }
1691 *bnop = rbno;
1692 *stat = 1;
1693 return 0;
1694}
1695
1696/*
1697 * Update keys at all levels from here to the root along the cursor's path.
1698 */
1699STATIC int /* error */
1700xfs_alloc_updkey(
1701 xfs_btree_cur_t *cur, /* btree cursor */
1702 xfs_alloc_key_t *keyp, /* new key value to update to */
1703 int level) /* starting level for update */
1704{
1705 int ptr; /* index of key in block */
1706
1707 /*
1708 * Go up the tree from this level toward the root.
1709 * At each level, update the key value to the value input.
1710 * Stop when we reach a level where the cursor isn't pointing
1711 * at the first entry in the block.
1712 */
1713 for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) {
dfc130f3 1714 xfs_alloc_block_t *block; /* btree block */
7a3bffe4 1715 xfs_buf_t *bp; /* buffer for block */
2bd0ea18
NS
1716#ifdef DEBUG
1717 int error; /* error return value */
1718#endif
1719 xfs_alloc_key_t *kp; /* ptr to btree block keys */
1720
1721 bp = cur->bc_bufs[level];
1722 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
1723#ifdef DEBUG
0e266570 1724 if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
2bd0ea18
NS
1725 return error;
1726#endif
1727 ptr = cur->bc_ptrs[level];
1728 kp = XFS_ALLOC_KEY_ADDR(block, ptr, cur);
1729 *kp = *keyp;
1730 xfs_alloc_log_keys(cur, bp, ptr, ptr);
1731 }
1732 return 0;
1733}
1734
1735/*
1736 * Externally visible routines.
1737 */
1738
1739/*
1740 * Decrement cursor by one record at the level.
1741 * For nonzero levels the leaf-ward information is untouched.
1742 */
1743int /* error */
1744xfs_alloc_decrement(
1745 xfs_btree_cur_t *cur, /* btree cursor */
1746 int level, /* level in btree, 0 is leaf */
1747 int *stat) /* success/failure */
1748{
dfc130f3 1749 xfs_alloc_block_t *block; /* btree block */
2bd0ea18
NS
1750 int error; /* error return value */
1751 int lev; /* btree level */
1752
1753 ASSERT(level < cur->bc_nlevels);
1754 /*
1755 * Read-ahead to the left at this level.
1756 */
1757 xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA);
1758 /*
1759 * Decrement the ptr at this level. If we're still in the block
1760 * then we're done.
1761 */
1762 if (--cur->bc_ptrs[level] > 0) {
1763 *stat = 1;
1764 return 0;
1765 }
1766 /*
1767 * Get a pointer to the btree block.
1768 */
1769 block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[level]);
1770#ifdef DEBUG
0e266570
NS
1771 if ((error = xfs_btree_check_sblock(cur, block, level,
1772 cur->bc_bufs[level])))
2bd0ea18
NS
1773 return error;
1774#endif
1775 /*
1776 * If we just went off the left edge of the tree, return failure.
1777 */
1778 if (INT_GET(block->bb_leftsib, ARCH_CONVERT) == NULLAGBLOCK) {
1779 *stat = 0;
1780 return 0;
1781 }
1782 /*
1783 * March up the tree decrementing pointers.
1784 * Stop when we don't go off the left edge of a block.
1785 */
1786 for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1787 if (--cur->bc_ptrs[lev] > 0)
1788 break;
1789 /*
5000d01d 1790 * Read-ahead the left block, we're going to read it
2bd0ea18
NS
1791 * in the next loop.
1792 */
1793 xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA);
1794 }
1795 /*
1796 * If we went off the root then we are seriously confused.
1797 */
1798 ASSERT(lev < cur->bc_nlevels);
1799 /*
1800 * Now walk back down the tree, fixing up the cursor's buffer
1801 * pointers and key numbers.
1802 */
1803 for (block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); lev > level; ) {
1804 xfs_agblock_t agbno; /* block number of btree block */
7a3bffe4 1805 xfs_buf_t *bp; /* buffer pointer for block */
2bd0ea18
NS
1806
1807 agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
0e266570 1808 if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
2bd0ea18 1809 cur->bc_private.a.agno, agbno, 0, &bp,
0e266570 1810 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1811 return error;
1812 lev--;
1813 xfs_btree_setbuf(cur, lev, bp);
1814 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
0e266570 1815 if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
2bd0ea18
NS
1816 return error;
1817 cur->bc_ptrs[lev] = INT_GET(block->bb_numrecs, ARCH_CONVERT);
1818 }
1819 *stat = 1;
1820 return 0;
1821}
1822
1823/*
1824 * Delete the record pointed to by cur.
1825 * The cursor refers to the place where the record was (could be inserted)
1826 * when the operation returns.
1827 */
1828int /* error */
1829xfs_alloc_delete(
dfc130f3 1830 xfs_btree_cur_t *cur, /* btree cursor */
2bd0ea18
NS
1831 int *stat) /* success/failure */
1832{
1833 int error; /* error return value */
1834 int i; /* result code */
1835 int level; /* btree level */
1836
1837 /*
1838 * Go up the tree, starting at leaf level.
1839 * If 2 is returned then a join was done; go to the next level.
1840 * Otherwise we are done.
1841 */
1842 for (level = 0, i = 2; i == 2; level++) {
0e266570 1843 if ((error = xfs_alloc_delrec(cur, level, &i)))
2bd0ea18
NS
1844 return error;
1845 }
1846 if (i == 0) {
1847 for (level = 1; level < cur->bc_nlevels; level++) {
1848 if (cur->bc_ptrs[level] == 0) {
0e266570 1849 if ((error = xfs_alloc_decrement(cur, level, &i)))
2bd0ea18
NS
1850 return error;
1851 break;
1852 }
1853 }
1854 }
1855 *stat = i;
1856 return 0;
1857}
1858
5000d01d 1859/*
2bd0ea18
NS
1860 * Get the data from the pointed-to record.
1861 */
1862int /* error */
1863xfs_alloc_get_rec(
1864 xfs_btree_cur_t *cur, /* btree cursor */
1865 xfs_agblock_t *bno, /* output: starting block of extent */
1866 xfs_extlen_t *len, /* output: length of extent */
1867 int *stat) /* output: success/failure */
1868{
dfc130f3 1869 xfs_alloc_block_t *block; /* btree block */
2bd0ea18
NS
1870#ifdef DEBUG
1871 int error; /* error return value */
1872#endif
1873 int ptr; /* record number */
1874
1875 ptr = cur->bc_ptrs[0];
1876 block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
1877#ifdef DEBUG
0e266570 1878 if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
2bd0ea18
NS
1879 return error;
1880#endif
1881 /*
1882 * Off the right end or left end, return failure.
1883 */
1884 if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) {
1885 *stat = 0;
1886 return 0;
1887 }
1888 /*
1889 * Point to the record and extract its data.
1890 */
1891 {
1892 xfs_alloc_rec_t *rec; /* record data */
1893
1894 rec = XFS_ALLOC_REC_ADDR(block, ptr, cur);
1895 *bno = INT_GET(rec->ar_startblock, ARCH_CONVERT);
1896 *len = INT_GET(rec->ar_blockcount, ARCH_CONVERT);
1897 }
1898 *stat = 1;
1899 return 0;
1900}
1901
1902/*
1903 * Increment cursor by one record at the level.
1904 * For nonzero levels the leaf-ward information is untouched.
1905 */
1906int /* error */
1907xfs_alloc_increment(
1908 xfs_btree_cur_t *cur, /* btree cursor */
1909 int level, /* level in btree, 0 is leaf */
1910 int *stat) /* success/failure */
1911{
dfc130f3 1912 xfs_alloc_block_t *block; /* btree block */
7a3bffe4 1913 xfs_buf_t *bp; /* tree block buffer */
2bd0ea18
NS
1914 int error; /* error return value */
1915 int lev; /* btree level */
1916
1917 ASSERT(level < cur->bc_nlevels);
1918 /*
1919 * Read-ahead to the right at this level.
1920 */
1921 xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
1922 /*
1923 * Get a pointer to the btree block.
1924 */
1925 bp = cur->bc_bufs[level];
1926 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
1927#ifdef DEBUG
0e266570 1928 if ((error = xfs_btree_check_sblock(cur, block, level, bp)))
2bd0ea18
NS
1929 return error;
1930#endif
1931 /*
1932 * Increment the ptr at this level. If we're still in the block
1933 * then we're done.
1934 */
1935 if (++cur->bc_ptrs[level] <= INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
1936 *stat = 1;
1937 return 0;
1938 }
1939 /*
1940 * If we just went off the right edge of the tree, return failure.
1941 */
1942 if (INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK) {
1943 *stat = 0;
1944 return 0;
1945 }
1946 /*
1947 * March up the tree incrementing pointers.
1948 * Stop when we don't go off the right edge of a block.
1949 */
1950 for (lev = level + 1; lev < cur->bc_nlevels; lev++) {
1951 bp = cur->bc_bufs[lev];
1952 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
1953#ifdef DEBUG
0e266570 1954 if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
2bd0ea18
NS
1955 return error;
1956#endif
1957 if (++cur->bc_ptrs[lev] <= INT_GET(block->bb_numrecs, ARCH_CONVERT))
1958 break;
1959 /*
5000d01d 1960 * Read-ahead the right block, we're going to read it
2bd0ea18
NS
1961 * in the next loop.
1962 */
1963 xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA);
1964 }
1965 /*
1966 * If we went off the root then we are seriously confused.
1967 */
1968 ASSERT(lev < cur->bc_nlevels);
1969 /*
1970 * Now walk back down the tree, fixing up the cursor's buffer
1971 * pointers and key numbers.
1972 */
1973 for (bp = cur->bc_bufs[lev], block = XFS_BUF_TO_ALLOC_BLOCK(bp);
1974 lev > level; ) {
1975 xfs_agblock_t agbno; /* block number of btree block */
1976
1977 agbno = INT_GET(*XFS_ALLOC_PTR_ADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT);
0e266570 1978 if ((error = xfs_btree_read_bufs(cur->bc_mp, cur->bc_tp,
2bd0ea18 1979 cur->bc_private.a.agno, agbno, 0, &bp,
0e266570 1980 XFS_ALLOC_BTREE_REF)))
2bd0ea18
NS
1981 return error;
1982 lev--;
1983 xfs_btree_setbuf(cur, lev, bp);
1984 block = XFS_BUF_TO_ALLOC_BLOCK(bp);
0e266570 1985 if ((error = xfs_btree_check_sblock(cur, block, lev, bp)))
2bd0ea18
NS
1986 return error;
1987 cur->bc_ptrs[lev] = 1;
1988 }
1989 *stat = 1;
1990 return 0;
1991}
1992
1993/*
1994 * Insert the current record at the point referenced by cur.
1995 * The cursor may be inconsistent on return if splits have been done.
1996 */
1997int /* error */
1998xfs_alloc_insert(
dfc130f3 1999 xfs_btree_cur_t *cur, /* btree cursor */
2bd0ea18
NS
2000 int *stat) /* success/failure */
2001{
2002 int error; /* error return value */
2003 int i; /* result value, 0 for failure */
2004 int level; /* current level number in btree */
2005 xfs_agblock_t nbno; /* new block number (split result) */
dfc130f3
RC
2006 xfs_btree_cur_t *ncur; /* new cursor (split result) */
2007 xfs_alloc_rec_t nrec; /* record being inserted this level */
2008 xfs_btree_cur_t *pcur; /* previous level's cursor */
2bd0ea18
NS
2009
2010 level = 0;
2011 nbno = NULLAGBLOCK;
2012 INT_SET(nrec.ar_startblock, ARCH_CONVERT, cur->bc_rec.a.ar_startblock);
2013 INT_SET(nrec.ar_blockcount, ARCH_CONVERT, cur->bc_rec.a.ar_blockcount);
2014 ncur = (xfs_btree_cur_t *)0;
2015 pcur = cur;
2016 /*
2017 * Loop going up the tree, starting at the leaf level.
2018 * Stop when we don't get a split block, that must mean that
2019 * the insert is finished with this level.
2020 */
2021 do {
2022 /*
2023 * Insert nrec/nbno into this level of the tree.
2024 * Note if we fail, nbno will be null.
2025 */
0e266570
NS
2026 if ((error = xfs_alloc_insrec(pcur, level++, &nbno, &nrec, &ncur,
2027 &i))) {
2bd0ea18
NS
2028 if (pcur != cur)
2029 xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR);
2030 return error;
2031 }
2032 /*
2033 * See if the cursor we just used is trash.
2034 * Can't trash the caller's cursor, but otherwise we should
2035 * if ncur is a new cursor or we're about to be done.
2036 */
2037 if (pcur != cur && (ncur || nbno == NULLAGBLOCK)) {
2038 cur->bc_nlevels = pcur->bc_nlevels;
2039 xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR);
2040 }
2041 /*
2042 * If we got a new cursor, switch to it.
2043 */
2044 if (ncur) {
2045 pcur = ncur;
2046 ncur = (xfs_btree_cur_t *)0;
2047 }
2048 } while (nbno != NULLAGBLOCK);
2049 *stat = i;
2050 return 0;
2051}
2052
2053/*
2054 * Lookup the record equal to [bno, len] in the btree given by cur.
2055 */
2056int /* error */
2057xfs_alloc_lookup_eq(
dfc130f3 2058 xfs_btree_cur_t *cur, /* btree cursor */
2bd0ea18
NS
2059 xfs_agblock_t bno, /* starting block of extent */
2060 xfs_extlen_t len, /* length of extent */
2061 int *stat) /* success/failure */
2062{
2063 cur->bc_rec.a.ar_startblock = bno;
2064 cur->bc_rec.a.ar_blockcount = len;
2065 return xfs_alloc_lookup(cur, XFS_LOOKUP_EQ, stat);
2066}
2067
2068/*
2069 * Lookup the first record greater than or equal to [bno, len]
2070 * in the btree given by cur.
2071 */
2072int /* error */
2073xfs_alloc_lookup_ge(
dfc130f3 2074 xfs_btree_cur_t *cur, /* btree cursor */
2bd0ea18
NS
2075 xfs_agblock_t bno, /* starting block of extent */
2076 xfs_extlen_t len, /* length of extent */
2077 int *stat) /* success/failure */
2078{
2079 cur->bc_rec.a.ar_startblock = bno;
2080 cur->bc_rec.a.ar_blockcount = len;
2081 return xfs_alloc_lookup(cur, XFS_LOOKUP_GE, stat);
2082}
2083
2084/*
2085 * Lookup the first record less than or equal to [bno, len]
2086 * in the btree given by cur.
2087 */
2088int /* error */
2089xfs_alloc_lookup_le(
dfc130f3 2090 xfs_btree_cur_t *cur, /* btree cursor */
2bd0ea18
NS
2091 xfs_agblock_t bno, /* starting block of extent */
2092 xfs_extlen_t len, /* length of extent */
2093 int *stat) /* success/failure */
2094{
2095 cur->bc_rec.a.ar_startblock = bno;
2096 cur->bc_rec.a.ar_blockcount = len;
2097 return xfs_alloc_lookup(cur, XFS_LOOKUP_LE, stat);
2098}
2099
2100/*
2101 * Update the record referred to by cur, to the value given by [bno, len].
2102 * This either works (return 0) or gets an EFSCORRUPTED error.
2103 */
2104int /* error */
2105xfs_alloc_update(
2106 xfs_btree_cur_t *cur, /* btree cursor */
2107 xfs_agblock_t bno, /* starting block of extent */
2108 xfs_extlen_t len) /* length of extent */
2109{
dfc130f3 2110 xfs_alloc_block_t *block; /* btree block to update */
2bd0ea18
NS
2111 int error; /* error return value */
2112 int ptr; /* current record number (updating) */
2113
2114 ASSERT(len > 0);
2115 /*
2116 * Pick up the a.g. freelist struct and the current block.
2117 */
2118 block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]);
2119#ifdef DEBUG
0e266570 2120 if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0])))
2bd0ea18
NS
2121 return error;
2122#endif
2123 /*
2124 * Get the address of the rec to be updated.
2125 */
2126 ptr = cur->bc_ptrs[0];
2127 {
2128 xfs_alloc_rec_t *rp; /* pointer to updated record */
2129
2130 rp = XFS_ALLOC_REC_ADDR(block, ptr, cur);
2131 /*
2132 * Fill in the new contents and log them.
2133 */
2134 INT_SET(rp->ar_startblock, ARCH_CONVERT, bno);
2135 INT_SET(rp->ar_blockcount, ARCH_CONVERT, len);
2136 xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr);
2137 }
2138 /*
2139 * If it's the by-size btree and it's the last leaf block and
2140 * it's the last record... then update the size of the longest
2141 * extent in the a.g., which we cache in the a.g. freelist header.
2142 */
2143 if (cur->bc_btnum == XFS_BTNUM_CNT &&
2144 INT_GET(block->bb_rightsib, ARCH_CONVERT) == NULLAGBLOCK &&
2145 ptr == INT_GET(block->bb_numrecs, ARCH_CONVERT)) {
2146 xfs_agf_t *agf; /* a.g. freespace header */
2147 xfs_agnumber_t seqno;
2148
2149 agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp);
2150 seqno = INT_GET(agf->agf_seqno, ARCH_CONVERT);
2151 cur->bc_mp->m_perag[seqno].pagf_longest = len;
2152 INT_SET(agf->agf_longest, ARCH_CONVERT, len);
2153 xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp,
2154 XFS_AGF_LONGEST);
2155 }
2156 /*
2157 * Updating first record in leaf. Pass new key value up to our parent.
2158 */
2159 if (ptr == 1) {
dfc130f3 2160 xfs_alloc_key_t key; /* key containing [bno, len] */
2bd0ea18
NS
2161
2162 INT_SET(key.ar_startblock, ARCH_CONVERT, bno);
2163 INT_SET(key.ar_blockcount, ARCH_CONVERT, len);
0e266570 2164 if ((error = xfs_alloc_updkey(cur, &key, 1)))
2bd0ea18
NS
2165 return error;
2166 }
2167 return 0;
2168}