1153323Srodrigc/* 2159451Srodrigc * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. 3159451Srodrigc * All Rights Reserved. 4153323Srodrigc * 5159451Srodrigc * This program is free software; you can redistribute it and/or 6159451Srodrigc * modify it under the terms of the GNU General Public License as 7153323Srodrigc * published by the Free Software Foundation. 8153323Srodrigc * 9159451Srodrigc * This program is distributed in the hope that it would be useful, 10159451Srodrigc * but WITHOUT ANY WARRANTY; without even the implied warranty of 11159451Srodrigc * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12159451Srodrigc * GNU General Public License for more details. 13153323Srodrigc * 14159451Srodrigc * You should have received a copy of the GNU General Public License 15159451Srodrigc * along with this program; if not, write the Free Software Foundation, 16159451Srodrigc * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 17153323Srodrigc */ 18153323Srodrigc#include "xfs.h" 19159451Srodrigc#include "xfs_fs.h" 20153323Srodrigc#include "xfs_types.h" 21159451Srodrigc#include "xfs_bit.h" 22159451Srodrigc#include "xfs_log.h" 23153323Srodrigc#include "xfs_inum.h" 24153323Srodrigc#include "xfs_trans.h" 25153323Srodrigc#include "xfs_sb.h" 26153323Srodrigc#include "xfs_ag.h" 27153323Srodrigc#include "xfs_dir.h" 28153323Srodrigc#include "xfs_dir2.h" 29153323Srodrigc#include "xfs_dmapi.h" 30153323Srodrigc#include "xfs_mount.h" 31159451Srodrigc#include "xfs_bmap_btree.h" 32153323Srodrigc#include "xfs_alloc_btree.h" 33153323Srodrigc#include "xfs_ialloc_btree.h" 34153323Srodrigc#include "xfs_dir_sf.h" 35153323Srodrigc#include "xfs_dir2_sf.h" 36159451Srodrigc#include "xfs_attr_sf.h" 37153323Srodrigc#include "xfs_dinode.h" 38159451Srodrigc#include "xfs_inode.h" 39153323Srodrigc#include "xfs_inode_item.h" 40153323Srodrigc#include "xfs_alloc.h" 41159451Srodrigc#include "xfs_btree.h" 42159451Srodrigc#include "xfs_ialloc.h" 43159451Srodrigc#include "xfs_itable.h" 44153323Srodrigc#include "xfs_bmap.h" 45153323Srodrigc#include "xfs_error.h" 46153323Srodrigc#include "xfs_quota.h" 47153323Srodrigc 48153323Srodrigc#if defined(XFS_BMBT_TRACE) 49153323Srodrigcktrace_t *xfs_bmbt_trace_buf; 50153323Srodrigc#endif 51153323Srodrigc 52153323Srodrigc/* 53153323Srodrigc * Prototypes for internal btree functions. 54153323Srodrigc */ 55153323Srodrigc 56153323Srodrigc 57153323SrodrigcSTATIC int xfs_bmbt_killroot(xfs_btree_cur_t *); 58153323SrodrigcSTATIC void xfs_bmbt_log_keys(xfs_btree_cur_t *, xfs_buf_t *, int, int); 59153323SrodrigcSTATIC void xfs_bmbt_log_ptrs(xfs_btree_cur_t *, xfs_buf_t *, int, int); 60153323SrodrigcSTATIC int xfs_bmbt_lshift(xfs_btree_cur_t *, int, int *); 61153323SrodrigcSTATIC int xfs_bmbt_rshift(xfs_btree_cur_t *, int, int *); 62153323SrodrigcSTATIC int xfs_bmbt_split(xfs_btree_cur_t *, int, xfs_fsblock_t *, 63153323Srodrigc xfs_bmbt_key_t *, xfs_btree_cur_t **, int *); 64153323SrodrigcSTATIC int xfs_bmbt_updkey(xfs_btree_cur_t *, xfs_bmbt_key_t *, int); 65153323Srodrigc 66153323Srodrigc 67153323Srodrigc#if defined(XFS_BMBT_TRACE) 68153323Srodrigc 69153323Srodrigcstatic char ARGS[] = "args"; 70153323Srodrigcstatic char ENTRY[] = "entry"; 71153323Srodrigcstatic char ERROR[] = "error"; 72153323Srodrigc#undef EXIT 73153323Srodrigcstatic char EXIT[] = "exit"; 74153323Srodrigc 75153323Srodrigc/* 76153323Srodrigc * Add a trace buffer entry for the arguments given to the routine, 77153323Srodrigc * generic form. 78153323Srodrigc */ 79153323SrodrigcSTATIC void 80153323Srodrigcxfs_bmbt_trace_enter( 81153323Srodrigc char *func, 82153323Srodrigc xfs_btree_cur_t *cur, 83153323Srodrigc char *s, 84153323Srodrigc int type, 85153323Srodrigc int line, 86153323Srodrigc __psunsigned_t a0, 87153323Srodrigc __psunsigned_t a1, 88153323Srodrigc __psunsigned_t a2, 89153323Srodrigc __psunsigned_t a3, 90153323Srodrigc __psunsigned_t a4, 91153323Srodrigc __psunsigned_t a5, 92153323Srodrigc __psunsigned_t a6, 93153323Srodrigc __psunsigned_t a7, 94153323Srodrigc __psunsigned_t a8, 95153323Srodrigc __psunsigned_t a9, 96153323Srodrigc __psunsigned_t a10) 97153323Srodrigc{ 98153323Srodrigc xfs_inode_t *ip; 99153323Srodrigc int whichfork; 100153323Srodrigc 101153323Srodrigc ip = cur->bc_private.b.ip; 102153323Srodrigc whichfork = cur->bc_private.b.whichfork; 103153323Srodrigc ktrace_enter(xfs_bmbt_trace_buf, 104153323Srodrigc (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), 105153323Srodrigc (void *)func, (void *)s, (void *)ip, (void *)cur, 106153323Srodrigc (void *)a0, (void *)a1, (void *)a2, (void *)a3, 107153323Srodrigc (void *)a4, (void *)a5, (void *)a6, (void *)a7, 108153323Srodrigc (void *)a8, (void *)a9, (void *)a10); 109153323Srodrigc ASSERT(ip->i_btrace); 110153323Srodrigc ktrace_enter(ip->i_btrace, 111153323Srodrigc (void *)((__psint_t)type | (whichfork << 8) | (line << 16)), 112153323Srodrigc (void *)func, (void *)s, (void *)ip, (void *)cur, 113153323Srodrigc (void *)a0, (void *)a1, (void *)a2, (void *)a3, 114153323Srodrigc (void *)a4, (void *)a5, (void *)a6, (void *)a7, 115153323Srodrigc (void *)a8, (void *)a9, (void *)a10); 116153323Srodrigc} 117153323Srodrigc/* 118153323Srodrigc * Add a trace buffer entry for arguments, for a buffer & 1 integer arg. 119153323Srodrigc */ 120153323SrodrigcSTATIC void 121153323Srodrigcxfs_bmbt_trace_argbi( 122153323Srodrigc char *func, 123153323Srodrigc xfs_btree_cur_t *cur, 124153323Srodrigc xfs_buf_t *b, 125153323Srodrigc int i, 126153323Srodrigc int line) 127153323Srodrigc{ 128153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBI, line, 129153323Srodrigc (__psunsigned_t)b, i, 0, 0, 130153323Srodrigc 0, 0, 0, 0, 131153323Srodrigc 0, 0, 0); 132153323Srodrigc} 133153323Srodrigc 134153323Srodrigc/* 135153323Srodrigc * Add a trace buffer entry for arguments, for a buffer & 2 integer args. 136153323Srodrigc */ 137153323SrodrigcSTATIC void 138153323Srodrigcxfs_bmbt_trace_argbii( 139153323Srodrigc char *func, 140153323Srodrigc xfs_btree_cur_t *cur, 141153323Srodrigc xfs_buf_t *b, 142153323Srodrigc int i0, 143153323Srodrigc int i1, 144153323Srodrigc int line) 145153323Srodrigc{ 146153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGBII, line, 147153323Srodrigc (__psunsigned_t)b, i0, i1, 0, 148153323Srodrigc 0, 0, 0, 0, 149153323Srodrigc 0, 0, 0); 150153323Srodrigc} 151153323Srodrigc 152153323Srodrigc/* 153153323Srodrigc * Add a trace buffer entry for arguments, for 3 block-length args 154153323Srodrigc * and an integer arg. 155153323Srodrigc */ 156153323SrodrigcSTATIC void 157153323Srodrigcxfs_bmbt_trace_argfffi( 158153323Srodrigc char *func, 159153323Srodrigc xfs_btree_cur_t *cur, 160153323Srodrigc xfs_dfiloff_t o, 161153323Srodrigc xfs_dfsbno_t b, 162153323Srodrigc xfs_dfilblks_t i, 163153323Srodrigc int j, 164153323Srodrigc int line) 165153323Srodrigc{ 166153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGFFFI, line, 167153323Srodrigc o >> 32, (int)o, b >> 32, (int)b, 168153323Srodrigc i >> 32, (int)i, (int)j, 0, 169153323Srodrigc 0, 0, 0); 170153323Srodrigc} 171153323Srodrigc 172153323Srodrigc/* 173153323Srodrigc * Add a trace buffer entry for arguments, for one integer arg. 174153323Srodrigc */ 175153323SrodrigcSTATIC void 176153323Srodrigcxfs_bmbt_trace_argi( 177153323Srodrigc char *func, 178153323Srodrigc xfs_btree_cur_t *cur, 179153323Srodrigc int i, 180153323Srodrigc int line) 181153323Srodrigc{ 182153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGI, line, 183153323Srodrigc i, 0, 0, 0, 184153323Srodrigc 0, 0, 0, 0, 185153323Srodrigc 0, 0, 0); 186153323Srodrigc} 187153323Srodrigc 188153323Srodrigc/* 189153323Srodrigc * Add a trace buffer entry for arguments, for int, fsblock, key. 190153323Srodrigc */ 191153323SrodrigcSTATIC void 192153323Srodrigcxfs_bmbt_trace_argifk( 193153323Srodrigc char *func, 194153323Srodrigc xfs_btree_cur_t *cur, 195153323Srodrigc int i, 196153323Srodrigc xfs_fsblock_t f, 197153323Srodrigc xfs_bmbt_key_t *k, 198153323Srodrigc int line) 199153323Srodrigc{ 200153323Srodrigc xfs_dfsbno_t d; 201153323Srodrigc xfs_dfiloff_t o; 202153323Srodrigc 203153323Srodrigc d = (xfs_dfsbno_t)f; 204153323Srodrigc o = INT_GET(k->br_startoff, ARCH_CONVERT); 205153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, 206153323Srodrigc i, d >> 32, (int)d, o >> 32, 207153323Srodrigc (int)o, 0, 0, 0, 208153323Srodrigc 0, 0, 0); 209153323Srodrigc} 210153323Srodrigc 211153323Srodrigc/* 212153323Srodrigc * Add a trace buffer entry for arguments, for int, fsblock, rec. 213153323Srodrigc */ 214153323SrodrigcSTATIC void 215153323Srodrigcxfs_bmbt_trace_argifr( 216153323Srodrigc char *func, 217153323Srodrigc xfs_btree_cur_t *cur, 218153323Srodrigc int i, 219153323Srodrigc xfs_fsblock_t f, 220153323Srodrigc xfs_bmbt_rec_t *r, 221153323Srodrigc int line) 222153323Srodrigc{ 223153323Srodrigc xfs_dfsbno_t b; 224153323Srodrigc xfs_dfilblks_t c; 225153323Srodrigc xfs_dfsbno_t d; 226153323Srodrigc xfs_dfiloff_t o; 227153323Srodrigc xfs_bmbt_irec_t s; 228153323Srodrigc 229153323Srodrigc d = (xfs_dfsbno_t)f; 230153323Srodrigc xfs_bmbt_disk_get_all(r, &s); 231153323Srodrigc o = (xfs_dfiloff_t)s.br_startoff; 232153323Srodrigc b = (xfs_dfsbno_t)s.br_startblock; 233153323Srodrigc c = s.br_blockcount; 234153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFR, line, 235153323Srodrigc i, d >> 32, (int)d, o >> 32, 236153323Srodrigc (int)o, b >> 32, (int)b, c >> 32, 237153323Srodrigc (int)c, 0, 0); 238153323Srodrigc} 239153323Srodrigc 240153323Srodrigc/* 241153323Srodrigc * Add a trace buffer entry for arguments, for int, key. 242153323Srodrigc */ 243153323SrodrigcSTATIC void 244153323Srodrigcxfs_bmbt_trace_argik( 245153323Srodrigc char *func, 246153323Srodrigc xfs_btree_cur_t *cur, 247153323Srodrigc int i, 248153323Srodrigc xfs_bmbt_key_t *k, 249153323Srodrigc int line) 250153323Srodrigc{ 251153323Srodrigc xfs_dfiloff_t o; 252153323Srodrigc 253153323Srodrigc o = INT_GET(k->br_startoff, ARCH_CONVERT); 254153323Srodrigc xfs_bmbt_trace_enter(func, cur, ARGS, XFS_BMBT_KTRACE_ARGIFK, line, 255153323Srodrigc i, o >> 32, (int)o, 0, 256153323Srodrigc 0, 0, 0, 0, 257153323Srodrigc 0, 0, 0); 258153323Srodrigc} 259153323Srodrigc 260153323Srodrigc/* 261153323Srodrigc * Add a trace buffer entry for the cursor/operation. 262153323Srodrigc */ 263153323SrodrigcSTATIC void 264153323Srodrigcxfs_bmbt_trace_cursor( 265153323Srodrigc char *func, 266153323Srodrigc xfs_btree_cur_t *cur, 267153323Srodrigc char *s, 268153323Srodrigc int line) 269153323Srodrigc{ 270153323Srodrigc xfs_bmbt_rec_t r; 271153323Srodrigc 272153323Srodrigc xfs_bmbt_set_all(&r, &cur->bc_rec.b); 273153323Srodrigc xfs_bmbt_trace_enter(func, cur, s, XFS_BMBT_KTRACE_CUR, line, 274153323Srodrigc (cur->bc_nlevels << 24) | (cur->bc_private.b.flags << 16) | 275153323Srodrigc cur->bc_private.b.allocated, 276153323Srodrigc 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), 277153323Srodrigc (unsigned long)cur->bc_bufs[0], (unsigned long)cur->bc_bufs[1], 278153323Srodrigc (unsigned long)cur->bc_bufs[2], (unsigned long)cur->bc_bufs[3], 279153323Srodrigc (cur->bc_ptrs[0] << 16) | cur->bc_ptrs[1], 280153323Srodrigc (cur->bc_ptrs[2] << 16) | cur->bc_ptrs[3]); 281153323Srodrigc} 282153323Srodrigc 283153323Srodrigc#define XFS_BMBT_TRACE_ARGBI(c,b,i) \ 284153323Srodrigc xfs_bmbt_trace_argbi(fname, c, b, i, __LINE__) 285153323Srodrigc#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) \ 286153323Srodrigc xfs_bmbt_trace_argbii(fname, c, b, i, j, __LINE__) 287153323Srodrigc#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) \ 288153323Srodrigc xfs_bmbt_trace_argfffi(fname, c, o, b, i, j, __LINE__) 289153323Srodrigc#define XFS_BMBT_TRACE_ARGI(c,i) \ 290153323Srodrigc xfs_bmbt_trace_argi(fname, c, i, __LINE__) 291153323Srodrigc#define XFS_BMBT_TRACE_ARGIFK(c,i,f,k) \ 292153323Srodrigc xfs_bmbt_trace_argifk(fname, c, i, f, k, __LINE__) 293153323Srodrigc#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) \ 294153323Srodrigc xfs_bmbt_trace_argifr(fname, c, i, f, r, __LINE__) 295153323Srodrigc#define XFS_BMBT_TRACE_ARGIK(c,i,k) \ 296153323Srodrigc xfs_bmbt_trace_argik(fname, c, i, k, __LINE__) 297153323Srodrigc#define XFS_BMBT_TRACE_CURSOR(c,s) \ 298153323Srodrigc xfs_bmbt_trace_cursor(fname, c, s, __LINE__) 299153323Srodrigc#else 300153323Srodrigc#define XFS_BMBT_TRACE_ARGBI(c,b,i) 301153323Srodrigc#define XFS_BMBT_TRACE_ARGBII(c,b,i,j) 302153323Srodrigc#define XFS_BMBT_TRACE_ARGFFFI(c,o,b,i,j) 303153323Srodrigc#define XFS_BMBT_TRACE_ARGI(c,i) 304153323Srodrigc#define XFS_BMBT_TRACE_ARGIFK(c,i,f,k) 305153323Srodrigc#define XFS_BMBT_TRACE_ARGIFR(c,i,f,r) 306153323Srodrigc#define XFS_BMBT_TRACE_ARGIK(c,i,k) 307153323Srodrigc#define XFS_BMBT_TRACE_CURSOR(c,s) 308153323Srodrigc#endif /* XFS_BMBT_TRACE */ 309153323Srodrigc 310153323Srodrigc 311153323Srodrigc/* 312153323Srodrigc * Internal functions. 313153323Srodrigc */ 314153323Srodrigc 315153323Srodrigc/* 316153323Srodrigc * Delete record pointed to by cur/level. 317153323Srodrigc */ 318153323SrodrigcSTATIC int /* error */ 319153323Srodrigcxfs_bmbt_delrec( 320153323Srodrigc xfs_btree_cur_t *cur, 321153323Srodrigc int level, 322153323Srodrigc int *stat) /* success/failure */ 323153323Srodrigc{ 324153323Srodrigc xfs_bmbt_block_t *block; /* bmap btree block */ 325153323Srodrigc xfs_fsblock_t bno; /* fs-relative block number */ 326153323Srodrigc xfs_buf_t *bp; /* buffer for block */ 327153323Srodrigc int error; /* error return value */ 328153323Srodrigc#ifdef XFS_BMBT_TRACE 329153323Srodrigc static char fname[] = "xfs_bmbt_delrec"; 330153323Srodrigc#endif 331153323Srodrigc int i; /* loop counter */ 332153323Srodrigc int j; /* temp state */ 333153323Srodrigc xfs_bmbt_key_t key; /* bmap btree key */ 334153323Srodrigc xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ 335153323Srodrigc xfs_fsblock_t lbno; /* left sibling block number */ 336153323Srodrigc xfs_buf_t *lbp; /* left buffer pointer */ 337153323Srodrigc xfs_bmbt_block_t *left; /* left btree block */ 338153323Srodrigc xfs_bmbt_key_t *lkp; /* left btree key */ 339153323Srodrigc xfs_bmbt_ptr_t *lpp; /* left address pointer */ 340153323Srodrigc int lrecs=0; /* left record count */ 341153323Srodrigc xfs_bmbt_rec_t *lrp; /* left record pointer */ 342153323Srodrigc xfs_mount_t *mp; /* file system mount point */ 343153323Srodrigc xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ 344153323Srodrigc int ptr; /* key/record index */ 345153323Srodrigc xfs_fsblock_t rbno; /* right sibling block number */ 346153323Srodrigc xfs_buf_t *rbp; /* right buffer pointer */ 347153323Srodrigc xfs_bmbt_block_t *right; /* right btree block */ 348153323Srodrigc xfs_bmbt_key_t *rkp; /* right btree key */ 349153323Srodrigc xfs_bmbt_rec_t *rp; /* pointer to bmap btree rec */ 350153323Srodrigc xfs_bmbt_ptr_t *rpp; /* right address pointer */ 351153323Srodrigc xfs_bmbt_block_t *rrblock; /* right-right btree block */ 352153323Srodrigc xfs_buf_t *rrbp; /* right-right buffer pointer */ 353153323Srodrigc int rrecs=0; /* right record count */ 354153323Srodrigc xfs_bmbt_rec_t *rrp; /* right record pointer */ 355153323Srodrigc xfs_btree_cur_t *tcur; /* temporary btree cursor */ 356153323Srodrigc int numrecs; /* temporary numrec count */ 357153323Srodrigc int numlrecs, numrrecs; 358153323Srodrigc 359153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 360153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, level); 361153323Srodrigc ptr = cur->bc_ptrs[level]; 362153323Srodrigc tcur = (xfs_btree_cur_t *)0; 363153323Srodrigc if (ptr == 0) { 364153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 365153323Srodrigc *stat = 0; 366153323Srodrigc return 0; 367153323Srodrigc } 368153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 369159451Srodrigc numrecs = be16_to_cpu(block->bb_numrecs); 370153323Srodrigc#ifdef DEBUG 371153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 372153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 373153323Srodrigc goto error0; 374153323Srodrigc } 375153323Srodrigc#endif 376153323Srodrigc if (ptr > numrecs) { 377153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 378153323Srodrigc *stat = 0; 379153323Srodrigc return 0; 380153323Srodrigc } 381153323Srodrigc XFS_STATS_INC(xs_bmbt_delrec); 382153323Srodrigc if (level > 0) { 383153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 384153323Srodrigc pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 385153323Srodrigc#ifdef DEBUG 386153323Srodrigc for (i = ptr; i < numrecs; i++) { 387153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) { 388153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 389153323Srodrigc goto error0; 390153323Srodrigc } 391153323Srodrigc } 392153323Srodrigc#endif 393153323Srodrigc if (ptr < numrecs) { 394153323Srodrigc memmove(&kp[ptr - 1], &kp[ptr], 395153323Srodrigc (numrecs - ptr) * sizeof(*kp)); 396153323Srodrigc memmove(&pp[ptr - 1], &pp[ptr], /* INT_: direct copy */ 397153323Srodrigc (numrecs - ptr) * sizeof(*pp)); 398153323Srodrigc xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs - 1); 399153323Srodrigc xfs_bmbt_log_keys(cur, bp, ptr, numrecs - 1); 400153323Srodrigc } 401153323Srodrigc } else { 402153323Srodrigc rp = XFS_BMAP_REC_IADDR(block, 1, cur); 403153323Srodrigc if (ptr < numrecs) { 404153323Srodrigc memmove(&rp[ptr - 1], &rp[ptr], 405153323Srodrigc (numrecs - ptr) * sizeof(*rp)); 406153323Srodrigc xfs_bmbt_log_recs(cur, bp, ptr, numrecs - 1); 407153323Srodrigc } 408153323Srodrigc if (ptr == 1) { 409153323Srodrigc INT_SET(key.br_startoff, ARCH_CONVERT, xfs_bmbt_disk_get_startoff(rp)); 410153323Srodrigc kp = &key; 411153323Srodrigc } 412153323Srodrigc } 413153323Srodrigc numrecs--; 414159451Srodrigc block->bb_numrecs = cpu_to_be16(numrecs); 415153323Srodrigc xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); 416153323Srodrigc /* 417153323Srodrigc * We're at the root level. 418153323Srodrigc * First, shrink the root block in-memory. 419153323Srodrigc * Try to get rid of the next level down. 420153323Srodrigc * If we can't then there's nothing left to do. 421153323Srodrigc */ 422153323Srodrigc if (level == cur->bc_nlevels - 1) { 423153323Srodrigc xfs_iroot_realloc(cur->bc_private.b.ip, -1, 424153323Srodrigc cur->bc_private.b.whichfork); 425153323Srodrigc if ((error = xfs_bmbt_killroot(cur))) { 426153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 427153323Srodrigc goto error0; 428153323Srodrigc } 429153323Srodrigc if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { 430153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 431153323Srodrigc goto error0; 432153323Srodrigc } 433153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 434153323Srodrigc *stat = 1; 435153323Srodrigc return 0; 436153323Srodrigc } 437153323Srodrigc if (ptr == 1 && (error = xfs_bmbt_updkey(cur, kp, level + 1))) { 438153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 439153323Srodrigc goto error0; 440153323Srodrigc } 441153323Srodrigc if (numrecs >= XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 442153323Srodrigc if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &j))) { 443153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 444153323Srodrigc goto error0; 445153323Srodrigc } 446153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 447153323Srodrigc *stat = 1; 448153323Srodrigc return 0; 449153323Srodrigc } 450159451Srodrigc rbno = be64_to_cpu(block->bb_rightsib); 451159451Srodrigc lbno = be64_to_cpu(block->bb_leftsib); 452153323Srodrigc /* 453153323Srodrigc * One child of root, need to get a chance to copy its contents 454153323Srodrigc * into the root and delete it. Can't go up to next level, 455153323Srodrigc * there's nothing to delete there. 456153323Srodrigc */ 457153323Srodrigc if (lbno == NULLFSBLOCK && rbno == NULLFSBLOCK && 458153323Srodrigc level == cur->bc_nlevels - 2) { 459153323Srodrigc if ((error = xfs_bmbt_killroot(cur))) { 460153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 461153323Srodrigc goto error0; 462153323Srodrigc } 463153323Srodrigc if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { 464153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 465153323Srodrigc goto error0; 466153323Srodrigc } 467153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 468153323Srodrigc *stat = 1; 469153323Srodrigc return 0; 470153323Srodrigc } 471153323Srodrigc ASSERT(rbno != NULLFSBLOCK || lbno != NULLFSBLOCK); 472153323Srodrigc if ((error = xfs_btree_dup_cursor(cur, &tcur))) { 473153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 474153323Srodrigc goto error0; 475153323Srodrigc } 476153323Srodrigc bno = NULLFSBLOCK; 477153323Srodrigc if (rbno != NULLFSBLOCK) { 478153323Srodrigc i = xfs_btree_lastrec(tcur, level); 479153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 480153323Srodrigc if ((error = xfs_bmbt_increment(tcur, level, &i))) { 481153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 482153323Srodrigc goto error0; 483153323Srodrigc } 484153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 485153323Srodrigc i = xfs_btree_lastrec(tcur, level); 486153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 487153323Srodrigc rbp = tcur->bc_bufs[level]; 488153323Srodrigc right = XFS_BUF_TO_BMBT_BLOCK(rbp); 489153323Srodrigc#ifdef DEBUG 490153323Srodrigc if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 491153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 492153323Srodrigc goto error0; 493153323Srodrigc } 494153323Srodrigc#endif 495159451Srodrigc bno = be64_to_cpu(right->bb_leftsib); 496159451Srodrigc if (be16_to_cpu(right->bb_numrecs) - 1 >= 497153323Srodrigc XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 498153323Srodrigc if ((error = xfs_bmbt_lshift(tcur, level, &i))) { 499153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 500153323Srodrigc goto error0; 501153323Srodrigc } 502153323Srodrigc if (i) { 503159451Srodrigc ASSERT(be16_to_cpu(block->bb_numrecs) >= 504153323Srodrigc XFS_BMAP_BLOCK_IMINRECS(level, tcur)); 505153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 506153323Srodrigc tcur = NULL; 507153323Srodrigc if (level > 0) { 508153323Srodrigc if ((error = xfs_bmbt_decrement(cur, 509153323Srodrigc level, &i))) { 510153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, 511153323Srodrigc ERROR); 512153323Srodrigc goto error0; 513153323Srodrigc } 514153323Srodrigc } 515153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 516153323Srodrigc *stat = 1; 517153323Srodrigc return 0; 518153323Srodrigc } 519153323Srodrigc } 520159451Srodrigc rrecs = be16_to_cpu(right->bb_numrecs); 521153323Srodrigc if (lbno != NULLFSBLOCK) { 522153323Srodrigc i = xfs_btree_firstrec(tcur, level); 523153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 524153323Srodrigc if ((error = xfs_bmbt_decrement(tcur, level, &i))) { 525153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 526153323Srodrigc goto error0; 527153323Srodrigc } 528153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 529153323Srodrigc } 530153323Srodrigc } 531153323Srodrigc if (lbno != NULLFSBLOCK) { 532153323Srodrigc i = xfs_btree_firstrec(tcur, level); 533153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 534153323Srodrigc /* 535153323Srodrigc * decrement to last in block 536153323Srodrigc */ 537153323Srodrigc if ((error = xfs_bmbt_decrement(tcur, level, &i))) { 538153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 539153323Srodrigc goto error0; 540153323Srodrigc } 541153323Srodrigc i = xfs_btree_firstrec(tcur, level); 542153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 543153323Srodrigc lbp = tcur->bc_bufs[level]; 544153323Srodrigc left = XFS_BUF_TO_BMBT_BLOCK(lbp); 545153323Srodrigc#ifdef DEBUG 546153323Srodrigc if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 547153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 548153323Srodrigc goto error0; 549153323Srodrigc } 550153323Srodrigc#endif 551159451Srodrigc bno = be64_to_cpu(left->bb_rightsib); 552159451Srodrigc if (be16_to_cpu(left->bb_numrecs) - 1 >= 553153323Srodrigc XFS_BMAP_BLOCK_IMINRECS(level, cur)) { 554153323Srodrigc if ((error = xfs_bmbt_rshift(tcur, level, &i))) { 555153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 556153323Srodrigc goto error0; 557153323Srodrigc } 558153323Srodrigc if (i) { 559159451Srodrigc ASSERT(be16_to_cpu(block->bb_numrecs) >= 560153323Srodrigc XFS_BMAP_BLOCK_IMINRECS(level, tcur)); 561153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 562153323Srodrigc tcur = NULL; 563153323Srodrigc if (level == 0) 564153323Srodrigc cur->bc_ptrs[0]++; 565153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 566153323Srodrigc *stat = 1; 567153323Srodrigc return 0; 568153323Srodrigc } 569153323Srodrigc } 570159451Srodrigc lrecs = be16_to_cpu(left->bb_numrecs); 571153323Srodrigc } 572153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 573153323Srodrigc tcur = NULL; 574153323Srodrigc mp = cur->bc_mp; 575153323Srodrigc ASSERT(bno != NULLFSBLOCK); 576153323Srodrigc if (lbno != NULLFSBLOCK && 577159451Srodrigc lrecs + be16_to_cpu(block->bb_numrecs) <= XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 578153323Srodrigc rbno = bno; 579153323Srodrigc right = block; 580153323Srodrigc rbp = bp; 581153323Srodrigc if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, lbno, 0, &lbp, 582153323Srodrigc XFS_BMAP_BTREE_REF))) { 583153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 584153323Srodrigc goto error0; 585153323Srodrigc } 586153323Srodrigc left = XFS_BUF_TO_BMBT_BLOCK(lbp); 587153323Srodrigc if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 588153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 589153323Srodrigc goto error0; 590153323Srodrigc } 591153323Srodrigc } else if (rbno != NULLFSBLOCK && 592159451Srodrigc rrecs + be16_to_cpu(block->bb_numrecs) <= 593153323Srodrigc XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 594153323Srodrigc lbno = bno; 595153323Srodrigc left = block; 596153323Srodrigc lbp = bp; 597153323Srodrigc if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, rbno, 0, &rbp, 598153323Srodrigc XFS_BMAP_BTREE_REF))) { 599153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 600153323Srodrigc goto error0; 601153323Srodrigc } 602153323Srodrigc right = XFS_BUF_TO_BMBT_BLOCK(rbp); 603153323Srodrigc if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 604153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 605153323Srodrigc goto error0; 606153323Srodrigc } 607159451Srodrigc lrecs = be16_to_cpu(left->bb_numrecs); 608153323Srodrigc } else { 609153323Srodrigc if (level > 0 && (error = xfs_bmbt_decrement(cur, level, &i))) { 610153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 611153323Srodrigc goto error0; 612153323Srodrigc } 613153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 614153323Srodrigc *stat = 1; 615153323Srodrigc return 0; 616153323Srodrigc } 617159451Srodrigc numlrecs = be16_to_cpu(left->bb_numrecs); 618159451Srodrigc numrrecs = be16_to_cpu(right->bb_numrecs); 619153323Srodrigc if (level > 0) { 620153323Srodrigc lkp = XFS_BMAP_KEY_IADDR(left, numlrecs + 1, cur); 621153323Srodrigc lpp = XFS_BMAP_PTR_IADDR(left, numlrecs + 1, cur); 622153323Srodrigc rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 623153323Srodrigc rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 624153323Srodrigc#ifdef DEBUG 625153323Srodrigc for (i = 0; i < numrrecs; i++) { 626153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) { 627153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 628153323Srodrigc goto error0; 629153323Srodrigc } 630153323Srodrigc } 631153323Srodrigc#endif 632153323Srodrigc memcpy(lkp, rkp, numrrecs * sizeof(*lkp)); 633153323Srodrigc memcpy(lpp, rpp, numrrecs * sizeof(*lpp)); 634153323Srodrigc xfs_bmbt_log_keys(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 635153323Srodrigc xfs_bmbt_log_ptrs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 636153323Srodrigc } else { 637153323Srodrigc lrp = XFS_BMAP_REC_IADDR(left, numlrecs + 1, cur); 638153323Srodrigc rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 639153323Srodrigc memcpy(lrp, rrp, numrrecs * sizeof(*lrp)); 640153323Srodrigc xfs_bmbt_log_recs(cur, lbp, numlrecs + 1, numlrecs + numrrecs); 641153323Srodrigc } 642159451Srodrigc be16_add(&left->bb_numrecs, numrrecs); 643159451Srodrigc left->bb_rightsib = right->bb_rightsib; 644153323Srodrigc xfs_bmbt_log_block(cur, lbp, XFS_BB_RIGHTSIB | XFS_BB_NUMRECS); 645159451Srodrigc if (be64_to_cpu(left->bb_rightsib) != NULLDFSBNO) { 646153323Srodrigc if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, 647159451Srodrigc be64_to_cpu(left->bb_rightsib), 648153323Srodrigc 0, &rrbp, XFS_BMAP_BTREE_REF))) { 649153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 650153323Srodrigc goto error0; 651153323Srodrigc } 652153323Srodrigc rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); 653153323Srodrigc if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { 654153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 655153323Srodrigc goto error0; 656153323Srodrigc } 657159451Srodrigc rrblock->bb_leftsib = cpu_to_be64(lbno); 658153323Srodrigc xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); 659153323Srodrigc } 660153323Srodrigc xfs_bmap_add_free(XFS_DADDR_TO_FSB(mp, XFS_BUF_ADDR(rbp)), 1, 661153323Srodrigc cur->bc_private.b.flist, mp); 662153323Srodrigc cur->bc_private.b.ip->i_d.di_nblocks--; 663153323Srodrigc xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, XFS_ILOG_CORE); 664153323Srodrigc XFS_TRANS_MOD_DQUOT_BYINO(mp, cur->bc_tp, cur->bc_private.b.ip, 665153323Srodrigc XFS_TRANS_DQ_BCOUNT, -1L); 666153323Srodrigc xfs_trans_binval(cur->bc_tp, rbp); 667153323Srodrigc if (bp != lbp) { 668153323Srodrigc cur->bc_bufs[level] = lbp; 669153323Srodrigc cur->bc_ptrs[level] += lrecs; 670153323Srodrigc cur->bc_ra[level] = 0; 671153323Srodrigc } else if ((error = xfs_bmbt_increment(cur, level + 1, &i))) { 672153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 673153323Srodrigc goto error0; 674153323Srodrigc } 675153323Srodrigc if (level > 0) 676153323Srodrigc cur->bc_ptrs[level]--; 677153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 678153323Srodrigc *stat = 2; 679153323Srodrigc return 0; 680153323Srodrigc 681153323Srodrigcerror0: 682153323Srodrigc if (tcur) 683153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); 684153323Srodrigc return error; 685153323Srodrigc} 686153323Srodrigc 687159451Srodrigc#ifdef DEBUG 688153323Srodrigc/* 689153323Srodrigc * Get the data from the pointed-to record. 690153323Srodrigc */ 691153323Srodrigcint 692153323Srodrigcxfs_bmbt_get_rec( 693153323Srodrigc xfs_btree_cur_t *cur, 694153323Srodrigc xfs_fileoff_t *off, 695153323Srodrigc xfs_fsblock_t *bno, 696153323Srodrigc xfs_filblks_t *len, 697153323Srodrigc xfs_exntst_t *state, 698153323Srodrigc int *stat) 699153323Srodrigc{ 700153323Srodrigc xfs_bmbt_block_t *block; 701153323Srodrigc xfs_buf_t *bp; 702153323Srodrigc#ifdef DEBUG 703153323Srodrigc int error; 704153323Srodrigc#endif 705153323Srodrigc int ptr; 706153323Srodrigc xfs_bmbt_rec_t *rp; 707153323Srodrigc 708153323Srodrigc block = xfs_bmbt_get_block(cur, 0, &bp); 709153323Srodrigc ptr = cur->bc_ptrs[0]; 710153323Srodrigc#ifdef DEBUG 711153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) 712153323Srodrigc return error; 713153323Srodrigc#endif 714159451Srodrigc if (ptr > be16_to_cpu(block->bb_numrecs) || ptr <= 0) { 715153323Srodrigc *stat = 0; 716153323Srodrigc return 0; 717153323Srodrigc } 718153323Srodrigc rp = XFS_BMAP_REC_IADDR(block, ptr, cur); 719153323Srodrigc *off = xfs_bmbt_disk_get_startoff(rp); 720153323Srodrigc *bno = xfs_bmbt_disk_get_startblock(rp); 721153323Srodrigc *len = xfs_bmbt_disk_get_blockcount(rp); 722153323Srodrigc *state = xfs_bmbt_disk_get_state(rp); 723153323Srodrigc *stat = 1; 724153323Srodrigc return 0; 725153323Srodrigc} 726153323Srodrigc#endif 727153323Srodrigc 728153323Srodrigc/* 729153323Srodrigc * Insert one record/level. Return information to the caller 730153323Srodrigc * allowing the next level up to proceed if necessary. 731153323Srodrigc */ 732153323SrodrigcSTATIC int /* error */ 733153323Srodrigcxfs_bmbt_insrec( 734153323Srodrigc xfs_btree_cur_t *cur, 735153323Srodrigc int level, 736153323Srodrigc xfs_fsblock_t *bnop, 737153323Srodrigc xfs_bmbt_rec_t *recp, 738153323Srodrigc xfs_btree_cur_t **curp, 739153323Srodrigc int *stat) /* no-go/done/continue */ 740153323Srodrigc{ 741153323Srodrigc xfs_bmbt_block_t *block; /* bmap btree block */ 742153323Srodrigc xfs_buf_t *bp; /* buffer for block */ 743153323Srodrigc int error; /* error return value */ 744153323Srodrigc#ifdef XFS_BMBT_TRACE 745153323Srodrigc static char fname[] = "xfs_bmbt_insrec"; 746153323Srodrigc#endif 747153323Srodrigc int i; /* loop index */ 748153323Srodrigc xfs_bmbt_key_t key; /* bmap btree key */ 749153323Srodrigc xfs_bmbt_key_t *kp=NULL; /* pointer to bmap btree key */ 750153323Srodrigc int logflags; /* inode logging flags */ 751153323Srodrigc xfs_fsblock_t nbno; /* new block number */ 752153323Srodrigc struct xfs_btree_cur *ncur; /* new btree cursor */ 753153323Srodrigc xfs_bmbt_key_t nkey; /* new btree key value */ 754153323Srodrigc xfs_bmbt_rec_t nrec; /* new record count */ 755153323Srodrigc int optr; /* old key/record index */ 756153323Srodrigc xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ 757153323Srodrigc int ptr; /* key/record index */ 758153323Srodrigc xfs_bmbt_rec_t *rp=NULL; /* pointer to bmap btree rec */ 759153323Srodrigc int numrecs; 760153323Srodrigc 761153323Srodrigc ASSERT(level < cur->bc_nlevels); 762153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 763153323Srodrigc XFS_BMBT_TRACE_ARGIFR(cur, level, *bnop, recp); 764153323Srodrigc ncur = (xfs_btree_cur_t *)0; 765153323Srodrigc INT_SET(key.br_startoff, ARCH_CONVERT, 766153323Srodrigc xfs_bmbt_disk_get_startoff(recp)); 767153323Srodrigc optr = ptr = cur->bc_ptrs[level]; 768153323Srodrigc if (ptr == 0) { 769153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 770153323Srodrigc *stat = 0; 771153323Srodrigc return 0; 772153323Srodrigc } 773153323Srodrigc XFS_STATS_INC(xs_bmbt_insrec); 774153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 775159451Srodrigc numrecs = be16_to_cpu(block->bb_numrecs); 776170124Skan nkey.br_startoff = 0; 777153323Srodrigc#ifdef DEBUG 778153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 779153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 780153323Srodrigc return error; 781153323Srodrigc } 782153323Srodrigc if (ptr <= numrecs) { 783153323Srodrigc if (level == 0) { 784153323Srodrigc rp = XFS_BMAP_REC_IADDR(block, ptr, cur); 785153323Srodrigc xfs_btree_check_rec(XFS_BTNUM_BMAP, recp, rp); 786153323Srodrigc } else { 787153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); 788153323Srodrigc xfs_btree_check_key(XFS_BTNUM_BMAP, &key, kp); 789153323Srodrigc } 790153323Srodrigc } 791153323Srodrigc#endif 792153323Srodrigc nbno = NULLFSBLOCK; 793153323Srodrigc if (numrecs == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 794153323Srodrigc if (numrecs < XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { 795153323Srodrigc /* 796153323Srodrigc * A root block, that can be made bigger. 797153323Srodrigc */ 798153323Srodrigc xfs_iroot_realloc(cur->bc_private.b.ip, 1, 799153323Srodrigc cur->bc_private.b.whichfork); 800153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 801153323Srodrigc } else if (level == cur->bc_nlevels - 1) { 802153323Srodrigc if ((error = xfs_bmbt_newroot(cur, &logflags, stat)) || 803153323Srodrigc *stat == 0) { 804153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 805153323Srodrigc return error; 806153323Srodrigc } 807153323Srodrigc xfs_trans_log_inode(cur->bc_tp, cur->bc_private.b.ip, 808153323Srodrigc logflags); 809153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 810153323Srodrigc } else { 811153323Srodrigc if ((error = xfs_bmbt_rshift(cur, level, &i))) { 812153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 813153323Srodrigc return error; 814153323Srodrigc } 815153323Srodrigc if (i) { 816153323Srodrigc /* nothing */ 817153323Srodrigc } else { 818153323Srodrigc if ((error = xfs_bmbt_lshift(cur, level, &i))) { 819153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 820153323Srodrigc return error; 821153323Srodrigc } 822153323Srodrigc if (i) { 823153323Srodrigc optr = ptr = cur->bc_ptrs[level]; 824153323Srodrigc } else { 825153323Srodrigc if ((error = xfs_bmbt_split(cur, level, 826153323Srodrigc &nbno, &nkey, &ncur, 827153323Srodrigc &i))) { 828153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, 829153323Srodrigc ERROR); 830153323Srodrigc return error; 831153323Srodrigc } 832153323Srodrigc if (i) { 833153323Srodrigc block = xfs_bmbt_get_block( 834153323Srodrigc cur, level, &bp); 835153323Srodrigc#ifdef DEBUG 836153323Srodrigc if ((error = 837153323Srodrigc xfs_btree_check_lblock(cur, 838153323Srodrigc block, level, bp))) { 839153323Srodrigc XFS_BMBT_TRACE_CURSOR( 840153323Srodrigc cur, ERROR); 841153323Srodrigc return error; 842153323Srodrigc } 843153323Srodrigc#endif 844153323Srodrigc ptr = cur->bc_ptrs[level]; 845153323Srodrigc xfs_bmbt_disk_set_allf(&nrec, 846153323Srodrigc nkey.br_startoff, 0, 0, 847153323Srodrigc XFS_EXT_NORM); 848153323Srodrigc } else { 849153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, 850153323Srodrigc EXIT); 851153323Srodrigc *stat = 0; 852153323Srodrigc return 0; 853153323Srodrigc } 854153323Srodrigc } 855153323Srodrigc } 856153323Srodrigc } 857153323Srodrigc } 858159451Srodrigc numrecs = be16_to_cpu(block->bb_numrecs); 859153323Srodrigc if (level > 0) { 860153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 861153323Srodrigc pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 862153323Srodrigc#ifdef DEBUG 863153323Srodrigc for (i = numrecs; i >= ptr; i--) { 864153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i - 1], ARCH_CONVERT), 865153323Srodrigc level))) { 866153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 867153323Srodrigc return error; 868153323Srodrigc } 869153323Srodrigc } 870153323Srodrigc#endif 871153323Srodrigc memmove(&kp[ptr], &kp[ptr - 1], 872153323Srodrigc (numrecs - ptr + 1) * sizeof(*kp)); 873153323Srodrigc memmove(&pp[ptr], &pp[ptr - 1], /* INT_: direct copy */ 874153323Srodrigc (numrecs - ptr + 1) * sizeof(*pp)); 875153323Srodrigc#ifdef DEBUG 876153323Srodrigc if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)*bnop, 877153323Srodrigc level))) { 878153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 879153323Srodrigc return error; 880153323Srodrigc } 881153323Srodrigc#endif 882153323Srodrigc kp[ptr - 1] = key; 883153323Srodrigc INT_SET(pp[ptr - 1], ARCH_CONVERT, *bnop); 884153323Srodrigc numrecs++; 885159451Srodrigc block->bb_numrecs = cpu_to_be16(numrecs); 886153323Srodrigc xfs_bmbt_log_keys(cur, bp, ptr, numrecs); 887153323Srodrigc xfs_bmbt_log_ptrs(cur, bp, ptr, numrecs); 888153323Srodrigc } else { 889153323Srodrigc rp = XFS_BMAP_REC_IADDR(block, 1, cur); 890153323Srodrigc memmove(&rp[ptr], &rp[ptr - 1], 891153323Srodrigc (numrecs - ptr + 1) * sizeof(*rp)); 892153323Srodrigc rp[ptr - 1] = *recp; 893153323Srodrigc numrecs++; 894159451Srodrigc block->bb_numrecs = cpu_to_be16(numrecs); 895153323Srodrigc xfs_bmbt_log_recs(cur, bp, ptr, numrecs); 896153323Srodrigc } 897153323Srodrigc xfs_bmbt_log_block(cur, bp, XFS_BB_NUMRECS); 898153323Srodrigc#ifdef DEBUG 899153323Srodrigc if (ptr < numrecs) { 900153323Srodrigc if (level == 0) 901153323Srodrigc xfs_btree_check_rec(XFS_BTNUM_BMAP, rp + ptr - 1, 902153323Srodrigc rp + ptr); 903153323Srodrigc else 904153323Srodrigc xfs_btree_check_key(XFS_BTNUM_BMAP, kp + ptr - 1, 905153323Srodrigc kp + ptr); 906153323Srodrigc } 907153323Srodrigc#endif 908153323Srodrigc if (optr == 1 && (error = xfs_bmbt_updkey(cur, &key, level + 1))) { 909153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 910153323Srodrigc return error; 911153323Srodrigc } 912153323Srodrigc *bnop = nbno; 913153323Srodrigc if (nbno != NULLFSBLOCK) { 914153323Srodrigc *recp = nrec; 915153323Srodrigc *curp = ncur; 916153323Srodrigc } 917153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 918153323Srodrigc *stat = 1; 919153323Srodrigc return 0; 920153323Srodrigc} 921153323Srodrigc 922153323SrodrigcSTATIC int 923153323Srodrigcxfs_bmbt_killroot( 924153323Srodrigc xfs_btree_cur_t *cur) 925153323Srodrigc{ 926153323Srodrigc xfs_bmbt_block_t *block; 927153323Srodrigc xfs_bmbt_block_t *cblock; 928153323Srodrigc xfs_buf_t *cbp; 929153323Srodrigc xfs_bmbt_key_t *ckp; 930153323Srodrigc xfs_bmbt_ptr_t *cpp; 931153323Srodrigc#ifdef DEBUG 932153323Srodrigc int error; 933153323Srodrigc#endif 934153323Srodrigc#ifdef XFS_BMBT_TRACE 935153323Srodrigc static char fname[] = "xfs_bmbt_killroot"; 936153323Srodrigc#endif 937153323Srodrigc int i; 938153323Srodrigc xfs_bmbt_key_t *kp; 939153323Srodrigc xfs_inode_t *ip; 940153323Srodrigc xfs_ifork_t *ifp; 941153323Srodrigc int level; 942153323Srodrigc xfs_bmbt_ptr_t *pp; 943153323Srodrigc 944153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 945153323Srodrigc level = cur->bc_nlevels - 1; 946153323Srodrigc ASSERT(level >= 1); 947153323Srodrigc /* 948153323Srodrigc * Don't deal with the root block needs to be a leaf case. 949153323Srodrigc * We're just going to turn the thing back into extents anyway. 950153323Srodrigc */ 951153323Srodrigc if (level == 1) { 952153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 953153323Srodrigc return 0; 954153323Srodrigc } 955153323Srodrigc block = xfs_bmbt_get_block(cur, level, &cbp); 956153323Srodrigc /* 957153323Srodrigc * Give up if the root has multiple children. 958153323Srodrigc */ 959159451Srodrigc if (be16_to_cpu(block->bb_numrecs) != 1) { 960153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 961153323Srodrigc return 0; 962153323Srodrigc } 963153323Srodrigc /* 964153323Srodrigc * Only do this if the next level will fit. 965153323Srodrigc * Then the data must be copied up to the inode, 966153323Srodrigc * instead of freeing the root you free the next level. 967153323Srodrigc */ 968153323Srodrigc cbp = cur->bc_bufs[level - 1]; 969153323Srodrigc cblock = XFS_BUF_TO_BMBT_BLOCK(cbp); 970159451Srodrigc if (be16_to_cpu(cblock->bb_numrecs) > XFS_BMAP_BLOCK_DMAXRECS(level, cur)) { 971153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 972153323Srodrigc return 0; 973153323Srodrigc } 974159451Srodrigc ASSERT(be64_to_cpu(cblock->bb_leftsib) == NULLDFSBNO); 975159451Srodrigc ASSERT(be64_to_cpu(cblock->bb_rightsib) == NULLDFSBNO); 976153323Srodrigc ip = cur->bc_private.b.ip; 977153323Srodrigc ifp = XFS_IFORK_PTR(ip, cur->bc_private.b.whichfork); 978153323Srodrigc ASSERT(XFS_BMAP_BLOCK_IMAXRECS(level, cur) == 979153323Srodrigc XFS_BMAP_BROOT_MAXRECS(ifp->if_broot_bytes)); 980159451Srodrigc i = (int)(be16_to_cpu(cblock->bb_numrecs) - XFS_BMAP_BLOCK_IMAXRECS(level, cur)); 981153323Srodrigc if (i) { 982153323Srodrigc xfs_iroot_realloc(ip, i, cur->bc_private.b.whichfork); 983153323Srodrigc block = ifp->if_broot; 984153323Srodrigc } 985159451Srodrigc be16_add(&block->bb_numrecs, i); 986159451Srodrigc ASSERT(block->bb_numrecs == cblock->bb_numrecs); 987153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 988153323Srodrigc ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); 989159451Srodrigc memcpy(kp, ckp, be16_to_cpu(block->bb_numrecs) * sizeof(*kp)); 990153323Srodrigc pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 991153323Srodrigc cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); 992153323Srodrigc#ifdef DEBUG 993159451Srodrigc for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { 994153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(cpp[i], ARCH_CONVERT), level - 1))) { 995153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 996153323Srodrigc return error; 997153323Srodrigc } 998153323Srodrigc } 999153323Srodrigc#endif 1000159451Srodrigc memcpy(pp, cpp, be16_to_cpu(block->bb_numrecs) * sizeof(*pp)); 1001153323Srodrigc xfs_bmap_add_free(XFS_DADDR_TO_FSB(cur->bc_mp, XFS_BUF_ADDR(cbp)), 1, 1002153323Srodrigc cur->bc_private.b.flist, cur->bc_mp); 1003153323Srodrigc ip->i_d.di_nblocks--; 1004153323Srodrigc XFS_TRANS_MOD_DQUOT_BYINO(cur->bc_mp, cur->bc_tp, ip, 1005153323Srodrigc XFS_TRANS_DQ_BCOUNT, -1L); 1006153323Srodrigc xfs_trans_binval(cur->bc_tp, cbp); 1007153323Srodrigc cur->bc_bufs[level - 1] = NULL; 1008159451Srodrigc be16_add(&block->bb_level, -1); 1009153323Srodrigc xfs_trans_log_inode(cur->bc_tp, ip, 1010153323Srodrigc XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1011153323Srodrigc cur->bc_nlevels--; 1012153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1013153323Srodrigc return 0; 1014153323Srodrigc} 1015153323Srodrigc 1016153323Srodrigc/* 1017153323Srodrigc * Log key values from the btree block. 1018153323Srodrigc */ 1019153323SrodrigcSTATIC void 1020153323Srodrigcxfs_bmbt_log_keys( 1021153323Srodrigc xfs_btree_cur_t *cur, 1022153323Srodrigc xfs_buf_t *bp, 1023153323Srodrigc int kfirst, 1024153323Srodrigc int klast) 1025153323Srodrigc{ 1026153323Srodrigc#ifdef XFS_BMBT_TRACE 1027153323Srodrigc static char fname[] = "xfs_bmbt_log_keys"; 1028153323Srodrigc#endif 1029153323Srodrigc xfs_trans_t *tp; 1030153323Srodrigc 1031153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1032153323Srodrigc XFS_BMBT_TRACE_ARGBII(cur, bp, kfirst, klast); 1033153323Srodrigc tp = cur->bc_tp; 1034153323Srodrigc if (bp) { 1035153323Srodrigc xfs_bmbt_block_t *block; 1036153323Srodrigc int first; 1037153323Srodrigc xfs_bmbt_key_t *kp; 1038153323Srodrigc int last; 1039153323Srodrigc 1040153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 1041153323Srodrigc kp = XFS_BMAP_KEY_DADDR(block, 1, cur); 1042153323Srodrigc first = (int)((xfs_caddr_t)&kp[kfirst - 1] - (xfs_caddr_t)block); 1043153323Srodrigc last = (int)(((xfs_caddr_t)&kp[klast] - 1) - (xfs_caddr_t)block); 1044153323Srodrigc xfs_trans_log_buf(tp, bp, first, last); 1045153323Srodrigc } else { 1046153323Srodrigc xfs_inode_t *ip; 1047153323Srodrigc 1048153323Srodrigc ip = cur->bc_private.b.ip; 1049153323Srodrigc xfs_trans_log_inode(tp, ip, 1050153323Srodrigc XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1051153323Srodrigc } 1052153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1053153323Srodrigc} 1054153323Srodrigc 1055153323Srodrigc/* 1056153323Srodrigc * Log pointer values from the btree block. 1057153323Srodrigc */ 1058153323SrodrigcSTATIC void 1059153323Srodrigcxfs_bmbt_log_ptrs( 1060153323Srodrigc xfs_btree_cur_t *cur, 1061153323Srodrigc xfs_buf_t *bp, 1062153323Srodrigc int pfirst, 1063153323Srodrigc int plast) 1064153323Srodrigc{ 1065153323Srodrigc#ifdef XFS_BMBT_TRACE 1066153323Srodrigc static char fname[] = "xfs_bmbt_log_ptrs"; 1067153323Srodrigc#endif 1068153323Srodrigc xfs_trans_t *tp; 1069153323Srodrigc 1070153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1071153323Srodrigc XFS_BMBT_TRACE_ARGBII(cur, bp, pfirst, plast); 1072153323Srodrigc tp = cur->bc_tp; 1073153323Srodrigc if (bp) { 1074153323Srodrigc xfs_bmbt_block_t *block; 1075153323Srodrigc int first; 1076153323Srodrigc int last; 1077153323Srodrigc xfs_bmbt_ptr_t *pp; 1078153323Srodrigc 1079153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 1080153323Srodrigc pp = XFS_BMAP_PTR_DADDR(block, 1, cur); 1081153323Srodrigc first = (int)((xfs_caddr_t)&pp[pfirst - 1] - (xfs_caddr_t)block); 1082153323Srodrigc last = (int)(((xfs_caddr_t)&pp[plast] - 1) - (xfs_caddr_t)block); 1083153323Srodrigc xfs_trans_log_buf(tp, bp, first, last); 1084153323Srodrigc } else { 1085153323Srodrigc xfs_inode_t *ip; 1086153323Srodrigc 1087153323Srodrigc ip = cur->bc_private.b.ip; 1088153323Srodrigc xfs_trans_log_inode(tp, ip, 1089153323Srodrigc XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 1090153323Srodrigc } 1091153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1092153323Srodrigc} 1093153323Srodrigc 1094153323Srodrigc/* 1095153323Srodrigc * Lookup the record. The cursor is made to point to it, based on dir. 1096153323Srodrigc */ 1097153323SrodrigcSTATIC int /* error */ 1098153323Srodrigcxfs_bmbt_lookup( 1099153323Srodrigc xfs_btree_cur_t *cur, 1100153323Srodrigc xfs_lookup_t dir, 1101153323Srodrigc int *stat) /* success/failure */ 1102153323Srodrigc{ 1103153323Srodrigc xfs_bmbt_block_t *block=NULL; 1104153323Srodrigc xfs_buf_t *bp; 1105153323Srodrigc xfs_daddr_t d; 1106153323Srodrigc xfs_sfiloff_t diff; 1107153323Srodrigc int error; /* error return value */ 1108153323Srodrigc#ifdef XFS_BMBT_TRACE 1109153323Srodrigc static char fname[] = "xfs_bmbt_lookup"; 1110153323Srodrigc#endif 1111153323Srodrigc xfs_fsblock_t fsbno=0; 1112153323Srodrigc int high; 1113153323Srodrigc int i; 1114153323Srodrigc int keyno=0; 1115153323Srodrigc xfs_bmbt_key_t *kkbase=NULL; 1116153323Srodrigc xfs_bmbt_key_t *kkp; 1117153323Srodrigc xfs_bmbt_rec_t *krbase=NULL; 1118153323Srodrigc xfs_bmbt_rec_t *krp; 1119153323Srodrigc int level; 1120153323Srodrigc int low; 1121153323Srodrigc xfs_mount_t *mp; 1122153323Srodrigc xfs_bmbt_ptr_t *pp; 1123153323Srodrigc xfs_bmbt_irec_t *rp; 1124153323Srodrigc xfs_fileoff_t startoff; 1125153323Srodrigc xfs_trans_t *tp; 1126153323Srodrigc 1127153323Srodrigc XFS_STATS_INC(xs_bmbt_lookup); 1128153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1129153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, (int)dir); 1130153323Srodrigc tp = cur->bc_tp; 1131153323Srodrigc mp = cur->bc_mp; 1132153323Srodrigc rp = &cur->bc_rec.b; 1133153323Srodrigc for (level = cur->bc_nlevels - 1, diff = 1; level >= 0; level--) { 1134153323Srodrigc if (level < cur->bc_nlevels - 1) { 1135153323Srodrigc d = XFS_FSB_TO_DADDR(mp, fsbno); 1136153323Srodrigc bp = cur->bc_bufs[level]; 1137153323Srodrigc if (bp && XFS_BUF_ADDR(bp) != d) 1138153323Srodrigc bp = (xfs_buf_t *)0; 1139153323Srodrigc if (!bp) { 1140153323Srodrigc if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 1141153323Srodrigc 0, &bp, XFS_BMAP_BTREE_REF))) { 1142153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1143153323Srodrigc return error; 1144153323Srodrigc } 1145153323Srodrigc xfs_btree_setbuf(cur, level, bp); 1146153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 1147153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, 1148153323Srodrigc level, bp))) { 1149153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1150153323Srodrigc return error; 1151153323Srodrigc } 1152153323Srodrigc } else 1153153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 1154153323Srodrigc } else 1155153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 1156153323Srodrigc if (diff == 0) 1157153323Srodrigc keyno = 1; 1158153323Srodrigc else { 1159153323Srodrigc if (level > 0) 1160153323Srodrigc kkbase = XFS_BMAP_KEY_IADDR(block, 1, cur); 1161153323Srodrigc else 1162153323Srodrigc krbase = XFS_BMAP_REC_IADDR(block, 1, cur); 1163153323Srodrigc low = 1; 1164159451Srodrigc if (!(high = be16_to_cpu(block->bb_numrecs))) { 1165153323Srodrigc ASSERT(level == 0); 1166153323Srodrigc cur->bc_ptrs[0] = dir != XFS_LOOKUP_LE; 1167153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1168153323Srodrigc *stat = 0; 1169153323Srodrigc return 0; 1170153323Srodrigc } 1171153323Srodrigc while (low <= high) { 1172153323Srodrigc XFS_STATS_INC(xs_bmbt_compare); 1173153323Srodrigc keyno = (low + high) >> 1; 1174153323Srodrigc if (level > 0) { 1175153323Srodrigc kkp = kkbase + keyno - 1; 1176153323Srodrigc startoff = INT_GET(kkp->br_startoff, ARCH_CONVERT); 1177153323Srodrigc } else { 1178153323Srodrigc krp = krbase + keyno - 1; 1179153323Srodrigc startoff = xfs_bmbt_disk_get_startoff(krp); 1180153323Srodrigc } 1181153323Srodrigc diff = (xfs_sfiloff_t) 1182153323Srodrigc (startoff - rp->br_startoff); 1183153323Srodrigc if (diff < 0) 1184153323Srodrigc low = keyno + 1; 1185153323Srodrigc else if (diff > 0) 1186153323Srodrigc high = keyno - 1; 1187153323Srodrigc else 1188153323Srodrigc break; 1189153323Srodrigc } 1190153323Srodrigc } 1191153323Srodrigc if (level > 0) { 1192153323Srodrigc if (diff > 0 && --keyno < 1) 1193153323Srodrigc keyno = 1; 1194153323Srodrigc pp = XFS_BMAP_PTR_IADDR(block, keyno, cur); 1195153323Srodrigc#ifdef DEBUG 1196153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { 1197153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1198153323Srodrigc return error; 1199153323Srodrigc } 1200153323Srodrigc#endif 1201153323Srodrigc fsbno = INT_GET(*pp, ARCH_CONVERT); 1202153323Srodrigc cur->bc_ptrs[level] = keyno; 1203153323Srodrigc } 1204153323Srodrigc } 1205153323Srodrigc if (dir != XFS_LOOKUP_LE && diff < 0) { 1206153323Srodrigc keyno++; 1207153323Srodrigc /* 1208153323Srodrigc * If ge search and we went off the end of the block, but it's 1209153323Srodrigc * not the last block, we're in the wrong block. 1210153323Srodrigc */ 1211159451Srodrigc if (dir == XFS_LOOKUP_GE && keyno > be16_to_cpu(block->bb_numrecs) && 1212159451Srodrigc be64_to_cpu(block->bb_rightsib) != NULLDFSBNO) { 1213153323Srodrigc cur->bc_ptrs[0] = keyno; 1214153323Srodrigc if ((error = xfs_bmbt_increment(cur, 0, &i))) { 1215153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1216153323Srodrigc return error; 1217153323Srodrigc } 1218153323Srodrigc XFS_WANT_CORRUPTED_RETURN(i == 1); 1219153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1220153323Srodrigc *stat = 1; 1221153323Srodrigc return 0; 1222153323Srodrigc } 1223153323Srodrigc } 1224153323Srodrigc else if (dir == XFS_LOOKUP_LE && diff > 0) 1225153323Srodrigc keyno--; 1226153323Srodrigc cur->bc_ptrs[0] = keyno; 1227159451Srodrigc if (keyno == 0 || keyno > be16_to_cpu(block->bb_numrecs)) { 1228153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1229153323Srodrigc *stat = 0; 1230153323Srodrigc } else { 1231153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1232153323Srodrigc *stat = ((dir != XFS_LOOKUP_EQ) || (diff == 0)); 1233153323Srodrigc } 1234153323Srodrigc return 0; 1235153323Srodrigc} 1236153323Srodrigc 1237153323Srodrigc/* 1238153323Srodrigc * Move 1 record left from cur/level if possible. 1239153323Srodrigc * Update cur to reflect the new path. 1240153323Srodrigc */ 1241153323SrodrigcSTATIC int /* error */ 1242153323Srodrigcxfs_bmbt_lshift( 1243153323Srodrigc xfs_btree_cur_t *cur, 1244153323Srodrigc int level, 1245153323Srodrigc int *stat) /* success/failure */ 1246153323Srodrigc{ 1247153323Srodrigc int error; /* error return value */ 1248153323Srodrigc#ifdef XFS_BMBT_TRACE 1249153323Srodrigc static char fname[] = "xfs_bmbt_lshift"; 1250153323Srodrigc#endif 1251153323Srodrigc#ifdef DEBUG 1252153323Srodrigc int i; /* loop counter */ 1253153323Srodrigc#endif 1254153323Srodrigc xfs_bmbt_key_t key; /* bmap btree key */ 1255153323Srodrigc xfs_buf_t *lbp; /* left buffer pointer */ 1256153323Srodrigc xfs_bmbt_block_t *left; /* left btree block */ 1257153323Srodrigc xfs_bmbt_key_t *lkp=NULL; /* left btree key */ 1258153323Srodrigc xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1259153323Srodrigc int lrecs; /* left record count */ 1260153323Srodrigc xfs_bmbt_rec_t *lrp=NULL; /* left record pointer */ 1261153323Srodrigc xfs_mount_t *mp; /* file system mount point */ 1262153323Srodrigc xfs_buf_t *rbp; /* right buffer pointer */ 1263153323Srodrigc xfs_bmbt_block_t *right; /* right btree block */ 1264153323Srodrigc xfs_bmbt_key_t *rkp=NULL; /* right btree key */ 1265153323Srodrigc xfs_bmbt_ptr_t *rpp=NULL; /* right address pointer */ 1266153323Srodrigc xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ 1267153323Srodrigc int rrecs; /* right record count */ 1268153323Srodrigc 1269153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1270153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, level); 1271153323Srodrigc if (level == cur->bc_nlevels - 1) { 1272153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1273153323Srodrigc *stat = 0; 1274153323Srodrigc return 0; 1275153323Srodrigc } 1276153323Srodrigc rbp = cur->bc_bufs[level]; 1277153323Srodrigc right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1278153323Srodrigc#ifdef DEBUG 1279153323Srodrigc if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 1280153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1281153323Srodrigc return error; 1282153323Srodrigc } 1283153323Srodrigc#endif 1284159451Srodrigc if (be64_to_cpu(right->bb_leftsib) == NULLDFSBNO) { 1285153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1286153323Srodrigc *stat = 0; 1287153323Srodrigc return 0; 1288153323Srodrigc } 1289153323Srodrigc if (cur->bc_ptrs[level] <= 1) { 1290153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1291153323Srodrigc *stat = 0; 1292153323Srodrigc return 0; 1293153323Srodrigc } 1294153323Srodrigc mp = cur->bc_mp; 1295159451Srodrigc if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(right->bb_leftsib), 0, 1296153323Srodrigc &lbp, XFS_BMAP_BTREE_REF))) { 1297153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1298153323Srodrigc return error; 1299153323Srodrigc } 1300153323Srodrigc left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1301153323Srodrigc if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 1302153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1303153323Srodrigc return error; 1304153323Srodrigc } 1305159451Srodrigc if (be16_to_cpu(left->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 1306153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1307153323Srodrigc *stat = 0; 1308153323Srodrigc return 0; 1309153323Srodrigc } 1310159451Srodrigc lrecs = be16_to_cpu(left->bb_numrecs) + 1; 1311153323Srodrigc if (level > 0) { 1312153323Srodrigc lkp = XFS_BMAP_KEY_IADDR(left, lrecs, cur); 1313153323Srodrigc rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1314153323Srodrigc *lkp = *rkp; 1315153323Srodrigc xfs_bmbt_log_keys(cur, lbp, lrecs, lrecs); 1316153323Srodrigc lpp = XFS_BMAP_PTR_IADDR(left, lrecs, cur); 1317153323Srodrigc rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1318153323Srodrigc#ifdef DEBUG 1319153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(*rpp, ARCH_CONVERT), level))) { 1320153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1321153323Srodrigc return error; 1322153323Srodrigc } 1323153323Srodrigc#endif 1324153323Srodrigc *lpp = *rpp; /* INT_: direct copy */ 1325153323Srodrigc xfs_bmbt_log_ptrs(cur, lbp, lrecs, lrecs); 1326153323Srodrigc } else { 1327153323Srodrigc lrp = XFS_BMAP_REC_IADDR(left, lrecs, cur); 1328153323Srodrigc rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1329153323Srodrigc *lrp = *rrp; 1330153323Srodrigc xfs_bmbt_log_recs(cur, lbp, lrecs, lrecs); 1331153323Srodrigc } 1332159451Srodrigc left->bb_numrecs = cpu_to_be16(lrecs); 1333153323Srodrigc xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); 1334153323Srodrigc#ifdef DEBUG 1335153323Srodrigc if (level > 0) 1336153323Srodrigc xfs_btree_check_key(XFS_BTNUM_BMAP, lkp - 1, lkp); 1337153323Srodrigc else 1338153323Srodrigc xfs_btree_check_rec(XFS_BTNUM_BMAP, lrp - 1, lrp); 1339153323Srodrigc#endif 1340159451Srodrigc rrecs = be16_to_cpu(right->bb_numrecs) - 1; 1341159451Srodrigc right->bb_numrecs = cpu_to_be16(rrecs); 1342153323Srodrigc xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); 1343153323Srodrigc if (level > 0) { 1344153323Srodrigc#ifdef DEBUG 1345153323Srodrigc for (i = 0; i < rrecs; i++) { 1346153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i + 1], ARCH_CONVERT), 1347153323Srodrigc level))) { 1348153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1349153323Srodrigc return error; 1350153323Srodrigc } 1351153323Srodrigc } 1352153323Srodrigc#endif 1353153323Srodrigc memmove(rkp, rkp + 1, rrecs * sizeof(*rkp)); 1354153323Srodrigc memmove(rpp, rpp + 1, rrecs * sizeof(*rpp)); 1355153323Srodrigc xfs_bmbt_log_keys(cur, rbp, 1, rrecs); 1356153323Srodrigc xfs_bmbt_log_ptrs(cur, rbp, 1, rrecs); 1357153323Srodrigc } else { 1358153323Srodrigc memmove(rrp, rrp + 1, rrecs * sizeof(*rrp)); 1359153323Srodrigc xfs_bmbt_log_recs(cur, rbp, 1, rrecs); 1360153323Srodrigc INT_SET(key.br_startoff, ARCH_CONVERT, 1361153323Srodrigc xfs_bmbt_disk_get_startoff(rrp)); 1362153323Srodrigc rkp = &key; 1363153323Srodrigc } 1364153323Srodrigc if ((error = xfs_bmbt_updkey(cur, rkp, level + 1))) { 1365153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1366153323Srodrigc return error; 1367153323Srodrigc } 1368153323Srodrigc cur->bc_ptrs[level]--; 1369153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1370153323Srodrigc *stat = 1; 1371153323Srodrigc return 0; 1372153323Srodrigc} 1373153323Srodrigc 1374153323Srodrigc/* 1375153323Srodrigc * Move 1 record right from cur/level if possible. 1376153323Srodrigc * Update cur to reflect the new path. 1377153323Srodrigc */ 1378153323SrodrigcSTATIC int /* error */ 1379153323Srodrigcxfs_bmbt_rshift( 1380153323Srodrigc xfs_btree_cur_t *cur, 1381153323Srodrigc int level, 1382153323Srodrigc int *stat) /* success/failure */ 1383153323Srodrigc{ 1384153323Srodrigc int error; /* error return value */ 1385153323Srodrigc#ifdef XFS_BMBT_TRACE 1386153323Srodrigc static char fname[] = "xfs_bmbt_rshift"; 1387153323Srodrigc#endif 1388153323Srodrigc int i; /* loop counter */ 1389153323Srodrigc xfs_bmbt_key_t key; /* bmap btree key */ 1390153323Srodrigc xfs_buf_t *lbp; /* left buffer pointer */ 1391153323Srodrigc xfs_bmbt_block_t *left; /* left btree block */ 1392153323Srodrigc xfs_bmbt_key_t *lkp; /* left btree key */ 1393153323Srodrigc xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1394153323Srodrigc xfs_bmbt_rec_t *lrp; /* left record pointer */ 1395153323Srodrigc xfs_mount_t *mp; /* file system mount point */ 1396153323Srodrigc xfs_buf_t *rbp; /* right buffer pointer */ 1397153323Srodrigc xfs_bmbt_block_t *right; /* right btree block */ 1398153323Srodrigc xfs_bmbt_key_t *rkp; /* right btree key */ 1399153323Srodrigc xfs_bmbt_ptr_t *rpp; /* right address pointer */ 1400153323Srodrigc xfs_bmbt_rec_t *rrp=NULL; /* right record pointer */ 1401153323Srodrigc struct xfs_btree_cur *tcur; /* temporary btree cursor */ 1402153323Srodrigc 1403153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1404153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, level); 1405153323Srodrigc if (level == cur->bc_nlevels - 1) { 1406153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1407153323Srodrigc *stat = 0; 1408153323Srodrigc return 0; 1409153323Srodrigc } 1410153323Srodrigc lbp = cur->bc_bufs[level]; 1411153323Srodrigc left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1412153323Srodrigc#ifdef DEBUG 1413153323Srodrigc if ((error = xfs_btree_check_lblock(cur, left, level, lbp))) { 1414153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1415153323Srodrigc return error; 1416153323Srodrigc } 1417153323Srodrigc#endif 1418159451Srodrigc if (be64_to_cpu(left->bb_rightsib) == NULLDFSBNO) { 1419153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1420153323Srodrigc *stat = 0; 1421153323Srodrigc return 0; 1422153323Srodrigc } 1423159451Srodrigc if (cur->bc_ptrs[level] >= be16_to_cpu(left->bb_numrecs)) { 1424153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1425153323Srodrigc *stat = 0; 1426153323Srodrigc return 0; 1427153323Srodrigc } 1428153323Srodrigc mp = cur->bc_mp; 1429159451Srodrigc if ((error = xfs_btree_read_bufl(mp, cur->bc_tp, be64_to_cpu(left->bb_rightsib), 0, 1430153323Srodrigc &rbp, XFS_BMAP_BTREE_REF))) { 1431153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1432153323Srodrigc return error; 1433153323Srodrigc } 1434153323Srodrigc right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1435153323Srodrigc if ((error = xfs_btree_check_lblock(cur, right, level, rbp))) { 1436153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1437153323Srodrigc return error; 1438153323Srodrigc } 1439159451Srodrigc if (be16_to_cpu(right->bb_numrecs) == XFS_BMAP_BLOCK_IMAXRECS(level, cur)) { 1440153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1441153323Srodrigc *stat = 0; 1442153323Srodrigc return 0; 1443153323Srodrigc } 1444153323Srodrigc if (level > 0) { 1445159451Srodrigc lkp = XFS_BMAP_KEY_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); 1446159451Srodrigc lpp = XFS_BMAP_PTR_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); 1447153323Srodrigc rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1448153323Srodrigc rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1449153323Srodrigc#ifdef DEBUG 1450159451Srodrigc for (i = be16_to_cpu(right->bb_numrecs) - 1; i >= 0; i--) { 1451153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(rpp[i], ARCH_CONVERT), level))) { 1452153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1453153323Srodrigc return error; 1454153323Srodrigc } 1455153323Srodrigc } 1456153323Srodrigc#endif 1457159451Srodrigc memmove(rkp + 1, rkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); 1458159451Srodrigc memmove(rpp + 1, rpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); 1459153323Srodrigc#ifdef DEBUG 1460153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(*lpp, ARCH_CONVERT), level))) { 1461153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1462153323Srodrigc return error; 1463153323Srodrigc } 1464153323Srodrigc#endif 1465153323Srodrigc *rkp = *lkp; 1466153323Srodrigc *rpp = *lpp; /* INT_: direct copy */ 1467159451Srodrigc xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); 1468159451Srodrigc xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); 1469153323Srodrigc } else { 1470159451Srodrigc lrp = XFS_BMAP_REC_IADDR(left, be16_to_cpu(left->bb_numrecs), cur); 1471153323Srodrigc rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1472159451Srodrigc memmove(rrp + 1, rrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); 1473153323Srodrigc *rrp = *lrp; 1474159451Srodrigc xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs) + 1); 1475153323Srodrigc INT_SET(key.br_startoff, ARCH_CONVERT, 1476153323Srodrigc xfs_bmbt_disk_get_startoff(rrp)); 1477153323Srodrigc rkp = &key; 1478153323Srodrigc } 1479159451Srodrigc be16_add(&left->bb_numrecs, -1); 1480153323Srodrigc xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS); 1481159451Srodrigc be16_add(&right->bb_numrecs, 1); 1482153323Srodrigc#ifdef DEBUG 1483153323Srodrigc if (level > 0) 1484153323Srodrigc xfs_btree_check_key(XFS_BTNUM_BMAP, rkp, rkp + 1); 1485153323Srodrigc else 1486153323Srodrigc xfs_btree_check_rec(XFS_BTNUM_BMAP, rrp, rrp + 1); 1487153323Srodrigc#endif 1488153323Srodrigc xfs_bmbt_log_block(cur, rbp, XFS_BB_NUMRECS); 1489153323Srodrigc if ((error = xfs_btree_dup_cursor(cur, &tcur))) { 1490153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1491153323Srodrigc return error; 1492153323Srodrigc } 1493153323Srodrigc i = xfs_btree_lastrec(tcur, level); 1494153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 1495153323Srodrigc if ((error = xfs_bmbt_increment(tcur, level, &i))) { 1496153323Srodrigc XFS_BMBT_TRACE_CURSOR(tcur, ERROR); 1497153323Srodrigc goto error1; 1498153323Srodrigc } 1499153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 1500153323Srodrigc if ((error = xfs_bmbt_updkey(tcur, rkp, level + 1))) { 1501153323Srodrigc XFS_BMBT_TRACE_CURSOR(tcur, ERROR); 1502153323Srodrigc goto error1; 1503153323Srodrigc } 1504153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); 1505153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1506153323Srodrigc *stat = 1; 1507153323Srodrigc return 0; 1508153323Srodrigcerror0: 1509153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1510153323Srodrigcerror1: 1511153323Srodrigc xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); 1512153323Srodrigc return error; 1513153323Srodrigc} 1514153323Srodrigc 1515153323Srodrigc/* 1516153323Srodrigc * Determine the extent state. 1517153323Srodrigc */ 1518153323Srodrigc/* ARGSUSED */ 1519153323SrodrigcSTATIC xfs_exntst_t 1520153323Srodrigcxfs_extent_state( 1521153323Srodrigc xfs_filblks_t blks, 1522153323Srodrigc int extent_flag) 1523153323Srodrigc{ 1524153323Srodrigc if (extent_flag) { 1525153323Srodrigc ASSERT(blks != 0); /* saved for DMIG */ 1526153323Srodrigc return XFS_EXT_UNWRITTEN; 1527153323Srodrigc } 1528153323Srodrigc return XFS_EXT_NORM; 1529153323Srodrigc} 1530153323Srodrigc 1531153323Srodrigc 1532153323Srodrigc/* 1533153323Srodrigc * Split cur/level block in half. 1534153323Srodrigc * Return new block number and its first record (to be inserted into parent). 1535153323Srodrigc */ 1536153323SrodrigcSTATIC int /* error */ 1537153323Srodrigcxfs_bmbt_split( 1538153323Srodrigc xfs_btree_cur_t *cur, 1539153323Srodrigc int level, 1540153323Srodrigc xfs_fsblock_t *bnop, 1541153323Srodrigc xfs_bmbt_key_t *keyp, 1542153323Srodrigc xfs_btree_cur_t **curp, 1543153323Srodrigc int *stat) /* success/failure */ 1544153323Srodrigc{ 1545153323Srodrigc xfs_alloc_arg_t args; /* block allocation args */ 1546153323Srodrigc int error; /* error return value */ 1547153323Srodrigc#ifdef XFS_BMBT_TRACE 1548153323Srodrigc static char fname[] = "xfs_bmbt_split"; 1549153323Srodrigc#endif 1550153323Srodrigc int i; /* loop counter */ 1551153323Srodrigc xfs_fsblock_t lbno; /* left sibling block number */ 1552153323Srodrigc xfs_buf_t *lbp; /* left buffer pointer */ 1553153323Srodrigc xfs_bmbt_block_t *left; /* left btree block */ 1554153323Srodrigc xfs_bmbt_key_t *lkp; /* left btree key */ 1555153323Srodrigc xfs_bmbt_ptr_t *lpp; /* left address pointer */ 1556153323Srodrigc xfs_bmbt_rec_t *lrp; /* left record pointer */ 1557153323Srodrigc xfs_buf_t *rbp; /* right buffer pointer */ 1558153323Srodrigc xfs_bmbt_block_t *right; /* right btree block */ 1559153323Srodrigc xfs_bmbt_key_t *rkp; /* right btree key */ 1560153323Srodrigc xfs_bmbt_ptr_t *rpp; /* right address pointer */ 1561153323Srodrigc xfs_bmbt_block_t *rrblock; /* right-right btree block */ 1562153323Srodrigc xfs_buf_t *rrbp; /* right-right buffer pointer */ 1563153323Srodrigc xfs_bmbt_rec_t *rrp; /* right record pointer */ 1564153323Srodrigc 1565153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1566153323Srodrigc XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, keyp); 1567153323Srodrigc args.tp = cur->bc_tp; 1568153323Srodrigc args.mp = cur->bc_mp; 1569153323Srodrigc lbp = cur->bc_bufs[level]; 1570153323Srodrigc lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); 1571153323Srodrigc left = XFS_BUF_TO_BMBT_BLOCK(lbp); 1572153323Srodrigc args.fsbno = cur->bc_private.b.firstblock; 1573153323Srodrigc if (args.fsbno == NULLFSBLOCK) { 1574153323Srodrigc args.fsbno = lbno; 1575153323Srodrigc args.type = XFS_ALLOCTYPE_START_BNO; 1576153323Srodrigc } else if (cur->bc_private.b.flist->xbf_low) 1577153323Srodrigc args.type = XFS_ALLOCTYPE_FIRST_AG; 1578153323Srodrigc else 1579153323Srodrigc args.type = XFS_ALLOCTYPE_NEAR_BNO; 1580153323Srodrigc args.mod = args.minleft = args.alignment = args.total = args.isfl = 1581153323Srodrigc args.userdata = args.minalignslop = 0; 1582153323Srodrigc args.minlen = args.maxlen = args.prod = 1; 1583153323Srodrigc args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; 1584153323Srodrigc if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { 1585153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1586153323Srodrigc return XFS_ERROR(ENOSPC); 1587153323Srodrigc } 1588153323Srodrigc if ((error = xfs_alloc_vextent(&args))) { 1589153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1590153323Srodrigc return error; 1591153323Srodrigc } 1592153323Srodrigc if (args.fsbno == NULLFSBLOCK) { 1593153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1594153323Srodrigc *stat = 0; 1595153323Srodrigc return 0; 1596153323Srodrigc } 1597153323Srodrigc ASSERT(args.len == 1); 1598153323Srodrigc cur->bc_private.b.firstblock = args.fsbno; 1599153323Srodrigc cur->bc_private.b.allocated++; 1600153323Srodrigc cur->bc_private.b.ip->i_d.di_nblocks++; 1601153323Srodrigc xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); 1602153323Srodrigc XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, 1603153323Srodrigc XFS_TRANS_DQ_BCOUNT, 1L); 1604153323Srodrigc rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); 1605153323Srodrigc right = XFS_BUF_TO_BMBT_BLOCK(rbp); 1606153323Srodrigc#ifdef DEBUG 1607153323Srodrigc if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { 1608153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1609153323Srodrigc return error; 1610153323Srodrigc } 1611153323Srodrigc#endif 1612159451Srodrigc right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); 1613159451Srodrigc right->bb_level = left->bb_level; 1614159451Srodrigc right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); 1615159451Srodrigc if ((be16_to_cpu(left->bb_numrecs) & 1) && 1616159451Srodrigc cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) 1617159451Srodrigc be16_add(&right->bb_numrecs, 1); 1618159451Srodrigc i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; 1619153323Srodrigc if (level > 0) { 1620153323Srodrigc lkp = XFS_BMAP_KEY_IADDR(left, i, cur); 1621153323Srodrigc lpp = XFS_BMAP_PTR_IADDR(left, i, cur); 1622153323Srodrigc rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); 1623153323Srodrigc rpp = XFS_BMAP_PTR_IADDR(right, 1, cur); 1624153323Srodrigc#ifdef DEBUG 1625159451Srodrigc for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { 1626153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(lpp[i], ARCH_CONVERT), level))) { 1627153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1628153323Srodrigc return error; 1629153323Srodrigc } 1630153323Srodrigc } 1631153323Srodrigc#endif 1632159451Srodrigc memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); 1633159451Srodrigc memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); 1634159451Srodrigc xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); 1635159451Srodrigc xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); 1636153323Srodrigc keyp->br_startoff = INT_GET(rkp->br_startoff, ARCH_CONVERT); 1637153323Srodrigc } else { 1638153323Srodrigc lrp = XFS_BMAP_REC_IADDR(left, i, cur); 1639153323Srodrigc rrp = XFS_BMAP_REC_IADDR(right, 1, cur); 1640159451Srodrigc memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); 1641159451Srodrigc xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); 1642153323Srodrigc keyp->br_startoff = xfs_bmbt_disk_get_startoff(rrp); 1643153323Srodrigc } 1644159451Srodrigc be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); 1645159451Srodrigc right->bb_rightsib = left->bb_rightsib; 1646159451Srodrigc left->bb_rightsib = cpu_to_be64(args.fsbno); 1647159451Srodrigc right->bb_leftsib = cpu_to_be64(lbno); 1648153323Srodrigc xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); 1649153323Srodrigc xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); 1650159451Srodrigc if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { 1651153323Srodrigc if ((error = xfs_btree_read_bufl(args.mp, args.tp, 1652159451Srodrigc be64_to_cpu(right->bb_rightsib), 0, &rrbp, 1653153323Srodrigc XFS_BMAP_BTREE_REF))) { 1654153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1655153323Srodrigc return error; 1656153323Srodrigc } 1657153323Srodrigc rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); 1658153323Srodrigc if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { 1659153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1660153323Srodrigc return error; 1661153323Srodrigc } 1662159451Srodrigc rrblock->bb_leftsib = cpu_to_be64(args.fsbno); 1663153323Srodrigc xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); 1664153323Srodrigc } 1665159451Srodrigc if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { 1666153323Srodrigc xfs_btree_setbuf(cur, level, rbp); 1667159451Srodrigc cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); 1668153323Srodrigc } 1669153323Srodrigc if (level + 1 < cur->bc_nlevels) { 1670153323Srodrigc if ((error = xfs_btree_dup_cursor(cur, curp))) { 1671153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1672153323Srodrigc return error; 1673153323Srodrigc } 1674153323Srodrigc (*curp)->bc_ptrs[level + 1]++; 1675153323Srodrigc } 1676153323Srodrigc *bnop = args.fsbno; 1677153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1678153323Srodrigc *stat = 1; 1679153323Srodrigc return 0; 1680153323Srodrigc} 1681153323Srodrigc 1682153323Srodrigc 1683153323Srodrigc/* 1684153323Srodrigc * Update keys for the record. 1685153323Srodrigc */ 1686153323SrodrigcSTATIC int 1687153323Srodrigcxfs_bmbt_updkey( 1688153323Srodrigc xfs_btree_cur_t *cur, 1689153323Srodrigc xfs_bmbt_key_t *keyp, /* on-disk format */ 1690153323Srodrigc int level) 1691153323Srodrigc{ 1692153323Srodrigc xfs_bmbt_block_t *block; 1693153323Srodrigc xfs_buf_t *bp; 1694153323Srodrigc#ifdef DEBUG 1695153323Srodrigc int error; 1696153323Srodrigc#endif 1697153323Srodrigc#ifdef XFS_BMBT_TRACE 1698153323Srodrigc static char fname[] = "xfs_bmbt_updkey"; 1699153323Srodrigc#endif 1700153323Srodrigc xfs_bmbt_key_t *kp; 1701153323Srodrigc int ptr; 1702153323Srodrigc 1703153323Srodrigc ASSERT(level >= 1); 1704153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1705153323Srodrigc XFS_BMBT_TRACE_ARGIK(cur, level, keyp); 1706153323Srodrigc for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { 1707153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 1708153323Srodrigc#ifdef DEBUG 1709153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 1710153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1711153323Srodrigc return error; 1712153323Srodrigc } 1713153323Srodrigc#endif 1714153323Srodrigc ptr = cur->bc_ptrs[level]; 1715153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); 1716153323Srodrigc *kp = *keyp; 1717153323Srodrigc xfs_bmbt_log_keys(cur, bp, ptr, ptr); 1718153323Srodrigc } 1719153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1720153323Srodrigc return 0; 1721153323Srodrigc} 1722153323Srodrigc 1723153323Srodrigc/* 1724153323Srodrigc * Convert on-disk form of btree root to in-memory form. 1725153323Srodrigc */ 1726153323Srodrigcvoid 1727153323Srodrigcxfs_bmdr_to_bmbt( 1728153323Srodrigc xfs_bmdr_block_t *dblock, 1729153323Srodrigc int dblocklen, 1730153323Srodrigc xfs_bmbt_block_t *rblock, 1731153323Srodrigc int rblocklen) 1732153323Srodrigc{ 1733153323Srodrigc int dmxr; 1734153323Srodrigc xfs_bmbt_key_t *fkp; 1735153323Srodrigc xfs_bmbt_ptr_t *fpp; 1736153323Srodrigc xfs_bmbt_key_t *tkp; 1737153323Srodrigc xfs_bmbt_ptr_t *tpp; 1738153323Srodrigc 1739159451Srodrigc rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); 1740159451Srodrigc rblock->bb_level = dblock->bb_level; 1741159451Srodrigc ASSERT(be16_to_cpu(rblock->bb_level) > 0); 1742159451Srodrigc rblock->bb_numrecs = dblock->bb_numrecs; 1743159451Srodrigc rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); 1744159451Srodrigc rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); 1745153323Srodrigc dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); 1746153323Srodrigc fkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); 1747153323Srodrigc tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); 1748153323Srodrigc fpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); 1749153323Srodrigc tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); 1750159451Srodrigc dmxr = be16_to_cpu(dblock->bb_numrecs); 1751153323Srodrigc memcpy(tkp, fkp, sizeof(*fkp) * dmxr); 1752153323Srodrigc memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */ 1753153323Srodrigc} 1754153323Srodrigc 1755153323Srodrigc/* 1756153323Srodrigc * Decrement cursor by one record at the level. 1757153323Srodrigc * For nonzero levels the leaf-ward information is untouched. 1758153323Srodrigc */ 1759153323Srodrigcint /* error */ 1760153323Srodrigcxfs_bmbt_decrement( 1761153323Srodrigc xfs_btree_cur_t *cur, 1762153323Srodrigc int level, 1763153323Srodrigc int *stat) /* success/failure */ 1764153323Srodrigc{ 1765153323Srodrigc xfs_bmbt_block_t *block; 1766153323Srodrigc xfs_buf_t *bp; 1767153323Srodrigc int error; /* error return value */ 1768153323Srodrigc#ifdef XFS_BMBT_TRACE 1769153323Srodrigc static char fname[] = "xfs_bmbt_decrement"; 1770153323Srodrigc#endif 1771153323Srodrigc xfs_fsblock_t fsbno; 1772153323Srodrigc int lev; 1773153323Srodrigc xfs_mount_t *mp; 1774153323Srodrigc xfs_trans_t *tp; 1775153323Srodrigc 1776153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1777153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, level); 1778153323Srodrigc ASSERT(level < cur->bc_nlevels); 1779153323Srodrigc if (level < cur->bc_nlevels - 1) 1780153323Srodrigc xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); 1781153323Srodrigc if (--cur->bc_ptrs[level] > 0) { 1782153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1783153323Srodrigc *stat = 1; 1784153323Srodrigc return 0; 1785153323Srodrigc } 1786153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 1787153323Srodrigc#ifdef DEBUG 1788153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 1789153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1790153323Srodrigc return error; 1791153323Srodrigc } 1792153323Srodrigc#endif 1793159451Srodrigc if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) { 1794153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1795153323Srodrigc *stat = 0; 1796153323Srodrigc return 0; 1797153323Srodrigc } 1798153323Srodrigc for (lev = level + 1; lev < cur->bc_nlevels; lev++) { 1799153323Srodrigc if (--cur->bc_ptrs[lev] > 0) 1800153323Srodrigc break; 1801153323Srodrigc if (lev < cur->bc_nlevels - 1) 1802153323Srodrigc xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); 1803153323Srodrigc } 1804153323Srodrigc if (lev == cur->bc_nlevels) { 1805153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1806153323Srodrigc *stat = 0; 1807153323Srodrigc return 0; 1808153323Srodrigc } 1809153323Srodrigc tp = cur->bc_tp; 1810153323Srodrigc mp = cur->bc_mp; 1811153323Srodrigc for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { 1812153323Srodrigc fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT); 1813153323Srodrigc if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, 1814153323Srodrigc XFS_BMAP_BTREE_REF))) { 1815153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1816153323Srodrigc return error; 1817153323Srodrigc } 1818153323Srodrigc lev--; 1819153323Srodrigc xfs_btree_setbuf(cur, lev, bp); 1820153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 1821153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { 1822153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1823153323Srodrigc return error; 1824153323Srodrigc } 1825159451Srodrigc cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs); 1826153323Srodrigc } 1827153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1828153323Srodrigc *stat = 1; 1829153323Srodrigc return 0; 1830153323Srodrigc} 1831153323Srodrigc 1832153323Srodrigc/* 1833153323Srodrigc * Delete the record pointed to by cur. 1834153323Srodrigc */ 1835153323Srodrigcint /* error */ 1836153323Srodrigcxfs_bmbt_delete( 1837153323Srodrigc xfs_btree_cur_t *cur, 1838153323Srodrigc int *stat) /* success/failure */ 1839153323Srodrigc{ 1840153323Srodrigc int error; /* error return value */ 1841153323Srodrigc#ifdef XFS_BMBT_TRACE 1842153323Srodrigc static char fname[] = "xfs_bmbt_delete"; 1843153323Srodrigc#endif 1844153323Srodrigc int i; 1845153323Srodrigc int level; 1846153323Srodrigc 1847153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 1848153323Srodrigc for (level = 0, i = 2; i == 2; level++) { 1849153323Srodrigc if ((error = xfs_bmbt_delrec(cur, level, &i))) { 1850153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1851153323Srodrigc return error; 1852153323Srodrigc } 1853153323Srodrigc } 1854153323Srodrigc if (i == 0) { 1855153323Srodrigc for (level = 1; level < cur->bc_nlevels; level++) { 1856153323Srodrigc if (cur->bc_ptrs[level] == 0) { 1857153323Srodrigc if ((error = xfs_bmbt_decrement(cur, level, 1858153323Srodrigc &i))) { 1859153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 1860153323Srodrigc return error; 1861153323Srodrigc } 1862153323Srodrigc break; 1863153323Srodrigc } 1864153323Srodrigc } 1865153323Srodrigc } 1866153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 1867153323Srodrigc *stat = i; 1868153323Srodrigc return 0; 1869153323Srodrigc} 1870153323Srodrigc 1871153323Srodrigc/* 1872153323Srodrigc * Convert a compressed bmap extent record to an uncompressed form. 1873153323Srodrigc * This code must be in sync with the routines xfs_bmbt_get_startoff, 1874153323Srodrigc * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. 1875153323Srodrigc */ 1876153323Srodrigc 1877153323SrodrigcSTATIC __inline__ void 1878153323Srodrigc__xfs_bmbt_get_all( 1879153323Srodrigc __uint64_t l0, 1880153323Srodrigc __uint64_t l1, 1881153323Srodrigc xfs_bmbt_irec_t *s) 1882153323Srodrigc{ 1883153323Srodrigc int ext_flag; 1884153323Srodrigc xfs_exntst_t st; 1885153323Srodrigc 1886153323Srodrigc ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); 1887153323Srodrigc s->br_startoff = ((xfs_fileoff_t)l0 & 1888153323Srodrigc XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; 1889153323Srodrigc#if XFS_BIG_BLKNOS 1890153323Srodrigc s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) | 1891153323Srodrigc (((xfs_fsblock_t)l1) >> 21); 1892153323Srodrigc#else 1893153323Srodrigc#ifdef DEBUG 1894153323Srodrigc { 1895153323Srodrigc xfs_dfsbno_t b; 1896153323Srodrigc 1897153323Srodrigc b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) | 1898153323Srodrigc (((xfs_dfsbno_t)l1) >> 21); 1899153323Srodrigc ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); 1900153323Srodrigc s->br_startblock = (xfs_fsblock_t)b; 1901153323Srodrigc } 1902153323Srodrigc#else /* !DEBUG */ 1903153323Srodrigc s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21); 1904153323Srodrigc#endif /* DEBUG */ 1905153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 1906153323Srodrigc s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21)); 1907153323Srodrigc /* This is xfs_extent_state() in-line */ 1908153323Srodrigc if (ext_flag) { 1909153323Srodrigc ASSERT(s->br_blockcount != 0); /* saved for DMIG */ 1910153323Srodrigc st = XFS_EXT_UNWRITTEN; 1911153323Srodrigc } else 1912153323Srodrigc st = XFS_EXT_NORM; 1913153323Srodrigc s->br_state = st; 1914153323Srodrigc} 1915153323Srodrigc 1916153323Srodrigcvoid 1917153323Srodrigcxfs_bmbt_get_all( 1918153323Srodrigc xfs_bmbt_rec_t *r, 1919153323Srodrigc xfs_bmbt_irec_t *s) 1920153323Srodrigc{ 1921153323Srodrigc __xfs_bmbt_get_all(r->l0, r->l1, s); 1922153323Srodrigc} 1923153323Srodrigc 1924153323Srodrigc/* 1925153323Srodrigc * Get the block pointer for the given level of the cursor. 1926153323Srodrigc * Fill in the buffer pointer, if applicable. 1927153323Srodrigc */ 1928153323Srodrigcxfs_bmbt_block_t * 1929153323Srodrigcxfs_bmbt_get_block( 1930153323Srodrigc xfs_btree_cur_t *cur, 1931153323Srodrigc int level, 1932153323Srodrigc xfs_buf_t **bpp) 1933153323Srodrigc{ 1934153323Srodrigc xfs_ifork_t *ifp; 1935153323Srodrigc xfs_bmbt_block_t *rval; 1936153323Srodrigc 1937153323Srodrigc if (level < cur->bc_nlevels - 1) { 1938153323Srodrigc *bpp = cur->bc_bufs[level]; 1939153323Srodrigc rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); 1940153323Srodrigc } else { 1941159451Srodrigc *bpp = NULL; 1942153323Srodrigc ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, 1943153323Srodrigc cur->bc_private.b.whichfork); 1944153323Srodrigc rval = ifp->if_broot; 1945153323Srodrigc } 1946153323Srodrigc return rval; 1947153323Srodrigc} 1948153323Srodrigc 1949153323Srodrigc/* 1950153323Srodrigc * Extract the blockcount field from an in memory bmap extent record. 1951153323Srodrigc */ 1952153323Srodrigcxfs_filblks_t 1953153323Srodrigcxfs_bmbt_get_blockcount( 1954153323Srodrigc xfs_bmbt_rec_t *r) 1955153323Srodrigc{ 1956153323Srodrigc return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21)); 1957153323Srodrigc} 1958153323Srodrigc 1959153323Srodrigc/* 1960153323Srodrigc * Extract the startblock field from an in memory bmap extent record. 1961153323Srodrigc */ 1962153323Srodrigcxfs_fsblock_t 1963153323Srodrigcxfs_bmbt_get_startblock( 1964153323Srodrigc xfs_bmbt_rec_t *r) 1965153323Srodrigc{ 1966153323Srodrigc#if XFS_BIG_BLKNOS 1967153323Srodrigc return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) | 1968153323Srodrigc (((xfs_fsblock_t)r->l1) >> 21); 1969153323Srodrigc#else 1970153323Srodrigc#ifdef DEBUG 1971153323Srodrigc xfs_dfsbno_t b; 1972153323Srodrigc 1973153323Srodrigc b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) | 1974153323Srodrigc (((xfs_dfsbno_t)r->l1) >> 21); 1975153323Srodrigc ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); 1976153323Srodrigc return (xfs_fsblock_t)b; 1977153323Srodrigc#else /* !DEBUG */ 1978153323Srodrigc return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21); 1979153323Srodrigc#endif /* DEBUG */ 1980153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 1981153323Srodrigc} 1982153323Srodrigc 1983153323Srodrigc/* 1984153323Srodrigc * Extract the startoff field from an in memory bmap extent record. 1985153323Srodrigc */ 1986153323Srodrigcxfs_fileoff_t 1987153323Srodrigcxfs_bmbt_get_startoff( 1988153323Srodrigc xfs_bmbt_rec_t *r) 1989153323Srodrigc{ 1990153323Srodrigc return ((xfs_fileoff_t)r->l0 & 1991153323Srodrigc XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; 1992153323Srodrigc} 1993153323Srodrigc 1994153323Srodrigcxfs_exntst_t 1995153323Srodrigcxfs_bmbt_get_state( 1996153323Srodrigc xfs_bmbt_rec_t *r) 1997153323Srodrigc{ 1998153323Srodrigc int ext_flag; 1999153323Srodrigc 2000153323Srodrigc ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); 2001153323Srodrigc return xfs_extent_state(xfs_bmbt_get_blockcount(r), 2002153323Srodrigc ext_flag); 2003153323Srodrigc} 2004153323Srodrigc 2005159451Srodrigc#ifndef XFS_NATIVE_HOST 2006153323Srodrigc/* Endian flipping versions of the bmbt extraction functions */ 2007153323Srodrigcvoid 2008153323Srodrigcxfs_bmbt_disk_get_all( 2009153323Srodrigc xfs_bmbt_rec_t *r, 2010153323Srodrigc xfs_bmbt_irec_t *s) 2011153323Srodrigc{ 2012153323Srodrigc __uint64_t l0, l1; 2013153323Srodrigc 2014153323Srodrigc l0 = INT_GET(r->l0, ARCH_CONVERT); 2015153323Srodrigc l1 = INT_GET(r->l1, ARCH_CONVERT); 2016153323Srodrigc 2017153323Srodrigc __xfs_bmbt_get_all(l0, l1, s); 2018153323Srodrigc} 2019153323Srodrigc 2020153323Srodrigc/* 2021153323Srodrigc * Extract the blockcount field from an on disk bmap extent record. 2022153323Srodrigc */ 2023153323Srodrigcxfs_filblks_t 2024153323Srodrigcxfs_bmbt_disk_get_blockcount( 2025153323Srodrigc xfs_bmbt_rec_t *r) 2026153323Srodrigc{ 2027153323Srodrigc return (xfs_filblks_t)(INT_GET(r->l1, ARCH_CONVERT) & XFS_MASK64LO(21)); 2028153323Srodrigc} 2029153323Srodrigc 2030153323Srodrigc/* 2031153323Srodrigc * Extract the startblock field from an on disk bmap extent record. 2032153323Srodrigc */ 2033153323Srodrigcxfs_fsblock_t 2034153323Srodrigcxfs_bmbt_disk_get_startblock( 2035153323Srodrigc xfs_bmbt_rec_t *r) 2036153323Srodrigc{ 2037153323Srodrigc#if XFS_BIG_BLKNOS 2038153323Srodrigc return (((xfs_fsblock_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) | 2039153323Srodrigc (((xfs_fsblock_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); 2040153323Srodrigc#else 2041153323Srodrigc#ifdef DEBUG 2042153323Srodrigc xfs_dfsbno_t b; 2043153323Srodrigc 2044153323Srodrigc b = (((xfs_dfsbno_t)INT_GET(r->l0, ARCH_CONVERT) & XFS_MASK64LO(9)) << 43) | 2045153323Srodrigc (((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); 2046153323Srodrigc ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); 2047153323Srodrigc return (xfs_fsblock_t)b; 2048153323Srodrigc#else /* !DEBUG */ 2049153323Srodrigc return (xfs_fsblock_t)(((xfs_dfsbno_t)INT_GET(r->l1, ARCH_CONVERT)) >> 21); 2050153323Srodrigc#endif /* DEBUG */ 2051153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2052153323Srodrigc} 2053153323Srodrigc 2054153323Srodrigc/* 2055153323Srodrigc * Extract the startoff field from a disk format bmap extent record. 2056153323Srodrigc */ 2057153323Srodrigcxfs_fileoff_t 2058153323Srodrigcxfs_bmbt_disk_get_startoff( 2059153323Srodrigc xfs_bmbt_rec_t *r) 2060153323Srodrigc{ 2061153323Srodrigc return ((xfs_fileoff_t)INT_GET(r->l0, ARCH_CONVERT) & 2062153323Srodrigc XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9; 2063153323Srodrigc} 2064153323Srodrigc 2065153323Srodrigcxfs_exntst_t 2066153323Srodrigcxfs_bmbt_disk_get_state( 2067153323Srodrigc xfs_bmbt_rec_t *r) 2068153323Srodrigc{ 2069153323Srodrigc int ext_flag; 2070153323Srodrigc 2071153323Srodrigc ext_flag = (int)((INT_GET(r->l0, ARCH_CONVERT)) >> (64 - BMBT_EXNTFLAG_BITLEN)); 2072153323Srodrigc return xfs_extent_state(xfs_bmbt_disk_get_blockcount(r), 2073153323Srodrigc ext_flag); 2074153323Srodrigc} 2075159451Srodrigc#endif /* XFS_NATIVE_HOST */ 2076153323Srodrigc 2077153323Srodrigc 2078153323Srodrigc/* 2079153323Srodrigc * Increment cursor by one record at the level. 2080153323Srodrigc * For nonzero levels the leaf-ward information is untouched. 2081153323Srodrigc */ 2082153323Srodrigcint /* error */ 2083153323Srodrigcxfs_bmbt_increment( 2084153323Srodrigc xfs_btree_cur_t *cur, 2085153323Srodrigc int level, 2086153323Srodrigc int *stat) /* success/failure */ 2087153323Srodrigc{ 2088153323Srodrigc xfs_bmbt_block_t *block; 2089153323Srodrigc xfs_buf_t *bp; 2090153323Srodrigc int error; /* error return value */ 2091153323Srodrigc#ifdef XFS_BMBT_TRACE 2092153323Srodrigc static char fname[] = "xfs_bmbt_increment"; 2093153323Srodrigc#endif 2094153323Srodrigc xfs_fsblock_t fsbno; 2095153323Srodrigc int lev; 2096153323Srodrigc xfs_mount_t *mp; 2097153323Srodrigc xfs_trans_t *tp; 2098153323Srodrigc 2099153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2100153323Srodrigc XFS_BMBT_TRACE_ARGI(cur, level); 2101153323Srodrigc ASSERT(level < cur->bc_nlevels); 2102153323Srodrigc if (level < cur->bc_nlevels - 1) 2103153323Srodrigc xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA); 2104153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 2105153323Srodrigc#ifdef DEBUG 2106153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { 2107153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2108153323Srodrigc return error; 2109153323Srodrigc } 2110153323Srodrigc#endif 2111159451Srodrigc if (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) { 2112153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2113153323Srodrigc *stat = 1; 2114153323Srodrigc return 0; 2115153323Srodrigc } 2116159451Srodrigc if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) { 2117153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2118153323Srodrigc *stat = 0; 2119153323Srodrigc return 0; 2120153323Srodrigc } 2121153323Srodrigc for (lev = level + 1; lev < cur->bc_nlevels; lev++) { 2122153323Srodrigc block = xfs_bmbt_get_block(cur, lev, &bp); 2123153323Srodrigc#ifdef DEBUG 2124153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { 2125153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2126153323Srodrigc return error; 2127153323Srodrigc } 2128153323Srodrigc#endif 2129159451Srodrigc if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs)) 2130153323Srodrigc break; 2131153323Srodrigc if (lev < cur->bc_nlevels - 1) 2132153323Srodrigc xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); 2133153323Srodrigc } 2134153323Srodrigc if (lev == cur->bc_nlevels) { 2135153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2136153323Srodrigc *stat = 0; 2137153323Srodrigc return 0; 2138153323Srodrigc } 2139153323Srodrigc tp = cur->bc_tp; 2140153323Srodrigc mp = cur->bc_mp; 2141153323Srodrigc for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { 2142153323Srodrigc fsbno = INT_GET(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur), ARCH_CONVERT); 2143153323Srodrigc if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, 2144153323Srodrigc XFS_BMAP_BTREE_REF))) { 2145153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2146153323Srodrigc return error; 2147153323Srodrigc } 2148153323Srodrigc lev--; 2149153323Srodrigc xfs_btree_setbuf(cur, lev, bp); 2150153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 2151153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { 2152153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2153153323Srodrigc return error; 2154153323Srodrigc } 2155153323Srodrigc cur->bc_ptrs[lev] = 1; 2156153323Srodrigc } 2157153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2158153323Srodrigc *stat = 1; 2159153323Srodrigc return 0; 2160153323Srodrigc} 2161153323Srodrigc 2162153323Srodrigc/* 2163153323Srodrigc * Insert the current record at the point referenced by cur. 2164153323Srodrigc */ 2165153323Srodrigcint /* error */ 2166153323Srodrigcxfs_bmbt_insert( 2167153323Srodrigc xfs_btree_cur_t *cur, 2168153323Srodrigc int *stat) /* success/failure */ 2169153323Srodrigc{ 2170153323Srodrigc int error; /* error return value */ 2171153323Srodrigc#ifdef XFS_BMBT_TRACE 2172153323Srodrigc static char fname[] = "xfs_bmbt_insert"; 2173153323Srodrigc#endif 2174153323Srodrigc int i; 2175153323Srodrigc int level; 2176153323Srodrigc xfs_fsblock_t nbno; 2177153323Srodrigc xfs_btree_cur_t *ncur; 2178153323Srodrigc xfs_bmbt_rec_t nrec; 2179153323Srodrigc xfs_btree_cur_t *pcur; 2180153323Srodrigc 2181153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2182153323Srodrigc level = 0; 2183153323Srodrigc nbno = NULLFSBLOCK; 2184153323Srodrigc xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); 2185153323Srodrigc ncur = (xfs_btree_cur_t *)0; 2186153323Srodrigc pcur = cur; 2187153323Srodrigc do { 2188153323Srodrigc if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, 2189153323Srodrigc &i))) { 2190153323Srodrigc if (pcur != cur) 2191153323Srodrigc xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); 2192153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2193153323Srodrigc return error; 2194153323Srodrigc } 2195153323Srodrigc XFS_WANT_CORRUPTED_GOTO(i == 1, error0); 2196153323Srodrigc if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { 2197153323Srodrigc cur->bc_nlevels = pcur->bc_nlevels; 2198153323Srodrigc cur->bc_private.b.allocated += 2199153323Srodrigc pcur->bc_private.b.allocated; 2200153323Srodrigc pcur->bc_private.b.allocated = 0; 2201153323Srodrigc ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || 2202153323Srodrigc (cur->bc_private.b.ip->i_d.di_flags & 2203153323Srodrigc XFS_DIFLAG_REALTIME)); 2204153323Srodrigc cur->bc_private.b.firstblock = 2205153323Srodrigc pcur->bc_private.b.firstblock; 2206153323Srodrigc ASSERT(cur->bc_private.b.flist == 2207153323Srodrigc pcur->bc_private.b.flist); 2208153323Srodrigc xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); 2209153323Srodrigc } 2210153323Srodrigc if (ncur) { 2211153323Srodrigc pcur = ncur; 2212153323Srodrigc ncur = (xfs_btree_cur_t *)0; 2213153323Srodrigc } 2214153323Srodrigc } while (nbno != NULLFSBLOCK); 2215153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2216153323Srodrigc *stat = i; 2217153323Srodrigc return 0; 2218153323Srodrigcerror0: 2219153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2220153323Srodrigc return error; 2221153323Srodrigc} 2222153323Srodrigc 2223153323Srodrigc/* 2224153323Srodrigc * Log fields from the btree block header. 2225153323Srodrigc */ 2226153323Srodrigcvoid 2227153323Srodrigcxfs_bmbt_log_block( 2228153323Srodrigc xfs_btree_cur_t *cur, 2229153323Srodrigc xfs_buf_t *bp, 2230153323Srodrigc int fields) 2231153323Srodrigc{ 2232153323Srodrigc int first; 2233153323Srodrigc#ifdef XFS_BMBT_TRACE 2234153323Srodrigc static char fname[] = "xfs_bmbt_log_block"; 2235153323Srodrigc#endif 2236153323Srodrigc int last; 2237153323Srodrigc xfs_trans_t *tp; 2238153323Srodrigc static const short offsets[] = { 2239153323Srodrigc offsetof(xfs_bmbt_block_t, bb_magic), 2240153323Srodrigc offsetof(xfs_bmbt_block_t, bb_level), 2241153323Srodrigc offsetof(xfs_bmbt_block_t, bb_numrecs), 2242153323Srodrigc offsetof(xfs_bmbt_block_t, bb_leftsib), 2243153323Srodrigc offsetof(xfs_bmbt_block_t, bb_rightsib), 2244153323Srodrigc sizeof(xfs_bmbt_block_t) 2245153323Srodrigc }; 2246153323Srodrigc 2247153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2248153323Srodrigc XFS_BMBT_TRACE_ARGBI(cur, bp, fields); 2249153323Srodrigc tp = cur->bc_tp; 2250153323Srodrigc if (bp) { 2251153323Srodrigc xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, 2252153323Srodrigc &last); 2253153323Srodrigc xfs_trans_log_buf(tp, bp, first, last); 2254153323Srodrigc } else 2255153323Srodrigc xfs_trans_log_inode(tp, cur->bc_private.b.ip, 2256153323Srodrigc XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); 2257153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2258153323Srodrigc} 2259153323Srodrigc 2260153323Srodrigc/* 2261153323Srodrigc * Log record values from the btree block. 2262153323Srodrigc */ 2263153323Srodrigcvoid 2264153323Srodrigcxfs_bmbt_log_recs( 2265153323Srodrigc xfs_btree_cur_t *cur, 2266153323Srodrigc xfs_buf_t *bp, 2267153323Srodrigc int rfirst, 2268153323Srodrigc int rlast) 2269153323Srodrigc{ 2270153323Srodrigc xfs_bmbt_block_t *block; 2271153323Srodrigc int first; 2272153323Srodrigc#ifdef XFS_BMBT_TRACE 2273153323Srodrigc static char fname[] = "xfs_bmbt_log_recs"; 2274153323Srodrigc#endif 2275153323Srodrigc int last; 2276153323Srodrigc xfs_bmbt_rec_t *rp; 2277153323Srodrigc xfs_trans_t *tp; 2278153323Srodrigc 2279153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2280153323Srodrigc XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); 2281153323Srodrigc ASSERT(bp); 2282153323Srodrigc tp = cur->bc_tp; 2283153323Srodrigc block = XFS_BUF_TO_BMBT_BLOCK(bp); 2284153323Srodrigc rp = XFS_BMAP_REC_DADDR(block, 1, cur); 2285153323Srodrigc first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); 2286153323Srodrigc last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); 2287153323Srodrigc xfs_trans_log_buf(tp, bp, first, last); 2288153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2289153323Srodrigc} 2290153323Srodrigc 2291153323Srodrigcint /* error */ 2292153323Srodrigcxfs_bmbt_lookup_eq( 2293153323Srodrigc xfs_btree_cur_t *cur, 2294153323Srodrigc xfs_fileoff_t off, 2295153323Srodrigc xfs_fsblock_t bno, 2296153323Srodrigc xfs_filblks_t len, 2297153323Srodrigc int *stat) /* success/failure */ 2298153323Srodrigc{ 2299153323Srodrigc cur->bc_rec.b.br_startoff = off; 2300153323Srodrigc cur->bc_rec.b.br_startblock = bno; 2301153323Srodrigc cur->bc_rec.b.br_blockcount = len; 2302153323Srodrigc return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat); 2303153323Srodrigc} 2304153323Srodrigc 2305153323Srodrigcint /* error */ 2306153323Srodrigcxfs_bmbt_lookup_ge( 2307153323Srodrigc xfs_btree_cur_t *cur, 2308153323Srodrigc xfs_fileoff_t off, 2309153323Srodrigc xfs_fsblock_t bno, 2310153323Srodrigc xfs_filblks_t len, 2311153323Srodrigc int *stat) /* success/failure */ 2312153323Srodrigc{ 2313153323Srodrigc cur->bc_rec.b.br_startoff = off; 2314153323Srodrigc cur->bc_rec.b.br_startblock = bno; 2315153323Srodrigc cur->bc_rec.b.br_blockcount = len; 2316153323Srodrigc return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat); 2317153323Srodrigc} 2318153323Srodrigc 2319153323Srodrigc/* 2320153323Srodrigc * Give the bmap btree a new root block. Copy the old broot contents 2321153323Srodrigc * down into a real block and make the broot point to it. 2322153323Srodrigc */ 2323153323Srodrigcint /* error */ 2324153323Srodrigcxfs_bmbt_newroot( 2325153323Srodrigc xfs_btree_cur_t *cur, /* btree cursor */ 2326153323Srodrigc int *logflags, /* logging flags for inode */ 2327153323Srodrigc int *stat) /* return status - 0 fail */ 2328153323Srodrigc{ 2329153323Srodrigc xfs_alloc_arg_t args; /* allocation arguments */ 2330153323Srodrigc xfs_bmbt_block_t *block; /* bmap btree block */ 2331153323Srodrigc xfs_buf_t *bp; /* buffer for block */ 2332153323Srodrigc xfs_bmbt_block_t *cblock; /* child btree block */ 2333153323Srodrigc xfs_bmbt_key_t *ckp; /* child key pointer */ 2334153323Srodrigc xfs_bmbt_ptr_t *cpp; /* child ptr pointer */ 2335153323Srodrigc int error; /* error return code */ 2336153323Srodrigc#ifdef XFS_BMBT_TRACE 2337153323Srodrigc static char fname[] = "xfs_bmbt_newroot"; 2338153323Srodrigc#endif 2339153323Srodrigc#ifdef DEBUG 2340153323Srodrigc int i; /* loop counter */ 2341153323Srodrigc#endif 2342153323Srodrigc xfs_bmbt_key_t *kp; /* pointer to bmap btree key */ 2343153323Srodrigc int level; /* btree level */ 2344153323Srodrigc xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ 2345153323Srodrigc 2346153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2347153323Srodrigc level = cur->bc_nlevels - 1; 2348153323Srodrigc block = xfs_bmbt_get_block(cur, level, &bp); 2349153323Srodrigc /* 2350153323Srodrigc * Copy the root into a real block. 2351153323Srodrigc */ 2352153323Srodrigc args.mp = cur->bc_mp; 2353153323Srodrigc pp = XFS_BMAP_PTR_IADDR(block, 1, cur); 2354153323Srodrigc args.tp = cur->bc_tp; 2355153323Srodrigc args.fsbno = cur->bc_private.b.firstblock; 2356153323Srodrigc args.mod = args.minleft = args.alignment = args.total = args.isfl = 2357153323Srodrigc args.userdata = args.minalignslop = 0; 2358153323Srodrigc args.minlen = args.maxlen = args.prod = 1; 2359153323Srodrigc args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; 2360153323Srodrigc if (args.fsbno == NULLFSBLOCK) { 2361153323Srodrigc#ifdef DEBUG 2362153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { 2363153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2364153323Srodrigc return error; 2365153323Srodrigc } 2366153323Srodrigc#endif 2367153323Srodrigc args.fsbno = INT_GET(*pp, ARCH_CONVERT); 2368153323Srodrigc args.type = XFS_ALLOCTYPE_START_BNO; 2369153323Srodrigc } else if (args.wasdel) 2370153323Srodrigc args.type = XFS_ALLOCTYPE_FIRST_AG; 2371153323Srodrigc else 2372153323Srodrigc args.type = XFS_ALLOCTYPE_NEAR_BNO; 2373153323Srodrigc if ((error = xfs_alloc_vextent(&args))) { 2374153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2375153323Srodrigc return error; 2376153323Srodrigc } 2377153323Srodrigc if (args.fsbno == NULLFSBLOCK) { 2378153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2379153323Srodrigc *stat = 0; 2380153323Srodrigc return 0; 2381153323Srodrigc } 2382153323Srodrigc ASSERT(args.len == 1); 2383153323Srodrigc cur->bc_private.b.firstblock = args.fsbno; 2384153323Srodrigc cur->bc_private.b.allocated++; 2385153323Srodrigc cur->bc_private.b.ip->i_d.di_nblocks++; 2386153323Srodrigc XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, 2387153323Srodrigc XFS_TRANS_DQ_BCOUNT, 1L); 2388153323Srodrigc bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); 2389153323Srodrigc cblock = XFS_BUF_TO_BMBT_BLOCK(bp); 2390153323Srodrigc *cblock = *block; 2391159451Srodrigc be16_add(&block->bb_level, 1); 2392159451Srodrigc block->bb_numrecs = cpu_to_be16(1); 2393153323Srodrigc cur->bc_nlevels++; 2394153323Srodrigc cur->bc_ptrs[level + 1] = 1; 2395153323Srodrigc kp = XFS_BMAP_KEY_IADDR(block, 1, cur); 2396153323Srodrigc ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); 2397159451Srodrigc memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); 2398153323Srodrigc cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur); 2399153323Srodrigc#ifdef DEBUG 2400159451Srodrigc for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { 2401153323Srodrigc if ((error = xfs_btree_check_lptr(cur, INT_GET(pp[i], ARCH_CONVERT), level))) { 2402153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2403153323Srodrigc return error; 2404153323Srodrigc } 2405153323Srodrigc } 2406153323Srodrigc#endif 2407159451Srodrigc memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp)); 2408153323Srodrigc#ifdef DEBUG 2409153323Srodrigc if ((error = xfs_btree_check_lptr(cur, (xfs_bmbt_ptr_t)args.fsbno, 2410153323Srodrigc level))) { 2411153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2412153323Srodrigc return error; 2413153323Srodrigc } 2414153323Srodrigc#endif 2415153323Srodrigc INT_SET(*pp, ARCH_CONVERT, args.fsbno); 2416159451Srodrigc xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), 2417153323Srodrigc cur->bc_private.b.whichfork); 2418153323Srodrigc xfs_btree_setbuf(cur, level, bp); 2419153323Srodrigc /* 2420153323Srodrigc * Do all this logging at the end so that 2421153323Srodrigc * the root is at the right level. 2422153323Srodrigc */ 2423153323Srodrigc xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); 2424159451Srodrigc xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); 2425159451Srodrigc xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); 2426153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2427153323Srodrigc *logflags |= 2428153323Srodrigc XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); 2429153323Srodrigc *stat = 1; 2430153323Srodrigc return 0; 2431153323Srodrigc} 2432153323Srodrigc 2433153323Srodrigc/* 2434153323Srodrigc * Set all the fields in a bmap extent record from the uncompressed form. 2435153323Srodrigc */ 2436153323Srodrigcvoid 2437153323Srodrigcxfs_bmbt_set_all( 2438153323Srodrigc xfs_bmbt_rec_t *r, 2439153323Srodrigc xfs_bmbt_irec_t *s) 2440153323Srodrigc{ 2441153323Srodrigc int extent_flag; 2442153323Srodrigc 2443153323Srodrigc ASSERT((s->br_state == XFS_EXT_NORM) || 2444153323Srodrigc (s->br_state == XFS_EXT_UNWRITTEN)); 2445153323Srodrigc extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1; 2446153323Srodrigc ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0); 2447153323Srodrigc ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0); 2448153323Srodrigc#if XFS_BIG_BLKNOS 2449153323Srodrigc ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0); 2450153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2451153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9) | 2452153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startblock >> 43); 2453153323Srodrigc r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2454153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2455153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2456153323Srodrigc#else /* !XFS_BIG_BLKNOS */ 2457153323Srodrigc if (ISNULLSTARTBLOCK(s->br_startblock)) { 2458153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2459153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9) | 2460153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); 2461153323Srodrigc r->l1 = XFS_MASK64HI(11) | 2462153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2463153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2464153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2465153323Srodrigc } else { 2466153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2467153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9); 2468153323Srodrigc r->l1 = ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2469153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2470153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2471153323Srodrigc } 2472153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2473153323Srodrigc} 2474153323Srodrigc 2475153323Srodrigc/* 2476153323Srodrigc * Set all the fields in a bmap extent record from the arguments. 2477153323Srodrigc */ 2478153323Srodrigcvoid 2479153323Srodrigcxfs_bmbt_set_allf( 2480153323Srodrigc xfs_bmbt_rec_t *r, 2481153323Srodrigc xfs_fileoff_t o, 2482153323Srodrigc xfs_fsblock_t b, 2483153323Srodrigc xfs_filblks_t c, 2484153323Srodrigc xfs_exntst_t v) 2485153323Srodrigc{ 2486153323Srodrigc int extent_flag; 2487153323Srodrigc 2488153323Srodrigc ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN)); 2489153323Srodrigc extent_flag = (v == XFS_EXT_NORM) ? 0 : 1; 2490153323Srodrigc ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); 2491153323Srodrigc ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); 2492153323Srodrigc#if XFS_BIG_BLKNOS 2493153323Srodrigc ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); 2494153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2495153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9) | 2496153323Srodrigc ((xfs_bmbt_rec_base_t)b >> 43); 2497153323Srodrigc r->l1 = ((xfs_bmbt_rec_base_t)b << 21) | 2498153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2499153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2500153323Srodrigc#else /* !XFS_BIG_BLKNOS */ 2501153323Srodrigc if (ISNULLSTARTBLOCK(b)) { 2502153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2503153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9) | 2504153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); 2505153323Srodrigc r->l1 = XFS_MASK64HI(11) | 2506153323Srodrigc ((xfs_bmbt_rec_base_t)b << 21) | 2507153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2508153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2509153323Srodrigc } else { 2510153323Srodrigc r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2511153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9); 2512153323Srodrigc r->l1 = ((xfs_bmbt_rec_base_t)b << 21) | 2513153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2514153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2515153323Srodrigc } 2516153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2517153323Srodrigc} 2518153323Srodrigc 2519159451Srodrigc#ifndef XFS_NATIVE_HOST 2520153323Srodrigc/* 2521153323Srodrigc * Set all the fields in a bmap extent record from the uncompressed form. 2522153323Srodrigc */ 2523153323Srodrigcvoid 2524153323Srodrigcxfs_bmbt_disk_set_all( 2525153323Srodrigc xfs_bmbt_rec_t *r, 2526153323Srodrigc xfs_bmbt_irec_t *s) 2527153323Srodrigc{ 2528153323Srodrigc int extent_flag; 2529153323Srodrigc 2530153323Srodrigc ASSERT((s->br_state == XFS_EXT_NORM) || 2531153323Srodrigc (s->br_state == XFS_EXT_UNWRITTEN)); 2532153323Srodrigc extent_flag = (s->br_state == XFS_EXT_NORM) ? 0 : 1; 2533153323Srodrigc ASSERT((s->br_startoff & XFS_MASK64HI(9)) == 0); 2534153323Srodrigc ASSERT((s->br_blockcount & XFS_MASK64HI(43)) == 0); 2535153323Srodrigc#if XFS_BIG_BLKNOS 2536153323Srodrigc ASSERT((s->br_startblock & XFS_MASK64HI(12)) == 0); 2537153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2538153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9) | 2539153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startblock >> 43)); 2540153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2541153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2542153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2543153323Srodrigc#else /* !XFS_BIG_BLKNOS */ 2544153323Srodrigc if (ISNULLSTARTBLOCK(s->br_startblock)) { 2545153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2546153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9) | 2547153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); 2548153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) | 2549153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2550153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2551153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2552153323Srodrigc } else { 2553153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2554153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_startoff << 9)); 2555153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)s->br_startblock << 21) | 2556153323Srodrigc ((xfs_bmbt_rec_base_t)s->br_blockcount & 2557153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2558153323Srodrigc } 2559153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2560153323Srodrigc} 2561153323Srodrigc 2562153323Srodrigc/* 2563153323Srodrigc * Set all the fields in a disk format bmap extent record from the arguments. 2564153323Srodrigc */ 2565153323Srodrigcvoid 2566153323Srodrigcxfs_bmbt_disk_set_allf( 2567153323Srodrigc xfs_bmbt_rec_t *r, 2568153323Srodrigc xfs_fileoff_t o, 2569153323Srodrigc xfs_fsblock_t b, 2570153323Srodrigc xfs_filblks_t c, 2571153323Srodrigc xfs_exntst_t v) 2572153323Srodrigc{ 2573153323Srodrigc int extent_flag; 2574153323Srodrigc 2575153323Srodrigc ASSERT((v == XFS_EXT_NORM) || (v == XFS_EXT_UNWRITTEN)); 2576153323Srodrigc extent_flag = (v == XFS_EXT_NORM) ? 0 : 1; 2577153323Srodrigc ASSERT((o & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); 2578153323Srodrigc ASSERT((c & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0); 2579153323Srodrigc#if XFS_BIG_BLKNOS 2580153323Srodrigc ASSERT((b & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); 2581153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2582153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9) | 2583153323Srodrigc ((xfs_bmbt_rec_base_t)b >> 43)); 2584153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) | 2585153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2586153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2587153323Srodrigc#else /* !XFS_BIG_BLKNOS */ 2588153323Srodrigc if (ISNULLSTARTBLOCK(b)) { 2589153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2590153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9) | 2591153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); 2592153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, XFS_MASK64HI(11) | 2593153323Srodrigc ((xfs_bmbt_rec_base_t)b << 21) | 2594153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2595153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2596153323Srodrigc } else { 2597153323Srodrigc INT_SET(r->l0, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)extent_flag << 63) | 2598153323Srodrigc ((xfs_bmbt_rec_base_t)o << 9)); 2599153323Srodrigc INT_SET(r->l1, ARCH_CONVERT, ((xfs_bmbt_rec_base_t)b << 21) | 2600153323Srodrigc ((xfs_bmbt_rec_base_t)c & 2601153323Srodrigc (xfs_bmbt_rec_base_t)XFS_MASK64LO(21))); 2602153323Srodrigc } 2603153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2604153323Srodrigc} 2605159451Srodrigc#endif /* XFS_NATIVE_HOST */ 2606153323Srodrigc 2607153323Srodrigc/* 2608153323Srodrigc * Set the blockcount field in a bmap extent record. 2609153323Srodrigc */ 2610153323Srodrigcvoid 2611153323Srodrigcxfs_bmbt_set_blockcount( 2612153323Srodrigc xfs_bmbt_rec_t *r, 2613153323Srodrigc xfs_filblks_t v) 2614153323Srodrigc{ 2615153323Srodrigc ASSERT((v & XFS_MASK64HI(43)) == 0); 2616153323Srodrigc r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(43)) | 2617153323Srodrigc (xfs_bmbt_rec_base_t)(v & XFS_MASK64LO(21)); 2618153323Srodrigc} 2619153323Srodrigc 2620153323Srodrigc/* 2621153323Srodrigc * Set the startblock field in a bmap extent record. 2622153323Srodrigc */ 2623153323Srodrigcvoid 2624153323Srodrigcxfs_bmbt_set_startblock( 2625153323Srodrigc xfs_bmbt_rec_t *r, 2626153323Srodrigc xfs_fsblock_t v) 2627153323Srodrigc{ 2628153323Srodrigc#if XFS_BIG_BLKNOS 2629153323Srodrigc ASSERT((v & XFS_MASK64HI(12)) == 0); 2630153323Srodrigc r->l0 = (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64HI(55)) | 2631153323Srodrigc (xfs_bmbt_rec_base_t)(v >> 43); 2632153323Srodrigc r->l1 = (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)) | 2633153323Srodrigc (xfs_bmbt_rec_base_t)(v << 21); 2634153323Srodrigc#else /* !XFS_BIG_BLKNOS */ 2635153323Srodrigc if (ISNULLSTARTBLOCK(v)) { 2636153323Srodrigc r->l0 |= (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); 2637153323Srodrigc r->l1 = (xfs_bmbt_rec_base_t)XFS_MASK64HI(11) | 2638153323Srodrigc ((xfs_bmbt_rec_base_t)v << 21) | 2639153323Srodrigc (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2640153323Srodrigc } else { 2641153323Srodrigc r->l0 &= ~(xfs_bmbt_rec_base_t)XFS_MASK64LO(9); 2642153323Srodrigc r->l1 = ((xfs_bmbt_rec_base_t)v << 21) | 2643153323Srodrigc (r->l1 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); 2644153323Srodrigc } 2645153323Srodrigc#endif /* XFS_BIG_BLKNOS */ 2646153323Srodrigc} 2647153323Srodrigc 2648153323Srodrigc/* 2649153323Srodrigc * Set the startoff field in a bmap extent record. 2650153323Srodrigc */ 2651153323Srodrigcvoid 2652153323Srodrigcxfs_bmbt_set_startoff( 2653153323Srodrigc xfs_bmbt_rec_t *r, 2654153323Srodrigc xfs_fileoff_t v) 2655153323Srodrigc{ 2656153323Srodrigc ASSERT((v & XFS_MASK64HI(9)) == 0); 2657153323Srodrigc r->l0 = (r->l0 & (xfs_bmbt_rec_base_t) XFS_MASK64HI(1)) | 2658153323Srodrigc ((xfs_bmbt_rec_base_t)v << 9) | 2659153323Srodrigc (r->l0 & (xfs_bmbt_rec_base_t)XFS_MASK64LO(9)); 2660153323Srodrigc} 2661153323Srodrigc 2662153323Srodrigc/* 2663153323Srodrigc * Set the extent state field in a bmap extent record. 2664153323Srodrigc */ 2665153323Srodrigcvoid 2666153323Srodrigcxfs_bmbt_set_state( 2667153323Srodrigc xfs_bmbt_rec_t *r, 2668153323Srodrigc xfs_exntst_t v) 2669153323Srodrigc{ 2670153323Srodrigc ASSERT(v == XFS_EXT_NORM || v == XFS_EXT_UNWRITTEN); 2671153323Srodrigc if (v == XFS_EXT_NORM) 2672153323Srodrigc r->l0 &= XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN); 2673153323Srodrigc else 2674153323Srodrigc r->l0 |= XFS_MASK64HI(BMBT_EXNTFLAG_BITLEN); 2675153323Srodrigc} 2676153323Srodrigc 2677153323Srodrigc/* 2678153323Srodrigc * Convert in-memory form of btree root to on-disk form. 2679153323Srodrigc */ 2680153323Srodrigcvoid 2681153323Srodrigcxfs_bmbt_to_bmdr( 2682153323Srodrigc xfs_bmbt_block_t *rblock, 2683153323Srodrigc int rblocklen, 2684153323Srodrigc xfs_bmdr_block_t *dblock, 2685153323Srodrigc int dblocklen) 2686153323Srodrigc{ 2687153323Srodrigc int dmxr; 2688153323Srodrigc xfs_bmbt_key_t *fkp; 2689153323Srodrigc xfs_bmbt_ptr_t *fpp; 2690153323Srodrigc xfs_bmbt_key_t *tkp; 2691153323Srodrigc xfs_bmbt_ptr_t *tpp; 2692153323Srodrigc 2693159451Srodrigc ASSERT(be32_to_cpu(rblock->bb_magic) == XFS_BMAP_MAGIC); 2694159451Srodrigc ASSERT(be64_to_cpu(rblock->bb_leftsib) == NULLDFSBNO); 2695159451Srodrigc ASSERT(be64_to_cpu(rblock->bb_rightsib) == NULLDFSBNO); 2696159451Srodrigc ASSERT(be16_to_cpu(rblock->bb_level) > 0); 2697159451Srodrigc dblock->bb_level = rblock->bb_level; 2698159451Srodrigc dblock->bb_numrecs = rblock->bb_numrecs; 2699153323Srodrigc dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); 2700153323Srodrigc fkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); 2701153323Srodrigc tkp = XFS_BTREE_KEY_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); 2702153323Srodrigc fpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); 2703153323Srodrigc tpp = XFS_BTREE_PTR_ADDR(dblocklen, xfs_bmdr, dblock, 1, dmxr); 2704159451Srodrigc dmxr = be16_to_cpu(dblock->bb_numrecs); 2705153323Srodrigc memcpy(tkp, fkp, sizeof(*fkp) * dmxr); 2706153323Srodrigc memcpy(tpp, fpp, sizeof(*fpp) * dmxr); /* INT_: direct copy */ 2707153323Srodrigc} 2708153323Srodrigc 2709153323Srodrigc/* 2710153323Srodrigc * Update the record to the passed values. 2711153323Srodrigc */ 2712153323Srodrigcint 2713153323Srodrigcxfs_bmbt_update( 2714153323Srodrigc xfs_btree_cur_t *cur, 2715153323Srodrigc xfs_fileoff_t off, 2716153323Srodrigc xfs_fsblock_t bno, 2717153323Srodrigc xfs_filblks_t len, 2718153323Srodrigc xfs_exntst_t state) 2719153323Srodrigc{ 2720153323Srodrigc xfs_bmbt_block_t *block; 2721153323Srodrigc xfs_buf_t *bp; 2722153323Srodrigc int error; 2723153323Srodrigc#ifdef XFS_BMBT_TRACE 2724153323Srodrigc static char fname[] = "xfs_bmbt_update"; 2725153323Srodrigc#endif 2726153323Srodrigc xfs_bmbt_key_t key; 2727153323Srodrigc int ptr; 2728153323Srodrigc xfs_bmbt_rec_t *rp; 2729153323Srodrigc 2730153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ENTRY); 2731153323Srodrigc XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno, 2732153323Srodrigc (xfs_dfilblks_t)len, (int)state); 2733153323Srodrigc block = xfs_bmbt_get_block(cur, 0, &bp); 2734153323Srodrigc#ifdef DEBUG 2735153323Srodrigc if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) { 2736153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2737153323Srodrigc return error; 2738153323Srodrigc } 2739153323Srodrigc#endif 2740153323Srodrigc ptr = cur->bc_ptrs[0]; 2741153323Srodrigc rp = XFS_BMAP_REC_IADDR(block, ptr, cur); 2742153323Srodrigc xfs_bmbt_disk_set_allf(rp, off, bno, len, state); 2743153323Srodrigc xfs_bmbt_log_recs(cur, bp, ptr, ptr); 2744153323Srodrigc if (ptr > 1) { 2745153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2746153323Srodrigc return 0; 2747153323Srodrigc } 2748153323Srodrigc INT_SET(key.br_startoff, ARCH_CONVERT, off); 2749153323Srodrigc if ((error = xfs_bmbt_updkey(cur, &key, 1))) { 2750153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, ERROR); 2751153323Srodrigc return error; 2752153323Srodrigc } 2753153323Srodrigc XFS_BMBT_TRACE_CURSOR(cur, EXIT); 2754153323Srodrigc return 0; 2755153323Srodrigc} 2756153323Srodrigc 2757153323Srodrigc/* 2758159451Srodrigc * Check extent records, which have just been read, for 2759153323Srodrigc * any bit in the extent flag field. ASSERT on debug 2760153323Srodrigc * kernels, as this condition should not occur. 2761153323Srodrigc * Return an error condition (1) if any flags found, 2762153323Srodrigc * otherwise return 0. 2763153323Srodrigc */ 2764153323Srodrigc 2765153323Srodrigcint 2766153323Srodrigcxfs_check_nostate_extents( 2767159451Srodrigc xfs_ifork_t *ifp, 2768159451Srodrigc xfs_extnum_t idx, 2769153323Srodrigc xfs_extnum_t num) 2770153323Srodrigc{ 2771159451Srodrigc xfs_bmbt_rec_t *ep; 2772159451Srodrigc 2773159451Srodrigc for (; num > 0; num--, idx++) { 2774159451Srodrigc ep = xfs_iext_get_ext(ifp, idx); 2775153323Srodrigc if ((ep->l0 >> 2776153323Srodrigc (64 - BMBT_EXNTFLAG_BITLEN)) != 0) { 2777153323Srodrigc ASSERT(0); 2778153323Srodrigc return 1; 2779153323Srodrigc } 2780153323Srodrigc } 2781153323Srodrigc return 0; 2782153323Srodrigc} 2783