/fs/xfs/xfs_bmap_btree.c
C | 2807 lines | 2454 code | 115 blank | 238 comment | 389 complexity | 08587f72db288bd87645ba7773483b56 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
1/* 2 * Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of version 2 of the GNU General Public License as 6 * published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope that it would be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11 * 12 * Further, this software is distributed without any warranty that it is 13 * free of the rightful claim of any third person regarding infringement 14 * or the like. Any license provided herein, whether implied or 15 * otherwise, applies only to this software file. Patent licenses, if 16 * any, provided herein do not apply to combinations of this program with 17 * other software, or any other product whatsoever. 18 * 19 * You should have received a copy of the GNU General Public License along 20 * with this program; if not, write the Free Software Foundation, Inc., 59 21 * Temple Place - Suite 330, Boston MA 02111-1307, USA. 22 * 23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy, 24 * Mountain View, CA 94043, or: 25 * 26 * http://www.sgi.com 27 * 28 * For further information regarding this notice, see: 29 * 30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/ 31 */ 32 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_dir2.h" 44#include "xfs_dmapi.h" 45#include "xfs_mount.h" 46#include "xfs_alloc_btree.h" 47#include "xfs_bmap_btree.h" 48#include "xfs_ialloc_btree.h" 49#include "xfs_btree.h" 50#include "xfs_ialloc.h" 51#include "xfs_itable.h" 52#include "xfs_attr_sf.h" 53#include "xfs_dir_sf.h" 54#include "xfs_dir2_sf.h" 55#include "xfs_dinode.h" 56#include "xfs_inode_item.h" 57#include "xfs_inode.h" 58#include "xfs_alloc.h" 59#include "xfs_bit.h" 60#include "xfs_bmap.h" 61#include "xfs_error.h" 62#include "xfs_quota.h" 63 64#if defined(XFS_BMBT_TRACE) 65ktrace_t *xfs_bmbt_trace_buf; 66#endif 67 68/* 69 * Prototypes for internal btree functions. 70 */ 71 72 73STATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); 74STATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); 75STATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 76STATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); 77STATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *); 78STATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, 79 xfs_bmbt_key_t *, xfs_btree_cur_t **, int *); 80STATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int); 81 82 83#if defined(XFS_BMBT_TRACE) 84 85static char ARGS[] = "args"; 86static char ENTRY[] = "entry"; 87static char ERROR[] = "error"; 88#undef EXIT 89static char EXIT[] = "exit"; 90 91/* 92 * Add a trace buffer entry for the arguments given to the routine, 93 * generic form. 94 */ 95STATIC void 96xfs_bmbt_trace_enter( 97 char *func, 98 xfs_btree_cur_t *cur, 99 char *s, 100 int type, 101 int line, 102 __psunsigned_t a0, 103 __psunsigned_t a1, 104 __psunsigned_t a2, 105 __psunsigned_t a3, 106 __psunsigned_t a4, 107 __psunsigned_t a5, 108 __psunsigned_t a6, 109 __psunsigned_t a7, 110 __psunsigned_t a8, 111 __psunsigned_t a9, 112 __psunsigned_t a10) 113{ 114 xfs_inode_t *ip; 115 int whichfork; 116 117 ip = cur->bc_private.b.ip; 118 whichfork = cur->bc_private.b.whichfork; 119 ktrace_enter(xfs_bmbt_trace_buf, 120 (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), 121 (void *)func, (void *)s, (void *)ip, (void *)cur, 122 (void *)a0, (void *)a1, (void *)a2, (void *)a3, 123 (void *)a4, (void *)a5, (void *)a6, (void *)a7, 124 (void *)a8, (void *)a9, (void *)a10); 125 ASSERT(ip->i_btrace); 126 ktrace_enter(ip->i_btrace, 127 (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), 128 (void *)func, (void *)s, (void *)ip, (void *)cur, 129 (void *)a0, (void *)a1, (void *)a2, (void *)a3, 130 (void *)a4, (void *)a5, (void *)a6, (void *)a7, 131 (void *)a8, (void *)a9, (void *)a10); 132} 133/* 134 * Add a trace buffer entry for arguments, for a buffer & 1 integer arg. 135 */ 136STATIC void 137xfs_bmbt_trace_argbi( 138 char *func, 139 xfs_btree_cur_t *cur, 140 xfs_buf_t *b, 141 int i, 142 int line) 143{ 144 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line, 145 (__psunsigned_t)b, i, 0, 0, 146 0, 0, 0, 0, 147 0, 0, 0); 148} 149 150/* 151 * Add a trace buffer entry for arguments, for a buffer & 2 integer args. 152 */ 153STATIC void 154xfs_bmbt_trace_argbii( 155 char *func, 156 xfs_btree_cur_t *cur, 157 xfs_buf_t *b, 158 int i0, 159 int i1, 160 int line) 161{ 162 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line, 163 (__psunsigned_t)b, i0, i1, 0, 164 0, 0, 0, 0, 165 0, 0, 0); 166} 167 168/* 169 * Add a trace buffer entry for arguments, for 3 block-length args 170 * and an integer arg. 171 */ 172STATIC void 173xfs_bmbt_trace_argfffi( 174 char *func, 175 xfs_btree_cur_t *cur, 176 xfs_dfiloff_t o, 177 xfs_dfsbno_t b, 178 xfs_dfilblks_t i, 179 int j, 180 int line) 181{ 182 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line, 183 o >> 32, (int)o, b >> 32, (int)b, 184 i >> 32, (int)i, (int)j, 0, 185 0, 0, 0); 186} 187 188/* 189 * Add a trace buffer entry for arguments, for one integer arg. 190 */ 191STATIC void 192xfs_bmbt_trace_argi( 193 char *func, 194 xfs_btree_cur_t *cur, 195 int i, 196 int line) 197{ 198 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line, 199 i, 0, 0, 0, 200 0, 0, 0, 0, 201 0, 0, 0); 202} 203 204/* 205 * Add a trace buffer entry for arguments, for int, fsblock, key. 206 */ 207STATIC void 208xfs_bmbt_trace_argifk( 209 char *func, 210 xfs_btree_cur_t *cur, 211 int i, 212 xfs_fsblock_t f, 213 xfs_bmbt_key_t *k, 214 int line) 215{ 216 xfs_dfsbno_t d; 217 xfs_dfiloff_t o; 218 219 d = (xfs_dfsbno_t)f; 220 o = INT_GET(k->br_startoff, ARCH_CONVERT); 221 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, 222 i, d >> 32, (int)d, o >> 32, 223 (int)o, 0, 0, 0, 224 0, 0, 0); 225} 226 227/* 228 * Add a trace buffer entry for arguments, for int, fsblock, rec. 229 */ 230STATIC void 231xfs_bmbt_trace_argifr( 232 char *func, 233 xfs_btree_cur_t *cur, 234 int i, 235 xfs_fsblock_t f, 236 xfs_bmbt_rec_t *r, 237 int line) 238{ 239 xfs_dfsbno_t b; 240 xfs_dfilblks_t c; 241 xfs_dfsbno_t d; 242 xfs_dfiloff_t o; 243 xfs_bmbt_irec_t s; 244 245 d = (xfs_dfsbno_t)f; 246 xfs_bmbt_disk_get_all(r, &s); 247 o = (xfs_dfiloff_t)s.br_startoff; 248 b = (xfs_dfsbno_t)s.br_startblock; 249 c = s.br_blockcount; 250 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line, 251 i, d >> 32, (int)d, o >> 32, 252 (int)o, b >> 32, (int)b, c >> 32, 253 (int)c, 0, 0); 254} 255 256/* 257 * Add a trace buffer entry for arguments, for int, key. 258 */ 259STATIC void 260xfs_bmbt_trace_argik( 261 char *func, 262 xfs_btree_cur_t *cur, 263 int i, 264 xfs_bmbt_key_t *k, 265 int line) 266{ 267 xfs_dfiloff_t o; 268 269 o = INT_GET(k->br_startoff, ARCH_CONVERT); 270 xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, 271 i, o >> 32, (int)o, 0, 272 0, 0, 0, 0, 273 0, 0, 0); 274} 275 276/* 277 * Add a trace buffer entry for the cursor/operation. 278 */ 279STATIC void 280xfs_bmbt_trace_cursor( 281 char *func, 282 xfs_btree_cur_t *cur, 283 char *s, 284 int line) 285{ 286 xfs_bmbt_rec_t r; 287 288 xfs_bmbt_set_all(&r, &cur->bc_rec.b); 289 xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line, 290 (cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) | 291 cur->bc_private.b.allocated, 292 INT_GET(r.l0, ARCH_CONVERT) >> 32, (int)INT_GET(r.l0, ARCH_CONVERT), INT_GET(r.l1, ARCH_CONVERT) >> 32, (int)INT_GET(r.l1, ARCH_CONVERT), 293 (unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1], 294 (unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3], 295 (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1], 296 (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]); 297} 298 299#define XFS_BMBT_TRACE_ARGBI(c,b,i) \ 300 xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__) 301#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ 302 xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__) 303#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ 304 xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__) 305#define XFS_BMBT_TRACE_ARGI(c,i) \ 306 xfs_bmbt_trace_argi(fname, c, i, __LINE__) 307#define XFS_BMBT_TRACE_ARGIFK(c,i,f,k) \ 308 xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__) 309#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ 310 xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__) 311#define XFS_BMBT_TRACE_ARGIK(c,i,k) \ 312 xfs_bmbt_trace_argik(fname, c, i, k, __LINE__) 313#define XFS_BMBT_TRACE_CURSOR(c,s) \ 314 xfs_bmbt_trace_cursor(fname, c, s, __LINE__) 315#else 316#define XFS_BMBT_TRACE_ARGBI(c,b,i) 317#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) 318#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) 319#define XFS_BMBT_TRACE_ARGI(c,i) 320#define XFS_BMBT_TRACE_ARGIFK(c,i,f,k) 321#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) 322#define XFS_BMBT_TRACE_ARGIK(c,i,k) 323#define XFS_BMBT_TRACE_CURSOR(c,s) 324#endif /* XFS_BMBT_TRACE */ 325 326 327/* 328 * Internal functions. 329 */ 330 331/* 332 * Delete record pointed to by cur/level. 333 */ 334STATIC int /* error */ 335xfs_bmbt_delrec( 336 xfs_btree_cur_t *cur, 337 int level, 338 int *stat) /* success/failure */ 339{ 340 xfs_bmbt_block_t *block; /* bmap btree block */ 341 xfs_fsblock_t bno; /* fs-relative block number */ 342 xfs_buf_t *bp; /* buffer for block */ 343 int error; /* error return value */ 344#ifdef XFS_BMBT_TRACE 345 static char fname[] = "xfs_bmbt_delrec"; 346#endif 347 int i; /* loop counter */ 348 int j; /* temp state */ 349 xfs_bmbt_key_t key; /* bmap btree key */ 350 xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ 351 xfs_fsblock_t lbno; /* left sibling block number */ 352 xfs_buf_t *lbp; /* left buffer pointer */ 353 xfs_bmbt_block_t *left; /* left btree block */ 354 xfs_bmbt_key_t *lkp; /* left btree key */ 355 xfs_bmbt_ptr_t *lpp; /* left address pointer */ 356 int lrecs=0; /* left record count */ 357 xfs_bmbt_rec_t *lrp; /* left record pointer */ 358 xfs_mount_t *mp; /* file system mount point */ 359 xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ 360 int ptr; /* key/record index */ 361 xfs_fsblock_t rbno; /* right sibling block number */ 362 xfs_buf_t *rbp; /* right buffer pointer */ 363 xfs_bmbt_block_t *right; /* right btree block */ 364 xfs_bmbt_key_t *rkp; /* right btree key */ 365 xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */ 366 xfs_bmbt_ptr_t *rpp; /* right address pointer */ 367 xfs_bmbt_block_t *rrblock; /* right-right btree block */ 368 xfs_buf_t *rrbp; /* right-right buffer pointer */ 369 int rrecs=0; /* right record count */ 370 xfs_bmbt_rec_t *rrp; /* right record pointer */ 371 xfs_btree_cur_t *tcur; /* temporary btree cursor */ 372 int numrecs; /* temporary numrec count */ 373 int numlrecs, numrrecs; 374 375 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 376 XFS_BMBT_TRACE_ARGI(cur, level); 377 ptr = cur->bc_ptrs[level]; 378 tcur = (xfs_btree_cur_t *)0; 379 if (ptr == 0) { 380 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 381 *stat = 0; 382 return 0; 383 } 384 block = xfs_bmbt_get_block(cur, level, &bp); 385 numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT); 386#ifdef DEBUG 387 if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 388 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 389 goto error0; 390 } 391#endif 392 if (ptr > numrecs) { 393 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 394 *stat = 0; 395 return 0; 396 } 397 XFS_STATS_INC(xs_bmbt_delrec); 398 if (level > 0) { 399 kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 400 pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 401#ifdef DEBUG 402 for (i = ptr; i < numrecs; i++) { 403 if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) { 404 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 405 goto error0; 406 } 407 } 408#endif 409 if (ptr < numrecs) { 410 memmove(&kp[ptr - 1], &kp[ptr], 411 (numrecs - ptr) * sizeof(*kp)); 412 memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */ 413 (numrecs - ptr) * sizeof(*pp)); 414 xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); 415 xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); 416 } 417 } else { 418 rp = XFS_BMAP_REC_IADDR(block, 1, cur); 419 if (ptr < numrecs) { 420 memmove(&rp[ptr - 1], &rp[ptr], 421 (numrecs - ptr) * sizeof(*rp)); 422 xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); 423 } 424 if (ptr == 1) { 425 INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp)); 426 kp = &key; 427 } 428 } 429 numrecs--; 430 INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs); 431 xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); 432 /* 433 * We're at the root level. 434 * First, shrink the root block in-memory. 435 * Try to get rid of the next level down. 436 * If we can't then there's nothing left to do. 437 */ 438 if (level == cur->bc_nlevels - 1) { 439 xfs_iroot_realloc(cur->bc_private.b.ip, -1, 440 cur->bc_private.b.whichfork); 441 if ((error = xfs_bmbt_killroot(cur))) { 442 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 443 goto error0; 444 } 445 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { 446 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 447 goto error0; 448 } 449 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 450 *stat = 1; 451 return 0; 452 } 453 if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) { 454 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 455 goto error0; 456 } 457 if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 458 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { 459 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 460 goto error0; 461 } 462 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 463 *stat = 1; 464 return 0; 465 } 466 rbno = INT_GET(block->bb_rightsib, ARCH_CONVERT); 467 lbno = INT_GET(block->bb_leftsib, ARCH_CONVERT); 468 /* 469 * One child of root, need to get a chance to copy its contents 470 * into the root and delete it. Can't go up to next level, 471 * there's nothing to delete there. 472 */ 473 if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && 474 level == cur->bc_nlevels - 2) { 475 if ((error = xfs_bmbt_killroot(cur))) { 476 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 477 goto error0; 478 } 479 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { 480 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 481 goto error0; 482 } 483 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 484 *stat = 1; 485 return 0; 486 } 487 ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); 488 if ((error = xfs_btree_dup_cursor(cur, &tcur))) { 489 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 490 goto error0; 491 } 492 bno = NULLFSBLOCK; 493 if (rbno != NULLFSBLOCK) { 494 i = xfs_btree_lastrec(tcur, level); 495 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 496 if ((error = xfs_bmbt_increment(tcur, level, &i))) { 497 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 498 goto error0; 499 } 500 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 501 i = xfs_btree_lastrec(tcur, level); 502 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 503 rbp = tcur->bc_bufs[level]; 504 right = XFS_BUF_TO_BMBT_BLOCK(rbp); 505#ifdef DEBUG 506 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 507 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 508 goto error0; 509 } 510#endif 511 bno = INT_GET(right->bb_leftsib, ARCH_CONVERT); 512 if (INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1 >= 513 XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 514 if ((error = xfs_bmbt_lshift(tcur, level, &i))) { 515 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 516 goto error0; 517 } 518 if (i) { 519 ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >= 520 XFS_BMAP_BLOCK_IMINRECS(level, tcur)); 521 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 522 tcur = NULL; 523 if (level > 0) { 524 if ((error = xfs_bmbt_decrement(cur, 525 level, &i))) { 526 XFS_BMBT_TRACE_CURSOR(cur, 527 ERROR); 528 goto error0; 529 } 530 } 531 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 532 *stat = 1; 533 return 0; 534 } 535 } 536 rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT); 537 if (lbno != NULLFSBLOCK) { 538 i = xfs_btree_firstrec(tcur, level); 539 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 540 if ((error = xfs_bmbt_decrement(tcur, level, &i))) { 541 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 542 goto error0; 543 } 544 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 545 } 546 } 547 if (lbno != NULLFSBLOCK) { 548 i = xfs_btree_firstrec(tcur, level); 549 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 550 /* 551 * decrement to last in block 552 */ 553 if ((error = xfs_bmbt_decrement(tcur, level, &i))) { 554 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 555 goto error0; 556 } 557 i = xfs_btree_firstrec(tcur, level); 558 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 559 lbp = tcur->bc_bufs[level]; 560 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 561#ifdef DEBUG 562 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 563 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 564 goto error0; 565 } 566#endif 567 bno = INT_GET(left->bb_rightsib, ARCH_CONVERT); 568 if (INT_GET(left->bb_numrecs, ARCH_CONVERT) - 1 >= 569 XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 570 if ((error = xfs_bmbt_rshift(tcur, level, &i))) { 571 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 572 goto error0; 573 } 574 if (i) { 575 ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) >= 576 XFS_BMAP_BLOCK_IMINRECS(level, tcur)); 577 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 578 tcur = NULL; 579 if (level == 0) 580 cur->bc_ptrs[0]++; 581 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 582 *stat = 1; 583 return 0; 584 } 585 } 586 lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT); 587 } 588 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 589 tcur = NULL; 590 mp = cur->bc_mp; 591 ASSERT(bno != NULLFSBLOCK); 592 if (lbno != NULLFSBLOCK && 593 lrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 594 rbno = bno; 595 right = block; 596 rbp = bp; 597 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, 598 XFS_BMAP_BTREE_REF))) { 599 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 600 goto error0; 601 } 602 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 603 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 604 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 605 goto error0; 606 } 607 } else if (rbno != NULLFSBLOCK && 608 rrecs + INT_GET(block->bb_numrecs, ARCH_CONVERT) <= 609 XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 610 lbno = bno; 611 left = block; 612 lbp = bp; 613 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, 614 XFS_BMAP_BTREE_REF))) { 615 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 616 goto error0; 617 } 618 right = XFS_BUF_TO_BMBT_BLOCK(rbp); 619 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 620 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 621 goto error0; 622 } 623 lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT); 624 } else { 625 if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { 626 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 627 goto error0; 628 } 629 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 630 *stat = 1; 631 return 0; 632 } 633 numlrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT); 634 numrrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT); 635 if (level > 0) { 636 lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); 637 lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); 638 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 639 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 640#ifdef DEBUG 641 for (i = 0; i < numrrecs; i++) { 642 if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) { 643 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 644 goto error0; 645 } 646 } 647#endif 648 memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); 649 memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); 650 xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 651 xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 652 } else { 653 lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); 654 rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 655 memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); 656 xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 657 } 658 INT_MOD(left->bb_numrecs, ARCH_CONVERT, numrrecs); 659 left->bb_rightsib = right->bb_rightsib; /* INT_: direct copy */ 660 xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); 661 if (INT_GET(left->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { 662 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, 663 INT_GET(left->bb_rightsib, ARCH_CONVERT), 664 0, &rrbp, XFS_BMAP_BTREE_REF))) { 665 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 666 goto error0; 667 } 668 rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); 669 if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { 670 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 671 goto error0; 672 } 673 INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, lbno); 674 xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); 675 } 676 xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, 677 cur->bc_private.b.flist, mp); 678 cur->bc_private.b.ip->i_d.di_nblocks--; 679 xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); 680 XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, 681 XFS_TRANS_DQ_BCOUNT, -1L); 682 xfs_trans_binval(cur->bc_tp, rbp); 683 if (bp != lbp) { 684 cur->bc_bufs[level] = lbp; 685 cur->bc_ptrs[level] += lrecs; 686 cur->bc_ra[level] = 0; 687 } else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) { 688 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 689 goto error0; 690 } 691 if (level > 0) 692 cur->bc_ptrs[level]--; 693 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 694 *stat = 2; 695 return 0; 696 697error0: 698 if (tcur) 699 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); 700 return error; 701} 702 703#ifdef DEBUG 704/* 705 * Get the data from the pointed-to record. 706 */ 707int 708xfs_bmbt_get_rec( 709 xfs_btree_cur_t *cur, 710 xfs_fileoff_t *off, 711 xfs_fsblock_t *bno, 712 xfs_filblks_t *len, 713 xfs_exntst_t *state, 714 int *stat) 715{ 716 xfs_bmbt_block_t *block; 717 xfs_buf_t *bp; 718#ifdef DEBUG 719 int error; 720#endif 721 int ptr; 722 xfs_bmbt_rec_t *rp; 723 724 block = xfs_bmbt_get_block(cur, 0, &bp); 725 ptr = cur->bc_ptrs[0]; 726#ifdef DEBUG 727 if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) 728 return error; 729#endif 730 if (ptr > INT_GET(block->bb_numrecs, ARCH_CONVERT) || ptr <= 0) { 731 *stat = 0; 732 return 0; 733 } 734 rp = XFS_BMAP_REC_IADDR(block, ptr, cur); 735 *off = xfs_bmbt_disk_get_startoff(rp); 736 *bno = xfs_bmbt_disk_get_startblock(rp); 737 *len = xfs_bmbt_disk_get_blockcount(rp); 738 *state = xfs_bmbt_disk_get_state(rp); 739 *stat = 1; 740 return 0; 741} 742#endif 743 744/* 745 * Insert one record/level. Return information to the caller 746 * allowing the next level up to proceed if necessary. 747 */ 748STATIC int /* error */ 749xfs_bmbt_insrec( 750 xfs_btree_cur_t *cur, 751 int level, 752 xfs_fsblock_t *bnop, 753 xfs_bmbt_rec_t *recp, 754 xfs_btree_cur_t **curp, 755 int *stat) /* no-go/done/continue */ 756{ 757 xfs_bmbt_block_t *block; /* bmap btree block */ 758 xfs_buf_t *bp; /* buffer for block */ 759 int error; /* error return value */ 760#ifdef XFS_BMBT_TRACE 761 static char fname[] = "xfs_bmbt_insrec"; 762#endif 763 int i; /* loop index */ 764 xfs_bmbt_key_t key; /* bmap btree key */ 765 xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ 766 int logflags; /* inode logging flags */ 767 xfs_fsblock_t nbno; /* new block number */ 768 struct xfs_btree_cur *ncur; /* new btree cursor */ 769 xfs_bmbt_key_t nkey; /* new btree key value */ 770 xfs_bmbt_rec_t nrec; /* new record count */ 771 int optr; /* old key/record index */ 772 xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ 773 int ptr; /* key/record index */ 774 xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ 775 int numrecs; 776 777 ASSERT(level < cur->bc_nlevels); 778 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 779 XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); 780 ncur = (xfs_btree_cur_t *)0; 781 INT_SET(key.br_startoff, ARCH_CONVERT, 782 xfs_bmbt_disk_get_startoff(recp)); 783 optr = ptr = cur->bc_ptrs[level]; 784 if (ptr == 0) { 785 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 786 *stat = 0; 787 return 0; 788 } 789 XFS_STATS_INC(xs_bmbt_insrec); 790 block = xfs_bmbt_get_block(cur, level, &bp); 791 numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT); 792#ifdef DEBUG 793 if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 794 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 795 return error; 796 } 797 if (ptr <= numrecs) { 798 if (level == 0) { 799 rp = XFS_BMAP_REC_IADDR(block, ptr, cur); 800 xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); 801 } else { 802 kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); 803 xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); 804 } 805 } 806#endif 807 nbno = NULLFSBLOCK; 808 if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 809 if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { 810 /* 811 * A root block, that can be made bigger. 812 */ 813 xfs_iroot_realloc(cur->bc_private.b.ip, 1, 814 cur->bc_private.b.whichfork); 815 block = xfs_bmbt_get_block(cur, level, &bp); 816 } else if (level == cur->bc_nlevels - 1) { 817 if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || 818 *stat == 0) { 819 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 820 return error; 821 } 822 xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, 823 logflags); 824 block = xfs_bmbt_get_block(cur, level, &bp); 825 } else { 826 if ((error = xfs_bmbt_rshift(cur, level, &i))) { 827 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 828 return error; 829 } 830 if (i) { 831 /* nothing */ 832 } else { 833 if ((error = xfs_bmbt_lshift(cur, level, &i))) { 834 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 835 return error; 836 } 837 if (i) { 838 optr = ptr = cur->bc_ptrs[level]; 839 } else { 840 if ((error = xfs_bmbt_split(cur, level, 841 &nbno, &nkey, &ncur, 842 &i))) { 843 XFS_BMBT_TRACE_CURSOR(cur, 844 ERROR); 845 return error; 846 } 847 if (i) { 848 block = xfs_bmbt_get_block( 849 cur, level, &bp); 850#ifdef DEBUG 851 if ((error = 852 xfs_btree_check_lblock(cur, 853 block, level, bp))) { 854 XFS_BMBT_TRACE_CURSOR( 855 cur, ERROR); 856 return error; 857 } 858#endif 859 ptr = cur->bc_ptrs[level]; 860 xfs_bmbt_disk_set_allf(&nrec, 861 nkey.br_startoff, 0, 0, 862 XFS_EXT_NORM); 863 } else { 864 XFS_BMBT_TRACE_CURSOR(cur, 865 EXIT); 866 *stat = 0; 867 return 0; 868 } 869 } 870 } 871 } 872 } 873 numrecs = INT_GET(block->bb_numrecs, ARCH_CONVERT); 874 if (level > 0) { 875 kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 876 pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 877#ifdef DEBUG 878 for (i = numrecs; i >= ptr; i--) { 879 if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT), 880 level))) { 881 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 882 return error; 883 } 884 } 885#endif 886 memmove(&kp[ptr], &kp[ptr - 1], 887 (numrecs - ptr + 1) * sizeof(*kp)); 888 memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */ 889 (numrecs - ptr + 1) * sizeof(*pp)); 890#ifdef DEBUG 891 if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop, 892 level))) { 893 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 894 return error; 895 } 896#endif 897 kp[ptr - 1] = key; 898 INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop); 899 numrecs++; 900 INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs); 901 xfs_bmbt_log_keys(cur, bp, ptr, numrecs); 902 xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); 903 } else { 904 rp = XFS_BMAP_REC_IADDR(block, 1, cur); 905 memmove(&rp[ptr], &rp[ptr - 1], 906 (numrecs - ptr + 1) * sizeof(*rp)); 907 rp[ptr - 1] = *recp; 908 numrecs++; 909 INT_SET(block->bb_numrecs, ARCH_CONVERT, numrecs); 910 xfs_bmbt_log_recs(cur, bp, ptr, numrecs); 911 } 912 xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); 913#ifdef DEBUG 914 if (ptr < numrecs) { 915 if (level == 0) 916 xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, 917 rp + ptr); 918 else 919 xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, 920 kp + ptr); 921 } 922#endif 923 if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) { 924 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 925 return error; 926 } 927 *bnop = nbno; 928 if (nbno != NULLFSBLOCK) { 929 *recp = nrec; 930 *curp = ncur; 931 } 932 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 933 *stat = 1; 934 return 0; 935} 936 937STATIC int 938xfs_bmbt_killroot( 939 xfs_btree_cur_t *cur) 940{ 941 xfs_bmbt_block_t *block; 942 xfs_bmbt_block_t *cblock; 943 xfs_buf_t *cbp; 944 xfs_bmbt_key_t *ckp; 945 xfs_bmbt_ptr_t *cpp; 946#ifdef DEBUG 947 int error; 948#endif 949#ifdef XFS_BMBT_TRACE 950 static char fname[] = "xfs_bmbt_killroot"; 951#endif 952 int i; 953 xfs_bmbt_key_t *kp; 954 xfs_inode_t *ip; 955 xfs_ifork_t *ifp; 956 int level; 957 xfs_bmbt_ptr_t *pp; 958 959 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 960 level = cur->bc_nlevels - 1; 961 ASSERT(level >= 1); 962 /* 963 * Don't deal with the root block needs to be a leaf case. 964 * We're just going to turn the thing back into extents anyway. 965 */ 966 if (level == 1) { 967 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 968 return 0; 969 } 970 block = xfs_bmbt_get_block(cur, level, &cbp); 971 /* 972 * Give up if the root has multiple children. 973 */ 974 if (INT_GET(block->bb_numrecs, ARCH_CONVERT) != 1) { 975 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 976 return 0; 977 } 978 /* 979 * Only do this if the next level will fit. 980 * Then the data must be copied up to the inode, 981 * instead of freeing the root you free the next level. 982 */ 983 cbp = cur->bc_bufs[level - 1]; 984 cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); 985 if (INT_GET(cblock->bb_numrecs, ARCH_CONVERT) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { 986 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 987 return 0; 988 } 989 ASSERT(INT_GET(cblock->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO); 990 ASSERT(INT_GET(cblock->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO); 991 ip = cur->bc_private.b.ip; 992 ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); 993 ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == 994 XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); 995 i = (int)(INT_GET(cblock->bb_numrecs, ARCH_CONVERT) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); 996 if (i) { 997 xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); 998 block = ifp->if_broot; 999 } 1000 INT_MOD(block->bb_numrecs, ARCH_CONVERT, i); 1001 ASSERT(INT_GET(block->bb_numrecs, ARCH_CONVERT) == INT_GET(cblock->bb_numrecs, ARCH_CONVERT)); 1002 kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 1003 ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); 1004 memcpy(kp, ckp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*kp)); 1005 pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 1006 cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); 1007#ifdef DEBUG 1008 for (i = 0; i < INT_GET(cblock->bb_numrecs, ARCH_CONVERT); i++) { 1009 if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) { 1010 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1011 return error; 1012 } 1013 } 1014#endif 1015 memcpy(pp, cpp, INT_GET(block->bb_numrecs, ARCH_CONVERT) * sizeof(*pp)); 1016 xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, 1017 cur->bc_private.b.flist, cur->bc_mp); 1018 ip->i_d.di_nblocks--; 1019 XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, 1020 XFS_TRANS_DQ_BCOUNT, -1L); 1021 xfs_trans_binval(cur->bc_tp, cbp); 1022 cur->bc_bufs[level - 1] = NULL; 1023 INT_MOD(block->bb_level, ARCH_CONVERT, -1); 1024 xfs_trans_log_inode(cur->bc_tp, ip, 1025 XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1026 cur->bc_nlevels--; 1027 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1028 return 0; 1029} 1030 1031/* 1032 * Log key values from the btree block. 1033 */ 1034STATIC void 1035xfs_bmbt_log_keys( 1036 xfs_btree_cur_t *cur, 1037 xfs_buf_t *bp, 1038 int kfirst, 1039 int klast) 1040{ 1041#ifdef XFS_BMBT_TRACE 1042 static char fname[] = "xfs_bmbt_log_keys"; 1043#endif 1044 xfs_trans_t *tp; 1045 1046 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1047 XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); 1048 tp = cur->bc_tp; 1049 if (bp) { 1050 xfs_bmbt_block_t *block; 1051 int first; 1052 xfs_bmbt_key_t *kp; 1053 int last; 1054 1055 block = XFS_BUF_TO_BMBT_BLOCK(bp); 1056 kp = XFS_BMAP_KEY_DADDR(block, 1, cur); 1057 first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); 1058 last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); 1059 xfs_trans_log_buf(tp, bp, first, last); 1060 } else { 1061 xfs_inode_t *ip; 1062 1063 ip = cur->bc_private.b.ip; 1064 xfs_trans_log_inode(tp, ip, 1065 XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1066 } 1067 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1068} 1069 1070/* 1071 * Log pointer values from the btree block. 1072 */ 1073STATIC void 1074xfs_bmbt_log_ptrs( 1075 xfs_btree_cur_t *cur, 1076 xfs_buf_t *bp, 1077 int pfirst, 1078 int plast) 1079{ 1080#ifdef XFS_BMBT_TRACE 1081 static char fname[] = "xfs_bmbt_log_ptrs"; 1082#endif 1083 xfs_trans_t *tp; 1084 1085 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1086 XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); 1087 tp = cur->bc_tp; 1088 if (bp) { 1089 xfs_bmbt_block_t *block; 1090 int first; 1091 int last; 1092 xfs_bmbt_ptr_t *pp; 1093 1094 block = XFS_BUF_TO_BMBT_BLOCK(bp); 1095 pp = XFS_BMAP_PTR_DADDR(block, 1, cur); 1096 first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); 1097 last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); 1098 xfs_trans_log_buf(tp, bp, first, last); 1099 } else { 1100 xfs_inode_t *ip; 1101 1102 ip = cur->bc_private.b.ip; 1103 xfs_trans_log_inode(tp, ip, 1104 XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1105 } 1106 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1107} 1108 1109/* 1110 * Lookup the record. The cursor is made to point to it, based on dir. 1111 */ 1112STATIC int /* error */ 1113xfs_bmbt_lookup( 1114 xfs_btree_cur_t *cur, 1115 xfs_lookup_t dir, 1116 int *stat) /* success/failure */ 1117{ 1118 xfs_bmbt_block_t *block=NULL; 1119 xfs_buf_t *bp; 1120 xfs_daddr_t d; 1121 xfs_sfiloff_t diff; 1122 int error; /* error return value */ 1123#ifdef XFS_BMBT_TRACE 1124 static char fname[] = "xfs_bmbt_lookup"; 1125#endif 1126 xfs_fsblock_t fsbno=0; 1127 int high; 1128 int i; 1129 int keyno=0; 1130 xfs_bmbt_key_t *kkbase=NULL; 1131 xfs_bmbt_key_t *kkp; 1132 xfs_bmbt_rec_t *krbase=NULL; 1133 xfs_bmbt_rec_t *krp; 1134 int level; 1135 int low; 1136 xfs_mount_t *mp; 1137 xfs_bmbt_ptr_t *pp; 1138 xfs_bmbt_irec_t *rp; 1139 xfs_fileoff_t startoff; 1140 xfs_trans_t *tp; 1141 1142 XFS_STATS_INC(xs_bmbt_lookup); 1143 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1144 XFS_BMBT_TRACE_ARGI(cur, (int)dir); 1145 tp = cur->bc_tp; 1146 mp = cur->bc_mp; 1147 rp = &cur->bc_rec.b; 1148 for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { 1149 if (level < cur->bc_nlevels - 1) { 1150 d = XFS_FSB_TO_DADDR(mp, fsbno); 1151 bp = cur->bc_bufs[level]; 1152 if (bp && XFS_BUF_ADDR(bp) != d) 1153 bp = (xfs_buf_t *)0; 1154 if (!bp) { 1155 if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 1156 0, &bp, XFS_BMAP_BTREE_REF))) { 1157 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1158 return error; 1159 } 1160 xfs_btree_setbuf(cur, level, bp); 1161 block = XFS_BUF_TO_BMBT_BLOCK(bp); 1162 if ((error = xfs_btree_check_lblock(cur, block, 1163 level, bp))) { 1164 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1165 return error; 1166 } 1167 } else 1168 block = XFS_BUF_TO_BMBT_BLOCK(bp); 1169 } else 1170 block = xfs_bmbt_get_block(cur, level, &bp); 1171 if (diff == 0) 1172 keyno = 1; 1173 else { 1174 if (level > 0) 1175 kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur); 1176 else 1177 krbase = XFS_BMAP_REC_IADDR(block, 1, cur); 1178 low = 1; 1179 if (!(high = INT_GET(block->bb_numrecs, ARCH_CONVERT))) { 1180 ASSERT(level == 0); 1181 cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; 1182 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1183 *stat = 0; 1184 return 0; 1185 } 1186 while (low <= high) { 1187 XFS_STATS_INC(xs_bmbt_compare); 1188 keyno = (low + high) >> 1; 1189 if (level > 0) { 1190 kkp = kkbase + keyno - 1; 1191 startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT); 1192 } else { 1193 krp = krbase + keyno - 1; 1194 startoff = xfs_bmbt_disk_get_startoff(krp); 1195 } 1196 diff = (xfs_sfiloff_t) 1197 (startoff - rp->br_startoff); 1198 if (diff < 0) 1199 low = keyno + 1; 1200 else if (diff > 0) 1201 high = keyno - 1; 1202 else 1203 break; 1204 } 1205 } 1206 if (level > 0) { 1207 if (diff > 0 && --keyno < 1) 1208 keyno = 1; 1209 pp = XFS_BMAP_PTR_IADDR(block, keyno, cur); 1210#ifdef DEBUG 1211 if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { 1212 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1213 return error; 1214 } 1215#endif 1216 fsbno = INT_GET(*pp, ARCH_CONVERT); 1217 cur->bc_ptrs[level] = keyno; 1218 } 1219 } 1220 if (dir != XFS_LOOKUP_LE && diff < 0) { 1221 keyno++; 1222 /* 1223 * If ge search and we went off the end of the block, but it's 1224 * not the last block, we're in the wrong block. 1225 */ 1226 if (dir == XFS_LOOKUP_GE && keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT) && 1227 INT_GET(block->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { 1228 cur->bc_ptrs[0] = keyno; 1229 if ((error = xfs_bmbt_increment(cur, 0, &i))) { 1230 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1231 return error; 1232 } 1233 XFS_WANT_CORRUPTED_RETURN(i == 1); 1234 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1235 *stat = 1; 1236 return 0; 1237 } 1238 } 1239 else if (dir == XFS_LOOKUP_LE && diff > 0) 1240 keyno--; 1241 cur->bc_ptrs[0] = keyno; 1242 if (keyno == 0 || keyno > INT_GET(block->bb_numrecs, ARCH_CONVERT)) { 1243 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1244 *stat = 0; 1245 } else { 1246 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1247 *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0)); 1248 } 1249 return 0; 1250} 1251 1252/* 1253 * Move 1 record left from cur/level if possible. 1254 * Update cur to reflect the new path. 1255 */ 1256STATIC int /* error */ 1257xfs_bmbt_lshift( 1258 xfs_btree_cur_t *cur, 1259 int level, 1260 int *stat) /* success/failure */ 1261{ 1262 int error; /* error return value */ 1263#ifdef XFS_BMBT_TRACE 1264 static char fname[] = "xfs_bmbt_lshift"; 1265#endif 1266#ifdef DEBUG 1267 int i; /* loop counter */ 1268#endif 1269 xfs_bmbt_key_t key; /* bmap btree key */ 1270 xfs_buf_t *lbp; /* left buffer pointer */ 1271 xfs_bmbt_block_t *left; /* left btree block */ 1272 xfs_bmbt_key_t *lkp=NULL; /* left btree key */ 1273 xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1274 int lrecs; /* left record count */ 1275 xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ 1276 xfs_mount_t *mp; /* file system mount point */ 1277 xfs_buf_t *rbp; /* right buffer pointer */ 1278 xfs_bmbt_block_t *right; /* right btree block */ 1279 xfs_bmbt_key_t *rkp=NULL; /* right btree key */ 1280 xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ 1281 xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ 1282 int rrecs; /* right record count */ 1283 1284 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1285 XFS_BMBT_TRACE_ARGI(cur, level); 1286 if (level == cur->bc_nlevels - 1) { 1287 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1288 *stat = 0; 1289 return 0; 1290 } 1291 rbp = cur->bc_bufs[level]; 1292 right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1293#ifdef DEBUG 1294 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 1295 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1296 return error; 1297 } 1298#endif 1299 if (INT_GET(right->bb_leftsib, ARCH_CONVERT) == NULLDFSBNO) { 1300 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1301 *stat = 0; 1302 return 0; 1303 } 1304 if (cur->bc_ptrs[level] <= 1) { 1305 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1306 *stat = 0; 1307 return 0; 1308 } 1309 mp = cur->bc_mp; 1310 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, INT_GET(right->bb_leftsib, ARCH_CONVERT), 0, 1311 &lbp, XFS_BMAP_BTREE_REF))) { 1312 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1313 return error; 1314 } 1315 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1316 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 1317 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1318 return error; 1319 } 1320 if (INT_GET(left->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 1321 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1322 *stat = 0; 1323 return 0; 1324 } 1325 lrecs = INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1; 1326 if (level > 0) { 1327 lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); 1328 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1329 *lkp = *rkp; 1330 xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); 1331 lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); 1332 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1333#ifdef DEBUG 1334 if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) { 1335 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1336 return error; 1337 } 1338#endif 1339 *lpp = *rpp; /* INT_: direct copy */ 1340 xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); 1341 } else { 1342 lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); 1343 rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1344 *lrp = *rrp; 1345 xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); 1346 } 1347 INT_SET(left->bb_numrecs, ARCH_CONVERT, lrecs); 1348 xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); 1349#ifdef DEBUG 1350 if (level > 0) 1351 xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); 1352 else 1353 xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); 1354#endif 1355 rrecs = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; 1356 INT_SET(right->bb_numrecs, ARCH_CONVERT, rrecs); 1357 xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); 1358 if (level > 0) { 1359#ifdef DEBUG 1360 for (i = 0; i < rrecs; i++) { 1361 if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT), 1362 level))) { 1363 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1364 return error; 1365 } 1366 } 1367#endif 1368 memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); 1369 memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); 1370 xfs_bmbt_log_keys(cur, rbp, 1, rrecs); 1371 xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); 1372 } else { 1373 memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); 1374 xfs_bmbt_log_recs(cur, rbp, 1, rrecs); 1375 INT_SET(key.br_startoff, ARCH_CONVERT, 1376 xfs_bmbt_disk_get_startoff(rrp)); 1377 rkp = &key; 1378 } 1379 if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) { 1380 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1381 return error; 1382 } 1383 cur->bc_ptrs[level]--; 1384 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1385 *stat = 1; 1386 return 0; 1387} 1388 1389/* 1390 * Move 1 record right from cur/level if possible. 1391 * Update cur to reflect the new path. 1392 */ 1393STATIC int /* error */ 1394xfs_bmbt_rshift( 1395 xfs_btree_cur_t *cur, 1396 int level, 1397 int *stat) /* success/failure */ 1398{ 1399 int error; /* error return value */ 1400#ifdef XFS_BMBT_TRACE 1401 static char fname[] = "xfs_bmbt_rshift"; 1402#endif 1403 int i; /* loop counter */ 1404 xfs_bmbt_key_t key; /* bmap btree key */ 1405 xfs_buf_t *lbp; /* left buffer pointer */ 1406 xfs_bmbt_block_t *left; /* left btree block */ 1407 xfs_bmbt_key_t *lkp; /* left btree key */ 1408 xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1409 xfs_bmbt_rec_t *lrp; /* left record pointer */ 1410 xfs_mount_t *mp; /* file system mount point */ 1411 xfs_buf_t *rbp; /* right buffer pointer */ 1412 xfs_bmbt_block_t *right; /* right btree block */ 1413 xfs_bmbt_key_t *rkp; /* right btree key */ 1414 xfs_bmbt_ptr_t *rpp; /* right address pointer */ 1415 xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ 1416 struct xfs_btree_cur *tcur; /* temporary btree cursor */ 1417 1418 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1419 XFS_BMBT_TRACE_ARGI(cur, level); 1420 if (level == cur->bc_nlevels - 1) { 1421 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1422 *stat = 0; 1423 return 0; 1424 } 1425 lbp = cur->bc_bufs[level]; 1426 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1427#ifdef DEBUG 1428 if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 1429 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1430 return error; 1431 } 1432#endif 1433 if (INT_GET(left->bb_rightsib, ARCH_CONVERT) == NULLDFSBNO) { 1434 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1435 *stat = 0; 1436 return 0; 1437 } 1438 if (cur->bc_ptrs[level] >= INT_GET(left->bb_numrecs, ARCH_CONVERT)) { 1439 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1440 *stat = 0; 1441 return 0; 1442 } 1443 mp = cur->bc_mp; 1444 if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, INT_GET(left->bb_rightsib, ARCH_CONVERT), 0, 1445 &rbp, XFS_BMAP_BTREE_REF))) { 1446 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1447 return error; 1448 } 1449 right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1450 if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 1451 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1452 return error; 1453 } 1454 if (INT_GET(right->bb_numrecs, ARCH_CONVERT) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 1455 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1456 *stat = 0; 1457 return 0; 1458 } 1459 if (level > 0) { 1460 lkp = XFS_BMAP_KEY_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); 1461 lpp = XFS_BMAP_PTR_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); 1462 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1463 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1464#ifdef DEBUG 1465 for (i = INT_GET(right->bb_numrecs, ARCH_CONVERT) - 1; i >= 0; i--) { 1466 if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) { 1467 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1468 return error; 1469 } 1470 } 1471#endif 1472 memmove(rkp + 1, rkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); 1473 memmove(rpp + 1, rpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); 1474#ifdef DEBUG 1475 if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) { 1476 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1477 return error; 1478 } 1479#endif 1480 *rkp = *lkp; 1481 *rpp = *lpp; /* INT_: direct copy */ 1482 xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); 1483 xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); 1484 } else { 1485 lrp = XFS_BMAP_REC_IADDR(left, INT_GET(left->bb_numrecs, ARCH_CONVERT), cur); 1486 rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1487 memmove(rrp + 1, rrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp)); 1488 *rrp = *lrp; 1489 xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1); 1490 INT_SET(key.br_startoff, ARCH_CONVERT, 1491 xfs_bmbt_disk_get_startoff(rrp)); 1492 rkp = &key; 1493 } 1494 INT_MOD(left->bb_numrecs, ARCH_CONVERT, -1); 1495 xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); 1496 INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1); 1497#ifdef DEBUG 1498 if (level > 0) 1499 xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); 1500 else 1501 xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1); 1502#endif 1503 xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); 1504 if ((error = xfs_btree_dup_cursor(cur, &tcur))) { 1505 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1506 return error; 1507 } 1508 i = xfs_btree_lastrec(tcur, level); 1509 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 1510 if ((error = xfs_bmbt_increment(tcur, level, &i))) { 1511 XFS_BMBT_TRACE_CURSOR(tcur, ERROR); 1512 goto error1; 1513 } 1514 XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 1515 if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) { 1516 XFS_BMBT_TRACE_CURSOR(tcur, ERROR); 1517 goto error1; 1518 } 1519 xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 1520 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1521 *stat = 1; 1522 return 0; 1523error0: 1524 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1525error1: 1526 xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); 1527 return error; 1528} 1529 1530/* 1531 * Determine the extent state. 1532 */ 1533/* ARGSUSED */ 1534STATIC xfs_exntst_t 1535xfs_extent_state( 1536 xfs_filblks_t blks, 1537 int extent_flag) 1538{ 1539 if (extent_flag) { 1540 ASSERT(blks != 0); /* saved for DMIG */ 1541 return XFS_EXT_UNWRITTEN; 1542 } 1543 return XFS_EXT_NORM; 1544} 1545 1546 1547/* 1548 * Split cur/level block in half. 1549 * Return new block number and its first record (to be inserted into parent). 1550 */ 1551STATIC int /* error */ 1552xfs_bmbt_split( 1553 xfs_btree_cur_t *cur, 1554 int level, 1555 xfs_fsblock_t *bnop, 1556 xfs_bmbt_key_t *keyp, 1557 xfs_btree_cur_t **curp, 1558 int *stat) /* success/failure */ 1559{ 1560 xfs_alloc_arg_t args; /* block allocation args */ 1561 int error; /* error return value */ 1562#ifdef XFS_BMBT_TRACE 1563 static char fname[] = "xfs_bmbt_split"; 1564#endif 1565 int i; /* loop counter */ 1566 xfs_fsblock_t lbno; /* left sibling block number */ 1567 xfs_buf_t *lbp; /* left buffer pointer */ 1568 xfs_bmbt_block_t *left; /* left btree block */ 1569 xfs_bmbt_key_t *lkp; /* left btree key */ 1570 xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1571 xfs_bmbt_rec_t *lrp; /* left record pointer */ 1572 xfs_buf_t *rbp; /* right buffer pointer */ 1573 xfs_bmbt_block_t *right; /* right btree block */ 1574 xfs_bmbt_key_t *rkp; /* right btree key */ 1575 xfs_bmbt_ptr_t *rpp; /* right address pointer */ 1576 xfs_bmbt_block_t *rrblock; /* right-right btree block */ 1577 xfs_buf_t *rrbp; /* right-right buffer pointer */ 1578 xfs_bmbt_rec_t *rrp; /* right record pointer */ 1579 1580 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1581 XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp); 1582 args.tp = cur->bc_tp; 1583 args.mp = cur->bc_mp; 1584 lbp = cur->bc_bufs[level]; 1585 lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); 1586 left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1587 args.fsbno = cur->bc_private.b.firstblock; 1588 if (args.fsbno == NULLFSBLOCK) { 1589 args.fsbno = lbno; 1590 args.type = XFS_ALLOCTYPE_START_BNO; 1591 } else if (cur->bc_private.b.flist->xbf_low) 1592 args.type = XFS_ALLOCTYPE_FIRST_AG; 1593 else 1594 args.type = XFS_ALLOCTYPE_NEAR_BNO; 1595 args.mod = args.minleft = args.alignment = args.total = args.isfl = 1596 args.userdata = args.minalignslop = 0; 1597 args.minlen = args.maxlen = args.prod = 1; 1598 args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; 1599 if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { 1600 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1601 return XFS_ERROR(ENOSPC); 1602 } 1603 if ((error = xfs_alloc_vextent(&args))) { 1604 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1605 return error; 1606 } 1607 if (args.fsbno == NULLFSBLOCK) { 1608 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1609 *stat = 0; 1610 return 0; 1611 } 1612 ASSERT(args.len == 1); 1613 cur->bc_private.b.firstblock = args.fsbno; 1614 cur->bc_private.b.allocated++; 1615 cur->bc_private.b.ip->i_d.di_nblocks++; 1616 xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); 1617 XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, 1618 XFS_TRANS_DQ_BCOUNT, 1L); 1619 rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); 1620 right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1621#ifdef DEBUG 1622 if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { 1623 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1624 return error; 1625 } 1626#endif 1627 INT_SET(right->bb_magic, ARCH_CONVERT, XFS_BMAP_MAGIC); 1628 right->bb_level = left->bb_level; /* INT_: direct copy */ 1629 INT_SET(right->bb_numrecs, ARCH_CONVERT, (__uint16_t)(INT_GET(left->bb_numrecs, ARCH_CONVERT) / 2)); 1630 if ((INT_GET(left->bb_numrecs, ARCH_CONVERT) & 1) && 1631 cur->bc_ptrs[level] <= INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1) 1632 INT_MOD(right->bb_numrecs, ARCH_CONVERT, +1); 1633 i = INT_GET(left->bb_numrecs, ARCH_CONVERT) - INT_GET(right->bb_numrecs, ARCH_CONVERT) + 1; 1634 if (level > 0) { 1635 lkp = XFS_BMAP_KEY_IADDR(left, i, cur); 1636 lpp = XFS_BMAP_PTR_IADDR(left, i, cur); 1637 rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1638 rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1639#ifdef DEBUG 1640 for (i = 0; i < INT_GET(right->bb_numrecs, ARCH_CONVERT); i++) { 1641 if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) { 1642 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1643 return error; 1644 } 1645 } 1646#endif 1647 memcpy(rkp, lkp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rkp)); 1648 memcpy(rpp, lpp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rpp)); 1649 xfs_bmbt_log_keys(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); 1650 xfs_bmbt_log_ptrs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); 1651 keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT); 1652 } else { 1653 lrp = XFS_BMAP_REC_IADDR(left, i, cur); 1654 rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1655 memcpy(rrp, lrp, INT_GET(right->bb_numrecs, ARCH_CONVERT) * sizeof(*rrp)); 1656 xfs_bmbt_log_recs(cur, rbp, 1, INT_GET(right->bb_numrecs, ARCH_CONVERT)); 1657 keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp); 1658 } 1659 INT_MOD(left->bb_numrecs, ARCH_CONVERT, -(INT_GET(right->bb_numrecs, ARCH_CONVERT))); 1660 right->bb_rightsib = left->bb_rightsib; /* INT_: direct copy */ 1661 INT_SET(left->bb_rightsib, ARCH_CONVERT, args.fsbno); 1662 INT_SET(right->bb_leftsib, ARCH_CONVERT, lbno); 1663 xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); 1664 xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); 1665 if (INT_GET(right->bb_rightsib, ARCH_CONVERT) != NULLDFSBNO) { 1666 if ((error = xfs_btree_read_bufl(args.mp, args.tp, 1667 INT_GET(right->bb_rightsib, ARCH_CONVERT), 0, &rrbp, 1668 XFS_BMAP_BTREE_REF))) { 1669 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1670 return error; 1671 } 1672 rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); 1673 if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { 1674 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1675 return error; 1676 } 1677 INT_SET(rrblock->bb_leftsib, ARCH_CONVERT, args.fsbno); 1678 xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); 1679 } 1680 if (cur->bc_ptrs[level] > INT_GET(left->bb_numrecs, ARCH_CONVERT) + 1) { 1681 xfs_btree_setbuf(cur, level, rbp); 1682 cur->bc_ptrs[level] -= INT_GET(left->bb_numrecs, ARCH_CONVERT); 1683 } 1684 if (level + 1 < cur->bc_nlevels) { 1685 if ((error = xfs_btree_dup_cursor(cur, curp))) { 1686 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1687 return error; 1688 } 1689 (*curp)->bc_ptrs[level + 1]++; 1690 } 1691 *bnop = args.fsbno; 1692 XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1693 *stat = 1; 1694 return 0; 1695} 1696 1697 1698/* 1699 * Update keys for the record. 1700 */ 1701STATIC int 1702xfs_bmbt_updkey( 1703 xfs_btree_cur_t *cur, 1704 xfs_bmbt_key_t *keyp, /* on-disk format */ 1705 int level) 1706{ 1707 xfs_bmbt_block_t *block; 1708 xfs_buf_t *bp; 1709#ifdef DEBUG 1710 int error; 1711#endif 1712#ifdef XFS_BMBT_TRACE 1713 static char fname[] = "xfs_bmbt_updkey"; 1714#endif 1715 xfs_bmbt_key_t *kp; 1716 int ptr; 1717 1718 ASSERT(level >= 1); 1719 XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1720 XFS_BMBT_TRACE_ARGIK(cur, level, keyp); 1721 for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { 1722 block = xfs_bmbt_get_block(cur, level, &bp); 1723#ifdef DEBUG 1724 if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 1725 XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1726 return error; 1727 } 1728#endif 1729 ptr = cur->bc_ptrs[level]; 1730 kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); 1731 *kp =…
Large files files are truncated, but you can click here to view the full file