📄 xfs_bmap_btree.c
字号:
XFS_BMBT_TRACE_CURSOR(tcur, ERROR); goto error1; } xfs_btree_del_cursor(tcur, XFS_BTREE_NOERROR); XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;error0: XFS_BMBT_TRACE_CURSOR(cur, ERROR);error1: xfs_btree_del_cursor(tcur, XFS_BTREE_ERROR); return error;}/* * Determine the extent state. *//* ARGSUSED */STATIC xfs_exntst_txfs_extent_state( xfs_filblks_t blks, int extent_flag){ if (extent_flag) { ASSERT(blks != 0); /* saved for DMIG */ return XFS_EXT_UNWRITTEN; } return XFS_EXT_NORM;}/* * Split cur/level block in half. * Return new block number and its first record (to be inserted into parent). */STATIC int /* error */xfs_bmbt_split( xfs_btree_cur_t *cur, int level, xfs_fsblock_t *bnop, __uint64_t *startoff, xfs_btree_cur_t **curp, int *stat) /* success/failure */{ xfs_alloc_arg_t args; /* block allocation args */ int error; /* error return value */ int i; /* loop counter */ xfs_fsblock_t lbno; /* left sibling block number */ xfs_buf_t *lbp; /* left buffer pointer */ xfs_bmbt_block_t *left; /* left btree block */ xfs_bmbt_key_t *lkp; /* left btree key */ xfs_bmbt_ptr_t *lpp; /* left address pointer */ xfs_bmbt_rec_t *lrp; /* left record pointer */ xfs_buf_t *rbp; /* right buffer pointer */ xfs_bmbt_block_t *right; /* right btree block */ xfs_bmbt_key_t *rkp; /* right btree key */ xfs_bmbt_ptr_t *rpp; /* right address pointer */ xfs_bmbt_block_t *rrblock; /* right-right btree block */ xfs_buf_t *rrbp; /* right-right buffer pointer */ xfs_bmbt_rec_t *rrp; /* right record pointer */ XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGIFK(cur, level, *bnop, *startoff); args.tp = cur->bc_tp; args.mp = cur->bc_mp; lbp = cur->bc_bufs[level]; lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); left = XFS_BUF_TO_BMBT_BLOCK(lbp); args.fsbno = cur->bc_private.b.firstblock; args.firstblock = args.fsbno; if (args.fsbno == NULLFSBLOCK) { args.fsbno = lbno; args.type = XFS_ALLOCTYPE_START_BNO; } else args.type = XFS_ALLOCTYPE_NEAR_BNO; args.mod = args.minleft = args.alignment = args.total = args.isfl = args.userdata = args.minalignslop = 0; args.minlen = args.maxlen = args.prod = 1; args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; if (!args.wasdel && xfs_trans_get_block_res(args.tp) == 0) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return XFS_ERROR(ENOSPC); } if ((error = xfs_alloc_vextent(&args))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } if (args.fsbno == NULLFSBLOCK) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } ASSERT(args.len == 1); cur->bc_private.b.firstblock = args.fsbno; cur->bc_private.b.allocated++; cur->bc_private.b.ip->i_d.di_nblocks++; xfs_trans_log_inode(args.tp, cur->bc_private.b.ip, XFS_ILOG_CORE); XFS_TRANS_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, 1L); rbp = xfs_btree_get_bufl(args.mp, args.tp, args.fsbno, 0); right = XFS_BUF_TO_BMBT_BLOCK(rbp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, left, level, rbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif right->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); right->bb_level = left->bb_level; right->bb_numrecs = cpu_to_be16(be16_to_cpu(left->bb_numrecs) / 2); if ((be16_to_cpu(left->bb_numrecs) & 1) && cur->bc_ptrs[level] <= be16_to_cpu(right->bb_numrecs) + 1) be16_add(&right->bb_numrecs, 1); i = be16_to_cpu(left->bb_numrecs) - be16_to_cpu(right->bb_numrecs) + 1; if (level > 0) { lkp = XFS_BMAP_KEY_IADDR(left, i, cur); lpp = XFS_BMAP_PTR_IADDR(left, i, cur); rkp = XFS_BMAP_KEY_IADDR(right, 1, cur); rpp = XFS_BMAP_PTR_IADDR(right, 1, cur);#ifdef DEBUG for (i = 0; i < be16_to_cpu(right->bb_numrecs); i++) { if ((error = xfs_btree_check_lptr_disk(cur, lpp[i], level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memcpy(rkp, lkp, be16_to_cpu(right->bb_numrecs) * sizeof(*rkp)); memcpy(rpp, lpp, be16_to_cpu(right->bb_numrecs) * sizeof(*rpp)); xfs_bmbt_log_keys(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); xfs_bmbt_log_ptrs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); *startoff = be64_to_cpu(rkp->br_startoff); } else { lrp = XFS_BMAP_REC_IADDR(left, i, cur); rrp = XFS_BMAP_REC_IADDR(right, 1, cur); memcpy(rrp, lrp, be16_to_cpu(right->bb_numrecs) * sizeof(*rrp)); xfs_bmbt_log_recs(cur, rbp, 1, be16_to_cpu(right->bb_numrecs)); *startoff = xfs_bmbt_disk_get_startoff(rrp); } be16_add(&left->bb_numrecs, -(be16_to_cpu(right->bb_numrecs))); right->bb_rightsib = left->bb_rightsib; left->bb_rightsib = cpu_to_be64(args.fsbno); right->bb_leftsib = cpu_to_be64(lbno); xfs_bmbt_log_block(cur, rbp, XFS_BB_ALL_BITS); xfs_bmbt_log_block(cur, lbp, XFS_BB_NUMRECS | XFS_BB_RIGHTSIB); if (be64_to_cpu(right->bb_rightsib) != NULLDFSBNO) { if ((error = xfs_btree_read_bufl(args.mp, args.tp, be64_to_cpu(right->bb_rightsib), 0, &rrbp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } rrblock = XFS_BUF_TO_BMBT_BLOCK(rrbp); if ((error = xfs_btree_check_lblock(cur, rrblock, level, rrbp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } rrblock->bb_leftsib = cpu_to_be64(args.fsbno); xfs_bmbt_log_block(cur, rrbp, XFS_BB_LEFTSIB); } if (cur->bc_ptrs[level] > be16_to_cpu(left->bb_numrecs) + 1) { xfs_btree_setbuf(cur, level, rbp); cur->bc_ptrs[level] -= be16_to_cpu(left->bb_numrecs); } if (level + 1 < cur->bc_nlevels) { if ((error = xfs_btree_dup_cursor(cur, curp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } (*curp)->bc_ptrs[level + 1]++; } *bnop = args.fsbno; XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Update keys for the record. */STATIC intxfs_bmbt_updkey( xfs_btree_cur_t *cur, xfs_bmbt_key_t *keyp, /* on-disk format */ int level){ xfs_bmbt_block_t *block; xfs_buf_t *bp;#ifdef DEBUG int error;#endif xfs_bmbt_key_t *kp; int ptr; ASSERT(level >= 1); XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGIK(cur, level, keyp); for (ptr = 1; ptr == 1 && level < cur->bc_nlevels; level++) { block = xfs_bmbt_get_block(cur, level, &bp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif ptr = cur->bc_ptrs[level]; kp = XFS_BMAP_KEY_IADDR(block, ptr, cur); *kp = *keyp; xfs_bmbt_log_keys(cur, bp, ptr, ptr); } XFS_BMBT_TRACE_CURSOR(cur, EXIT); return 0;}/* * Convert on-disk form of btree root to in-memory form. */voidxfs_bmdr_to_bmbt( xfs_bmdr_block_t *dblock, int dblocklen, xfs_bmbt_block_t *rblock, int rblocklen){ int dmxr; xfs_bmbt_key_t *fkp; __be64 *fpp; xfs_bmbt_key_t *tkp; __be64 *tpp; rblock->bb_magic = cpu_to_be32(XFS_BMAP_MAGIC); rblock->bb_level = dblock->bb_level; ASSERT(be16_to_cpu(rblock->bb_level) > 0); rblock->bb_numrecs = dblock->bb_numrecs; rblock->bb_leftsib = cpu_to_be64(NULLDFSBNO); rblock->bb_rightsib = cpu_to_be64(NULLDFSBNO); dmxr = (int)XFS_BTREE_BLOCK_MAXRECS(dblocklen, xfs_bmdr, 0); fkp = XFS_BTREE_KEY_ADDR(xfs_bmdr, dblock, 1); tkp = XFS_BMAP_BROOT_KEY_ADDR(rblock, 1, rblocklen); fpp = XFS_BTREE_PTR_ADDR(xfs_bmdr, dblock, 1, dmxr); tpp = XFS_BMAP_BROOT_PTR_ADDR(rblock, 1, rblocklen); dmxr = be16_to_cpu(dblock->bb_numrecs); memcpy(tkp, fkp, sizeof(*fkp) * dmxr); memcpy(tpp, fpp, sizeof(*fpp) * dmxr);}/* * Decrement cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_bmbt_decrement( xfs_btree_cur_t *cur, int level, int *stat) /* success/failure */{ xfs_bmbt_block_t *block; xfs_buf_t *bp; int error; /* error return value */ xfs_fsblock_t fsbno; int lev; xfs_mount_t *mp; xfs_trans_t *tp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGI(cur, level); ASSERT(level < cur->bc_nlevels); if (level < cur->bc_nlevels - 1) xfs_btree_readahead(cur, level, XFS_BTCUR_LEFTRA); if (--cur->bc_ptrs[level] > 0) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0; } block = xfs_bmbt_get_block(cur, level, &bp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, block, level, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif if (be64_to_cpu(block->bb_leftsib) == NULLDFSBNO) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } for (lev = level + 1; lev < cur->bc_nlevels; lev++) { if (--cur->bc_ptrs[lev] > 0) break; if (lev < cur->bc_nlevels - 1) xfs_btree_readahead(cur, lev, XFS_BTCUR_LEFTRA); } if (lev == cur->bc_nlevels) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } tp = cur->bc_tp; mp = cur->bc_mp; for (block = xfs_bmbt_get_block(cur, lev, &bp); lev > level; ) { fsbno = be64_to_cpu(*XFS_BMAP_PTR_IADDR(block, cur->bc_ptrs[lev], cur)); if ((error = xfs_btree_read_bufl(mp, tp, fsbno, 0, &bp, XFS_BMAP_BTREE_REF))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } lev--; xfs_btree_setbuf(cur, lev, bp); block = XFS_BUF_TO_BMBT_BLOCK(bp); if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } cur->bc_ptrs[lev] = be16_to_cpu(block->bb_numrecs); } XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Delete the record pointed to by cur. */int /* error */xfs_bmbt_delete( xfs_btree_cur_t *cur, int *stat) /* success/failure */{ int error; /* error return value */ int i; int level; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); for (level = 0, i = 2; i == 2; level++) { if ((error = xfs_bmbt_delrec(cur, level, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } } if (i == 0) { for (level = 1; level < cur->bc_nlevels; level++) { if (cur->bc_ptrs[level] == 0) { if ((error = xfs_bmbt_decrement(cur, level, &i))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } break; } } } XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = i; return 0;}/* * Convert a compressed bmap extent record to an uncompressed form. * This code must be in sync with the routines xfs_bmbt_get_startoff, * xfs_bmbt_get_startblock, xfs_bmbt_get_blockcount and xfs_bmbt_get_state. */STATIC_INLINE void__xfs_bmbt_get_all( __uint64_t l0, __uint64_t l1, xfs_bmbt_irec_t *s){ int ext_flag; xfs_exntst_t st; ext_flag = (int)(l0 >> (64 - BMBT_EXNTFLAG_BITLEN)); s->br_startoff = ((xfs_fileoff_t)l0 & XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;#if XFS_BIG_BLKNOS s->br_startblock = (((xfs_fsblock_t)l0 & XFS_MASK64LO(9)) << 43) | (((xfs_fsblock_t)l1) >> 21);#else#ifdef DEBUG { xfs_dfsbno_t b; b = (((xfs_dfsbno_t)l0 & XFS_MASK64LO(9)) << 43) | (((xfs_dfsbno_t)l1) >> 21); ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); s->br_startblock = (xfs_fsblock_t)b; }#else /* !DEBUG */ s->br_startblock = (xfs_fsblock_t)(((xfs_dfsbno_t)l1) >> 21);#endif /* DEBUG */#endif /* XFS_BIG_BLKNOS */ s->br_blockcount = (xfs_filblks_t)(l1 & XFS_MASK64LO(21)); /* This is xfs_extent_state() in-line */ if (ext_flag) { ASSERT(s->br_blockcount != 0); /* saved for DMIG */ st = XFS_EXT_UNWRITTEN; } else st = XFS_EXT_NORM; s->br_state = st;}voidxfs_bmbt_get_all( xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s){ __xfs_bmbt_get_all(r->l0, r->l1, s);}/* * Get the block pointer for the given level of the cursor. * Fill in the buffer pointer, if applicable. */xfs_bmbt_block_t *xfs_bmbt_get_block( xfs_btree_cur_t *cur, int level, xfs_buf_t **bpp){ xfs_ifork_t *ifp; xfs_bmbt_block_t *rval; if (level < cur->bc_nlevels - 1) { *bpp = cur->bc_bufs[level]; rval = XFS_BUF_TO_BMBT_BLOCK(*bpp); } else { *bpp = NULL; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, cur->bc_private.b.whichfork); rval = ifp->if_broot; } return rval;}/* * Extract the blockcount field from an in memory bmap extent record. */xfs_filblks_txfs_bmbt_get_blockcount( xfs_bmbt_rec_host_t *r){ return (xfs_filblks_t)(r->l1 & XFS_MASK64LO(21));}/* * Extract the startblock field from an in memory bmap extent record. */xfs_fsblock_txfs_bmbt_get_startblock( xfs_bmbt_rec_host_t *r){#if XFS_BIG_BLKNOS return (((xfs_fsblock_t)r->l0 & XFS_MASK64LO(9)) << 43) | (((xfs_fsblock_t)r->l1) >> 21);#else#ifdef DEBUG xfs_dfsbno_t b; b = (((xfs_dfsbno_t)r->l0 & XFS_MASK64LO(9)) << 43) | (((xfs_dfsbno_t)r->l1) >> 21); ASSERT((b >> 32) == 0 || ISNULLDSTARTBLOCK(b)); return (xfs_fsblock_t)b;#else /* !DEBUG */ return (xfs_fsblock_t)(((xfs_dfsbno_t)r->l1) >> 21);#endif /* DEBUG */#endif /* XFS_BIG_BLKNOS */}/* * Extract the startoff field from an in memory bmap extent record. */xfs_fileoff_txfs_bmbt_get_startoff( xfs_bmbt_rec_host_t *r)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -