📄 xfs_bmap_btree.c
字号:
{ return ((xfs_fileoff_t)r->l0 & XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;}xfs_exntst_txfs_bmbt_get_state( xfs_bmbt_rec_host_t *r){ int ext_flag; ext_flag = (int)((r->l0) >> (64 - BMBT_EXNTFLAG_BITLEN)); return xfs_extent_state(xfs_bmbt_get_blockcount(r), ext_flag);}/* Endian flipping versions of the bmbt extraction functions */voidxfs_bmbt_disk_get_all( xfs_bmbt_rec_t *r, xfs_bmbt_irec_t *s){ __xfs_bmbt_get_all(be64_to_cpu(r->l0), be64_to_cpu(r->l1), s);}/* * Extract the blockcount field from an on disk bmap extent record. */xfs_filblks_txfs_bmbt_disk_get_blockcount( xfs_bmbt_rec_t *r){ return (xfs_filblks_t)(be64_to_cpu(r->l1) & XFS_MASK64LO(21));}/* * Extract the startoff field from a disk format bmap extent record. */xfs_fileoff_txfs_bmbt_disk_get_startoff( xfs_bmbt_rec_t *r){ return ((xfs_fileoff_t)be64_to_cpu(r->l0) & XFS_MASK64LO(64 - BMBT_EXNTFLAG_BITLEN)) >> 9;}/* * Increment cursor by one record at the level. * For nonzero levels the leaf-ward information is untouched. */int /* error */xfs_bmbt_increment( 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_RIGHTRA); 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 (++cur->bc_ptrs[level] <= be16_to_cpu(block->bb_numrecs)) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0; } if (be64_to_cpu(block->bb_rightsib) == NULLDFSBNO) { XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 0; return 0; } for (lev = level + 1; lev < cur->bc_nlevels; lev++) { block = xfs_bmbt_get_block(cur, lev, &bp);#ifdef DEBUG if ((error = xfs_btree_check_lblock(cur, block, lev, bp))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif if (++cur->bc_ptrs[lev] <= be16_to_cpu(block->bb_numrecs)) break; if (lev < cur->bc_nlevels - 1) xfs_btree_readahead(cur, lev, XFS_BTCUR_RIGHTRA); } 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] = 1; } XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = 1; return 0;}/* * Insert the current record at the point referenced by cur. */int /* error */xfs_bmbt_insert( xfs_btree_cur_t *cur, int *stat) /* success/failure */{ int error; /* error return value */ int i; int level; xfs_fsblock_t nbno; xfs_btree_cur_t *ncur; xfs_bmbt_rec_t nrec; xfs_btree_cur_t *pcur; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); level = 0; nbno = NULLFSBLOCK; xfs_bmbt_disk_set_all(&nrec, &cur->bc_rec.b); ncur = NULL; pcur = cur; do { if ((error = xfs_bmbt_insrec(pcur, level++, &nbno, &nrec, &ncur, &i))) { if (pcur != cur) xfs_btree_del_cursor(pcur, XFS_BTREE_ERROR); XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } XFS_WANT_CORRUPTED_GOTO(i == 1, error0); if (pcur != cur && (ncur || nbno == NULLFSBLOCK)) { cur->bc_nlevels = pcur->bc_nlevels; cur->bc_private.b.allocated += pcur->bc_private.b.allocated; pcur->bc_private.b.allocated = 0; ASSERT((cur->bc_private.b.firstblock != NULLFSBLOCK) || (cur->bc_private.b.ip->i_d.di_flags & XFS_DIFLAG_REALTIME)); cur->bc_private.b.firstblock = pcur->bc_private.b.firstblock; ASSERT(cur->bc_private.b.flist == pcur->bc_private.b.flist); xfs_btree_del_cursor(pcur, XFS_BTREE_NOERROR); } if (ncur) { pcur = ncur; ncur = NULL; } } while (nbno != NULLFSBLOCK); XFS_BMBT_TRACE_CURSOR(cur, EXIT); *stat = i; return 0;error0: XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error;}/* * Log fields from the btree block header. */voidxfs_bmbt_log_block( xfs_btree_cur_t *cur, xfs_buf_t *bp, int fields){ int first; int last; xfs_trans_t *tp; static const short offsets[] = { offsetof(xfs_bmbt_block_t, bb_magic), offsetof(xfs_bmbt_block_t, bb_level), offsetof(xfs_bmbt_block_t, bb_numrecs), offsetof(xfs_bmbt_block_t, bb_leftsib), offsetof(xfs_bmbt_block_t, bb_rightsib), sizeof(xfs_bmbt_block_t) }; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGBI(cur, bp, fields); tp = cur->bc_tp; if (bp) { xfs_btree_offsets(fields, offsets, XFS_BB_NUM_BITS, &first, &last); xfs_trans_log_buf(tp, bp, first, last); } else xfs_trans_log_inode(tp, cur->bc_private.b.ip, XFS_ILOG_FBROOT(cur->bc_private.b.whichfork)); XFS_BMBT_TRACE_CURSOR(cur, EXIT);}/* * Log record values from the btree block. */voidxfs_bmbt_log_recs( xfs_btree_cur_t *cur, xfs_buf_t *bp, int rfirst, int rlast){ xfs_bmbt_block_t *block; int first; int last; xfs_bmbt_rec_t *rp; xfs_trans_t *tp; XFS_BMBT_TRACE_CURSOR(cur, ENTRY); XFS_BMBT_TRACE_ARGBII(cur, bp, rfirst, rlast); ASSERT(bp); tp = cur->bc_tp; block = XFS_BUF_TO_BMBT_BLOCK(bp); rp = XFS_BMAP_REC_DADDR(block, 1, cur); first = (int)((xfs_caddr_t)&rp[rfirst - 1] - (xfs_caddr_t)block); last = (int)(((xfs_caddr_t)&rp[rlast] - 1) - (xfs_caddr_t)block); xfs_trans_log_buf(tp, bp, first, last); XFS_BMBT_TRACE_CURSOR(cur, EXIT);}int /* error */xfs_bmbt_lookup_eq( xfs_btree_cur_t *cur, xfs_fileoff_t off, xfs_fsblock_t bno, xfs_filblks_t len, int *stat) /* success/failure */{ cur->bc_rec.b.br_startoff = off; cur->bc_rec.b.br_startblock = bno; cur->bc_rec.b.br_blockcount = len; return xfs_bmbt_lookup(cur, XFS_LOOKUP_EQ, stat);}int /* error */xfs_bmbt_lookup_ge( xfs_btree_cur_t *cur, xfs_fileoff_t off, xfs_fsblock_t bno, xfs_filblks_t len, int *stat) /* success/failure */{ cur->bc_rec.b.br_startoff = off; cur->bc_rec.b.br_startblock = bno; cur->bc_rec.b.br_blockcount = len; return xfs_bmbt_lookup(cur, XFS_LOOKUP_GE, stat);}/* * Give the bmap btree a new root block. Copy the old broot contents * down into a real block and make the broot point to it. */int /* error */xfs_bmbt_newroot( xfs_btree_cur_t *cur, /* btree cursor */ int *logflags, /* logging flags for inode */ int *stat) /* return status - 0 fail */{ xfs_alloc_arg_t args; /* allocation arguments */ xfs_bmbt_block_t *block; /* bmap btree block */ xfs_buf_t *bp; /* buffer for block */ xfs_bmbt_block_t *cblock; /* child btree block */ xfs_bmbt_key_t *ckp; /* child key pointer */ xfs_bmbt_ptr_t *cpp; /* child ptr pointer */ int error; /* error return code */#ifdef DEBUG int i; /* loop counter */#endif xfs_bmbt_key_t *kp; /* pointer to bmap btree key */ int level; /* btree level */ xfs_bmbt_ptr_t *pp; /* pointer to bmap block addr */ XFS_BMBT_TRACE_CURSOR(cur, ENTRY); level = cur->bc_nlevels - 1; block = xfs_bmbt_get_block(cur, level, &bp); /* * Copy the root into a real block. */ args.mp = cur->bc_mp; pp = XFS_BMAP_PTR_IADDR(block, 1, cur); args.tp = cur->bc_tp; args.fsbno = cur->bc_private.b.firstblock; 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; args.firstblock = args.fsbno; if (args.fsbno == NULLFSBLOCK) {#ifdef DEBUG if ((error = xfs_btree_check_lptr_disk(cur, *pp, level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif args.fsbno = be64_to_cpu(*pp); args.type = XFS_ALLOCTYPE_START_BNO; } else args.type = XFS_ALLOCTYPE_NEAR_BNO; 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_MOD_DQUOT_BYINO(args.mp, args.tp, cur->bc_private.b.ip, XFS_TRANS_DQ_BCOUNT, 1L); bp = xfs_btree_get_bufl(args.mp, cur->bc_tp, args.fsbno, 0); cblock = XFS_BUF_TO_BMBT_BLOCK(bp); *cblock = *block; be16_add(&block->bb_level, 1); block->bb_numrecs = cpu_to_be16(1); cur->bc_nlevels++; cur->bc_ptrs[level + 1] = 1; kp = XFS_BMAP_KEY_IADDR(block, 1, cur); ckp = XFS_BMAP_KEY_IADDR(cblock, 1, cur); memcpy(ckp, kp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*kp)); cpp = XFS_BMAP_PTR_IADDR(cblock, 1, cur);#ifdef DEBUG for (i = 0; i < be16_to_cpu(cblock->bb_numrecs); i++) { if ((error = xfs_btree_check_lptr_disk(cur, pp[i], level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; } }#endif memcpy(cpp, pp, be16_to_cpu(cblock->bb_numrecs) * sizeof(*pp));#ifdef DEBUG if ((error = xfs_btree_check_lptr(cur, args.fsbno, level))) { XFS_BMBT_TRACE_CURSOR(cur, ERROR); return error; }#endif *pp = cpu_to_be64(args.fsbno); xfs_iroot_realloc(cur->bc_private.b.ip, 1 - be16_to_cpu(cblock->bb_numrecs), cur->bc_private.b.whichfork); xfs_btree_setbuf(cur, level, bp); /* * Do all this logging at the end so that * the root is at the right level. */ xfs_bmbt_log_block(cur, bp, XFS_BB_ALL_BITS); xfs_bmbt_log_keys(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); xfs_bmbt_log_ptrs(cur, bp, 1, be16_to_cpu(cblock->bb_numrecs)); XFS_BMBT_TRACE_CURSOR(cur, EXIT); *logflags |= XFS_ILOG_CORE | XFS_ILOG_FBROOT(cur->bc_private.b.whichfork); *stat = 1; return 0;}/* * Set all the fields in a bmap extent record from the arguments. */voidxfs_bmbt_set_allf( xfs_bmbt_rec_host_t *r, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state){ int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);#if XFS_BIG_BLKNOS ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9) | ((xfs_bmbt_rec_base_t)startblock >> 43); r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21));#else /* !XFS_BIG_BLKNOS */ if (ISNULLSTARTBLOCK(startblock)) { r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9) | (xfs_bmbt_rec_base_t)XFS_MASK64LO(9); r->l1 = XFS_MASK64HI(11) | ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); } else { r->l0 = ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9); r->l1 = ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)); }#endif /* XFS_BIG_BLKNOS */}/* * Set all the fields in a bmap extent record from the uncompressed form. */voidxfs_bmbt_set_all( xfs_bmbt_rec_host_t *r, xfs_bmbt_irec_t *s){ xfs_bmbt_set_allf(r, s->br_startoff, s->br_startblock, s->br_blockcount, s->br_state);}/* * Set all the fields in a disk format bmap extent record from the arguments. */voidxfs_bmbt_disk_set_allf( xfs_bmbt_rec_t *r, xfs_fileoff_t startoff, xfs_fsblock_t startblock, xfs_filblks_t blockcount, xfs_exntst_t state){ int extent_flag = (state == XFS_EXT_NORM) ? 0 : 1; ASSERT(state == XFS_EXT_NORM || state == XFS_EXT_UNWRITTEN); ASSERT((startoff & XFS_MASK64HI(64-BMBT_STARTOFF_BITLEN)) == 0); ASSERT((blockcount & XFS_MASK64HI(64-BMBT_BLOCKCOUNT_BITLEN)) == 0);#if XFS_BIG_BLKNOS ASSERT((startblock & XFS_MASK64HI(64-BMBT_STARTBLOCK_BITLEN)) == 0); r->l0 = cpu_to_be64( ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs_bmbt_rec_base_t)startoff << 9) | ((xfs_bmbt_rec_base_t)startblock >> 43)); r->l1 = cpu_to_be64( ((xfs_bmbt_rec_base_t)startblock << 21) | ((xfs_bmbt_rec_base_t)blockcount & (xfs_bmbt_rec_base_t)XFS_MASK64LO(21)));#else /* !XFS_BIG_BLKNOS */ if (ISNULLSTARTBLOCK(startblock)) { r->l0 = cpu_to_be64( ((xfs_bmbt_rec_base_t)extent_flag << 63) | ((xfs
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -