📄 xfs_btree.c
字号:
* Get the block pointer for this level. */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); /* * It's empty, there is no such record. */ if (!block->bb_h.bb_numrecs) return 0; /* * Set the ptr value to 1, that's the first record/key. */ cur->bc_ptrs[level] = 1; return 1;}/* * Retrieve the block pointer from the cursor at the given level. * This may be a bmap btree root or from a buffer. */STATIC xfs_btree_block_t * /* generic btree block pointer */xfs_btree_get_block( xfs_btree_cur_t *cur, /* btree cursor */ int level, /* level in btree */ xfs_buf_t **bpp) /* buffer containing the block */{ xfs_btree_block_t *block; /* return value */ xfs_buf_t *bp; /* return buffer */ xfs_ifork_t *ifp; /* inode fork pointer */ int whichfork; /* data or attr fork */ if (cur->bc_btnum == XFS_BTNUM_BMAP && level == cur->bc_nlevels - 1) { whichfork = cur->bc_private.b.whichfork; ifp = XFS_IFORK_PTR(cur->bc_private.b.ip, whichfork); block = (xfs_btree_block_t *)ifp->if_broot; bp = NULL; } else { bp = cur->bc_bufs[level]; block = XFS_BUF_TO_BLOCK(bp); } ASSERT(block != NULL); *bpp = bp; return block;}/* * Get a buffer for the block, return it with no data read. * Long-form addressing. */xfs_buf_t * /* buffer for fsbno */xfs_btree_get_bufl( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock) /* lock flags for get_buf */{ xfs_buf_t *bp; /* buffer pointer (return value) */ xfs_daddr_t d; /* real disk block address */ ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); ASSERT(bp); ASSERT(!XFS_BUF_GETERROR(bp)); return bp;}/* * Get a buffer for the block, return it with no data read. * Short-form addressing. */xfs_buf_t * /* buffer for agno/agbno */xfs_btree_get_bufs( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ uint lock) /* lock flags for get_buf */{ xfs_buf_t *bp; /* buffer pointer (return value) */ xfs_daddr_t d; /* real disk block address */ ASSERT(agno != NULLAGNUMBER); ASSERT(agbno != NULLAGBLOCK); d = XFS_AGB_TO_DADDR(mp, agno, agbno); bp = xfs_trans_get_buf(tp, mp->m_ddev_targp, d, mp->m_bsize, lock); ASSERT(bp); ASSERT(!XFS_BUF_GETERROR(bp)); return bp;}/* * Allocate a new btree cursor. * The cursor is either for allocation (A) or bmap (B) or inodes (I). */xfs_btree_cur_t * /* new btree cursor */xfs_btree_init_cursor( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_buf_t *agbp, /* (A only) buffer for agf structure */ /* (I only) buffer for agi structure */ xfs_agnumber_t agno, /* (AI only) allocation group number */ xfs_btnum_t btnum, /* btree identifier */ xfs_inode_t *ip, /* (B only) inode owning the btree */ int whichfork) /* (B only) data or attr fork */{ xfs_agf_t *agf; /* (A) allocation group freespace */ xfs_agi_t *agi; /* (I) allocation group inodespace */ xfs_btree_cur_t *cur; /* return value */ xfs_ifork_t *ifp; /* (I) inode fork pointer */ int nlevels=0; /* number of levels in the btree */ ASSERT(xfs_btree_cur_zone != NULL); /* * Allocate a new cursor. */ cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP); /* * Deduce the number of btree levels from the arguments. */ switch (btnum) { case XFS_BTNUM_BNO: case XFS_BTNUM_CNT: agf = XFS_BUF_TO_AGF(agbp); nlevels = be32_to_cpu(agf->agf_levels[btnum]); break; case XFS_BTNUM_BMAP: ifp = XFS_IFORK_PTR(ip, whichfork); nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1; break; case XFS_BTNUM_INO: agi = XFS_BUF_TO_AGI(agbp); nlevels = be32_to_cpu(agi->agi_level); break; default: ASSERT(0); } /* * Fill in the common fields. */ cur->bc_tp = tp; cur->bc_mp = mp; cur->bc_nlevels = nlevels; cur->bc_btnum = btnum; cur->bc_blocklog = mp->m_sb.sb_blocklog; /* * Fill in private fields. */ switch (btnum) { case XFS_BTNUM_BNO: case XFS_BTNUM_CNT: /* * Allocation btree fields. */ cur->bc_private.a.agbp = agbp; cur->bc_private.a.agno = agno; break; case XFS_BTNUM_BMAP: /* * Bmap btree fields. */ cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork); cur->bc_private.b.ip = ip; cur->bc_private.b.firstblock = NULLFSBLOCK; cur->bc_private.b.flist = NULL; cur->bc_private.b.allocated = 0; cur->bc_private.b.flags = 0; cur->bc_private.b.whichfork = whichfork; break; case XFS_BTNUM_INO: /* * Inode allocation btree fields. */ cur->bc_private.i.agbp = agbp; cur->bc_private.i.agno = agno; break; default: ASSERT(0); } return cur;}/* * Check for the cursor referring to the last block at the given level. */int /* 1=is last block, 0=not last block */xfs_btree_islastblock( xfs_btree_cur_t *cur, /* btree cursor */ int level) /* level to check */{ xfs_btree_block_t *block; /* generic btree block pointer */ xfs_buf_t *bp; /* buffer containing block */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); if (XFS_BTREE_LONG_PTRS(cur->bc_btnum)) return be64_to_cpu(block->bb_u.l.bb_rightsib) == NULLDFSBNO; else return be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK;}/* * Change the cursor to point to the last record in the current block * at the given level. Other levels are unaffected. */int /* success=1, failure=0 */xfs_btree_lastrec( xfs_btree_cur_t *cur, /* btree cursor */ int level) /* level to change */{ xfs_btree_block_t *block; /* generic btree block pointer */ xfs_buf_t *bp; /* buffer containing block */ /* * Get the block pointer for this level. */ block = xfs_btree_get_block(cur, level, &bp); xfs_btree_check_block(cur, block, level, bp); /* * It's empty, there is no such record. */ if (!block->bb_h.bb_numrecs) return 0; /* * Set the ptr value to numrecs, that's the last record/key. */ cur->bc_ptrs[level] = be16_to_cpu(block->bb_h.bb_numrecs); return 1;}/* * Compute first and last byte offsets for the fields given. * Interprets the offsets table, which contains struct field offsets. */voidxfs_btree_offsets( __int64_t fields, /* bitmask of fields */ const short *offsets, /* table of field offsets */ int nbits, /* number of bits to inspect */ int *first, /* output: first byte offset */ int *last) /* output: last byte offset */{ int i; /* current bit number */ __int64_t imask; /* mask for current bit number */ ASSERT(fields != 0); /* * Find the lowest bit, so the first byte offset. */ for (i = 0, imask = 1LL; ; i++, imask <<= 1) { if (imask & fields) { *first = offsets[i]; break; } } /* * Find the highest bit, so the last byte offset. */ for (i = nbits - 1, imask = 1LL << i; ; i--, imask >>= 1) { if (imask & fields) { *last = offsets[i + 1] - 1; break; } }}/* * Get a buffer for the block, return it read in. * Long-form addressing. */int /* error */xfs_btree_read_bufl( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_fsblock_t fsbno, /* file system block number */ uint lock, /* lock flags for read_buf */ xfs_buf_t **bpp, /* buffer for fsbno */ int refval) /* ref count value for buffer */{ xfs_buf_t *bp; /* return value */ xfs_daddr_t d; /* real disk block address */ int error; ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, mp->m_bsize, lock, &bp))) { return error; } ASSERT(!bp || !XFS_BUF_GETERROR(bp)); if (bp != NULL) { XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); } *bpp = bp; return 0;}/* * Get a buffer for the block, return it read in. * Short-form addressing. */int /* error */xfs_btree_read_bufs( xfs_mount_t *mp, /* file system mount point */ xfs_trans_t *tp, /* transaction pointer */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ uint lock, /* lock flags for read_buf */ xfs_buf_t **bpp, /* buffer for agno/agbno */ int refval) /* ref count value for buffer */{ xfs_buf_t *bp; /* return value */ xfs_daddr_t d; /* real disk block address */ int error; ASSERT(agno != NULLAGNUMBER); ASSERT(agbno != NULLAGBLOCK); d = XFS_AGB_TO_DADDR(mp, agno, agbno); if ((error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, d, mp->m_bsize, lock, &bp))) { return error; } ASSERT(!bp || !XFS_BUF_GETERROR(bp)); if (bp != NULL) { switch (refval) { case XFS_ALLOC_BTREE_REF: XFS_BUF_SET_VTYPE_REF(bp, B_FS_MAP, refval); break; case XFS_INO_BTREE_REF: XFS_BUF_SET_VTYPE_REF(bp, B_FS_INOMAP, refval); break; } } *bpp = bp; return 0;}/* * Read-ahead the block, don't wait for it, don't return a buffer. * Long-form addressing. *//* ARGSUSED */voidxfs_btree_reada_bufl( xfs_mount_t *mp, /* file system mount point */ xfs_fsblock_t fsbno, /* file system block number */ xfs_extlen_t count) /* count of filesystem blocks */{ xfs_daddr_t d; ASSERT(fsbno != NULLFSBLOCK); d = XFS_FSB_TO_DADDR(mp, fsbno); xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);}/* * Read-ahead the block, don't wait for it, don't return a buffer. * Short-form addressing. *//* ARGSUSED */voidxfs_btree_reada_bufs( xfs_mount_t *mp, /* file system mount point */ xfs_agnumber_t agno, /* allocation group number */ xfs_agblock_t agbno, /* allocation group block number */ xfs_extlen_t count) /* count of filesystem blocks */{ xfs_daddr_t d; ASSERT(agno != NULLAGNUMBER); ASSERT(agbno != NULLAGBLOCK); d = XFS_AGB_TO_DADDR(mp, agno, agbno); xfs_baread(mp->m_ddev_targp, d, mp->m_bsize * count);}/* * Read-ahead btree blocks, at the given level. * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA. */intxfs_btree_readahead_core( xfs_btree_cur_t *cur, /* btree cursor */ int lev, /* level in btree */ int lr) /* left/right bits */{ xfs_alloc_block_t *a; xfs_bmbt_block_t *b; xfs_inobt_block_t *i; int rval = 0; ASSERT(cur->bc_bufs[lev] != NULL); cur->bc_ra[lev] |= lr; switch (cur->bc_btnum) { case XFS_BTNUM_BNO: case XFS_BTNUM_CNT: a = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[lev]); if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(a->bb_leftsib) != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, be32_to_cpu(a->bb_leftsib), 1); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(a->bb_rightsib) != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.a.agno, be32_to_cpu(a->bb_rightsib), 1); rval++; } break; case XFS_BTNUM_BMAP: b = XFS_BUF_TO_BMBT_BLOCK(cur->bc_bufs[lev]); if ((lr & XFS_BTCUR_LEFTRA) && be64_to_cpu(b->bb_leftsib) != NULLDFSBNO) { xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_leftsib), 1); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && be64_to_cpu(b->bb_rightsib) != NULLDFSBNO) { xfs_btree_reada_bufl(cur->bc_mp, be64_to_cpu(b->bb_rightsib), 1); rval++; } break; case XFS_BTNUM_INO: i = XFS_BUF_TO_INOBT_BLOCK(cur->bc_bufs[lev]); if ((lr & XFS_BTCUR_LEFTRA) && be32_to_cpu(i->bb_leftsib) != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, be32_to_cpu(i->bb_leftsib), 1); rval++; } if ((lr & XFS_BTCUR_RIGHTRA) && be32_to_cpu(i->bb_rightsib) != NULLAGBLOCK) { xfs_btree_reada_bufs(cur->bc_mp, cur->bc_private.i.agno, be32_to_cpu(i->bb_rightsib), 1); rval++; } break; default: ASSERT(0); } return rval;}/* * Set the buffer for level "lev" in the cursor to bp, releasing * any previous buffer. */voidxfs_btree_setbuf( xfs_btree_cur_t *cur, /* btree cursor */ int lev, /* level in btree */ xfs_buf_t *bp) /* new buffer to set */{ xfs_btree_block_t *b; /* btree block */ xfs_buf_t *obp; /* old buffer pointer */ obp = cur->bc_bufs[lev]; if (obp) xfs_trans_brelse(cur->bc_tp, obp); cur->bc_bufs[lev] = bp; cur->bc_ra[lev] = 0; if (!bp) return; b = XFS_BUF_TO_BLOCK(bp); if (XFS_BTREE_LONG_PTRS(cur->bc_btnum)) { if (be64_to_cpu(b->bb_u.l.bb_leftsib) == NULLDFSBNO) cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; if (be64_to_cpu(b->bb_u.l.bb_rightsib) == NULLDFSBNO) cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; } else { if (be32_to_cpu(b->bb_u.s.bb_leftsib) == NULLAGBLOCK) cur->bc_ra[lev] |= XFS_BTCUR_LEFTRA; if (be32_to_cpu(b->bb_u.s.bb_rightsib) == NULLAGBLOCK) cur->bc_ra[lev] |= XFS_BTCUR_RIGHTRA; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -