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